Files
team-planner/frontend/src/hooks/useIdeas.ts
2026-01-14 01:10:01 +03:00

126 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { ideasApi, type QueryIdeasParams } from '../services/ideas';
import type { CreateIdeaDto, UpdateIdeaDto } from '../types/idea';
import { useIdeasStore } from '../store/ideas';
const QUERY_KEY = 'ideas';
export function useIdeasQuery() {
const { filters, sorting, pagination } = useIdeasStore();
const params: QueryIdeasParams = {
...filters,
...sorting,
...pagination,
};
return useQuery({
queryKey: [QUERY_KEY, params],
queryFn: () => ideasApi.getAll(params),
});
}
export function useIdeaQuery(id: string) {
return useQuery({
queryKey: [QUERY_KEY, id],
queryFn: () => ideasApi.getOne(id),
enabled: !!id,
});
}
export function useModulesQuery() {
return useQuery({
queryKey: [QUERY_KEY, 'modules'],
queryFn: () => ideasApi.getModules(),
staleTime: 60000, // Cache for 1 minute
});
}
export function useCreateIdea() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (dto: CreateIdeaDto) => ideasApi.create(dto),
onSuccess: () => {
void queryClient.invalidateQueries({ queryKey: [QUERY_KEY] });
},
});
}
export function useUpdateIdea() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, dto }: { id: string; dto: UpdateIdeaDto }) =>
ideasApi.update(id, dto),
onSuccess: () => {
void queryClient.invalidateQueries({ queryKey: [QUERY_KEY] });
},
});
}
export function useDeleteIdea() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => ideasApi.delete(id),
onSuccess: () => {
void queryClient.invalidateQueries({ queryKey: [QUERY_KEY] });
},
});
}
export function useReorderIdeas() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (items: { id: string; order: number }[]) =>
ideasApi.reorder(items),
onMutate: async (items) => {
// Получаем актуальное состояние store
const { filters, sorting, pagination } = useIdeasStore.getState();
// Отменяем исходящие запросы чтобы не перезаписать оптимистичное обновление
await queryClient.cancelQueries({ queryKey: [QUERY_KEY] });
// Сохраняем предыдущее состояние для отката
const queryKey = [QUERY_KEY, { ...filters, ...sorting, ...pagination }];
const previousData = queryClient.getQueryData(queryKey);
// Оптимистично обновляем кэш
queryClient.setQueryData(
queryKey,
(
old:
| { data: { id: string; order: number }[]; meta: unknown }
| undefined,
) => {
if (!old) return old;
// Создаём новый порядок на основе items
const orderMap = new Map(items.map((item) => [item.id, item.order]));
const newData = [...old.data].sort((a, b) => {
const orderA = orderMap.get(a.id) ?? a.order;
const orderB = orderMap.get(b.id) ?? b.order;
return orderA - orderB;
});
return { ...old, data: newData };
},
);
return { previousData, queryKey };
},
onError: (_err, _items, context) => {
// Откатываем к предыдущему состоянию при ошибке
if (context?.previousData) {
queryClient.setQueryData(context.queryKey, context.previousData);
}
},
onSettled: () => {
// Инвалидируем для синхронизации с сервером
void queryClient.invalidateQueries({ queryKey: [QUERY_KEY] });
},
});
}