Skip to content

Commit

Permalink
Some improvements in web application context
Browse files Browse the repository at this point in the history
Signed-off-by: Cintia Sanchez Garcia <[email protected]>
  • Loading branch information
cynthia-sg committed Aug 30, 2023
1 parent 9aadd88 commit b298414
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 89 deletions.
4 changes: 2 additions & 2 deletions web/src/layout/common/Searchbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ChangeEvent, KeyboardEvent, useContext, useEffect, useRef, useState } f

import { useOutsideClick } from '../../hooks/useOutsideClick';
import { BaseItem, SVGIconKind } from '../../types';
import { AppContext, Context } from '../context/AppContext';
import { ActionsContext, AppActionsContext } from '../context/AppContext';
import HoverableItem from './HoverableItem';
import MaturityBadge from './MaturityBadge';
import styles from './Searchbar.module.css';
Expand All @@ -18,7 +18,7 @@ const SEARCH_DELAY = 3 * 100; // 300ms
const MIN_CHARACTERS_SEARCH = 2;

const Searchbar = (props: Props) => {
const { updateActiveItemId } = useContext(AppContext) as Context;
const { updateActiveItemId } = useContext(AppActionsContext) as ActionsContext;
const inputEl = useRef<HTMLInputElement>(null);
const dropdownRef = useRef(null);
const [value, setValue] = useState<string>('');
Expand Down
21 changes: 15 additions & 6 deletions web/src/layout/common/itemModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@ import cleanEmojis from '../../../utils/cleanEmojis';
import formatProfitLabel from '../../../utils/formatLabelProfit';
import itemsDataGetter from '../../../utils/itemsDataGetter';
import prettifyNumber from '../../../utils/prettifyNumber';
import { AppContext, Context } from '../../context/AppContext';
import {
ActionsContext,
AppActionsContext,
FullDataContext,
FullDataProps,
ItemContext,
ItemProps,
} from '../../context/AppContext';
import ExternalLink from '../ExternalLink';
import Image from '../Image';
import { Loading } from '../Loading';
Expand All @@ -19,7 +26,9 @@ import styles from './ItemModal.module.css';
import ParticipationStats from './ParticipationStats';

const ItemModal = () => {
const { activeItemId, updateActiveItemId, fullDataReady } = useContext(AppContext) as Context;
const { fullDataReady } = useContext(FullDataContext) as FullDataProps;
const { visibleItemId } = useContext(ItemContext) as ItemProps;
const { updateActiveItemId } = useContext(AppActionsContext) as ActionsContext;
const [itemInfo, setItemInfo] = useState<Item | null | undefined>(undefined);
let description = 'This item does not have a description available yet';
let stars: number | undefined;
Expand Down Expand Up @@ -75,20 +84,20 @@ const ItemModal = () => {
async function fetchItemInfo() {
try {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
setItemInfo(await itemsDataGetter.get(activeItemId!));
setItemInfo(await itemsDataGetter.findById(visibleItemId!));
} catch {
setItemInfo(null);
}
}

if (activeItemId && fullDataReady) {
if (visibleItemId && fullDataReady) {
fetchItemInfo();
} else {
setItemInfo(undefined);
}
}, [activeItemId, fullDataReady]);
}, [visibleItemId, fullDataReady]);

if (isUndefined(activeItemId)) return null;
if (isUndefined(visibleItemId)) return null;

return (
<Modal size="xl" open modalDialogClassName={styles.modalDialog} onClose={() => updateActiveItemId()}>
Expand Down
33 changes: 21 additions & 12 deletions web/src/layout/common/zoomModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ import { BaseItem, Item } from '../../../types';
import { calculateItemsPerRow, calculateWidthInPx } from '../../../utils/gridCategoryLayout';
import itemsDataGetter from '../../../utils/itemsDataGetter';
import sortItemsByOrderValue from '../../../utils/sortItemsByOrderValue';
import { AppContext, Context } from '../../context/AppContext';
import {
ActionsContext,
AppActionsContext,
FullDataContext,
FullDataProps,
ZoomContext,
ZoomProps,
} from '../../context/AppContext';
import GridItem from '../../explore/gridCategory/GridItem';
import FullScreenModal from '../FullScreenModal';
import { Loading } from '../Loading';
Expand All @@ -16,7 +23,9 @@ const GAP = 96 + 40; // Padding | Title
const CARD_WIDTH = 75;

const ZoomModal = () => {
const { activeSection, updateActiveSection, fullDataReady } = useContext(AppContext) as Context;
const { visibleZoomView } = useContext(ZoomContext) as ZoomProps;
const { fullDataReady } = useContext(FullDataContext) as FullDataProps;
const { updateActiveSection } = useContext(AppActionsContext) as ActionsContext;
const modal = useRef<HTMLDivElement>(null);
const container = useRef<HTMLDivElement>(null);
const [items, setItems] = useState<Item[] | undefined | null>();
Expand All @@ -38,24 +47,24 @@ const ZoomModal = () => {
async function fetchItems() {
try {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
setItems(await itemsDataGetter.filterItemsBySection(activeSection!));
setItems(await itemsDataGetter.filterItemsBySection(visibleZoomView!));
} catch {
setItems(null);
}
}

if (activeSection && fullDataReady) {
if (visibleZoomView && fullDataReady) {
fetchItems();
} else {
setItems(undefined);
}
}, [activeSection, fullDataReady]);
}, [visibleZoomView, fullDataReady]);

