tfwm-travel-updates-widget
Version:
A shareable travel updates (disruptions) widget which is shown on the TfWM homepage
68 lines (56 loc) • 3.02 kB
text/typescript
import { StateUpdater, useContext, useEffect, useState } from 'preact/hooks';
// State
import { GlobalContext } from 'globalState/GlobalStateContext';
// Types
import { DefaultModes, IsRowOpen, VisibleDisruptionIndicators } from 'sharedTypes';
import { InitialStateProps } from 'globalState/types';
type UseAccordionLogicReturn = {
state: InitialStateProps;
isRowOpen: IsRowOpen;
setIsRowOpen: StateUpdater<IsRowOpen>;
indicatorsVisibility: VisibleDisruptionIndicators[];
setIndicatorsVisibility: StateUpdater<VisibleDisruptionIndicators[]>;
};
const useAccordionLogic = (mode: DefaultModes, isFetching: boolean): UseAccordionLogicReturn => {
const [state] = useContext(GlobalContext); // Global state
const [indicatorsVisibility, setIndicatorsVisibility] = useState<VisibleDisruptionIndicators[]>(
[]
); // Array used to track visibility state of indicators
const [isRowOpen, setIsRowOpen] = useState<IsRowOpen>(false); // boolean | 'all' used to track the open/close of the arrow button
// ***
// USEEFFECTS TO HELP WITH ACCORDION AND INDICATOR STATE
// Run when isFetching complete
useEffect(() => {
// When fetching is complete and we don't already have disruptionIndicators already populated...
if (!isFetching && indicatorsVisibility.length === 0) {
const indicatorInitialState = state?.favs[mode].map(({ id }) => ({ id, visible: false }));
setIndicatorsVisibility(indicatorInitialState); // Then populate disruptionIndicators array with ids and visibility
}
}, [isFetching, mode, state?.favs, indicatorsVisibility.length]);
// Run everytime the disruptionIndicators changes state
useEffect(() => {
const visibleIndicators = indicatorsVisibility.filter(item => item.visible); // Loop through all disruption indicators and only return the visible ones
if (visibleIndicators.length === 0) setIsRowOpen(false); // If there are no visible ones, then the isRowOpen toggle button needs to be set to false
if (visibleIndicators.length > 0) setIsRowOpen(true); // Otherwise set it to true (open)
}, [setIsRowOpen, indicatorsVisibility]);
// Run everytime the isRowOpen button changes state
useEffect(() => {
// Function to set all disruption indicators of a row to visible or not
const setVisibilityOfAllInidicators = (visible: boolean) => {
setIndicatorsVisibility(prevState => {
const updatedIndicatorsVisibility = prevState.map(item => ({ ...item, visible }));
return updatedIndicatorsVisibility;
});
};
if (isRowOpen === 'all') setVisibilityOfAllInidicators(true); // If isRowOpen is all then we need to show everything so set visible to true
if (!isRowOpen) setVisibilityOfAllInidicators(false); // Otherwise if the row isn't open, then we need to set all indicators to not show
}, [isRowOpen, setIndicatorsVisibility]);
return {
state,
isRowOpen,
setIsRowOpen,
indicatorsVisibility,
setIndicatorsVisibility,
};
};
export default useAccordionLogic;