Skip to content

Commit 6d5bd97

Browse files
authored
Some improvements in web application context (#142)
Signed-off-by: Cintia Sanchez Garcia <[email protected]>
1 parent 9aadd88 commit 6d5bd97

File tree

10 files changed

+146
-89
lines changed

10 files changed

+146
-89
lines changed

web/src/layout/common/Searchbar.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ChangeEvent, KeyboardEvent, useContext, useEffect, useRef, useState } f
44

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

2020
const Searchbar = (props: Props) => {
21-
const { updateActiveItemId } = useContext(AppContext) as Context;
21+
const { updateActiveItemId } = useContext(AppActionsContext) as ActionsContext;
2222
const inputEl = useRef<HTMLInputElement>(null);
2323
const dropdownRef = useRef(null);
2424
const [value, setValue] = useState<string>('');

web/src/layout/common/itemModal/index.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,14 @@ import cleanEmojis from '../../../utils/cleanEmojis';
88
import formatProfitLabel from '../../../utils/formatLabelProfit';
99
import itemsDataGetter from '../../../utils/itemsDataGetter';
1010
import prettifyNumber from '../../../utils/prettifyNumber';
11-
import { AppContext, Context } from '../../context/AppContext';
11+
import {
12+
ActionsContext,
13+
AppActionsContext,
14+
FullDataContext,
15+
FullDataProps,
16+
ItemContext,
17+
ItemProps,
18+
} from '../../context/AppContext';
1219
import ExternalLink from '../ExternalLink';
1320
import Image from '../Image';
1421
import { Loading } from '../Loading';
@@ -19,7 +26,9 @@ import styles from './ItemModal.module.css';
1926
import ParticipationStats from './ParticipationStats';
2027

2128
const ItemModal = () => {
22-
const { activeItemId, updateActiveItemId, fullDataReady } = useContext(AppContext) as Context;
29+
const { fullDataReady } = useContext(FullDataContext) as FullDataProps;
30+
const { visibleItemId } = useContext(ItemContext) as ItemProps;
31+
const { updateActiveItemId } = useContext(AppActionsContext) as ActionsContext;
2332
const [itemInfo, setItemInfo] = useState<Item | null | undefined>(undefined);
2433
let description = 'This item does not have a description available yet';
2534
let stars: number | undefined;
@@ -75,20 +84,20 @@ const ItemModal = () => {
7584
async function fetchItemInfo() {
7685
try {
7786
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
78-
setItemInfo(await itemsDataGetter.get(activeItemId!));
87+
setItemInfo(await itemsDataGetter.findById(visibleItemId!));
7988
} catch {
8089
setItemInfo(null);
8190
}
8291
}
8392

84-
if (activeItemId && fullDataReady) {
93+
if (visibleItemId && fullDataReady) {
8594
fetchItemInfo();
8695
} else {
8796
setItemInfo(undefined);
8897
}
89-
}, [activeItemId, fullDataReady]);
98+
}, [visibleItemId, fullDataReady]);
9099

91-
if (isUndefined(activeItemId)) return null;
100+
if (isUndefined(visibleItemId)) return null;
92101

93102
return (
94103
<Modal size="xl" open modalDialogClassName={styles.modalDialog} onClose={() => updateActiveItemId()}>

web/src/layout/common/zoomModal/index.tsx

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ import { BaseItem, Item } from '../../../types';
66
import { calculateItemsPerRow, calculateWidthInPx } from '../../../utils/gridCategoryLayout';
77
import itemsDataGetter from '../../../utils/itemsDataGetter';
88
import sortItemsByOrderValue from '../../../utils/sortItemsByOrderValue';
9-
import { AppContext, Context } from '../../context/AppContext';
9+
import {
10+
ActionsContext,
11+
AppActionsContext,
12+
FullDataContext,
13+
FullDataProps,
14+
ZoomContext,
15+
ZoomProps,
16+
} from '../../context/AppContext';
1017
import GridItem from '../../explore/gridCategory/GridItem';
1118
import FullScreenModal from '../FullScreenModal';
1219
import { Loading } from '../Loading';
@@ -16,7 +23,9 @@ const GAP = 96 + 40; // Padding | Title
1623
const CARD_WIDTH = 75;
1724

1825
const ZoomModal = () => {
19-
const { activeSection, updateActiveSection, fullDataReady } = useContext(AppContext) as Context;
26+
const { visibleZoomView } = useContext(ZoomContext) as ZoomProps;
27+
const { fullDataReady } = useContext(FullDataContext) as FullDataProps;
28+
const { updateActiveSection } = useContext(AppActionsContext) as ActionsContext;
2029
const modal = useRef<HTMLDivElement>(null);
2130
const container = useRef<HTMLDivElement>(null);
2231
const [items, setItems] = useState<Item[] | undefined | null>();
@@ -38,24 +47,24 @@ const ZoomModal = () => {
3847
async function fetchItems() {
3948
try {
4049
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
41-
setItems(await itemsDataGetter.filterItemsBySection(activeSection!));
50+
setItems(await itemsDataGetter.filterItemsBySection(visibleZoomView!));
4251
} catch {
4352
setItems(null);
4453
}
4554
}
4655

47-
if (activeSection && fullDataReady) {
56+
if (visibleZoomView && fullDataReady) {
4857
fetchItems();
4958
} else {
5059
setItems(undefined);
5160
}
52-
}, [activeSection, fullDataReady]);
61+
}, [visibleZoomView, fullDataReady]);
5362

