Files
family_wishlist/apps/frontend/src/features/wishes/wishes.hooks.ts

146 lines
3.9 KiB
TypeScript

import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import type { CreateWishInput, UpdateWishInput } from '@family-wishlist/shared';
import { toast } from 'sonner';
import { wishesApi, type OwnerStatus } from './wishes.api';
import { ApiError } from '@/lib/api';
const LIST_KEY = (status: OwnerStatus) => ['wishes', status] as const;
function invalidateAll(client: ReturnType<typeof useQueryClient>): void {
void client.invalidateQueries({ queryKey: ['wishes'] });
}
function toastError(err: unknown, fallback = 'Something went wrong'): void {
if (err instanceof ApiError) toast.error(err.message);
else toast.error(fallback);
}
export function useWishes(status: OwnerStatus) {
return useQuery({
queryKey: LIST_KEY(status),
queryFn: () => wishesApi.list(status),
staleTime: 10_000,
});
}
export function useCreateWish() {
const client = useQueryClient();
return useMutation({
mutationFn: (input: CreateWishInput) => wishesApi.create(input),
onSuccess: () => {
invalidateAll(client);
toast.success('Wish added');
},
onError: (err) => toastError(err),
});
}
export function useUpdateWish() {
const client = useQueryClient();
return useMutation({
mutationFn: (vars: { id: string; input: UpdateWishInput }) =>
wishesApi.update(vars.id, vars.input),
onSuccess: () => {
invalidateAll(client);
toast.success('Saved');
},
onError: (err) => toastError(err),
});
}
export function useArchiveWish() {
const client = useQueryClient();
return useMutation({
mutationFn: (id: string) => wishesApi.archive(id),
onSuccess: () => {
invalidateAll(client);
toast.success('Moved to archive');
},
onError: (err) => toastError(err),
});
}
export function useCompleteWish() {
const client = useQueryClient();
return useMutation({
mutationFn: (id: string) => wishesApi.complete(id),
onSuccess: () => {
invalidateAll(client);
toast.success('Marked as fulfilled');
},
onError: (err) => toastError(err),
});
}
export function useDeleteWish() {
const client = useQueryClient();
return useMutation({
mutationFn: (id: string) => wishesApi.remove(id),
onSuccess: () => {
invalidateAll(client);
toast.success('Moved to trash (30 days to restore)');
},
onError: (err) => toastError(err),
});
}
export function useRestoreWish() {
const client = useQueryClient();
return useMutation({
mutationFn: (id: string) => wishesApi.restore(id),
onSuccess: () => {
invalidateAll(client);
toast.success('Restored');
},
onError: (err) => toastError(err),
});
}
export function useDuplicateWish() {
const client = useQueryClient();
return useMutation({
mutationFn: (id: string) => wishesApi.duplicate(id),
onSuccess: () => {
invalidateAll(client);
toast.success('New wish created from the fulfilled one');
},
onError: (err) => toastError(err),
});
}
export function useUploadWishImage() {
const client = useQueryClient();
return useMutation({
mutationFn: (vars: { id: string; file: File }) => wishesApi.uploadImage(vars.id, vars.file),
onSuccess: () => {
invalidateAll(client);
toast.success('Image updated');
},
onError: (err) => toastError(err),
});
}
export function useRefreshOg() {
const client = useQueryClient();
return useMutation({
mutationFn: (id: string) => wishesApi.refreshOg(id),
onSuccess: () => {
invalidateAll(client);
toast.success('Image refreshed from link');
},
onError: (err) => toastError(err, 'Could not fetch image from link'),
});
}
export function useResetWishImage() {
const client = useQueryClient();
return useMutation({
mutationFn: (id: string) => wishesApi.deleteImage(id),
onSuccess: () => {
invalidateAll(client);
toast.success('Reset to default image');
},
onError: (err) => toastError(err),
});
}