группы
This commit is contained in:
142
src/entity/group/api/groupApiService.ts
Normal file
142
src/entity/group/api/groupApiService.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
import { Group } from '@/type/template'
|
||||
|
||||
// Интерфейсы для API групп
|
||||
export interface GetGroupsOutput {
|
||||
groups: Group[]
|
||||
}
|
||||
|
||||
export interface GetGroupOutput {
|
||||
group: Group | null
|
||||
}
|
||||
|
||||
export interface CreateGroupInput {
|
||||
name: string
|
||||
order?: number
|
||||
}
|
||||
|
||||
export interface CreateGroupOutput {
|
||||
id: string
|
||||
}
|
||||
|
||||
export interface PatchGroupInput {
|
||||
name?: string | null
|
||||
order?: number | null
|
||||
}
|
||||
|
||||
export interface PatchGroupOutput extends Group {}
|
||||
|
||||
// API получение всех групп
|
||||
export async function getGroupsApi(): Promise<GetGroupsOutput> {
|
||||
try {
|
||||
const response = await fetch('/api/groups/', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
const result: GetGroupsOutput = await response.json()
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error('Ошибка при получении групп:', error)
|
||||
throw new Error('Ошибка при получении групп с сервера')
|
||||
}
|
||||
}
|
||||
|
||||
// API получение конкретной группы
|
||||
export async function getGroupApi(groupId: string): Promise<GetGroupOutput> {
|
||||
try {
|
||||
const response = await fetch(`/api/groups/${groupId}`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
const result: GetGroupOutput = await response.json()
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error('Ошибка при получении группы:', error)
|
||||
throw new Error('Ошибка при получении группы с сервера')
|
||||
}
|
||||
}
|
||||
|
||||
// API создание группы
|
||||
export async function createGroupApi(
|
||||
group: CreateGroupInput
|
||||
): Promise<CreateGroupOutput> {
|
||||
try {
|
||||
const response = await fetch('/api/groups/', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(group),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
const result: CreateGroupOutput = await response.json()
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error('Ошибка при создании группы:', error)
|
||||
throw new Error('Ошибка при создании группы на сервере')
|
||||
}
|
||||
}
|
||||
|
||||
// API обновление группы
|
||||
export async function patchGroupApi(
|
||||
groupId: string,
|
||||
group: PatchGroupInput
|
||||
): Promise<PatchGroupOutput> {
|
||||
try {
|
||||
const response = await fetch(`/api/groups/${groupId}`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(group),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
const result: PatchGroupOutput = await response.json()
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error('Ошибка при обновлении группы:', error)
|
||||
throw new Error('Ошибка при обновлении группы на сервере')
|
||||
}
|
||||
}
|
||||
|
||||
// API удаление группы (если потребуется)
|
||||
export async function deleteGroupApi(groupId: string): Promise<{success: boolean}> {
|
||||
try {
|
||||
const response = await fetch(`/api/groups/${groupId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
return { success: true }
|
||||
} catch (error) {
|
||||
console.error('Ошибка при удалении группы:', error)
|
||||
throw new Error('Ошибка при удалении группы на сервере')
|
||||
}
|
||||
}
|
||||
137
src/entity/group/model/GroupContext.tsx
Normal file
137
src/entity/group/model/GroupContext.tsx
Normal file
@@ -0,0 +1,137 @@
|
||||
import {
|
||||
createGroupApi,
|
||||
CreateGroupInput,
|
||||
deleteGroupApi,
|
||||
getGroupsApi,
|
||||
patchGroupApi,
|
||||
PatchGroupInput
|
||||
} from '@/entity/group/api/groupApiService'
|
||||
import { Group } from '@/type/template'
|
||||
import {
|
||||
QueryClient,
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
} from '@tanstack/react-query'
|
||||
import { createContext, ReactNode, useContext, useMemo } from 'react'
|
||||
|
||||
export const queryClient = new QueryClient()
|
||||
|
||||
interface GroupContextType {
|
||||
groups: Group[]
|
||||
isLoading: boolean
|
||||
error: Error | null
|
||||
refetchGroups: () => void
|
||||
addGroup: (data: CreateGroupInput) => Promise<Group>
|
||||
updateGroup: (
|
||||
groupId: string,
|
||||
data: PatchGroupInput
|
||||
) => Promise<Group>
|
||||
deleteGroup: (groupId: string) => Promise<string>
|
||||
getGroupById: (groupId: string) => Group | undefined
|
||||
}
|
||||
|
||||
const GroupContext = createContext<GroupContextType | undefined>(undefined)
|
||||
|
||||
export const GroupProvider: React.FC<{ children: ReactNode }> = ({
|
||||
children,
|
||||
}) => {
|
||||
const client = useQueryClient()
|
||||
|
||||
const {
|
||||
data: groups = [],
|
||||
status: listStatus,
|
||||
error: errorList,
|
||||
refetch,
|
||||
} = useQuery<Group[], Error>({
|
||||
queryKey: ['groups'],
|
||||
queryFn: async () => {
|
||||
const { groups: apiList } = await getGroupsApi()
|
||||
return apiList.sort((a, b) => a.order - b.order)
|
||||
},
|
||||
})
|
||||
|
||||
const createMutation = useMutation({
|
||||
mutationFn: async (group: CreateGroupInput) => {
|
||||
const { id } = await createGroupApi(group)
|
||||
// Возвращаем созданную группу, получив её с сервера
|
||||
const { groups: updatedGroups } = await getGroupsApi()
|
||||
const newGroup = updatedGroups.find(g => g.id === id)
|
||||
if (!newGroup) throw new Error('Группа не найдена после создания')
|
||||
return newGroup
|
||||
},
|
||||
onSuccess: () => {
|
||||
client.invalidateQueries({ queryKey: ['groups'] })
|
||||
},
|
||||
})
|
||||
|
||||
const updateMutation = useMutation({
|
||||
mutationFn: async ({
|
||||
groupId,
|
||||
data,
|
||||
}: {
|
||||
groupId: string
|
||||
data: PatchGroupInput
|
||||
}) => {
|
||||
return await patchGroupApi(groupId, data)
|
||||
},
|
||||
onSuccess: () => {
|
||||
client.invalidateQueries({ queryKey: ['groups'] })
|
||||
},
|
||||
})
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
mutationFn: async (groupId: string) => {
|
||||
await deleteGroupApi(groupId)
|
||||
return groupId
|
||||
},
|
||||
onSuccess: () => {
|
||||
client.invalidateQueries({ queryKey: ['groups'] })
|
||||
},
|
||||
})
|
||||
|
||||
const getGroupById = (groupId: string) =>
|
||||
groups.find(group => group.id === groupId)
|
||||
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
groups,
|
||||
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,
|
||||
refetchGroups: refetch,
|
||||
addGroup: createMutation.mutateAsync,
|
||||
updateGroup: async (groupId: string, data: PatchGroupInput) =>
|
||||
updateMutation.mutateAsync({ groupId, data }),
|
||||
deleteGroup: deleteMutation.mutateAsync,
|
||||
getGroupById,
|
||||
}),
|
||||
[
|
||||
groups,
|
||||
listStatus,
|
||||
errorList,
|
||||
createMutation,
|
||||
updateMutation,
|
||||
deleteMutation,
|
||||
refetch,
|
||||
]
|
||||
)
|
||||
|
||||
return <GroupContext.Provider value={value}>{children}</GroupContext.Provider>
|
||||
}
|
||||
|
||||
export const useGroupContext = (): GroupContextType => {
|
||||
const context = useContext(GroupContext)
|
||||
if (!context) {
|
||||
throw new Error('useGroupContext must be used within a GroupProvider')
|
||||
}
|
||||
return context
|
||||
}
|
||||
Reference in New Issue
Block a user