5463
useEffect(() => {
55-
if (container && container.current && activeSection) {
64+
if (container && container.current && visibleZoomView) {
5665
setContainerWidth(checkNumColumns(container.current.offsetWidth - GAP));
5766
}
58-
}, [container, activeSection]);
67+
}, [container, visibleZoomView]);
5968

6069
useEffect(() => {
6170
const checkContainerWidth = throttle(() => {
@@ -72,7 +81,7 @@ const ZoomModal = () => {
7281
return () => window.removeEventListener('resize', checkContainerWidth);
7382
}, []);
7483

75-
if (isUndefined(activeSection)) return null;
84+
if (isUndefined(visibleZoomView)) return null;
7685

7786
return (
7887
<FullScreenModal open refs={[modal]} onClose={() => updateActiveSection()}>
@@ -86,10 +95,10 @@ const ZoomModal = () => {
8695
>
8796
<div
8897
className={`text-white border border-3 border-white fw-semibold p-2 py-5 ${styles.catTitle}`}
89-
style={{ backgroundColor: activeSection.bgColor }}
98+
style={{ backgroundColor: visibleZoomView.bgColor }}
9099
>
91100
<div className="d-flex flex-row align-items-start justify-content-end">
92-
<div>{activeSection.category}</div>
101+
<div>{visibleZoomView.category}</div>
93102
</div>
94103
</div>
95104

@@ -99,9 +108,9 @@ const ZoomModal = () => {
99108
>
100109
<div
101110
className={`d-flex align-items-center text-white justify-content-center text-center px-2 w-100 fw-semibold ${styles.subcatTitle}`}
102-
style={{ backgroundColor: activeSection.bgColor }}
111+
style={{ backgroundColor: visibleZoomView.bgColor }}
103112
>
104-
<div className="text-truncate">{activeSection.subcategory}</div>
113+
<div className="text-truncate">{visibleZoomView.subcategory}</div>
105114
</div>
106115
</div>
107116
<div className={`h-100 overflow-auto ${styles.content}`}>

web/src/layout/context/AppContext.tsx

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
1-
import { createContext, useState } from 'react';
1+
import { createContext, useCallback, useMemo, useState } from 'react';
22

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

5-
export type Context = {
6-
activeItemId?: string;
5+
export type FullDataProps = {
6+
fullDataReady: boolean;
7+
};
8+
9+
export type ItemProps = {
10+
visibleItemId?: string;
11+
};
12+
13+
export type ZoomProps = {
14+
visibleZoomView?: ActiveSection;
15+
};
16+
17+
export type ActionsContext = {
718
updateActiveItemId: (itemId?: string) => void;
8-
activeSection?: ActiveSection;
919
updateActiveSection: (activeSection?: ActiveSection) => void;
10-
fullDataReady: boolean;
1120
};
1221

1322
export interface ActiveSection {
@@ -20,33 +29,67 @@ interface Props {
2029
children: JSX.Element;
2130
}
2231

23-
export const AppContext = createContext<Context | null>(null);
32+
export const FullDataContext = createContext<FullDataProps | null>(null);
33+
export const ItemContext = createContext<ItemProps | null>(null);
34+
export const ZoomContext = createContext<ZoomProps | null>(null);
35+
export const AppActionsContext = createContext<ActionsContext | null>(null);
2436

2537
const AppContextProvider = (props: Props) => {
26-
const [activeItemId, setActiveItemId] = useState<string | undefined>();
27-
const [activeSection, setActiveSection] = useState<ActiveSection | undefined>();
38+
const [visibleItemId, setVisibleItemId] = useState<string | undefined>();
39+
const [visibleZoomView, setVisibleZoomView] = useState<ActiveSection | undefined>();
2840
const [fullDataReady, setFullDataReady] = useState<boolean>(false);
2941

30-
const updateActiveItemId = (id?: string) => {
31-
setActiveItemId(id);
32-
};
42+
const updateActiveItemId = useCallback((id?: string) => {
43+
setVisibleItemId(id);
44+
}, []);
3345

34-
const updateActiveSection = (section?: ActiveSection) => {
35-
setActiveSection(section);
36-
};
46+
const updateActiveSection = useCallback((section?: ActiveSection) => {
47+
setVisibleZoomView(section);
48+
}, []);
49+
50+
const fullDataValue = useMemo(
51+
() => ({
52+
fullDataReady,
53+
}),
54+
[fullDataReady]
55+
);
56+
57+
const itemValue = useMemo(
58+
() => ({
59+
visibleItemId,
60+
}),
61+
[visibleItemId]
62+
);
63+
64+
const zoomValue = useMemo(
65+
() => ({
66+
visibleZoomView,
67+
}),
68+
[visibleZoomView]
69+
);
70+
71+
const contextActionsValue = useMemo(
72+
() => ({
73+
updateActiveItemId,
74+
updateActiveSection,
75+
}),
76+
[updateActiveItemId, updateActiveSection]
77+
);
3778

38-
itemsDataGetter.isReady({
79+
itemsDataGetter.subscribe({
3980
updateStatus: (status: boolean) => {
4081
setFullDataReady(status);
4182
},
4283
});
4384

4485
return (
45-
<AppContext.Provider
46-
value={{ activeItemId, updateActiveItemId, updateActiveSection, activeSection, fullDataReady }}
47-
>
48-
{props.children}
49-
</AppContext.Provider>
86+
<FullDataContext.Provider value={fullDataValue}>
87+
<ItemContext.Provider value={itemValue}>
88+
<ZoomContext.Provider value={zoomValue}>
89+
<AppActionsContext.Provider value={contextActionsValue}>{props.children}</AppActionsContext.Provider>
90+
</ZoomContext.Provider>
91+
</ItemContext.Provider>
92+
</FullDataContext.Provider>
5093
);
5194
};
5295

web/src/layout/explore/cardCategory/Content.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { orderBy } from 'lodash';
2-
import { useContext } from 'react';
2+
import { memo, useContext } from 'react';
33
import { useNavigate } from 'react-router-dom';
44
import { Waypoint } from 'react-waypoint';
55

66
import { BaseItem, CardMenu, Item } from '../../../types';
7+
import arePropsEqual from '../../../utils/areEqualProps';
78
import convertStringSpaces from '../../../utils/convertStringSpaces';
89
import isElementInView from '../../../utils/isElementInView';
910
import { CategoriesData } from '../../../utils/prepareData';
10-
import { AppContext, Context } from '../../context/AppContext';
11+
import { ActionsContext, AppActionsContext } from '../../context/AppContext';
1112
import Card from './Card';
1213
import styles from './Content.module.css';
1314

@@ -16,9 +17,9 @@ interface Props {
1617
data: CategoriesData;
1718
isVisible: boolean;
1819
}
19-
const Content = (props: Props) => {
20+
const Content = memo(function Content(props: Props) {
2021
const navigate = useNavigate();
21-
const { updateActiveItemId } = useContext(AppContext) as Context;
22+
const { updateActiveItemId } = useContext(AppActionsContext) as ActionsContext;
2223

2324
const sortItems = (firstCategory: string, firstSubcategory: string): BaseItem[] => {
2425
return orderBy(
@@ -88,6 +89,6 @@ const Content = (props: Props) => {
8889
})}
8990
</>
9091
);
91-
};
92+
}, arePropsEqual);
9293

9394
export default Content;

web/src/layout/explore/cardCategory/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { SubcategoryDetails } from '../../../utils/gridCategoryLayout';
1010
import isElementInView from '../../../utils/isElementInView';
1111
import { CategoriesData } from '../../../utils/prepareData';
1212
import { Loading } from '../../common/Loading';
13-
import { AppContext, Context } from '../../context/AppContext';
13+
import { FullDataContext, FullDataProps } from '../../context/AppContext';
1414
import ButtonToTopScroll from './ButtonToTopScroll';
1515
import Content from './Content';
1616
import Menu from './Menu';
@@ -24,7 +24,7 @@ interface Props {
2424
const TITLE_OFFSET = 16;
2525

2626
const CardCategory = memo(function CardCategory(props: Props) {
27-
const { fullDataReady } = useContext(AppContext) as Context;
27+
const { fullDataReady } = useContext(FullDataContext) as FullDataProps;
2828
const navigate = useNavigate();
2929
const [menu, setMenu] = useState<CardMenu | undefined>();
3030
const [initialFullRender, setInitialFullRender] = useState<boolean>(false);

web/src/layout/explore/gridCategory/Grid.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import getGridCategoryLayout, {
1515
import { SubcategoryData } from '../../../utils/prepareData';
1616
import sortItemsByOrderValue from '../../../utils/sortItemsByOrderValue';
1717
import SVGIcon from '../../common/SVGIcon';
18-
import { AppContext, Context } from '../../context/AppContext';
18+
import { ActionsContext, AppActionsContext } from '../../context/AppContext';
1919
import styles from './Grid.module.css';
2020
import GridItem from './GridItem';
2121

@@ -31,7 +31,7 @@ interface Props {
3131
}
3232

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

3737
useEffect(() => {
@@ -117,8 +117,8 @@ const Grid = memo(function Grid(props: Props) {
117117
{sortedItems.map((item: BaseItem | Item) => {
118118
return (
119119
<GridItem
120-
item={item}
121120
key={`item_${item.name}`}
121+
item={item}
122122
borderColor={props.backgroundColor}
123123
showMoreInfo
124124
/>

0 commit comments

Comments
 (0)