Files
edr-platform/apps/edr-freight-web/backoffice/src/super-admin/hooks/useSites.ts
2026-07-10 10:41:48 +03:00

186 lines
4.9 KiB
TypeScript

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
getSites,
getSiteById,
createSite,
updateSite,
softDeleteSite,
deleteSite,
restoreSite,
} from "@/super-admin/services/api/sitesService";
import { SiteDto, SitePayloadDto, SiteQueryParams } from "@/super-admin/dto/SitesDto";
import { toast } from "sonner";
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
import { useTranslation } from "react-i18next";
// Helper function to transform English name into snake_case format
export function toSnakeCase(str: string): string {
if (!str) return "";
return str
.toLowerCase()
.trim()
.replace(/[^a-z0-9\s-_]/g, "") // remove special characters
.replace(/[\s-]+/g, "_"); // replace spaces or hyphens with underscores
}
export const useSites = (params?: SiteQueryParams) => {
const queryClient = useQueryClient();
const { t } = useTranslation();
const { handleError } = useErrorHandler(t);
// 🔵 Query: Fetch sites list
const {
data: sitesResponse,
isLoading,
isError,
refetch,
} = useQuery({
queryKey: ["sites", params],
queryFn: async () => {
const { data } = await getSites(params);
// Defensively support both [{...}] and { items: [...], count: X } formats
const items = Array.isArray(data) ? data : (data?.items || []);
const count = Array.isArray(data) ? data.length : (data?.count || items.length || 0);
return {
items: items as SiteDto[],
count: count as number,
};
},
staleTime: 5 * 60 * 1000,
retry: false,
});
// 🟢 Mutation: Create Site
const { mutate: createMutation, isPending: isCreating } = useMutation({
mutationFn: async (payload: SitePayloadDto) => {
const transformedPayload: SitePayloadDto = {
...payload,
name: {
...payload.name,
en: toSnakeCase(payload.name.en),
},
};
const { data } = await createSite(transformedPayload);
return data;
},
onSuccess: () => {
toast.success("Site created successfully!");
queryClient.invalidateQueries({ queryKey: ["sites"] });
},
onError: (error) => {
handleError(error);
},
});
// 🟠 Mutation: Update Site
const { mutate: updateMutation, isPending: isUpdating } = useMutation({
mutationFn: async ({ id, payload }: { id: string; payload: SitePayloadDto }) => {
const transformedPayload: SitePayloadDto = {
...payload,
name: {
...payload.name,
en: toSnakeCase(payload.name.en),
},
};
const { data } = await updateSite(id, transformedPayload);
return data;
},
onSuccess: () => {
toast.success("Site updated successfully!");
queryClient.invalidateQueries({ queryKey: ["sites"] });
},
onError: (error) => {
handleError(error);
},
});
// 🟡 Mutation: Archive Site (Soft Delete)
const { mutate: archiveMutation, isPending: isArchiving } = useMutation({
mutationFn: async ({ id }: { id: string }) => {
const { data } = await softDeleteSite(id);
return data;
},
onSuccess: () => {
toast.success("Site archived successfully!");
queryClient.invalidateQueries({ queryKey: ["sites"] });
},
onError: (error) => {
handleError(error);
},
});
// 🔴 Mutation: Permanent Delete Site
const { mutate: deleteMutation, isPending: isDeleting } = useMutation({
mutationFn: async ({ id }: { id: string }) => {
const { data } = await deleteSite(id);
return data;
},
onSuccess: () => {
toast.success("Site permanently deleted!");
queryClient.invalidateQueries({ queryKey: ["sites"] });
},
onError: (error) => {
handleError(error);
},
});
// 🟣 Mutation: Restore Archived Site
const { mutate: restoreMutation, isPending: isRestoring } = useMutation({
mutationFn: async ({ id }: { id: string }) => {
const { data } = await restoreSite(id);
return data;
},
onSuccess: () => {
toast.success("Site restored successfully!");
queryClient.invalidateQueries({ queryKey: ["sites"] });
},
onError: (error) => {
handleError(error);
},
});
return {
sitesResponse,
isLoading,
isError,
refetch,
createSite: createMutation,
isCreating,
updateSite: updateMutation,
isUpdating,
archiveSite: archiveMutation,
isArchiving,
deleteSite: deleteMutation,
isDeleting,
restoreSite: restoreMutation,
isRestoring,
};
};
export const useSiteDetail = (id: string, enabled: boolean = true) => {
const {
data: site,
isLoading,
isError,
refetch,
} = useQuery({
queryKey: ["site", id],
queryFn: async () => {
const { data } = await getSiteById(id);
return data;
},
enabled: enabled && !!id,
staleTime: 5 * 60 * 1000,
retry: false,
});
return {
site,
isLoading,
isError,
refetch,
};
};