mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2025-07-29 23:00:08 +02:00
129 lines
3.2 KiB
TypeScript
129 lines
3.2 KiB
TypeScript
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<React.SetStateAction<Sort>>
|
|
searchText: string
|
|
setSearchText: React.Dispatch<React.SetStateAction<string>>
|
|
}
|
|
|
|
export const TemplateGalleryContext = createContext<
|
|
TemplateGalleryContextValue | undefined
|
|
>(undefined)
|
|
|
|
type TemplateGalleryProviderProps = {
|
|
children: ReactNode
|
|
}
|
|
|
|
export function TemplateGalleryProvider({ children }: TemplateGalleryProviderProps) {
|
|
const [loadedTemplates, setLoadedTemplates] = useState<Template[]>([])
|
|
const [visibleTemplates, setVisibleTemplates] = useState<Template[]>([])
|
|
const [totalTemplatesCount, setTotalTemplatesCount] = useState<number>(0)
|
|
const [sort, setSort] = useState<Sort>({
|
|
by: 'lastUpdated',
|
|
order: 'desc',
|
|
})
|
|
const prevSortRef = useRef<Sort>(sort)
|
|
|
|
const [searchText, setSearchText] = useState('')
|
|
|
|
const {
|
|
error,
|
|
runAsync,
|
|
} = useAsync<GetTemplatesResponseBody>()
|
|
|
|
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<TemplateGalleryContextValue>(
|
|
() => ({
|
|
error,
|
|
searchText,
|
|
setSearchText,
|
|
setSort,
|
|
sort,
|
|
totalTemplatesCount,
|
|
visibleTemplates,
|
|
}),
|
|
[
|
|
error,
|
|
searchText,
|
|
setSearchText,
|
|
setSort,
|
|
sort,
|
|
totalTemplatesCount,
|
|
visibleTemplates,
|
|
]
|
|
)
|
|
|
|
return (
|
|
<TemplateGalleryContext.Provider value={value}>
|
|
{children}
|
|
</TemplateGalleryContext.Provider>
|
|
)
|
|
}
|
|
|
|
export function useTemplateGalleryContext() {
|
|
const context = useContext(TemplateGalleryContext)
|
|
if (!context) {
|
|
throw new Error(
|
|
'TemplateGalleryContext is only available inside TemplateGalleryProvider'
|
|
)
|
|
}
|
|
return context
|
|
}
|