useEffect(() => {
if (container && container.current && activeSection) {
if (container && container.current && visibleZoomView) {
setContainerWidth(checkNumColumns(container.current.offsetWidth - GAP));
}
}, [container, activeSection]);
}, [container, visibleZoomView]);

useEffect(() => {
const checkContainerWidth = throttle(() => {
Expand All @@ -72,7 +81,7 @@ const ZoomModal = () => {
return () => window.removeEventListener('resize', checkContainerWidth);
}, []);

if (isUndefined(activeSection)) return null;
if (isUndefined(visibleZoomView)) return null;

return (
<FullScreenModal open refs={[modal]} onClose={() => updateActiveSection()}>
Expand All @@ -86,10 +95,10 @@ const ZoomModal = () => {
>
<div
className={`text-white border border-3 border-white fw-semibold p-2 py-5 ${styles.catTitle}`}
style={{ backgroundColor: activeSection.bgColor }}
style={{ backgroundColor: visibleZoomView.bgColor }}
>
<div className="d-flex flex-row align-items-start justify-content-end">
<div>{activeSection.category}</div>
<div>{visibleZoomView.category}</div>
</div>
</div>

Expand All @@ -99,9 +108,9 @@ const ZoomModal = () => {
>
<div
className={`d-flex align-items-center text-white justify-content-center text-center px-2 w-100 fw-semibold ${styles.subcatTitle}`}
style={{ backgroundColor: activeSection.bgColor }}
style={{ backgroundColor: visibleZoomView.bgColor }}
>
<div className="text-truncate">{activeSection.subcategory}</div>
<div className="text-truncate">{visibleZoomView.subcategory}</div>
</div>
</div>
<div className={`h-100 overflow-auto ${styles.content}`}>
Expand Down
83 changes: 63 additions & 20 deletions web/src/layout/context/AppContext.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import { createContext, useState } from 'react';
import { createContext, useCallback, useMemo, useState } from 'react';

import itemsDataGetter from '../../utils/itemsDataGetter';

export type Context = {
activeItemId?: string;
export type FullDataProps = {
fullDataReady: boolean;
};

export type ItemProps = {
visibleItemId?: string;
};

export type ZoomProps = {
visibleZoomView?: ActiveSection;
};

export type ActionsContext = {
updateActiveItemId: (itemId?: string) => void;
activeSection?: ActiveSection;
updateActiveSection: (activeSection?: ActiveSection) => void;
fullDataReady: boolean;
};

export interface ActiveSection {
Expand All @@ -20,33 +29,67 @@ interface Props {
children: JSX.Element;
}

export const AppContext = createContext<Context | null>(null);
export const FullDataContext = createContext<FullDataProps | null>(null);
export const ItemContext = createContext<ItemProps | null>(null);
export const ZoomContext = createContext<ZoomProps | null>(null);
export const AppActionsContext = createContext<ActionsContext | null>(null);

const AppContextProvider = (props: Props) => {
const [activeItemId, setActiveItemId] = useState<string | undefined>();
const [activeSection, setActiveSection] = useState<ActiveSection | undefined>();
const [visibleItemId, setVisibleItemId] = useState<string | undefined>();
const [visibleZoomView, setVisibleZoomView] = useState<ActiveSection | undefined>();
const [fullDataReady, setFullDataReady] = useState<boolean>(false);

const updateActiveItemId = (id?: string) => {
setActiveItemId(id);
};
const updateActiveItemId = useCallback((id?: string) => {
setVisibleItemId(id);
}, []);

const updateActiveSection = (section?: ActiveSection) => {
setActiveSection(section);
};
const updateActiveSection = useCallback((section?: ActiveSection) => {
setVisibleZoomView(section);
}, []);

const fullDataValue = useMemo(
() => ({
fullDataReady,
}),
[fullDataReady]
);

const itemValue = useMemo(
() => ({
visibleItemId,
}),
[visibleItemId]
);

const zoomValue = useMemo(
() => ({
visibleZoomView,
}),
[visibleZoomView]
);

const contextActionsValue = useMemo(
() => ({
updateActiveItemId,
updateActiveSection,
}),
[updateActiveItemId, updateActiveSection]
);

itemsDataGetter.isReady({
itemsDataGetter.subscribe({
updateStatus: (status: boolean) => {
setFullDataReady(status);
},
});

return (
<AppContext.Provider
value={{ activeItemId, updateActiveItemId, updateActiveSection, activeSection, fullDataReady }}
>
{props.children}
</AppContext.Provider>
<FullDataContext.Provider value={fullDataValue}>
<ItemContext.Provider value={itemValue}>
<ZoomContext.Provider value={zoomValue}>
<AppActionsContext.Provider value={contextActionsValue}>{props.children}</AppActionsContext.Provider>
</ZoomContext.Provider>
</ItemContext.Provider>
</FullDataContext.Provider>
);
};

Expand Down
11 changes: 6 additions & 5 deletions web/src/layout/explore/cardCategory/Content.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { orderBy } from 'lodash';
import { useContext } from 'react';
import { memo, useContext } from 'react';
import { useNavigate } from 'react-router-dom';
import { Waypoint } from 'react-waypoint';

import { BaseItem, CardMenu, Item } from '../../../types';
import arePropsEqual from '../../../utils/areEqualProps';
import convertStringSpaces from '../../../utils/convertStringSpaces';
import isElementInView from '../../../utils/isElementInView';
import { CategoriesData } from '../../../utils/prepareData';
import { AppContext, Context } from '../../context/AppContext';
import { ActionsContext, AppActionsContext } from '../../context/AppContext';
import Card from './Card';
import styles from './Content.module.css';

Expand All @@ -16,9 +17,9 @@ interface Props {
data: CategoriesData;
isVisible: boolean;
}
const Content = (props: Props) => {
const Content = memo(function Content(props: Props) {
const navigate = useNavigate();
const { updateActiveItemId } = useContext(AppContext) as Context;
const { updateActiveItemId } = useContext(AppActionsContext) as ActionsContext;

const sortItems = (firstCategory: string, firstSubcategory: string): BaseItem[] => {
return orderBy(
Expand Down Expand Up @@ -88,6 +89,6 @@ const Content = (props: Props) => {
})}
</>
);
};
}, arePropsEqual);

export default Content;
4 changes: 2 additions & 2 deletions web/src/layout/explore/cardCategory/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { SubcategoryDetails } from '../../../utils/gridCategoryLayout';
import isElementInView from '../../../utils/isElementInView';
import { CategoriesData } from '../../../utils/prepareData';
import { Loading } from '../../common/Loading';
import { AppContext, Context } from '../../context/AppContext';
import { FullDataContext, FullDataProps } from '../../context/AppContext';
import ButtonToTopScroll from './ButtonToTopScroll';
import Content from './Content';
import Menu from './Menu';
Expand All @@ -24,7 +24,7 @@ interface Props {
const TITLE_OFFSET = 16;

const CardCategory = memo(function CardCategory(props: Props) {
const { fullDataReady } = useContext(AppContext) as Context;
const { fullDataReady } = useContext(FullDataContext) as FullDataProps;
const navigate = useNavigate();
const [menu, setMenu] = useState<CardMenu | undefined>();
const [initialFullRender, setInitialFullRender] = useState<boolean>(false);
Expand Down
6 changes: 3 additions & 3 deletions web/src/layout/explore/gridCategory/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import getGridCategoryLayout, {
import { SubcategoryData } from '../../../utils/prepareData';
import sortItemsByOrderValue from '../../../utils/sortItemsByOrderValue';
import SVGIcon from '../../common/SVGIcon';
import { AppContext, Context } from '../../context/AppContext';
import { ActionsContext, AppActionsContext } from '../../context/AppContext';
import styles from './Grid.module.css';
import GridItem from './GridItem';

Expand All @@ -31,7 +31,7 @@ interface Props {
}

const Grid = memo(function Grid(props: Props) {
const { updateActiveSection } = useContext(AppContext) as Context;
const { updateActiveSection } = useContext(AppActionsContext) as ActionsContext;
const [grid, setGrid] = useState<GridCategoryLayout | undefined>();

useEffect(() => {
Expand Down Expand Up @@ -117,8 +117,8 @@ const Grid = memo(function Grid(props: Props) {
{sortedItems.map((item: BaseItem | Item) => {
return (
<GridItem
item={item}
key={`item_${item.name}`}
item={item}
borderColor={props.backgroundColor}
showMoreInfo
/>
Expand Down
Loading

0 comments on commit b298414

Please sign in to comment.