feat: yard scoping to position

This commit is contained in:
Nathnael
2026-08-18 12:55:11 +00:00
parent 983cc02e50
commit 6823a32fee
27 changed files with 2657 additions and 257 deletions

View File

@@ -0,0 +1,93 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
import type {
ListQuery,
ListResponse,
LocationType,
LocationTypePayload,
} from "@/user-management/dto/locations/location.type";
import { locationTypeService } from "../services/api/locationService";
export const useLocationTypes = (params: ListQuery = {}) => {
const { t } = useTranslation();
const { handleError } = useErrorHandler(t);
const queryClient = useQueryClient();
const invalidate = () =>
queryClient.invalidateQueries({ queryKey: ["location-types"] });
const {
data: locationTypes,
isLoading: isLoadingLocationTypes,
isError: isErrorLocationTypes,
refetch: refetchLocationTypes,
} = useQuery<ListResponse<LocationType>>({
queryKey: ["location-types", params],
queryFn: async () => {
const { data } = await locationTypeService.list(params);
return { count: data?.count ?? 0, items: data?.items ?? [] };
},
staleTime: 5 * 60 * 1000,
});
const { mutate: createLocationType, isPending: isCreatingLocationType } =
useMutation({
mutationFn: async (payload: LocationTypePayload) => {
const { data } = await locationTypeService.create(payload);
return data;
},
onSuccess: () => {
toast.success(t("locationType.created", "Location type created"));
invalidate();
},
onError: handleError,
});
const { mutate: updateLocationType, isPending: isUpdatingLocationType } =
useMutation({
mutationFn: async ({
id,
payload,
}: {
id: string;
payload: LocationTypePayload;
}) => {
const { data } = await locationTypeService.update(id, payload);
return data;
},
onSuccess: () => {
toast.success(t("locationType.updated", "Location type updated"));
invalidate();
},
onError: handleError,
});
const { mutate: deleteLocationType, isPending: isDeletingLocationType } =
useMutation({
mutationFn: async (id: string) => {
const { data } = await locationTypeService.remove(id);
return data;
},
onSuccess: () => {
toast.success(t("locationType.deleted", "Location type deleted"));
invalidate();
},
onError: handleError,
});
return {
locationTypes,
isLoadingLocationTypes,
isErrorLocationTypes,
refetchLocationTypes,
createLocationType,
isCreatingLocationType,
updateLocationType,
isUpdatingLocationType,
deleteLocationType,
isDeletingLocationType,
};
};

View File

@@ -0,0 +1,95 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
import type {
ListQuery,
ListResponse,
Location,
LocationPayload,
} from "@/user-management/dto/locations/location.type";
import { locationService } from "../services/api/locationService";
/**
* `params` is the whole server-side query surface: skip/take/orderBy. There is
* no search or filter endpoint, so a caller that needs every location (parent
* picker, name lookups) asks for a large `take`.
*/
export const useLocations = (params: ListQuery = {}) => {
const { t } = useTranslation();
const { handleError } = useErrorHandler(t);
const queryClient = useQueryClient();
const invalidate = () =>
queryClient.invalidateQueries({ queryKey: ["locations"] });
const {
data: locations,
isLoading: isLoadingLocations,
isError: isErrorLocations,
refetch: refetchLocations,
} = useQuery<ListResponse<Location>>({
queryKey: ["locations", params],
queryFn: async () => {
const { data } = await locationService.list(params);
return { count: data?.count ?? 0, items: data?.items ?? [] };
},
staleTime: 5 * 60 * 1000,
});
const { mutate: createLocation, isPending: isCreatingLocation } = useMutation({
mutationFn: async (payload: LocationPayload) => {
const { data } = await locationService.create(payload);
return data;
},
onSuccess: () => {
toast.success(t("location.created", "Location created"));
invalidate();
},
onError: handleError,
});
const { mutate: updateLocation, isPending: isUpdatingLocation } = useMutation({
mutationFn: async ({
id,
payload,
}: {
id: string;
payload: LocationPayload;
}) => {
const { data } = await locationService.update(id, payload);
return data;
},
onSuccess: () => {
toast.success(t("location.updated", "Location updated"));
invalidate();
},
onError: handleError,
});
const { mutate: deleteLocation, isPending: isDeletingLocation } = useMutation({
mutationFn: async (id: string) => {
const { data } = await locationService.remove(id);
return data;
},
onSuccess: () => {
toast.success(t("location.deleted", "Location deleted"));
invalidate();
},
onError: handleError,
});
return {
locations,
isLoadingLocations,
isErrorLocations,
refetchLocations,
createLocation,
isCreatingLocation,
updateLocation,
isUpdatingLocation,
deleteLocation,
isDeletingLocation,
};
};