/* eslint-disable react/prop-types */ /* eslint-disable @typescript-eslint/ban-types */ /* eslint-disable @typescript-eslint/no-empty-function */ import { useCallback, useReducer, createContext, useContext } from 'react' import type { Item } from '#types/Item' import type { Marker, Popup } from 'leaflet' interface LeafletRef { item: Item marker: Marker popup: Popup } type ActionType = | { type: 'ADD_MARKER'; item: Item; marker: Marker } | { type: 'ADD_POPUP'; item: Item; popup: Popup } type UseLeafletRefsManagerResult = ReturnType const LeafletRefsContext = createContext({ leafletRefs: {}, addMarker: () => {}, addPopup: () => {}, }) function useLeafletRefsManager(initialLeafletRefs: {}): { leafletRefs: Record addMarker: (item: Item, marker: Marker) => void addPopup: (item: Item, popup: Popup) => void } { const [leafletRefs, dispatch] = useReducer( (state: Record, action: ActionType) => { switch (action.type) { case 'ADD_MARKER': return { ...state, [action.item.id]: { ...state[action.item.id], marker: action.marker, item: action.item, }, } case 'ADD_POPUP': return { ...state, [action.item.id]: { ...state[action.item.id], popup: action.popup, item: action.item }, } default: throw new Error() } }, initialLeafletRefs, ) const addMarker = useCallback((item: Item, marker: Marker) => { dispatch({ type: 'ADD_MARKER', item, marker, }) }, []) const addPopup = useCallback((item: Item, popup: Popup) => { dispatch({ type: 'ADD_POPUP', item, popup, }) }, []) return { leafletRefs, addMarker, addPopup } } export const LeafletRefsProvider: React.FunctionComponent<{ initialLeafletRefs: {} children?: React.ReactNode }> = ({ initialLeafletRefs, children }) => ( {children} ) export const useLeafletRefs = (): Record => { const { leafletRefs } = useContext(LeafletRefsContext) return leafletRefs } export const useAddMarker = (): UseLeafletRefsManagerResult['addMarker'] => { const { addMarker } = useContext(LeafletRefsContext) return addMarker } export const useAddPopup = (): UseLeafletRefsManagerResult['addPopup'] => { const { addPopup } = useContext(LeafletRefsContext) return addPopup }