import { createContext, ReactNode, useContext, useEffect, useMemo, useRef, useState, } from 'react' import { Template } from '../../../../../types/template' import { GetTemplatesResponseBody, Sort } from '../types/api' import getMeta from '../../../utils/meta' import useAsync from '../../../shared/hooks/use-async' import { getTemplates } from '../util/api' import sortTemplates from '../util/sort-templates' import { debugConsole } from '@/utils/debugging' export type TemplateGalleryContextValue = { visibleTemplates: Template[] totalTemplatesCount: number error: Error | null sort: Sort setSort: React.Dispatch> searchText: string setSearchText: React.Dispatch> } export const TemplateGalleryContext = createContext< TemplateGalleryContextValue | undefined >(undefined) type TemplateGalleryProviderProps = { children: ReactNode } export function TemplateGalleryProvider({ children }: TemplateGalleryProviderProps) { const [loadedTemplates, setLoadedTemplates] = useState([]) const [visibleTemplates, setVisibleTemplates] = useState([]) const [totalTemplatesCount, setTotalTemplatesCount] = useState(0) const [sort, setSort] = useState({ by: 'lastUpdated', order: 'desc', }) const prevSortRef = useRef(sort) const [searchText, setSearchText] = useState('') const { error, runAsync, } = useAsync() const category = getMeta('ol-templateCategory') || 'all' useEffect(() => { runAsync(getTemplates(sort, category)) .then(data => { setLoadedTemplates(data.templates) setTotalTemplatesCount(data.totalSize) }) .catch(debugConsole.error) .finally(() => { }) }, [runAsync]) useEffect(() => { let filteredTemplates = [...loadedTemplates] if (searchText.length) { filteredTemplates = filteredTemplates.filter(template => template.name.toLowerCase().includes(searchText.toLowerCase()) || template.description.toLowerCase().includes(searchText.toLowerCase()) ) } if (prevSortRef.current !== sort) { filteredTemplates = sortTemplates(filteredTemplates, sort) const loadedTemplatesSorted = sortTemplates(loadedTemplates, sort) setLoadedTemplates(loadedTemplatesSorted) } setVisibleTemplates(filteredTemplates) }, [ loadedTemplates, searchText, sort, ]) useEffect(() => { prevSortRef.current = sort }, [sort]) const value = useMemo( () => ({ error, searchText, setSearchText, setSort, sort, totalTemplatesCount, visibleTemplates, }), [ error, searchText, setSearchText, setSort, sort, totalTemplatesCount, visibleTemplates, ] ) return ( {children} ) } export function useTemplateGalleryContext() { const context = useContext(TemplateGalleryContext) if (!context) { throw new Error( 'TemplateGalleryContext is only available inside TemplateGalleryProvider' ) } return context }