рефакторинг

This commit is contained in:
2025-07-21 17:07:03 +03:00
parent 84f0c9c6aa
commit 5737e37386
35 changed files with 526 additions and 579 deletions

View File

@@ -0,0 +1,143 @@
import {
apiTemplateToTemplate,
createTemplateApi,
getTemplateApi,
getTemplatesApi,
patchTemplateApi,
templateToCreateInput,
templateToPatchInput,
} from '@/entitiy/template/api/templateApiService'
import { Template } from '@/type/template'
import {
QueryClient,
useMutation,
useQuery,
useQueryClient,
} from '@tanstack/react-query'
import React, { createContext, ReactNode, useContext, useMemo } from 'react'
export const queryClient = new QueryClient()
interface TemplateContextType {
templates: Template[]
isLoading: boolean
error: Error | null
refetchTemplates: () => void
addTemplate: (
data: Omit<Template, 'id' | 'createdAt' | 'updatedAt'>
) => Promise<Template>
updateTemplate: (template: Template) => Promise<Template>
deleteTemplate: (id: UUID) => Promise<string>
}
const TemplateContext = createContext<TemplateContextType | undefined>(
undefined
)
export const TemplateProvider: React.FC<{ children: ReactNode }> = ({
children,
}) => {
const client = useQueryClient()
const {
data: templates = [],
status: listStatus,
error: errorList,
refetch,
} = useQuery<Template[], Error>({
queryKey: ['templates'],
queryFn: async () => {
const { templates: apiList } = await getTemplatesApi()
return apiList.map(apiTemplateToTemplate)
},
})
const createMutation = useMutation({
mutationFn: async (
newTemplate: Omit<Template, 'id' | 'createdAt' | 'updatedAt'>
) => {
const input = templateToCreateInput(newTemplate)
const { id } = await createTemplateApi(input)
const { template: apiTpl } = await getTemplateApi(id)
if (!apiTpl) throw new Error('Template not found')
return apiTemplateToTemplate(apiTpl)
},
onSuccess: () => {
client.invalidateQueries({ queryKey: ['templates'] })
},
})
const updateMutation = useMutation({
mutationFn: async (template: Template) => {
const input = templateToPatchInput(template)
await patchTemplateApi(template.id, input)
return template
},
onSuccess: updated => {
client.setQueryData<Template[]>(
['templates'],
old =>
old?.map((t: Template) => (t.id === updated.id ? updated : t)) ?? []
)
},
})
const deleteMutation = useMutation({
mutationFn: async (id: string) => {
// TODO: deleteTemplateApi
return id
},
onSuccess: id => {
client.setQueryData<Template[]>(
['templates'],
old => old?.filter((t: Template) => t.id !== id) ?? []
)
},
})
const value = useMemo(
() => ({
templates,
isLoading:
listStatus === 'pending' ||
createMutation.status === 'pending' ||
updateMutation.status === 'pending' ||
deleteMutation.status === 'pending',
error:
(errorList as Error) ||
(createMutation.error as Error) ||
(updateMutation.error as Error) ||
(deleteMutation.error as Error) ||
null,
refetchTemplates: refetch,
addTemplate: createMutation.mutateAsync,
updateTemplate: updateMutation.mutateAsync,
deleteTemplate: deleteMutation.mutateAsync,
}),
[
templates,
listStatus,
errorList,
createMutation.status,
createMutation.error,
updateMutation.status,
updateMutation.error,
deleteMutation.status,
deleteMutation.error,
refetch,
]
)
return (
<TemplateContext.Provider value={value}>
{children}
</TemplateContext.Provider>
)
}
export const useTemplateContext = (): TemplateContextType => {
const ctx = useContext(TemplateContext)
if (!ctx)
throw new Error('useTemplateContext must be used within TemplateProvider')
return ctx
}