mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 03:05:42 +00:00
fix ui
This commit is contained in:
@@ -1,72 +1,72 @@
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
applicationService,
|
||||
CreateApplicationDto,
|
||||
UpdateApplicationDto,
|
||||
} from "@/user-management/services/api/applicationService";
|
||||
import {
|
||||
ApplicationDto,
|
||||
ApplicationListResponse,
|
||||
} from "@/user-management/dto/applications/applicationDto";
|
||||
|
||||
export const useApplications = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
const { data, isLoading, isError, refetch } =
|
||||
useQuery<ApplicationListResponse>({
|
||||
queryKey: ["applications"],
|
||||
queryFn: () => applicationService.getAll().then((res) => res.data),
|
||||
staleTime: 1000 * 60 * 5,
|
||||
});
|
||||
|
||||
const createApplication = useMutation({
|
||||
mutationFn: (payload: CreateApplicationDto) =>
|
||||
applicationService.create(payload),
|
||||
onSuccess: () => {
|
||||
toast.success("Application created");
|
||||
queryClient.invalidateQueries({ queryKey: ["applications"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const updateApplication = useMutation({
|
||||
mutationFn: ({ id, data }: { id: string; data: UpdateApplicationDto }) =>
|
||||
applicationService.update(id, data),
|
||||
onSuccess: () => {
|
||||
toast.success("Application updated");
|
||||
queryClient.invalidateQueries({ queryKey: ["applications"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const deleteApplication = useMutation({
|
||||
mutationFn: (id: string) => applicationService.delete(id),
|
||||
onSuccess: () => {
|
||||
toast.success("Application deleted");
|
||||
queryClient.invalidateQueries({ queryKey: ["applications"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
applications: data?.items ?? [],
|
||||
applicationsResponse: data,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
createApplication,
|
||||
updateApplication,
|
||||
deleteApplication,
|
||||
};
|
||||
};
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
applicationService,
|
||||
CreateApplicationDto,
|
||||
UpdateApplicationDto,
|
||||
} from "@/user-management/services/api/applicationService";
|
||||
import {
|
||||
ApplicationDto,
|
||||
ApplicationListResponse,
|
||||
} from "@/user-management/dto/applications/applicationDto";
|
||||
|
||||
export const useApplications = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
const { data, isLoading, isError, refetch } =
|
||||
useQuery<ApplicationListResponse>({
|
||||
queryKey: ["applications"],
|
||||
queryFn: () => applicationService.getAll().then((res) => res.data),
|
||||
staleTime: 1000 * 60 * 5,
|
||||
});
|
||||
|
||||
const createApplication = useMutation({
|
||||
mutationFn: (payload: CreateApplicationDto) =>
|
||||
applicationService.create(payload),
|
||||
onSuccess: () => {
|
||||
toast.success("Application created");
|
||||
queryClient.invalidateQueries({ queryKey: ["applications"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const updateApplication = useMutation({
|
||||
mutationFn: ({ id, data }: { id: string; data: UpdateApplicationDto }) =>
|
||||
applicationService.update(id, data),
|
||||
onSuccess: () => {
|
||||
toast.success("Application updated");
|
||||
queryClient.invalidateQueries({ queryKey: ["applications"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const deleteApplication = useMutation({
|
||||
mutationFn: (id: string) => applicationService.delete(id),
|
||||
onSuccess: () => {
|
||||
toast.success("Application deleted");
|
||||
queryClient.invalidateQueries({ queryKey: ["applications"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
applications: data?.items ?? [],
|
||||
applicationsResponse: data,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
createApplication,
|
||||
updateApplication,
|
||||
deleteApplication,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,155 +1,155 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
getArchivedUnits,
|
||||
restoreUnit,
|
||||
softDeleteUnit,
|
||||
} from "@/user-management/services/api/unitService";
|
||||
import {
|
||||
getArchivedPositions,
|
||||
restorePosition,
|
||||
softDeletePosition,
|
||||
} from "@/user-management/services/api/positionService";
|
||||
import {
|
||||
getArchivedOrganizations,
|
||||
restoreOrganization,
|
||||
softDeleteOrganization,
|
||||
} from "@/shared/services/organizationsService";
|
||||
|
||||
export const useArchivedUnits = (parentId: string | undefined) => {
|
||||
return useQuery({
|
||||
queryKey: ["archived-units", parentId],
|
||||
queryFn: async () => {
|
||||
if (!parentId) return null;
|
||||
const { data } = await getArchivedUnits(parentId);
|
||||
return data;
|
||||
},
|
||||
staleTime: 0,
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const useArchivedOrganizations = () => {
|
||||
return useQuery({
|
||||
queryKey: ["archived-organizations"],
|
||||
queryFn: async () => {
|
||||
const { data } = await getArchivedOrganizations();
|
||||
return data;
|
||||
},
|
||||
staleTime: 0,
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const useArchivedPositions = (parentId: string | undefined) => {
|
||||
return useQuery({
|
||||
queryKey: ["archived-positions", parentId],
|
||||
queryFn: async () => {
|
||||
if (!parentId) return null;
|
||||
const { data } = await getArchivedPositions(parentId);
|
||||
return data;
|
||||
},
|
||||
staleTime: 0,
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const useArchiveActions = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
const invalidateArchivedUnits = () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["archived-units"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["unitList"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["unitChildren"] });
|
||||
};
|
||||
|
||||
const invalidateArchivedPositions = () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["archived-positions"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["positions"] });
|
||||
};
|
||||
|
||||
const invalidateArchivedOrganizations = () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["archived-organizations"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["organizations"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["organizationsResponse"] });
|
||||
};
|
||||
|
||||
const softDeleteUnitMutation = useMutation({
|
||||
mutationFn: (id: string) => softDeleteUnit(id),
|
||||
onSuccess: () => {
|
||||
toast.success(t("archive.unitArchived", "Unit archived"));
|
||||
invalidateArchivedUnits();
|
||||
},
|
||||
onError: handleError,
|
||||
});
|
||||
|
||||
const restoreUnitMutation = useMutation({
|
||||
mutationFn: (id: string) => restoreUnit(id),
|
||||
onSuccess: () => {
|
||||
toast.success(t("archive.unitRestored", "Unit restored"));
|
||||
invalidateArchivedUnits();
|
||||
},
|
||||
onError: handleError,
|
||||
});
|
||||
|
||||
const softDeletePositionMutation = useMutation({
|
||||
mutationFn: (id: string) => softDeletePosition(id),
|
||||
onSuccess: () => {
|
||||
toast.success(t("archive.positionArchived", "Position archived"));
|
||||
invalidateArchivedPositions();
|
||||
},
|
||||
onError: handleError,
|
||||
});
|
||||
|
||||
const restorePositionMutation = useMutation({
|
||||
mutationFn: (id: string) => restorePosition(id),
|
||||
onSuccess: () => {
|
||||
toast.success(t("archive.positionRestored", "Position restored"));
|
||||
invalidateArchivedPositions();
|
||||
},
|
||||
onError: handleError,
|
||||
});
|
||||
|
||||
const softDeleteOrganizationMutation = useMutation({
|
||||
mutationFn: (id: string) => softDeleteOrganization(id),
|
||||
onSuccess: () => {
|
||||
toast.success(t("archive.organizationArchived", "Organization archived"));
|
||||
invalidateArchivedOrganizations();
|
||||
},
|
||||
onError: handleError,
|
||||
});
|
||||
|
||||
const restoreOrganizationMutation = useMutation({
|
||||
mutationFn: (id: string) => restoreOrganization(id),
|
||||
onSuccess: () => {
|
||||
toast.success(
|
||||
t("archive.organizationRestored", "Organization restored"),
|
||||
);
|
||||
invalidateArchivedOrganizations();
|
||||
},
|
||||
onError: handleError,
|
||||
});
|
||||
|
||||
return {
|
||||
softDeleteUnit: softDeleteUnitMutation.mutate,
|
||||
isArchivingUnit: softDeleteUnitMutation.isPending,
|
||||
restoreUnit: restoreUnitMutation.mutate,
|
||||
isRestoringUnit: restoreUnitMutation.isPending,
|
||||
softDeletePosition: softDeletePositionMutation.mutate,
|
||||
isArchivingPosition: softDeletePositionMutation.isPending,
|
||||
restorePosition: restorePositionMutation.mutate,
|
||||
isRestoringPosition: restorePositionMutation.isPending,
|
||||
softDeleteOrganization: softDeleteOrganizationMutation.mutate,
|
||||
isArchivingOrganization: softDeleteOrganizationMutation.isPending,
|
||||
restoreOrganization: restoreOrganizationMutation.mutate,
|
||||
isRestoringOrganization: restoreOrganizationMutation.isPending,
|
||||
};
|
||||
};
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
getArchivedUnits,
|
||||
restoreUnit,
|
||||
softDeleteUnit,
|
||||
} from "@/user-management/services/api/unitService";
|
||||
import {
|
||||
getArchivedPositions,
|
||||
restorePosition,
|
||||
softDeletePosition,
|
||||
} from "@/user-management/services/api/positionService";
|
||||
import {
|
||||
getArchivedOrganizations,
|
||||
restoreOrganization,
|
||||
softDeleteOrganization,
|
||||
} from "@/shared/services/organizationsService";
|
||||
|
||||
export const useArchivedUnits = (parentId: string | undefined) => {
|
||||
return useQuery({
|
||||
queryKey: ["archived-units", parentId],
|
||||
queryFn: async () => {
|
||||
if (!parentId) return null;
|
||||
const { data } = await getArchivedUnits(parentId);
|
||||
return data;
|
||||
},
|
||||
staleTime: 0,
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const useArchivedOrganizations = () => {
|
||||
return useQuery({
|
||||
queryKey: ["archived-organizations"],
|
||||
queryFn: async () => {
|
||||
const { data } = await getArchivedOrganizations();
|
||||
return data;
|
||||
},
|
||||
staleTime: 0,
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const useArchivedPositions = (parentId: string | undefined) => {
|
||||
return useQuery({
|
||||
queryKey: ["archived-positions", parentId],
|
||||
queryFn: async () => {
|
||||
if (!parentId) return null;
|
||||
const { data } = await getArchivedPositions(parentId);
|
||||
return data;
|
||||
},
|
||||
staleTime: 0,
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const useArchiveActions = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
const invalidateArchivedUnits = () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["archived-units"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["unitList"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["unitChildren"] });
|
||||
};
|
||||
|
||||
const invalidateArchivedPositions = () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["archived-positions"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["positions"] });
|
||||
};
|
||||
|
||||
const invalidateArchivedOrganizations = () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["archived-organizations"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["organizations"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["organizationsResponse"] });
|
||||
};
|
||||
|
||||
const softDeleteUnitMutation = useMutation({
|
||||
mutationFn: (id: string) => softDeleteUnit(id),
|
||||
onSuccess: () => {
|
||||
toast.success(t("archive.unitArchived", "Unit archived"));
|
||||
invalidateArchivedUnits();
|
||||
},
|
||||
onError: handleError,
|
||||
});
|
||||
|
||||
const restoreUnitMutation = useMutation({
|
||||
mutationFn: (id: string) => restoreUnit(id),
|
||||
onSuccess: () => {
|
||||
toast.success(t("archive.unitRestored", "Unit restored"));
|
||||
invalidateArchivedUnits();
|
||||
},
|
||||
onError: handleError,
|
||||
});
|
||||
|
||||
const softDeletePositionMutation = useMutation({
|
||||
mutationFn: (id: string) => softDeletePosition(id),
|
||||
onSuccess: () => {
|
||||
toast.success(t("archive.positionArchived", "Position archived"));
|
||||
invalidateArchivedPositions();
|
||||
},
|
||||
onError: handleError,
|
||||
});
|
||||
|
||||
const restorePositionMutation = useMutation({
|
||||
mutationFn: (id: string) => restorePosition(id),
|
||||
onSuccess: () => {
|
||||
toast.success(t("archive.positionRestored", "Position restored"));
|
||||
invalidateArchivedPositions();
|
||||
},
|
||||
onError: handleError,
|
||||
});
|
||||
|
||||
const softDeleteOrganizationMutation = useMutation({
|
||||
mutationFn: (id: string) => softDeleteOrganization(id),
|
||||
onSuccess: () => {
|
||||
toast.success(t("archive.organizationArchived", "Organization archived"));
|
||||
invalidateArchivedOrganizations();
|
||||
},
|
||||
onError: handleError,
|
||||
});
|
||||
|
||||
const restoreOrganizationMutation = useMutation({
|
||||
mutationFn: (id: string) => restoreOrganization(id),
|
||||
onSuccess: () => {
|
||||
toast.success(
|
||||
t("archive.organizationRestored", "Organization restored"),
|
||||
);
|
||||
invalidateArchivedOrganizations();
|
||||
},
|
||||
onError: handleError,
|
||||
});
|
||||
|
||||
return {
|
||||
softDeleteUnit: softDeleteUnitMutation.mutate,
|
||||
isArchivingUnit: softDeleteUnitMutation.isPending,
|
||||
restoreUnit: restoreUnitMutation.mutate,
|
||||
isRestoringUnit: restoreUnitMutation.isPending,
|
||||
softDeletePosition: softDeletePositionMutation.mutate,
|
||||
isArchivingPosition: softDeletePositionMutation.isPending,
|
||||
restorePosition: restorePositionMutation.mutate,
|
||||
isRestoringPosition: restorePositionMutation.isPending,
|
||||
softDeleteOrganization: softDeleteOrganizationMutation.mutate,
|
||||
isArchivingOrganization: softDeleteOrganizationMutation.isPending,
|
||||
restoreOrganization: restoreOrganizationMutation.mutate,
|
||||
isRestoringOrganization: restoreOrganizationMutation.isPending,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,103 +1,103 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
employeePositionChangeRequestService,
|
||||
type BulkApproveEmployeePositionChangePayload,
|
||||
type EmployeePositionChangeDecisionPayload,
|
||||
type EmployeePositionChangeRequestParams,
|
||||
type TransferEmployeePositionPayload,
|
||||
} from "@/user-management/services/api/employeePositionChangeRequestService";
|
||||
|
||||
export const EMPLOYEE_POSITION_CHANGE_REQUESTS_QUERY_KEY =
|
||||
"employee-position-change-requests";
|
||||
|
||||
interface DecisionVariables extends EmployeePositionChangeDecisionPayload {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export const useEmployeePositionChangeRequests = (
|
||||
params: EmployeePositionChangeRequestParams = {},
|
||||
) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
const requestsQuery = useQuery({
|
||||
queryKey: [EMPLOYEE_POSITION_CHANGE_REQUESTS_QUERY_KEY, params],
|
||||
queryFn: () => employeePositionChangeRequestService.list(params),
|
||||
});
|
||||
|
||||
const getRequestByIdQuery = (id?: string | null) =>
|
||||
useQuery({
|
||||
queryKey: [EMPLOYEE_POSITION_CHANGE_REQUESTS_QUERY_KEY, id],
|
||||
queryFn: () => employeePositionChangeRequestService.getById(id!),
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
const invalidateRequests = () =>
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [EMPLOYEE_POSITION_CHANGE_REQUESTS_QUERY_KEY],
|
||||
});
|
||||
|
||||
const transferMutation = useMutation({
|
||||
mutationFn: (payload: TransferEmployeePositionPayload) =>
|
||||
employeePositionChangeRequestService.transfer(payload),
|
||||
onSuccess: () => {
|
||||
invalidateRequests();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const bulkApproveMutation = useMutation({
|
||||
mutationFn: (payload: BulkApproveEmployeePositionChangePayload) =>
|
||||
employeePositionChangeRequestService.bulkApprove(payload),
|
||||
onSuccess: () => {
|
||||
toast.success("Employee position change requests approved successfully");
|
||||
invalidateRequests();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const approveMutation = useMutation({
|
||||
mutationFn: ({ id, comment }: DecisionVariables) =>
|
||||
employeePositionChangeRequestService.approve(id, { comment }),
|
||||
onSuccess: () => {
|
||||
toast.success("Employee position change request approved successfully");
|
||||
invalidateRequests();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const rejectMutation = useMutation({
|
||||
mutationFn: ({ id, comment }: DecisionVariables) =>
|
||||
employeePositionChangeRequestService.reject(id, { comment }),
|
||||
onSuccess: () => {
|
||||
toast.success("Employee position change request rejected successfully");
|
||||
invalidateRequests();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
requestsQuery,
|
||||
getRequestByIdQuery,
|
||||
transfer: transferMutation.mutateAsync,
|
||||
isTransferring: transferMutation.isPending,
|
||||
bulkApprove: bulkApproveMutation.mutateAsync,
|
||||
isBulkApproving: bulkApproveMutation.isPending,
|
||||
approve: approveMutation.mutateAsync,
|
||||
isApproving: approveMutation.isPending,
|
||||
reject: rejectMutation.mutateAsync,
|
||||
isRejecting: rejectMutation.isPending,
|
||||
};
|
||||
};
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
employeePositionChangeRequestService,
|
||||
type BulkApproveEmployeePositionChangePayload,
|
||||
type EmployeePositionChangeDecisionPayload,
|
||||
type EmployeePositionChangeRequestParams,
|
||||
type TransferEmployeePositionPayload,
|
||||
} from "@/user-management/services/api/employeePositionChangeRequestService";
|
||||
|
||||
export const EMPLOYEE_POSITION_CHANGE_REQUESTS_QUERY_KEY =
|
||||
"employee-position-change-requests";
|
||||
|
||||
interface DecisionVariables extends EmployeePositionChangeDecisionPayload {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export const useEmployeePositionChangeRequests = (
|
||||
params: EmployeePositionChangeRequestParams = {},
|
||||
) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
const requestsQuery = useQuery({
|
||||
queryKey: [EMPLOYEE_POSITION_CHANGE_REQUESTS_QUERY_KEY, params],
|
||||
queryFn: () => employeePositionChangeRequestService.list(params),
|
||||
});
|
||||
|
||||
const getRequestByIdQuery = (id?: string | null) =>
|
||||
useQuery({
|
||||
queryKey: [EMPLOYEE_POSITION_CHANGE_REQUESTS_QUERY_KEY, id],
|
||||
queryFn: () => employeePositionChangeRequestService.getById(id!),
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
const invalidateRequests = () =>
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [EMPLOYEE_POSITION_CHANGE_REQUESTS_QUERY_KEY],
|
||||
});
|
||||
|
||||
const transferMutation = useMutation({
|
||||
mutationFn: (payload: TransferEmployeePositionPayload) =>
|
||||
employeePositionChangeRequestService.transfer(payload),
|
||||
onSuccess: () => {
|
||||
invalidateRequests();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const bulkApproveMutation = useMutation({
|
||||
mutationFn: (payload: BulkApproveEmployeePositionChangePayload) =>
|
||||
employeePositionChangeRequestService.bulkApprove(payload),
|
||||
onSuccess: () => {
|
||||
toast.success("Employee position change requests approved successfully");
|
||||
invalidateRequests();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const approveMutation = useMutation({
|
||||
mutationFn: ({ id, comment }: DecisionVariables) =>
|
||||
employeePositionChangeRequestService.approve(id, { comment }),
|
||||
onSuccess: () => {
|
||||
toast.success("Employee position change request approved successfully");
|
||||
invalidateRequests();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const rejectMutation = useMutation({
|
||||
mutationFn: ({ id, comment }: DecisionVariables) =>
|
||||
employeePositionChangeRequestService.reject(id, { comment }),
|
||||
onSuccess: () => {
|
||||
toast.success("Employee position change request rejected successfully");
|
||||
invalidateRequests();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
requestsQuery,
|
||||
getRequestByIdQuery,
|
||||
transfer: transferMutation.mutateAsync,
|
||||
isTransferring: transferMutation.isPending,
|
||||
bulkApprove: bulkApproveMutation.mutateAsync,
|
||||
isBulkApproving: bulkApproveMutation.isPending,
|
||||
approve: approveMutation.mutateAsync,
|
||||
isApproving: approveMutation.isPending,
|
||||
reject: rejectMutation.mutateAsync,
|
||||
isRejecting: rejectMutation.isPending,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,185 +1,185 @@
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
activateUser,
|
||||
AssignEmployeePayload,
|
||||
assignEmployees,
|
||||
assignFirstsForSecond,
|
||||
assignSecondsForFirst,
|
||||
deactivateUser,
|
||||
deleteEmployeePosition,
|
||||
EmployeePositionQueryParams,
|
||||
getGivenFirst,
|
||||
getGivenSecond,
|
||||
InactiveEPPayload,
|
||||
inviteEmployeePosition,
|
||||
removeFirstsForSecond,
|
||||
removeSecondsForFirst,
|
||||
setInactive,
|
||||
} from "../services/api/employeePositionsService";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
|
||||
export const useEmployeePositions = (params?: EmployeePositionQueryParams) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
// --- Queries ---
|
||||
const getGivenFirstQuery = (id: string) =>
|
||||
useQuery({
|
||||
queryKey: ["positionEmployees", "given-first", id],
|
||||
queryFn: () => getGivenFirst(id, params).then((res) => res.data),
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
const getGivenSecondQuery = (id: string) =>
|
||||
useQuery({
|
||||
queryKey: ["positionEmployees", "given-second", id],
|
||||
queryFn: () => getGivenSecond(id, params).then((res: any) => res.data),
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
// --- Mutations ---
|
||||
const invite = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
payload: any;
|
||||
successCallback: () => void;
|
||||
}) => inviteEmployeePosition(payload),
|
||||
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] });
|
||||
variables.successCallback();
|
||||
},
|
||||
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const deactivate = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
payload: string;
|
||||
successCallback: () => void;
|
||||
}) => deactivateUser(payload),
|
||||
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["deleteEmployees"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["employees"] });
|
||||
|
||||
|
||||
variables.successCallback();
|
||||
},
|
||||
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
const activate = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
payload: string;
|
||||
successCallback: () => void;
|
||||
}) => activateUser(payload),
|
||||
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["archived-users"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["employees"] });
|
||||
|
||||
variables.successCallback();
|
||||
},
|
||||
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const setInactiveMutation = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
payload: InactiveEPPayload;
|
||||
successCallback: () => void;
|
||||
}) => setInactive(payload),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] });
|
||||
toast.success("Team member removed successfully.");
|
||||
variables.successCallback();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const assignFirstsForSecondMutation = useMutation({
|
||||
mutationFn: (payload: any) => assignFirstsForSecond(payload),
|
||||
onSuccess: () =>
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] }),
|
||||
});
|
||||
|
||||
const assignSecondsForFirstMutation = useMutation({
|
||||
mutationFn: (payload: any) => assignSecondsForFirst(payload),
|
||||
onSuccess: () =>
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] }),
|
||||
});
|
||||
|
||||
const assignEmployeeForPosition = useMutation({
|
||||
mutationFn: (payload: AssignEmployeePayload) => assignEmployees(payload),
|
||||
onSuccess: () =>{
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["employees"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const removeFirstsForSecondMutation = useMutation({
|
||||
mutationFn: (payload: any) => removeFirstsForSecond(payload),
|
||||
onSuccess: () =>
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] }),
|
||||
});
|
||||
|
||||
const removeSecondsForFirstMutation = useMutation({
|
||||
mutationFn: (payload: any) => removeSecondsForFirst(payload),
|
||||
onSuccess: () =>
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] }),
|
||||
});
|
||||
|
||||
const remove = useMutation({
|
||||
mutationFn: (id: string) => deleteEmployeePosition(id),
|
||||
onSuccess: () =>
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] }),
|
||||
});
|
||||
|
||||
// --- Return exposed mutateAsync and query helpers ---
|
||||
return {
|
||||
getGivenFirstQuery,
|
||||
getGivenSecondQuery,
|
||||
invite: invite.mutateAsync,
|
||||
isInviting: invite.isPending,
|
||||
setInactive: setInactiveMutation.mutateAsync,
|
||||
isDeActivatingUser: setInactiveMutation.isPending,
|
||||
assignFirstsForSecond: assignFirstsForSecondMutation.mutateAsync,
|
||||
assignSecondsForFirst: assignSecondsForFirstMutation.mutateAsync,
|
||||
removeFirstsForSecond: removeFirstsForSecondMutation.mutateAsync,
|
||||
assignEmployee: assignEmployeeForPosition.mutateAsync,
|
||||
isAssigning: assignEmployeeForPosition.isPending,
|
||||
removeSecondsForFirst: removeSecondsForFirstMutation.mutateAsync,
|
||||
remove: remove.mutateAsync,
|
||||
deactivateUser: deactivate.mutateAsync,
|
||||
isDeactivating: deactivate.isPending,
|
||||
activateUser: activate.mutateAsync,
|
||||
isActivatingUser: activate.isPending,
|
||||
};
|
||||
};
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
activateUser,
|
||||
AssignEmployeePayload,
|
||||
assignEmployees,
|
||||
assignFirstsForSecond,
|
||||
assignSecondsForFirst,
|
||||
deactivateUser,
|
||||
deleteEmployeePosition,
|
||||
EmployeePositionQueryParams,
|
||||
getGivenFirst,
|
||||
getGivenSecond,
|
||||
InactiveEPPayload,
|
||||
inviteEmployeePosition,
|
||||
removeFirstsForSecond,
|
||||
removeSecondsForFirst,
|
||||
setInactive,
|
||||
} from "../services/api/employeePositionsService";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
|
||||
export const useEmployeePositions = (params?: EmployeePositionQueryParams) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
// --- Queries ---
|
||||
const getGivenFirstQuery = (id: string) =>
|
||||
useQuery({
|
||||
queryKey: ["positionEmployees", "given-first", id],
|
||||
queryFn: () => getGivenFirst(id, params).then((res) => res.data),
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
const getGivenSecondQuery = (id: string) =>
|
||||
useQuery({
|
||||
queryKey: ["positionEmployees", "given-second", id],
|
||||
queryFn: () => getGivenSecond(id, params).then((res: any) => res.data),
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
// --- Mutations ---
|
||||
const invite = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
payload: any;
|
||||
successCallback: () => void;
|
||||
}) => inviteEmployeePosition(payload),
|
||||
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] });
|
||||
variables.successCallback();
|
||||
},
|
||||
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const deactivate = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
payload: string;
|
||||
successCallback: () => void;
|
||||
}) => deactivateUser(payload),
|
||||
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["deleteEmployees"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["employees"] });
|
||||
|
||||
|
||||
variables.successCallback();
|
||||
},
|
||||
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
const activate = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
payload: string;
|
||||
successCallback: () => void;
|
||||
}) => activateUser(payload),
|
||||
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["archived-users"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["employees"] });
|
||||
|
||||
variables.successCallback();
|
||||
},
|
||||
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const setInactiveMutation = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
payload: InactiveEPPayload;
|
||||
successCallback: () => void;
|
||||
}) => setInactive(payload),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] });
|
||||
toast.success("Team member removed successfully.");
|
||||
variables.successCallback();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const assignFirstsForSecondMutation = useMutation({
|
||||
mutationFn: (payload: any) => assignFirstsForSecond(payload),
|
||||
onSuccess: () =>
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] }),
|
||||
});
|
||||
|
||||
const assignSecondsForFirstMutation = useMutation({
|
||||
mutationFn: (payload: any) => assignSecondsForFirst(payload),
|
||||
onSuccess: () =>
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] }),
|
||||
});
|
||||
|
||||
const assignEmployeeForPosition = useMutation({
|
||||
mutationFn: (payload: AssignEmployeePayload) => assignEmployees(payload),
|
||||
onSuccess: () =>{
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["employees"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const removeFirstsForSecondMutation = useMutation({
|
||||
mutationFn: (payload: any) => removeFirstsForSecond(payload),
|
||||
onSuccess: () =>
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] }),
|
||||
});
|
||||
|
||||
const removeSecondsForFirstMutation = useMutation({
|
||||
mutationFn: (payload: any) => removeSecondsForFirst(payload),
|
||||
onSuccess: () =>
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] }),
|
||||
});
|
||||
|
||||
const remove = useMutation({
|
||||
mutationFn: (id: string) => deleteEmployeePosition(id),
|
||||
onSuccess: () =>
|
||||
queryClient.invalidateQueries({ queryKey: ["positionEmployees"] }),
|
||||
});
|
||||
|
||||
// --- Return exposed mutateAsync and query helpers ---
|
||||
return {
|
||||
getGivenFirstQuery,
|
||||
getGivenSecondQuery,
|
||||
invite: invite.mutateAsync,
|
||||
isInviting: invite.isPending,
|
||||
setInactive: setInactiveMutation.mutateAsync,
|
||||
isDeActivatingUser: setInactiveMutation.isPending,
|
||||
assignFirstsForSecond: assignFirstsForSecondMutation.mutateAsync,
|
||||
assignSecondsForFirst: assignSecondsForFirstMutation.mutateAsync,
|
||||
removeFirstsForSecond: removeFirstsForSecondMutation.mutateAsync,
|
||||
assignEmployee: assignEmployeeForPosition.mutateAsync,
|
||||
isAssigning: assignEmployeeForPosition.isPending,
|
||||
removeSecondsForFirst: removeSecondsForFirstMutation.mutateAsync,
|
||||
remove: remove.mutateAsync,
|
||||
deactivateUser: deactivate.mutateAsync,
|
||||
isDeactivating: deactivate.isPending,
|
||||
activateUser: activate.mutateAsync,
|
||||
isActivatingUser: activate.isPending,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,98 +1,98 @@
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { EmployeeWithUnitListResponse, UserWithUnitListResponse } from "../dto/employees/employees";
|
||||
import { EmployeeQueryParams, employeeService } from "../services/api/employeesService";
|
||||
import { getEmployeesUnderOrg } from "@/shared/services/organizationsService";
|
||||
|
||||
export const useEmployees = ({
|
||||
unitId,
|
||||
organizationId,
|
||||
params,
|
||||
}: {
|
||||
unitId?: string;
|
||||
organizationId?: string;
|
||||
params?:EmployeeQueryParams;
|
||||
}) => {
|
||||
const {
|
||||
data: employeesResponse,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery<UserWithUnitListResponse>({
|
||||
queryKey: ["employees", unitId],
|
||||
queryFn: async () => {
|
||||
const { data } = await employeeService.getUsersWithUnitById(unitId!, {
|
||||
take: 3000,
|
||||
});
|
||||
return data;
|
||||
},
|
||||
enabled: !!unitId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
const {
|
||||
data: employeesResponseByOrg,
|
||||
isLoading: isLoadingEmployeesByOrg,
|
||||
isError: isErrorEmployeesByOrg,
|
||||
refetch: refetchEmployeesByOrg,
|
||||
} = useQuery<EmployeeWithUnitListResponse | UserWithUnitListResponse>({
|
||||
queryKey: ["employees", organizationId, unitId, params],
|
||||
queryFn: async () => {
|
||||
// If unitId is selected, use the active-with-unit endpoint
|
||||
if (unitId) {
|
||||
const { data } = await employeeService.getUsersWithUnitById(unitId, params || {});
|
||||
return data;
|
||||
}
|
||||
// Otherwise use the by-organization endpoint
|
||||
const { data } = await getEmployeesUnderOrg(
|
||||
organizationId!,
|
||||
params
|
||||
);
|
||||
return data;
|
||||
},
|
||||
enabled: !!(organizationId || unitId),
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
const { mutate: getEmployeeDetails, isPending: isFetchingEmployee } =
|
||||
useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
const { data } = await employeeService.getEmployee(id);
|
||||
return data;
|
||||
},
|
||||
});
|
||||
|
||||
// Normalize the response to always have a consistent structure
|
||||
const normalizedEmployeesResponseByOrg = employeesResponseByOrg
|
||||
? {
|
||||
count: employeesResponseByOrg.count,
|
||||
items: employeesResponseByOrg.items.map((item: any) => {
|
||||
// If the item already has a user property, it's EmployeeWithUnitDto
|
||||
if ('user' in item && item.user) {
|
||||
return item;
|
||||
}
|
||||
// If not, wrap it as UserDTO in the user property for consistency
|
||||
return {
|
||||
id: item.id,
|
||||
user: item,
|
||||
employeePositions: item.employeePositions || [],
|
||||
};
|
||||
}),
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
employeesResponse,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
getEmployeeByDetails: getEmployeeDetails,
|
||||
isFetchingEmployee,
|
||||
refetchEmployeesByOrg,
|
||||
isErrorEmployeesByOrg,
|
||||
isLoadingEmployeesByOrg,
|
||||
employeesResponseByOrg: normalizedEmployeesResponseByOrg,
|
||||
};
|
||||
};
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
|
||||
import { EmployeeWithUnitListResponse, UserWithUnitListResponse } from "../dto/employees/employees";
|
||||
import { EmployeeQueryParams, employeeService } from "../services/api/employeesService";
|
||||
import { getEmployeesUnderOrg } from "@/shared/services/organizationsService";
|
||||
|
||||
export const useEmployees = ({
|
||||
unitId,
|
||||
organizationId,
|
||||
params,
|
||||
}: {
|
||||
unitId?: string;
|
||||
organizationId?: string;
|
||||
params?:EmployeeQueryParams;
|
||||
}) => {
|
||||
const {
|
||||
data: employeesResponse,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery<UserWithUnitListResponse>({
|
||||
queryKey: ["employees", unitId],
|
||||
queryFn: async () => {
|
||||
const { data } = await employeeService.getUsersWithUnitById(unitId!, {
|
||||
take: 3000,
|
||||
});
|
||||
return data;
|
||||
},
|
||||
enabled: !!unitId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
const {
|
||||
data: employeesResponseByOrg,
|
||||
isLoading: isLoadingEmployeesByOrg,
|
||||
isError: isErrorEmployeesByOrg,
|
||||
refetch: refetchEmployeesByOrg,
|
||||
} = useQuery<EmployeeWithUnitListResponse | UserWithUnitListResponse>({
|
||||
queryKey: ["employees", organizationId, unitId, params],
|
||||
queryFn: async () => {
|
||||
// If unitId is selected, use the active-with-unit endpoint
|
||||
if (unitId) {
|
||||
const { data } = await employeeService.getUsersWithUnitById(unitId, params || {});
|
||||
return data;
|
||||
}
|
||||
// Otherwise use the by-organization endpoint
|
||||
const { data } = await getEmployeesUnderOrg(
|
||||
organizationId!,
|
||||
params
|
||||
);
|
||||
return data;
|
||||
},
|
||||
enabled: !!(organizationId || unitId),
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
const { mutate: getEmployeeDetails, isPending: isFetchingEmployee } =
|
||||
useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
const { data } = await employeeService.getEmployee(id);
|
||||
return data;
|
||||
},
|
||||
});
|
||||
|
||||
// Normalize the response to always have a consistent structure
|
||||
const normalizedEmployeesResponseByOrg = employeesResponseByOrg
|
||||
? {
|
||||
count: employeesResponseByOrg.count,
|
||||
items: employeesResponseByOrg.items.map((item: any) => {
|
||||
// If the item already has a user property, it's EmployeeWithUnitDto
|
||||
if ('user' in item && item.user) {
|
||||
return item;
|
||||
}
|
||||
// If not, wrap it as UserDTO in the user property for consistency
|
||||
return {
|
||||
id: item.id,
|
||||
user: item,
|
||||
employeePositions: item.employeePositions || [],
|
||||
};
|
||||
}),
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
employeesResponse,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
getEmployeeByDetails: getEmployeeDetails,
|
||||
isFetchingEmployee,
|
||||
refetchEmployeesByOrg,
|
||||
isErrorEmployeesByOrg,
|
||||
isLoadingEmployeesByOrg,
|
||||
employeesResponseByOrg: normalizedEmployeesResponseByOrg,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,138 +1,138 @@
|
||||
import {
|
||||
keepPreviousData,
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
} from "@tanstack/react-query";
|
||||
|
||||
import {
|
||||
getTemplatesByUnitId,
|
||||
getTemplateById,
|
||||
createTemplate,
|
||||
updateTemplate,
|
||||
deleteTemplate,
|
||||
LetterTemplatePayload,
|
||||
LetterTemplate,
|
||||
} from "@/user-management/services/api/letterTemplateService";
|
||||
|
||||
export interface UseLetterTemplatesOptions {
|
||||
skip?: number;
|
||||
take?: number;
|
||||
// BE expects "field:DIRECTION" form, e.g. "createdAt:DESC".
|
||||
orderBy?: string;
|
||||
order?: string;
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export const useLetterTemplates = (
|
||||
unitId: string,
|
||||
options: UseLetterTemplatesOptions = {},
|
||||
) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const {
|
||||
skip = 0,
|
||||
take = 20,
|
||||
// Default to newest-first so freshly-created templates appear at the top.
|
||||
orderBy = "createdAt:DESC",
|
||||
order,
|
||||
enabled = true,
|
||||
} = options;
|
||||
|
||||
const params = {
|
||||
skip,
|
||||
take,
|
||||
orderBy,
|
||||
...(order ? { order } : {}),
|
||||
};
|
||||
|
||||
// GET all templates by unitId
|
||||
const {
|
||||
data: letterTemplatesResponse,
|
||||
isLoading,
|
||||
isFetching,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery({
|
||||
queryKey: ["letter-templates", unitId, params],
|
||||
queryFn: async () => {
|
||||
const { data } = await getTemplatesByUnitId(unitId, params);
|
||||
return data;
|
||||
},
|
||||
enabled: !!unitId && enabled,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
placeholderData: keepPreviousData,
|
||||
});
|
||||
|
||||
// GET single template
|
||||
const { mutate: getTemplateByDetails, isPending: isFetchingTemplate } =
|
||||
useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
const { data } = await getTemplateById(id);
|
||||
return data as LetterTemplate;
|
||||
},
|
||||
});
|
||||
|
||||
// CREATE
|
||||
const { mutate: createLetterTemplate, isPending: isCreating } = useMutation({
|
||||
mutationFn: async (data: LetterTemplatePayload) => {
|
||||
const { data: created } = await createTemplate(data);
|
||||
return created;
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["letter-templates", variables.unitId],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// UPDATE
|
||||
const { mutate: updateLetterTemplate, isPending: isUpdating } = useMutation({
|
||||
mutationFn: async (payload: {
|
||||
id: string;
|
||||
data: LetterTemplatePayload;
|
||||
}) => {
|
||||
const { data: updated } = await updateTemplate(payload.id, payload.data);
|
||||
return updated;
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["letter-templates", variables.data.unitId],
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["letter-template", variables.id],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// DELETE
|
||||
const { mutate: deleteLetterTemplate, isPending: isDeleting } = useMutation({
|
||||
mutationFn: async ({ id }: { id: string }) => {
|
||||
await deleteTemplate(id);
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["letter-templates", unitId],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
letterTemplatesResponse,
|
||||
items: letterTemplatesResponse?.items ?? [],
|
||||
count: letterTemplatesResponse?.count ?? 0,
|
||||
isLoading,
|
||||
isFetching,
|
||||
isError,
|
||||
refetch,
|
||||
getTemplateByDetails,
|
||||
isFetchingTemplate,
|
||||
createLetterTemplate,
|
||||
isCreating,
|
||||
updateLetterTemplate,
|
||||
isUpdating,
|
||||
deleteLetterTemplate,
|
||||
isDeleting,
|
||||
};
|
||||
};
|
||||
import {
|
||||
keepPreviousData,
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
} from "@tanstack/react-query";
|
||||
|
||||
import {
|
||||
getTemplatesByUnitId,
|
||||
getTemplateById,
|
||||
createTemplate,
|
||||
updateTemplate,
|
||||
deleteTemplate,
|
||||
LetterTemplatePayload,
|
||||
LetterTemplate,
|
||||
} from "@/user-management/services/api/letterTemplateService";
|
||||
|
||||
export interface UseLetterTemplatesOptions {
|
||||
skip?: number;
|
||||
take?: number;
|
||||
// BE expects "field:DIRECTION" form, e.g. "createdAt:DESC".
|
||||
orderBy?: string;
|
||||
order?: string;
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export const useLetterTemplates = (
|
||||
unitId: string,
|
||||
options: UseLetterTemplatesOptions = {},
|
||||
) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const {
|
||||
skip = 0,
|
||||
take = 20,
|
||||
// Default to newest-first so freshly-created templates appear at the top.
|
||||
orderBy = "createdAt:DESC",
|
||||
order,
|
||||
enabled = true,
|
||||
} = options;
|
||||
|
||||
const params = {
|
||||
skip,
|
||||
take,
|
||||
orderBy,
|
||||
...(order ? { order } : {}),
|
||||
};
|
||||
|
||||
// GET all templates by unitId
|
||||
const {
|
||||
data: letterTemplatesResponse,
|
||||
isLoading,
|
||||
isFetching,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery({
|
||||
queryKey: ["letter-templates", unitId, params],
|
||||
queryFn: async () => {
|
||||
const { data } = await getTemplatesByUnitId(unitId, params);
|
||||
return data;
|
||||
},
|
||||
enabled: !!unitId && enabled,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
placeholderData: keepPreviousData,
|
||||
});
|
||||
|
||||
// GET single template
|
||||
const { mutate: getTemplateByDetails, isPending: isFetchingTemplate } =
|
||||
useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
const { data } = await getTemplateById(id);
|
||||
return data as LetterTemplate;
|
||||
},
|
||||
});
|
||||
|
||||
// CREATE
|
||||
const { mutate: createLetterTemplate, isPending: isCreating } = useMutation({
|
||||
mutationFn: async (data: LetterTemplatePayload) => {
|
||||
const { data: created } = await createTemplate(data);
|
||||
return created;
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["letter-templates", variables.unitId],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// UPDATE
|
||||
const { mutate: updateLetterTemplate, isPending: isUpdating } = useMutation({
|
||||
mutationFn: async (payload: {
|
||||
id: string;
|
||||
data: LetterTemplatePayload;
|
||||
}) => {
|
||||
const { data: updated } = await updateTemplate(payload.id, payload.data);
|
||||
return updated;
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["letter-templates", variables.data.unitId],
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["letter-template", variables.id],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// DELETE
|
||||
const { mutate: deleteLetterTemplate, isPending: isDeleting } = useMutation({
|
||||
mutationFn: async ({ id }: { id: string }) => {
|
||||
await deleteTemplate(id);
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["letter-templates", unitId],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
letterTemplatesResponse,
|
||||
items: letterTemplatesResponse?.items ?? [],
|
||||
count: letterTemplatesResponse?.count ?? 0,
|
||||
isLoading,
|
||||
isFetching,
|
||||
isError,
|
||||
refetch,
|
||||
getTemplateByDetails,
|
||||
isFetchingTemplate,
|
||||
createLetterTemplate,
|
||||
isCreating,
|
||||
updateLetterTemplate,
|
||||
isUpdating,
|
||||
deleteLetterTemplate,
|
||||
isDeleting,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,84 +1,84 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getMyAdminOrganizations } from "@/shared/services/organizationsService";
|
||||
import { getMyAdminUnits } from "@/user-management/services/api/unitService";
|
||||
import { Name } from "../userManagement/types";
|
||||
|
||||
export interface OrgAdminOrganization {
|
||||
id: string;
|
||||
name: Name;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface OrgAdminUnit {
|
||||
id: string;
|
||||
name: Name;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
// Stable empty arrays — reusing the same reference prevents useEffect dependency loops
|
||||
const EMPTY_ORGS: OrgAdminOrganization[] = [];
|
||||
const EMPTY_UNITS: OrgAdminUnit[] = [];
|
||||
|
||||
/**
|
||||
* Fetches the list of organizations this org-admin administers.
|
||||
* Calls GET /organizations/my-admin-organizations
|
||||
*/
|
||||
export const useMyAdminOrganizations = () => {
|
||||
const { data, isLoading, isError, refetch } = useQuery({
|
||||
queryKey: ["my-admin-organizations"],
|
||||
queryFn: async () => {
|
||||
const { data } = await getMyAdminOrganizations();
|
||||
if (Array.isArray(data)) {
|
||||
return { count: data.length, items: data as OrgAdminOrganization[] };
|
||||
}
|
||||
return {
|
||||
count: (data.count ?? data.items?.length ?? 0) as number,
|
||||
items: (data.items ?? data) as OrgAdminOrganization[],
|
||||
};
|
||||
},
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
return {
|
||||
organizations: data?.items ?? EMPTY_ORGS,
|
||||
count: data?.count ?? 0,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetches the units this org-admin administers inside a given organization.
|
||||
* Calls GET /units/my-admin-units/organization/{organizationId}
|
||||
*/
|
||||
export const useMyAdminUnits = (
|
||||
organizationId: string,
|
||||
enabled: boolean = true,
|
||||
) => {
|
||||
const { data, isLoading, isError, refetch } = useQuery({
|
||||
queryKey: ["my-admin-units", organizationId],
|
||||
queryFn: async () => {
|
||||
const { data } = await getMyAdminUnits(organizationId);
|
||||
if (Array.isArray(data)) {
|
||||
return { count: data.length, items: data as OrgAdminUnit[] };
|
||||
}
|
||||
return {
|
||||
count: (data.count ?? data.items?.length ?? 0) as number,
|
||||
items: (data.items ?? data) as OrgAdminUnit[],
|
||||
};
|
||||
},
|
||||
enabled: enabled && !!organizationId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
return {
|
||||
units: data?.items ?? EMPTY_UNITS,
|
||||
count: data?.count ?? 0,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getMyAdminOrganizations } from "@/shared/services/organizationsService";
|
||||
import { getMyAdminUnits } from "@/user-management/services/api/unitService";
|
||||
import { Name } from "../userManagement/types";
|
||||
|
||||
export interface OrgAdminOrganization {
|
||||
id: string;
|
||||
name: Name;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface OrgAdminUnit {
|
||||
id: string;
|
||||
name: Name;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
// Stable empty arrays — reusing the same reference prevents useEffect dependency loops
|
||||
const EMPTY_ORGS: OrgAdminOrganization[] = [];
|
||||
const EMPTY_UNITS: OrgAdminUnit[] = [];
|
||||
|
||||
/**
|
||||
* Fetches the list of organizations this org-admin administers.
|
||||
* Calls GET /organizations/my-admin-organizations
|
||||
*/
|
||||
export const useMyAdminOrganizations = () => {
|
||||
const { data, isLoading, isError, refetch } = useQuery({
|
||||
queryKey: ["my-admin-organizations"],
|
||||
queryFn: async () => {
|
||||
const { data } = await getMyAdminOrganizations();
|
||||
if (Array.isArray(data)) {
|
||||
return { count: data.length, items: data as OrgAdminOrganization[] };
|
||||
}
|
||||
return {
|
||||
count: (data.count ?? data.items?.length ?? 0) as number,
|
||||
items: (data.items ?? data) as OrgAdminOrganization[],
|
||||
};
|
||||
},
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
return {
|
||||
organizations: data?.items ?? EMPTY_ORGS,
|
||||
count: data?.count ?? 0,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetches the units this org-admin administers inside a given organization.
|
||||
* Calls GET /units/my-admin-units/organization/{organizationId}
|
||||
*/
|
||||
export const useMyAdminUnits = (
|
||||
organizationId: string,
|
||||
enabled: boolean = true,
|
||||
) => {
|
||||
const { data, isLoading, isError, refetch } = useQuery({
|
||||
queryKey: ["my-admin-units", organizationId],
|
||||
queryFn: async () => {
|
||||
const { data } = await getMyAdminUnits(organizationId);
|
||||
if (Array.isArray(data)) {
|
||||
return { count: data.length, items: data as OrgAdminUnit[] };
|
||||
}
|
||||
return {
|
||||
count: (data.count ?? data.items?.length ?? 0) as number,
|
||||
items: (data.items ?? data) as OrgAdminUnit[],
|
||||
};
|
||||
},
|
||||
enabled: enabled && !!organizationId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
return {
|
||||
units: data?.items ?? EMPTY_UNITS,
|
||||
count: data?.count ?? 0,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
import { useQuery, useQueries } from "@tanstack/react-query";
|
||||
import {
|
||||
getUnitList,
|
||||
getChildUnits,
|
||||
} from "@/user-management/services/api/unitService";
|
||||
|
||||
const extractItems = (data: any): any[] => {
|
||||
if (!data) return [];
|
||||
if (Array.isArray(data)) return data;
|
||||
if (Array.isArray(data.items)) return data.items;
|
||||
return [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Total count of every unit in an organization's hierarchy:
|
||||
* top-level units from `/units/list/{orgId}` plus every descendant
|
||||
* reachable via `/units/child-units/{parentId}`.
|
||||
*
|
||||
* Both create-unit and relate-from-sub-city flows count against this
|
||||
* same total so the configured cap is enforced consistently.
|
||||
*/
|
||||
export const useOrgUnitTotalCount = (organizationId: string) => {
|
||||
const topLevelQuery = useQuery({
|
||||
queryKey: ["unitList", organizationId, "capacity-total"],
|
||||
queryFn: () => getUnitList(organizationId, { take: 1000, skip: 0 }),
|
||||
enabled: !!organizationId,
|
||||
staleTime: 0,
|
||||
});
|
||||
|
||||
const topLevelItems = extractItems(topLevelQuery.data?.data);
|
||||
const topLevelIds: string[] = topLevelItems
|
||||
.map((u: any) => u?.id)
|
||||
.filter(Boolean);
|
||||
|
||||
const childQueries = useQueries({
|
||||
queries: topLevelIds.map((id) => ({
|
||||
queryKey: ["unitChildren", id, "capacity-total"],
|
||||
queryFn: () => getChildUnits(id),
|
||||
enabled: !!id,
|
||||
staleTime: 0,
|
||||
})),
|
||||
});
|
||||
|
||||
// De-dupe units by `id` because some backends include the parent in
|
||||
// `/units/child-units/{parentId}` responses, and some `/units/list/{orgId}`
|
||||
// implementations already include non-top-level units.
|
||||
const uniqueIds = new Set<string>();
|
||||
for (const unit of topLevelItems) {
|
||||
const id = unit?.id;
|
||||
if (id) uniqueIds.add(String(id));
|
||||
}
|
||||
for (const q of childQueries) {
|
||||
if (!q.data) continue;
|
||||
const items = extractItems((q.data as any).data);
|
||||
for (const unit of items) {
|
||||
const id = unit?.id;
|
||||
if (id) uniqueIds.add(String(id));
|
||||
}
|
||||
}
|
||||
|
||||
const total = uniqueIds.size;
|
||||
const isLoading =
|
||||
topLevelQuery.isLoading ||
|
||||
topLevelQuery.isFetching ||
|
||||
childQueries.some((q) => q.isLoading || q.isFetching);
|
||||
|
||||
return { total, isLoading };
|
||||
};
|
||||
import { useQuery, useQueries } from "@tanstack/react-query";
|
||||
import {
|
||||
getUnitList,
|
||||
getChildUnits,
|
||||
} from "@/user-management/services/api/unitService";
|
||||
|
||||
const extractItems = (data: any): any[] => {
|
||||
if (!data) return [];
|
||||
if (Array.isArray(data)) return data;
|
||||
if (Array.isArray(data.items)) return data.items;
|
||||
return [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Total count of every unit in an organization's hierarchy:
|
||||
* top-level units from `/units/list/{orgId}` plus every descendant
|
||||
* reachable via `/units/child-units/{parentId}`.
|
||||
*
|
||||
* Both create-unit and relate-from-sub-city flows count against this
|
||||
* same total so the configured cap is enforced consistently.
|
||||
*/
|
||||
export const useOrgUnitTotalCount = (organizationId: string) => {
|
||||
const topLevelQuery = useQuery({
|
||||
queryKey: ["unitList", organizationId, "capacity-total"],
|
||||
queryFn: () => getUnitList(organizationId, { take: 1000, skip: 0 }),
|
||||
enabled: !!organizationId,
|
||||
staleTime: 0,
|
||||
});
|
||||
|
||||
const topLevelItems = extractItems(topLevelQuery.data?.data);
|
||||
const topLevelIds: string[] = topLevelItems
|
||||
.map((u: any) => u?.id)
|
||||
.filter(Boolean);
|
||||
|
||||
const childQueries = useQueries({
|
||||
queries: topLevelIds.map((id) => ({
|
||||
queryKey: ["unitChildren", id, "capacity-total"],
|
||||
queryFn: () => getChildUnits(id),
|
||||
enabled: !!id,
|
||||
staleTime: 0,
|
||||
})),
|
||||
});
|
||||
|
||||
// De-dupe units by `id` because some backends include the parent in
|
||||
// `/units/child-units/{parentId}` responses, and some `/units/list/{orgId}`
|
||||
// implementations already include non-top-level units.
|
||||
const uniqueIds = new Set<string>();
|
||||
for (const unit of topLevelItems) {
|
||||
const id = unit?.id;
|
||||
if (id) uniqueIds.add(String(id));
|
||||
}
|
||||
for (const q of childQueries) {
|
||||
if (!q.data) continue;
|
||||
const items = extractItems((q.data as any).data);
|
||||
for (const unit of items) {
|
||||
const id = unit?.id;
|
||||
if (id) uniqueIds.add(String(id));
|
||||
}
|
||||
}
|
||||
|
||||
const total = uniqueIds.size;
|
||||
const isLoading =
|
||||
topLevelQuery.isLoading ||
|
||||
topLevelQuery.isFetching ||
|
||||
childQueries.some((q) => q.isLoading || q.isFetching);
|
||||
|
||||
return { total, isLoading };
|
||||
};
|
||||
|
||||
@@ -1,141 +1,141 @@
|
||||
import { useState, useEffect, useMemo } from "react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
EmployeeQueryParams,
|
||||
employeeService,
|
||||
} from "../services/api/employeesService";
|
||||
import { useLocalizedName } from "@/shared/common/localizedName";
|
||||
import {
|
||||
EmployeeWithUnitDto,
|
||||
EmployeeWithUnitListResponse,
|
||||
} from "../dto/employees/employees";
|
||||
|
||||
// Use the existing EmployeeWithUnitDto interface
|
||||
export type OrganizationEmployee = EmployeeWithUnitDto;
|
||||
|
||||
export const useOrganizationEmployeeSearch = (
|
||||
organizationId?: string,
|
||||
params?: EmployeeQueryParams,
|
||||
) => {
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [dynamicParams, setDynamicParams] = useState<
|
||||
EmployeeQueryParams | undefined
|
||||
>({
|
||||
...params,
|
||||
take: params?.take || 3000, // Initial take value of 3000
|
||||
});
|
||||
const [hasSetCount, setHasSetCount] = useState(false);
|
||||
const localizedName = useLocalizedName();
|
||||
|
||||
const {
|
||||
data: employeesData,
|
||||
isLoading,
|
||||
error,
|
||||
refetch,
|
||||
} = useQuery<EmployeeWithUnitListResponse>({
|
||||
queryKey: ["organizationEmployees", organizationId, dynamicParams],
|
||||
queryFn: async () => {
|
||||
if (!organizationId) throw new Error("Organization ID is required");
|
||||
const response = await employeeService.getEmployeesWithOrganizationById(
|
||||
organizationId,
|
||||
dynamicParams,
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
enabled: !!organizationId,
|
||||
});
|
||||
|
||||
// Update params with count from response using useEffect
|
||||
useEffect(() => {
|
||||
if (employeesData?.count && !hasSetCount) {
|
||||
setDynamicParams((prev) => ({
|
||||
...prev,
|
||||
take: employeesData.count,
|
||||
}));
|
||||
setHasSetCount(true);
|
||||
}
|
||||
}, [employeesData?.count, hasSetCount]);
|
||||
|
||||
// Deduplicate employees by ID and filter based on search query
|
||||
const filteredEmployees = useMemo(() => {
|
||||
if (!employeesData?.items) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// First, deduplicate employees by their ID
|
||||
const uniqueEmployees = employeesData.items.reduce((acc, employee) => {
|
||||
if (!acc.find((e) => e.id === employee.id)) {
|
||||
acc.push(employee);
|
||||
}
|
||||
return acc;
|
||||
}, [] as EmployeeWithUnitDto[]);
|
||||
|
||||
// Then filter based on search query
|
||||
if (!searchQuery.trim()) {
|
||||
return uniqueEmployees;
|
||||
}
|
||||
|
||||
const query = searchQuery.toLowerCase().trim();
|
||||
|
||||
return uniqueEmployees.filter((employee) => {
|
||||
// Search by user name (both am and en)
|
||||
const userNameAm = employee.user.name.am?.toLowerCase() || "";
|
||||
const userNameEn = employee.user.name.en?.toLowerCase() || "";
|
||||
const localizedUserName =
|
||||
localizedName(employee.user.name)?.toLowerCase() || "";
|
||||
|
||||
// Search by employee name (both am and en)
|
||||
const empNameAm = employee.name.am?.toLowerCase() || "";
|
||||
const empNameEn = employee.name.en?.toLowerCase() || "";
|
||||
const localizedEmpName =
|
||||
localizedName(employee.name)?.toLowerCase() || "";
|
||||
|
||||
// Search by email
|
||||
const email = employee.user.email?.toLowerCase() || "";
|
||||
|
||||
// Search by phone number
|
||||
const phoneNumber = employee.user.phoneNumber?.toLowerCase() || "";
|
||||
|
||||
// Search by position name
|
||||
const positionNames = (employee.employeePositions ?? [])
|
||||
.filter((ep) => ep?.position?.name)
|
||||
.map((ep) => localizedName(ep.position.name)?.toLowerCase() || "")
|
||||
.join(" ");
|
||||
|
||||
return (
|
||||
userNameAm.includes(query) ||
|
||||
userNameEn.includes(query) ||
|
||||
localizedUserName.includes(query) ||
|
||||
empNameAm.includes(query) ||
|
||||
empNameEn.includes(query) ||
|
||||
localizedEmpName.includes(query) ||
|
||||
email.includes(query) ||
|
||||
phoneNumber.includes(query) ||
|
||||
positionNames.includes(query)
|
||||
);
|
||||
});
|
||||
}, [employeesData?.items, searchQuery, localizedName]);
|
||||
|
||||
// Get unique employees for total count
|
||||
const uniqueEmployees = useMemo(() => {
|
||||
if (!employeesData?.items) return [];
|
||||
return employeesData.items.reduce((acc, employee) => {
|
||||
if (!acc.find((e) => e.id === employee.id)) {
|
||||
acc.push(employee);
|
||||
}
|
||||
return acc;
|
||||
}, [] as EmployeeWithUnitDto[]);
|
||||
}, [employeesData?.items]);
|
||||
|
||||
return {
|
||||
employees: uniqueEmployees,
|
||||
filteredEmployees,
|
||||
totalCount: uniqueEmployees.length,
|
||||
filteredCount: filteredEmployees.length,
|
||||
searchQuery,
|
||||
setSearchQuery,
|
||||
isLoading,
|
||||
error,
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
import { useState, useEffect, useMemo } from "react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
EmployeeQueryParams,
|
||||
employeeService,
|
||||
} from "../services/api/employeesService";
|
||||
import { useLocalizedName } from "@/shared/common/localizedName";
|
||||
import {
|
||||
EmployeeWithUnitDto,
|
||||
EmployeeWithUnitListResponse,
|
||||
} from "../dto/employees/employees";
|
||||
|
||||
// Use the existing EmployeeWithUnitDto interface
|
||||
export type OrganizationEmployee = EmployeeWithUnitDto;
|
||||
|
||||
export const useOrganizationEmployeeSearch = (
|
||||
organizationId?: string,
|
||||
params?: EmployeeQueryParams,
|
||||
) => {
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [dynamicParams, setDynamicParams] = useState<
|
||||
EmployeeQueryParams | undefined
|
||||
>({
|
||||
...params,
|
||||
take: params?.take || 3000, // Initial take value of 3000
|
||||
});
|
||||
const [hasSetCount, setHasSetCount] = useState(false);
|
||||
const localizedName = useLocalizedName();
|
||||
|
||||
const {
|
||||
data: employeesData,
|
||||
isLoading,
|
||||
error,
|
||||
refetch,
|
||||
} = useQuery<EmployeeWithUnitListResponse>({
|
||||
queryKey: ["organizationEmployees", organizationId, dynamicParams],
|
||||
queryFn: async () => {
|
||||
if (!organizationId) throw new Error("Organization ID is required");
|
||||
const response = await employeeService.getEmployeesWithOrganizationById(
|
||||
organizationId,
|
||||
dynamicParams,
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
enabled: !!organizationId,
|
||||
});
|
||||
|
||||
// Update params with count from response using useEffect
|
||||
useEffect(() => {
|
||||
if (employeesData?.count && !hasSetCount) {
|
||||
setDynamicParams((prev) => ({
|
||||
...prev,
|
||||
take: employeesData.count,
|
||||
}));
|
||||
setHasSetCount(true);
|
||||
}
|
||||
}, [employeesData?.count, hasSetCount]);
|
||||
|
||||
// Deduplicate employees by ID and filter based on search query
|
||||
const filteredEmployees = useMemo(() => {
|
||||
if (!employeesData?.items) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// First, deduplicate employees by their ID
|
||||
const uniqueEmployees = employeesData.items.reduce((acc, employee) => {
|
||||
if (!acc.find((e) => e.id === employee.id)) {
|
||||
acc.push(employee);
|
||||
}
|
||||
return acc;
|
||||
}, [] as EmployeeWithUnitDto[]);
|
||||
|
||||
// Then filter based on search query
|
||||
if (!searchQuery.trim()) {
|
||||
return uniqueEmployees;
|
||||
}
|
||||
|
||||
const query = searchQuery.toLowerCase().trim();
|
||||
|
||||
return uniqueEmployees.filter((employee) => {
|
||||
// Search by user name (both am and en)
|
||||
const userNameAm = employee.user.name.am?.toLowerCase() || "";
|
||||
const userNameEn = employee.user.name.en?.toLowerCase() || "";
|
||||
const localizedUserName =
|
||||
localizedName(employee.user.name)?.toLowerCase() || "";
|
||||
|
||||
// Search by employee name (both am and en)
|
||||
const empNameAm = employee.name.am?.toLowerCase() || "";
|
||||
const empNameEn = employee.name.en?.toLowerCase() || "";
|
||||
const localizedEmpName =
|
||||
localizedName(employee.name)?.toLowerCase() || "";
|
||||
|
||||
// Search by email
|
||||
const email = employee.user.email?.toLowerCase() || "";
|
||||
|
||||
// Search by phone number
|
||||
const phoneNumber = employee.user.phoneNumber?.toLowerCase() || "";
|
||||
|
||||
// Search by position name
|
||||
const positionNames = (employee.employeePositions ?? [])
|
||||
.filter((ep) => ep?.position?.name)
|
||||
.map((ep) => localizedName(ep.position.name)?.toLowerCase() || "")
|
||||
.join(" ");
|
||||
|
||||
return (
|
||||
userNameAm.includes(query) ||
|
||||
userNameEn.includes(query) ||
|
||||
localizedUserName.includes(query) ||
|
||||
empNameAm.includes(query) ||
|
||||
empNameEn.includes(query) ||
|
||||
localizedEmpName.includes(query) ||
|
||||
email.includes(query) ||
|
||||
phoneNumber.includes(query) ||
|
||||
positionNames.includes(query)
|
||||
);
|
||||
});
|
||||
}, [employeesData?.items, searchQuery, localizedName]);
|
||||
|
||||
// Get unique employees for total count
|
||||
const uniqueEmployees = useMemo(() => {
|
||||
if (!employeesData?.items) return [];
|
||||
return employeesData.items.reduce((acc, employee) => {
|
||||
if (!acc.find((e) => e.id === employee.id)) {
|
||||
acc.push(employee);
|
||||
}
|
||||
return acc;
|
||||
}, [] as EmployeeWithUnitDto[]);
|
||||
}, [employeesData?.items]);
|
||||
|
||||
return {
|
||||
employees: uniqueEmployees,
|
||||
filteredEmployees,
|
||||
totalCount: uniqueEmployees.length,
|
||||
filteredCount: filteredEmployees.length,
|
||||
searchQuery,
|
||||
setSearchQuery,
|
||||
isLoading,
|
||||
error,
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,61 +1,61 @@
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
getOrganizations,
|
||||
OrgQueryParams,
|
||||
getOrganizationById,
|
||||
} from "@/shared/services/organizationsService";
|
||||
|
||||
import { OrganizationDto } from "@/shared/dto/organization/organizationDto";
|
||||
|
||||
interface Unit {
|
||||
id: string;
|
||||
name: string;
|
||||
departments: any[];
|
||||
isExpanded?: boolean;
|
||||
}
|
||||
|
||||
export interface Organization {
|
||||
id: string;
|
||||
name: string;
|
||||
units: Unit[];
|
||||
isExpanded?: boolean;
|
||||
}
|
||||
|
||||
export const useOrganizations = (params?: OrgQueryParams) => {
|
||||
const {
|
||||
data: organizationsResponse,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery({
|
||||
queryKey: ["organizations", params],
|
||||
queryFn: async () => {
|
||||
const { data } = await getOrganizations(params);
|
||||
return {
|
||||
count: data.count as number,
|
||||
items: data.items as OrganizationDto[],
|
||||
};
|
||||
},
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
const { mutate: getOrganization, isPending: isFetchingOrganization } =
|
||||
useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
const { data } = await getOrganizationById(id);
|
||||
return data;
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
return data;
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
organizationsResponse,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
getOrganizationByDetails: getOrganization,
|
||||
};
|
||||
};
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
getOrganizations,
|
||||
OrgQueryParams,
|
||||
getOrganizationById,
|
||||
} from "@/shared/services/organizationsService";
|
||||
|
||||
import { OrganizationDto } from "@/shared/dto/organization/organizationDto";
|
||||
|
||||
interface Unit {
|
||||
id: string;
|
||||
name: string;
|
||||
departments: any[];
|
||||
isExpanded?: boolean;
|
||||
}
|
||||
|
||||
export interface Organization {
|
||||
id: string;
|
||||
name: string;
|
||||
units: Unit[];
|
||||
isExpanded?: boolean;
|
||||
}
|
||||
|
||||
export const useOrganizations = (params?: OrgQueryParams) => {
|
||||
const {
|
||||
data: organizationsResponse,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
} = useQuery({
|
||||
queryKey: ["organizations", params],
|
||||
queryFn: async () => {
|
||||
const { data } = await getOrganizations(params);
|
||||
return {
|
||||
count: data.count as number,
|
||||
items: data.items as OrganizationDto[],
|
||||
};
|
||||
},
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
const { mutate: getOrganization, isPending: isFetchingOrganization } =
|
||||
useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
const { data } = await getOrganizationById(id);
|
||||
return data;
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
return data;
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
organizationsResponse,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
getOrganizationByDetails: getOrganization,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,101 +1,101 @@
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
permissionService,
|
||||
CreatePermissionDto,
|
||||
PermissionQueryParams,
|
||||
} from "../services/api/permissionService";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
PermissionDto,
|
||||
PermissionListResponse,
|
||||
} from "../dto/permissions/permissonDto";
|
||||
|
||||
interface UsePermissionManagerProps {
|
||||
params?: PermissionQueryParams;
|
||||
permissionId?: string;
|
||||
}
|
||||
|
||||
export const usePermissionManager = ({
|
||||
params,
|
||||
permissionId,
|
||||
}: UsePermissionManagerProps = {}) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
// Fetch all permissions
|
||||
const {
|
||||
data: permissions,
|
||||
isLoading: isPermissionsLoading,
|
||||
refetch: refetchPermissions,
|
||||
} = useQuery<PermissionListResponse>({
|
||||
queryKey: ["permissions", params],
|
||||
queryFn: () => permissionService.getAll(params).then((res) => res.data),
|
||||
enabled: !!params,
|
||||
staleTime: 1000 * 60 * 5,
|
||||
});
|
||||
|
||||
// Fetch single permission (for edit)
|
||||
const {
|
||||
data: selectedPermission,
|
||||
isLoading: isPermissionLoading,
|
||||
refetch: refetchPermission,
|
||||
} = useQuery<PermissionDto>({
|
||||
queryKey: ["permission", permissionId],
|
||||
queryFn: () =>
|
||||
permissionService.getById(permissionId!).then((res) => res.data),
|
||||
enabled: !!permissionId,
|
||||
});
|
||||
|
||||
// Create
|
||||
const createPermission = useMutation({
|
||||
mutationFn: (payload: CreatePermissionDto) =>
|
||||
permissionService.create(payload),
|
||||
onSuccess: () => {
|
||||
toast.success("Permission created");
|
||||
queryClient.invalidateQueries({ queryKey: ["permissions"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// Update
|
||||
const updatePermission = useMutation({
|
||||
mutationFn: ({ id, data }: { id: string; data: CreatePermissionDto }) =>
|
||||
permissionService.update(id, data),
|
||||
onSuccess: () => {
|
||||
toast.success("Permission updated");
|
||||
queryClient.invalidateQueries({ queryKey: ["permissions"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// Delete
|
||||
const deletePermission = useMutation({
|
||||
mutationFn: (id: string) => permissionService.delete(id),
|
||||
onSuccess: () => {
|
||||
toast.success("Permission deleted");
|
||||
queryClient.invalidateQueries({ queryKey: ["permissions"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
permissions,
|
||||
selectedPermission,
|
||||
isPermissionsLoading,
|
||||
isPermissionLoading,
|
||||
refetchPermissions,
|
||||
refetchPermission,
|
||||
createPermission,
|
||||
updatePermission,
|
||||
deletePermission,
|
||||
};
|
||||
};
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
permissionService,
|
||||
CreatePermissionDto,
|
||||
PermissionQueryParams,
|
||||
} from "../services/api/permissionService";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
PermissionDto,
|
||||
PermissionListResponse,
|
||||
} from "../dto/permissions/permissonDto";
|
||||
|
||||
interface UsePermissionManagerProps {
|
||||
params?: PermissionQueryParams;
|
||||
permissionId?: string;
|
||||
}
|
||||
|
||||
export const usePermissionManager = ({
|
||||
params,
|
||||
permissionId,
|
||||
}: UsePermissionManagerProps = {}) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
// Fetch all permissions
|
||||
const {
|
||||
data: permissions,
|
||||
isLoading: isPermissionsLoading,
|
||||
refetch: refetchPermissions,
|
||||
} = useQuery<PermissionListResponse>({
|
||||
queryKey: ["permissions", params],
|
||||
queryFn: () => permissionService.getAll(params).then((res) => res.data),
|
||||
enabled: !!params,
|
||||
staleTime: 1000 * 60 * 5,
|
||||
});
|
||||
|
||||
// Fetch single permission (for edit)
|
||||
const {
|
||||
data: selectedPermission,
|
||||
isLoading: isPermissionLoading,
|
||||
refetch: refetchPermission,
|
||||
} = useQuery<PermissionDto>({
|
||||
queryKey: ["permission", permissionId],
|
||||
queryFn: () =>
|
||||
permissionService.getById(permissionId!).then((res) => res.data),
|
||||
enabled: !!permissionId,
|
||||
});
|
||||
|
||||
// Create
|
||||
const createPermission = useMutation({
|
||||
mutationFn: (payload: CreatePermissionDto) =>
|
||||
permissionService.create(payload),
|
||||
onSuccess: () => {
|
||||
toast.success("Permission created");
|
||||
queryClient.invalidateQueries({ queryKey: ["permissions"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// Update
|
||||
const updatePermission = useMutation({
|
||||
mutationFn: ({ id, data }: { id: string; data: CreatePermissionDto }) =>
|
||||
permissionService.update(id, data),
|
||||
onSuccess: () => {
|
||||
toast.success("Permission updated");
|
||||
queryClient.invalidateQueries({ queryKey: ["permissions"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// Delete
|
||||
const deletePermission = useMutation({
|
||||
mutationFn: (id: string) => permissionService.delete(id),
|
||||
onSuccess: () => {
|
||||
toast.success("Permission deleted");
|
||||
queryClient.invalidateQueries({ queryKey: ["permissions"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
permissions,
|
||||
selectedPermission,
|
||||
isPermissionsLoading,
|
||||
isPermissionLoading,
|
||||
refetchPermissions,
|
||||
refetchPermission,
|
||||
createPermission,
|
||||
updatePermission,
|
||||
deletePermission,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,199 +1,199 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
getPositions,
|
||||
PositionQueryParams,
|
||||
getPositionById,
|
||||
getPositionHierarchy,
|
||||
getPositionList,
|
||||
getEmployeesUnderPosition,
|
||||
PositionPayload,
|
||||
createPosition,
|
||||
updatePosition,
|
||||
deletePosition,
|
||||
MovePostionPayload,
|
||||
movePosition,
|
||||
} from "@/user-management/services/api/positionService";
|
||||
|
||||
import { PositionDto } from "../dto/positions/positionDto";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
|
||||
export interface Position {
|
||||
id: string;
|
||||
name: string;
|
||||
code?: string;
|
||||
parentId?: string;
|
||||
organizationId?: string;
|
||||
isExpanded?: boolean;
|
||||
children?: PositionDto[];
|
||||
}
|
||||
|
||||
export interface PositionWithEmployees extends Position {
|
||||
employees?: any[];
|
||||
}
|
||||
|
||||
export const usePositions = (params?: PositionQueryParams) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
// Main positions query
|
||||
const usePositionsQuery = () => {
|
||||
return useQuery({
|
||||
queryKey: ["positions", params],
|
||||
queryFn: () => getPositions(params),
|
||||
select: (data) => ({
|
||||
count: data.data.count as number,
|
||||
items: data.data.items as PositionDto[],
|
||||
}),
|
||||
staleTime: 5 * 60 * 1000,
|
||||
enabled: params ? true : false,
|
||||
});
|
||||
};
|
||||
|
||||
// Single position by ID
|
||||
const usePositionById = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["position", id],
|
||||
queryFn: () => getPositionById(id),
|
||||
enabled: !!id,
|
||||
select: (data) => data.data,
|
||||
});
|
||||
};
|
||||
|
||||
// Position hierarchy
|
||||
const usePositionHierarchy = (id: string = "root") => {
|
||||
return useQuery({
|
||||
queryKey: ["positionHierarchy", id],
|
||||
queryFn: () => getPositionHierarchy(id),
|
||||
enabled: !!id,
|
||||
select: (data) => data.data,
|
||||
});
|
||||
};
|
||||
|
||||
// Employees under position
|
||||
const useEmployeesUnderPosition = (positionId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["positionEmployees", positionId],
|
||||
queryFn: () => getEmployeesUnderPosition(positionId),
|
||||
enabled: !!positionId || params ? true : false,
|
||||
});
|
||||
};
|
||||
|
||||
// Position list by unit/organization
|
||||
const usePositionListByUnitId = (
|
||||
organizationId: string,
|
||||
params: PositionQueryParams
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: ["positionList", organizationId, params],
|
||||
queryFn: () => getPositionList(organizationId, params),
|
||||
enabled: !!organizationId,
|
||||
select: (data) => data.data,
|
||||
});
|
||||
};
|
||||
const createPositionMutation = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
payload: PositionPayload;
|
||||
successCallback: () => void;
|
||||
}) => createPosition(payload),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["positionHierarchy"] });
|
||||
variables.successCallback();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const updatePositionMutation = useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
id: string;
|
||||
payload: PositionPayload;
|
||||
successCallback: () => void;
|
||||
}) => updatePosition(id, payload),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["positionHierarchy"] });
|
||||
variables.successCallback();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const deletePositionMutation = useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
successCallback,
|
||||
}: {
|
||||
id: string;
|
||||
successCallback: () => void;
|
||||
}) => deletePosition(id),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["positionHierarchy"] });
|
||||
toast.success("Department removed successfully.");
|
||||
|
||||
variables.successCallback();
|
||||
},
|
||||
onError: (error: any) => {
|
||||
// Check if it's a "Referenced Entity" error (meaning department has related employees)
|
||||
if (error?.response?.status === 400 && error?.response?.data?.message) {
|
||||
const errorMessage = error?.response?.data?.message;
|
||||
|
||||
if (errorMessage.includes("Referenced Entity") || errorMessage.includes("referenced")) {
|
||||
toast.error(
|
||||
t("department.cannotDeleteWithEmployees", "Cannot delete department with assigned employees"),
|
||||
{
|
||||
description: t("department.reassignEmployeesFirst", "Please reassign or remove all employees from this department first."),
|
||||
duration: 5000
|
||||
}
|
||||
);
|
||||
} else {
|
||||
handleError(error);
|
||||
}
|
||||
} else {
|
||||
handleError(error);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
usePositionsQuery,
|
||||
usePositionById,
|
||||
usePositionHierarchy,
|
||||
useEmployeesUnderPosition,
|
||||
usePositionListByUnitId,
|
||||
createPosition: createPositionMutation.mutateAsync,
|
||||
isCreating: createPositionMutation.isPending,
|
||||
updatePosition: updatePositionMutation.mutateAsync,
|
||||
isUpdating: updatePositionMutation.isPending,
|
||||
deletePosition: deletePositionMutation.mutateAsync,
|
||||
isDeleting: deletePositionMutation.isPending,
|
||||
};
|
||||
};
|
||||
|
||||
export const useMovePosition = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (data: MovePostionPayload) => movePosition(data),
|
||||
onSuccess: (_data, variables) => {
|
||||
// ✅ Invalidate anything related to positions so UI updates
|
||||
queryClient.invalidateQueries({ queryKey: ["positions"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["positionHierarchy"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
};
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
getPositions,
|
||||
PositionQueryParams,
|
||||
getPositionById,
|
||||
getPositionHierarchy,
|
||||
getPositionList,
|
||||
getEmployeesUnderPosition,
|
||||
PositionPayload,
|
||||
createPosition,
|
||||
updatePosition,
|
||||
deletePosition,
|
||||
MovePostionPayload,
|
||||
movePosition,
|
||||
} from "@/user-management/services/api/positionService";
|
||||
|
||||
import { PositionDto } from "../dto/positions/positionDto";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
|
||||
export interface Position {
|
||||
id: string;
|
||||
name: string;
|
||||
code?: string;
|
||||
parentId?: string;
|
||||
organizationId?: string;
|
||||
isExpanded?: boolean;
|
||||
children?: PositionDto[];
|
||||
}
|
||||
|
||||
export interface PositionWithEmployees extends Position {
|
||||
employees?: any[];
|
||||
}
|
||||
|
||||
export const usePositions = (params?: PositionQueryParams) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
// Main positions query
|
||||
const usePositionsQuery = () => {
|
||||
return useQuery({
|
||||
queryKey: ["positions", params],
|
||||
queryFn: () => getPositions(params),
|
||||
select: (data) => ({
|
||||
count: data.data.count as number,
|
||||
items: data.data.items as PositionDto[],
|
||||
}),
|
||||
staleTime: 5 * 60 * 1000,
|
||||
enabled: params ? true : false,
|
||||
});
|
||||
};
|
||||
|
||||
// Single position by ID
|
||||
const usePositionById = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["position", id],
|
||||
queryFn: () => getPositionById(id),
|
||||
enabled: !!id,
|
||||
select: (data) => data.data,
|
||||
});
|
||||
};
|
||||
|
||||
// Position hierarchy
|
||||
const usePositionHierarchy = (id: string = "root") => {
|
||||
return useQuery({
|
||||
queryKey: ["positionHierarchy", id],
|
||||
queryFn: () => getPositionHierarchy(id),
|
||||
enabled: !!id,
|
||||
select: (data) => data.data,
|
||||
});
|
||||
};
|
||||
|
||||
// Employees under position
|
||||
const useEmployeesUnderPosition = (positionId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["positionEmployees", positionId],
|
||||
queryFn: () => getEmployeesUnderPosition(positionId),
|
||||
enabled: !!positionId || params ? true : false,
|
||||
});
|
||||
};
|
||||
|
||||
// Position list by unit/organization
|
||||
const usePositionListByUnitId = (
|
||||
organizationId: string,
|
||||
params: PositionQueryParams
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: ["positionList", organizationId, params],
|
||||
queryFn: () => getPositionList(organizationId, params),
|
||||
enabled: !!organizationId,
|
||||
select: (data) => data.data,
|
||||
});
|
||||
};
|
||||
const createPositionMutation = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
payload: PositionPayload;
|
||||
successCallback: () => void;
|
||||
}) => createPosition(payload),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["positionHierarchy"] });
|
||||
variables.successCallback();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const updatePositionMutation = useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
id: string;
|
||||
payload: PositionPayload;
|
||||
successCallback: () => void;
|
||||
}) => updatePosition(id, payload),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["positionHierarchy"] });
|
||||
variables.successCallback();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const deletePositionMutation = useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
successCallback,
|
||||
}: {
|
||||
id: string;
|
||||
successCallback: () => void;
|
||||
}) => deletePosition(id),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["positionHierarchy"] });
|
||||
toast.success("Department removed successfully.");
|
||||
|
||||
variables.successCallback();
|
||||
},
|
||||
onError: (error: any) => {
|
||||
// Check if it's a "Referenced Entity" error (meaning department has related employees)
|
||||
if (error?.response?.status === 400 && error?.response?.data?.message) {
|
||||
const errorMessage = error?.response?.data?.message;
|
||||
|
||||
if (errorMessage.includes("Referenced Entity") || errorMessage.includes("referenced")) {
|
||||
toast.error(
|
||||
t("department.cannotDeleteWithEmployees", "Cannot delete department with assigned employees"),
|
||||
{
|
||||
description: t("department.reassignEmployeesFirst", "Please reassign or remove all employees from this department first."),
|
||||
duration: 5000
|
||||
}
|
||||
);
|
||||
} else {
|
||||
handleError(error);
|
||||
}
|
||||
} else {
|
||||
handleError(error);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
usePositionsQuery,
|
||||
usePositionById,
|
||||
usePositionHierarchy,
|
||||
useEmployeesUnderPosition,
|
||||
usePositionListByUnitId,
|
||||
createPosition: createPositionMutation.mutateAsync,
|
||||
isCreating: createPositionMutation.isPending,
|
||||
updatePosition: updatePositionMutation.mutateAsync,
|
||||
isUpdating: updatePositionMutation.isPending,
|
||||
deletePosition: deletePositionMutation.mutateAsync,
|
||||
isDeleting: deletePositionMutation.isPending,
|
||||
};
|
||||
};
|
||||
|
||||
export const useMovePosition = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (data: MovePostionPayload) => movePosition(data),
|
||||
onSuccess: (_data, variables) => {
|
||||
// ✅ Invalidate anything related to positions so UI updates
|
||||
queryClient.invalidateQueries({ queryKey: ["positions"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["positionHierarchy"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,224 +1,224 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
CreatePositionTypePayload,
|
||||
PositionRequest,
|
||||
positionTypeService,
|
||||
UpdatePositionTypePayload,
|
||||
} from "../services/api/positionTypesService";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
PositionTypeDto,
|
||||
PositionTypesListResponse,
|
||||
} from "../dto/positions/positionType";
|
||||
|
||||
interface positionParams {
|
||||
take: number;
|
||||
skip: number;
|
||||
orderBy: string;
|
||||
order?: string;
|
||||
}
|
||||
|
||||
interface UsePositionTypeManagerProps {
|
||||
id?: string;
|
||||
unitId?: string;
|
||||
organizationId?: string;
|
||||
params?: positionParams; // 👈 we expected query params to be passed like this
|
||||
}
|
||||
|
||||
export const usePositionTypes = ({
|
||||
id,
|
||||
params = {
|
||||
take: 1000,
|
||||
skip: 0,
|
||||
orderBy: "createdAt:Desc",
|
||||
},
|
||||
unitId,
|
||||
organizationId,
|
||||
}: UsePositionTypeManagerProps = {}) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
const { data, isLoading, isError, refetch } = useQuery({
|
||||
queryKey: ["position-types", params],
|
||||
queryFn: () => positionTypeService.getAll(params).then((res) => res.data),
|
||||
});
|
||||
// Single Position Type (for edit)
|
||||
const {
|
||||
data: positionType,
|
||||
isLoading: isLoadingSingle,
|
||||
isError: isErrorSingle,
|
||||
refetch: refetchSingle,
|
||||
} = useQuery<PositionTypeDto>({
|
||||
queryKey: ["position-type", id],
|
||||
queryFn: () => positionTypeService.getById(id!).then((res) => res.data),
|
||||
enabled: !!id,
|
||||
});
|
||||
const {
|
||||
data: positionTypeByUnitId,
|
||||
isLoading: isLoadingPosition,
|
||||
isError: isErrorPosition,
|
||||
refetch: refetchPosition,
|
||||
} = useQuery<PositionTypesListResponse | undefined>({
|
||||
queryKey: ["position-type", unitId, params],
|
||||
queryFn: async () => {
|
||||
if (!unitId) return undefined;
|
||||
const res = await positionTypeService.getByUnitId(unitId, params);
|
||||
return res.data as PositionTypesListResponse | undefined;
|
||||
},
|
||||
enabled: !!unitId,
|
||||
});
|
||||
|
||||
// Position types by organization ID
|
||||
const {
|
||||
data: positionTypeByOrgId,
|
||||
isLoading: isLoadingOrgPosition,
|
||||
isError: isErrorOrgPosition,
|
||||
refetch: refetchOrgPosition,
|
||||
} = useQuery<PositionTypesListResponse | undefined>({
|
||||
queryKey: ["position-type-org", organizationId, params],
|
||||
queryFn: async () => {
|
||||
if (!organizationId) return undefined;
|
||||
const res = await positionTypeService.getByOrganizationId(organizationId, params);
|
||||
return res.data as PositionTypesListResponse | undefined;
|
||||
},
|
||||
enabled: !!organizationId,
|
||||
});
|
||||
|
||||
// Common types with organization ID (includes both org-specific and common types)
|
||||
const {
|
||||
data: commonPositionTypesByOrgId,
|
||||
isLoading: isLoadingCommonOrgTypes,
|
||||
isError: isErrorCommonOrgTypes,
|
||||
refetch: refetchCommonOrgTypes,
|
||||
} = useQuery<PositionTypesListResponse | undefined>({
|
||||
queryKey: ["position-types-common-org", organizationId, params],
|
||||
queryFn: async () => {
|
||||
if (!organizationId) return undefined;
|
||||
const res = await positionTypeService.getCommonTypesByOrganizationId(organizationId, params);
|
||||
return res.data as PositionTypesListResponse | undefined;
|
||||
},
|
||||
enabled: !!organizationId,
|
||||
});
|
||||
|
||||
// Common types with unit ID (includes both unit-specific and common types)
|
||||
const {
|
||||
data: commonPositionTypes,
|
||||
isLoading: isLoadingCommonTypes,
|
||||
isError: isErrorCommonTypes,
|
||||
refetch: refetchCommonTypes,
|
||||
} = useQuery<PositionTypesListResponse | undefined>({
|
||||
queryKey: ["position-types-common", unitId, params],
|
||||
queryFn: async () => {
|
||||
if (!unitId) return undefined;
|
||||
const res = await positionTypeService.getCommonTypesById(unitId, params);
|
||||
return res.data as PositionTypesListResponse | undefined;
|
||||
},
|
||||
enabled: !!unitId,
|
||||
});
|
||||
|
||||
// Create
|
||||
const createPositionType = useMutation({
|
||||
mutationFn: (payload: CreatePositionTypePayload) =>
|
||||
positionTypeService.create(payload),
|
||||
onSuccess: () => {
|
||||
toast.success("Position type created");
|
||||
queryClient.invalidateQueries({ queryKey: ["position-types"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// Update
|
||||
const updatePositionType = useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
data,
|
||||
}: {
|
||||
id: string;
|
||||
data: UpdatePositionTypePayload;
|
||||
}) => positionTypeService.update(id, data),
|
||||
onSuccess: () => {
|
||||
toast.success("Position type updated");
|
||||
queryClient.invalidateQueries({ queryKey: ["position-types"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["position-type", id] });
|
||||
},
|
||||
onError: () => {},
|
||||
});
|
||||
|
||||
//update positon from to
|
||||
const updatePositionTypeFromTo = useMutation({
|
||||
mutationFn: ({ toId, fromId }: { toId: string; fromId: string }) =>
|
||||
positionTypeService.updateFromto(toId, fromId),
|
||||
onSuccess: () => {
|
||||
toast.success("Position type migration updated");
|
||||
queryClient.invalidateQueries({ queryKey: ["position-types-to"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["position-type", id] });
|
||||
},
|
||||
onError: () => {},
|
||||
});
|
||||
//update all postions
|
||||
const migratePositionsByPositions = useMutation({
|
||||
mutationFn: ({ id, data }: { id: string; data: PositionRequest }) =>
|
||||
positionTypeService.updateByPostion(id, data),
|
||||
onSuccess: () => {
|
||||
toast.success("Position type migration updated");
|
||||
queryClient.invalidateQueries({ queryKey: ["position-types-migration"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["position-type", id] });
|
||||
},
|
||||
onError: () => {},
|
||||
});
|
||||
|
||||
// Delete
|
||||
const deletePositionType = useMutation({
|
||||
mutationFn: (id: string) => positionTypeService.delete(id),
|
||||
onSuccess: () => {
|
||||
toast.success("Position type deleted");
|
||||
queryClient.invalidateQueries({ queryKey: ["position-types"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
positionTypes: data?.items ?? [],
|
||||
positionTypeResponse: data,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
// single
|
||||
positionType,
|
||||
isLoadingSingle,
|
||||
isErrorSingle,
|
||||
refetchSingle,
|
||||
|
||||
// mutations
|
||||
createPositionType,
|
||||
updatePositionType,
|
||||
deletePositionType,
|
||||
positionTypeByUnitId,
|
||||
migratePositionsByPositions,
|
||||
updatePositionTypeFromTo,
|
||||
refetchPosition,
|
||||
isErrorPosition,
|
||||
isLoadingPosition,
|
||||
// organization-based position types
|
||||
positionTypeByOrgId,
|
||||
refetchOrgPosition,
|
||||
isErrorOrgPosition,
|
||||
isLoadingOrgPosition,
|
||||
// common types with organization ID
|
||||
commonPositionTypesByOrgId,
|
||||
refetchCommonOrgTypes,
|
||||
isErrorCommonOrgTypes,
|
||||
isLoadingCommonOrgTypes,
|
||||
// common types with unit ID
|
||||
commonPositionTypes: commonPositionTypes?.items ?? [],
|
||||
isLoadingCommonTypes,
|
||||
isErrorCommonTypes,
|
||||
refetchCommonTypes,
|
||||
};
|
||||
};
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
CreatePositionTypePayload,
|
||||
PositionRequest,
|
||||
positionTypeService,
|
||||
UpdatePositionTypePayload,
|
||||
} from "../services/api/positionTypesService";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
PositionTypeDto,
|
||||
PositionTypesListResponse,
|
||||
} from "../dto/positions/positionType";
|
||||
|
||||
interface positionParams {
|
||||
take: number;
|
||||
skip: number;
|
||||
orderBy: string;
|
||||
order?: string;
|
||||
}
|
||||
|
||||
interface UsePositionTypeManagerProps {
|
||||
id?: string;
|
||||
unitId?: string;
|
||||
organizationId?: string;
|
||||
params?: positionParams; // 👈 we expected query params to be passed like this
|
||||
}
|
||||
|
||||
export const usePositionTypes = ({
|
||||
id,
|
||||
params = {
|
||||
take: 1000,
|
||||
skip: 0,
|
||||
orderBy: "createdAt:Desc",
|
||||
},
|
||||
unitId,
|
||||
organizationId,
|
||||
}: UsePositionTypeManagerProps = {}) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
const { data, isLoading, isError, refetch } = useQuery({
|
||||
queryKey: ["position-types", params],
|
||||
queryFn: () => positionTypeService.getAll(params).then((res) => res.data),
|
||||
});
|
||||
// Single Position Type (for edit)
|
||||
const {
|
||||
data: positionType,
|
||||
isLoading: isLoadingSingle,
|
||||
isError: isErrorSingle,
|
||||
refetch: refetchSingle,
|
||||
} = useQuery<PositionTypeDto>({
|
||||
queryKey: ["position-type", id],
|
||||
queryFn: () => positionTypeService.getById(id!).then((res) => res.data),
|
||||
enabled: !!id,
|
||||
});
|
||||
const {
|
||||
data: positionTypeByUnitId,
|
||||
isLoading: isLoadingPosition,
|
||||
isError: isErrorPosition,
|
||||
refetch: refetchPosition,
|
||||
} = useQuery<PositionTypesListResponse | undefined>({
|
||||
queryKey: ["position-type", unitId, params],
|
||||
queryFn: async () => {
|
||||
if (!unitId) return undefined;
|
||||
const res = await positionTypeService.getByUnitId(unitId, params);
|
||||
return res.data as PositionTypesListResponse | undefined;
|
||||
},
|
||||
enabled: !!unitId,
|
||||
});
|
||||
|
||||
// Position types by organization ID
|
||||
const {
|
||||
data: positionTypeByOrgId,
|
||||
isLoading: isLoadingOrgPosition,
|
||||
isError: isErrorOrgPosition,
|
||||
refetch: refetchOrgPosition,
|
||||
} = useQuery<PositionTypesListResponse | undefined>({
|
||||
queryKey: ["position-type-org", organizationId, params],
|
||||
queryFn: async () => {
|
||||
if (!organizationId) return undefined;
|
||||
const res = await positionTypeService.getByOrganizationId(organizationId, params);
|
||||
return res.data as PositionTypesListResponse | undefined;
|
||||
},
|
||||
enabled: !!organizationId,
|
||||
});
|
||||
|
||||
// Common types with organization ID (includes both org-specific and common types)
|
||||
const {
|
||||
data: commonPositionTypesByOrgId,
|
||||
isLoading: isLoadingCommonOrgTypes,
|
||||
isError: isErrorCommonOrgTypes,
|
||||
refetch: refetchCommonOrgTypes,
|
||||
} = useQuery<PositionTypesListResponse | undefined>({
|
||||
queryKey: ["position-types-common-org", organizationId, params],
|
||||
queryFn: async () => {
|
||||
if (!organizationId) return undefined;
|
||||
const res = await positionTypeService.getCommonTypesByOrganizationId(organizationId, params);
|
||||
return res.data as PositionTypesListResponse | undefined;
|
||||
},
|
||||
enabled: !!organizationId,
|
||||
});
|
||||
|
||||
// Common types with unit ID (includes both unit-specific and common types)
|
||||
const {
|
||||
data: commonPositionTypes,
|
||||
isLoading: isLoadingCommonTypes,
|
||||
isError: isErrorCommonTypes,
|
||||
refetch: refetchCommonTypes,
|
||||
} = useQuery<PositionTypesListResponse | undefined>({
|
||||
queryKey: ["position-types-common", unitId, params],
|
||||
queryFn: async () => {
|
||||
if (!unitId) return undefined;
|
||||
const res = await positionTypeService.getCommonTypesById(unitId, params);
|
||||
return res.data as PositionTypesListResponse | undefined;
|
||||
},
|
||||
enabled: !!unitId,
|
||||
});
|
||||
|
||||
// Create
|
||||
const createPositionType = useMutation({
|
||||
mutationFn: (payload: CreatePositionTypePayload) =>
|
||||
positionTypeService.create(payload),
|
||||
onSuccess: () => {
|
||||
toast.success("Position type created");
|
||||
queryClient.invalidateQueries({ queryKey: ["position-types"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// Update
|
||||
const updatePositionType = useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
data,
|
||||
}: {
|
||||
id: string;
|
||||
data: UpdatePositionTypePayload;
|
||||
}) => positionTypeService.update(id, data),
|
||||
onSuccess: () => {
|
||||
toast.success("Position type updated");
|
||||
queryClient.invalidateQueries({ queryKey: ["position-types"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["position-type", id] });
|
||||
},
|
||||
onError: () => {},
|
||||
});
|
||||
|
||||
//update positon from to
|
||||
const updatePositionTypeFromTo = useMutation({
|
||||
mutationFn: ({ toId, fromId }: { toId: string; fromId: string }) =>
|
||||
positionTypeService.updateFromto(toId, fromId),
|
||||
onSuccess: () => {
|
||||
toast.success("Position type migration updated");
|
||||
queryClient.invalidateQueries({ queryKey: ["position-types-to"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["position-type", id] });
|
||||
},
|
||||
onError: () => {},
|
||||
});
|
||||
//update all postions
|
||||
const migratePositionsByPositions = useMutation({
|
||||
mutationFn: ({ id, data }: { id: string; data: PositionRequest }) =>
|
||||
positionTypeService.updateByPostion(id, data),
|
||||
onSuccess: () => {
|
||||
toast.success("Position type migration updated");
|
||||
queryClient.invalidateQueries({ queryKey: ["position-types-migration"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["position-type", id] });
|
||||
},
|
||||
onError: () => {},
|
||||
});
|
||||
|
||||
// Delete
|
||||
const deletePositionType = useMutation({
|
||||
mutationFn: (id: string) => positionTypeService.delete(id),
|
||||
onSuccess: () => {
|
||||
toast.success("Position type deleted");
|
||||
queryClient.invalidateQueries({ queryKey: ["position-types"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
positionTypes: data?.items ?? [],
|
||||
positionTypeResponse: data,
|
||||
isLoading,
|
||||
isError,
|
||||
refetch,
|
||||
// single
|
||||
positionType,
|
||||
isLoadingSingle,
|
||||
isErrorSingle,
|
||||
refetchSingle,
|
||||
|
||||
// mutations
|
||||
createPositionType,
|
||||
updatePositionType,
|
||||
deletePositionType,
|
||||
positionTypeByUnitId,
|
||||
migratePositionsByPositions,
|
||||
updatePositionTypeFromTo,
|
||||
refetchPosition,
|
||||
isErrorPosition,
|
||||
isLoadingPosition,
|
||||
// organization-based position types
|
||||
positionTypeByOrgId,
|
||||
refetchOrgPosition,
|
||||
isErrorOrgPosition,
|
||||
isLoadingOrgPosition,
|
||||
// common types with organization ID
|
||||
commonPositionTypesByOrgId,
|
||||
refetchCommonOrgTypes,
|
||||
isErrorCommonOrgTypes,
|
||||
isLoadingCommonOrgTypes,
|
||||
// common types with unit ID
|
||||
commonPositionTypes: commonPositionTypes?.items ?? [],
|
||||
isLoadingCommonTypes,
|
||||
isErrorCommonTypes,
|
||||
refetchCommonTypes,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,99 +1,99 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
getPositionTypeConfigurationsByUnitId,
|
||||
getPositionTypeConfigurationById,
|
||||
createPositionTypeConfiguration,
|
||||
updatePositionTypeConfiguration,
|
||||
CreatePositionTypeConfigurationPayload,
|
||||
UpdatePositionTypeConfigurationPayload,
|
||||
} from "../services/api/positionTypeConfigurationService";
|
||||
|
||||
export const usePositionTypeConfiguration = (unitId?: string | null) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
// GET: List by unitId
|
||||
const {
|
||||
data: configurationsData,
|
||||
isLoading: isLoadingConfigurations,
|
||||
isError: isConfigurationsError,
|
||||
refetch: refetchConfigurations,
|
||||
} = useQuery({
|
||||
queryKey: ["positionTypeConfigurations", unitId],
|
||||
queryFn: async () => {
|
||||
const response = await getPositionTypeConfigurationsByUnitId(unitId!);
|
||||
return response.data;
|
||||
},
|
||||
enabled: !!unitId,
|
||||
});
|
||||
|
||||
// GET: Single by id
|
||||
const getConfigurationById = (id: string | null) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
return useQuery({
|
||||
queryKey: ["positionTypeConfiguration", id],
|
||||
queryFn: async () => {
|
||||
const response = await getPositionTypeConfigurationById(id!);
|
||||
return response.data;
|
||||
},
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
// POST: Create
|
||||
const createConfigurationMutation = useMutation({
|
||||
mutationFn: async (payload: CreatePositionTypeConfigurationPayload) => {
|
||||
const response = await createPositionTypeConfiguration(payload);
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["positionTypeConfigurations", unitId],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// PUT: Update
|
||||
const updateConfigurationMutation = useMutation({
|
||||
mutationFn: async ({
|
||||
id,
|
||||
payload,
|
||||
}: {
|
||||
id: string;
|
||||
payload: UpdatePositionTypeConfigurationPayload;
|
||||
}) => {
|
||||
const response = await updatePositionTypeConfiguration(id, payload);
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["positionTypeConfigurations", unitId],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
// Queries
|
||||
configurations: configurationsData?.items || [],
|
||||
totalConfigurations: configurationsData?.count || 0,
|
||||
isLoadingConfigurations,
|
||||
isConfigurationsError,
|
||||
refetchConfigurations,
|
||||
getConfigurationById,
|
||||
|
||||
// Mutations
|
||||
createConfiguration: createConfigurationMutation.mutateAsync,
|
||||
isCreatingConfiguration: createConfigurationMutation.isPending,
|
||||
updateConfiguration: updateConfigurationMutation.mutateAsync,
|
||||
isUpdatingConfiguration: updateConfigurationMutation.isPending,
|
||||
};
|
||||
};
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
getPositionTypeConfigurationsByUnitId,
|
||||
getPositionTypeConfigurationById,
|
||||
createPositionTypeConfiguration,
|
||||
updatePositionTypeConfiguration,
|
||||
CreatePositionTypeConfigurationPayload,
|
||||
UpdatePositionTypeConfigurationPayload,
|
||||
} from "../services/api/positionTypeConfigurationService";
|
||||
|
||||
export const usePositionTypeConfiguration = (unitId?: string | null) => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
// GET: List by unitId
|
||||
const {
|
||||
data: configurationsData,
|
||||
isLoading: isLoadingConfigurations,
|
||||
isError: isConfigurationsError,
|
||||
refetch: refetchConfigurations,
|
||||
} = useQuery({
|
||||
queryKey: ["positionTypeConfigurations", unitId],
|
||||
queryFn: async () => {
|
||||
const response = await getPositionTypeConfigurationsByUnitId(unitId!);
|
||||
return response.data;
|
||||
},
|
||||
enabled: !!unitId,
|
||||
});
|
||||
|
||||
// GET: Single by id
|
||||
const getConfigurationById = (id: string | null) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
return useQuery({
|
||||
queryKey: ["positionTypeConfiguration", id],
|
||||
queryFn: async () => {
|
||||
const response = await getPositionTypeConfigurationById(id!);
|
||||
return response.data;
|
||||
},
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
// POST: Create
|
||||
const createConfigurationMutation = useMutation({
|
||||
mutationFn: async (payload: CreatePositionTypeConfigurationPayload) => {
|
||||
const response = await createPositionTypeConfiguration(payload);
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["positionTypeConfigurations", unitId],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// PUT: Update
|
||||
const updateConfigurationMutation = useMutation({
|
||||
mutationFn: async ({
|
||||
id,
|
||||
payload,
|
||||
}: {
|
||||
id: string;
|
||||
payload: UpdatePositionTypeConfigurationPayload;
|
||||
}) => {
|
||||
const response = await updatePositionTypeConfiguration(id, payload);
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["positionTypeConfigurations", unitId],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
// Queries
|
||||
configurations: configurationsData?.items || [],
|
||||
totalConfigurations: configurationsData?.count || 0,
|
||||
isLoadingConfigurations,
|
||||
isConfigurationsError,
|
||||
refetchConfigurations,
|
||||
getConfigurationById,
|
||||
|
||||
// Mutations
|
||||
createConfiguration: createConfigurationMutation.mutateAsync,
|
||||
isCreatingConfiguration: createConfigurationMutation.isPending,
|
||||
updateConfiguration: updateConfigurationMutation.mutateAsync,
|
||||
isUpdatingConfiguration: updateConfigurationMutation.isPending,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,207 +1,207 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
CreatePrefixPayload,
|
||||
CreateSuffixPayload,
|
||||
prefixSuffixService,
|
||||
} from "@/user-management/services/api/prefixSuffixService";
|
||||
|
||||
export const usePrefixesList = (
|
||||
unitId: string,
|
||||
recordTypeKey: string,
|
||||
skip = 0,
|
||||
take = 10
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: ["prefixes", unitId, recordTypeKey, { cc: false }],
|
||||
queryFn: () => prefixSuffixService.getPrefix(unitId, recordTypeKey, skip, take),
|
||||
enabled: !!unitId && !!recordTypeKey,
|
||||
});
|
||||
|
||||
export const useCCPrefixesList = (
|
||||
unitId: string,
|
||||
recordTypeKey: string,
|
||||
skip = 0,
|
||||
take = 10
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: ["prefixes", unitId, recordTypeKey, { cc: true }],
|
||||
queryFn: () =>
|
||||
prefixSuffixService.getPrefixCC(unitId, recordTypeKey, skip, take),
|
||||
enabled: !!unitId && !!recordTypeKey,
|
||||
});
|
||||
|
||||
export const usePositionPrefixesList = (
|
||||
unitId: string,
|
||||
recordTypeKey: string,
|
||||
skip = 0,
|
||||
take = 10
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: ["prefixes-by-position", unitId, recordTypeKey],
|
||||
queryFn: () =>
|
||||
prefixSuffixService.getPrefixByPosition(unitId, recordTypeKey, skip, take),
|
||||
enabled: !!unitId && !!recordTypeKey,
|
||||
});
|
||||
|
||||
export const usePrefixDetail = (id: string) =>
|
||||
useQuery({
|
||||
queryKey: ["prefix", id],
|
||||
queryFn: () => prefixSuffixService.getPrefixById(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
export const useCreatePrefix = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (payload: CreatePrefixPayload) =>
|
||||
prefixSuffixService.createPrefix(payload),
|
||||
onSuccess: (_, payload) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [
|
||||
"prefixes",
|
||||
payload.unitId,
|
||||
payload.recordTypeKey,
|
||||
{ cc: payload.isForCC },
|
||||
],
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdatePrefix = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ id, payload }: { id: string; payload: CreatePrefixPayload }) =>
|
||||
prefixSuffixService.editPrefix(id, payload),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [
|
||||
"prefixes",
|
||||
variables.payload.unitId,
|
||||
variables.payload.recordTypeKey,
|
||||
{ cc: variables.payload.isForCC },
|
||||
],
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: ["prefix", variables.id] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeletePrefix = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
}: {
|
||||
id: string;
|
||||
unitId: string;
|
||||
recordTypeKey: string;
|
||||
isForCC: boolean;
|
||||
}) => prefixSuffixService.deletePrefix(id),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [
|
||||
"prefixes",
|
||||
variables.unitId,
|
||||
variables.recordTypeKey,
|
||||
{ cc: variables.isForCC },
|
||||
],
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: ["prefix", variables.id] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useSuffixesList = (
|
||||
unitId: string,
|
||||
recordTypeKey: string,
|
||||
skip = 0,
|
||||
take = 10
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: ["suffixes", unitId, recordTypeKey, { cc: false }],
|
||||
queryFn: () => prefixSuffixService.getSuffix(unitId, recordTypeKey, skip, take),
|
||||
enabled: !!unitId && !!recordTypeKey,
|
||||
});
|
||||
|
||||
export const useCCSuffixesList = (
|
||||
unitId: string,
|
||||
recordTypeKey: string,
|
||||
skip = 0,
|
||||
take = 10
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: ["suffixes", unitId, recordTypeKey, { cc: true }],
|
||||
queryFn: () =>
|
||||
prefixSuffixService.getSuffixCC(unitId, recordTypeKey, skip, take),
|
||||
enabled: !!unitId && !!recordTypeKey,
|
||||
});
|
||||
|
||||
export const useSuffixDetail = (id: string) =>
|
||||
useQuery({
|
||||
queryKey: ["suffix", id],
|
||||
queryFn: () => prefixSuffixService.getSuffixById(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
export const useCreateSuffix = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (payload: CreateSuffixPayload) =>
|
||||
prefixSuffixService.createSuffix(payload),
|
||||
onSuccess: (_, payload) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [
|
||||
"suffixes",
|
||||
payload.unitId,
|
||||
payload.recordTypeKey,
|
||||
{ cc: payload.isForCC },
|
||||
],
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateSuffix = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ id, payload }: { id: string; payload: CreateSuffixPayload }) =>
|
||||
prefixSuffixService.editSuffix(id, payload),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [
|
||||
"suffixes",
|
||||
variables.payload.unitId,
|
||||
variables.payload.recordTypeKey,
|
||||
{ cc: variables.payload.isForCC },
|
||||
],
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: ["suffix", variables.id] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteSuffix = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
}: {
|
||||
id: string;
|
||||
unitId: string;
|
||||
recordTypeKey: string;
|
||||
isForCC: boolean;
|
||||
}) => prefixSuffixService.deleteSuffix(id),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [
|
||||
"suffixes",
|
||||
variables.unitId,
|
||||
variables.recordTypeKey,
|
||||
{ cc: variables.isForCC },
|
||||
],
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: ["suffix", variables.id] });
|
||||
},
|
||||
});
|
||||
};
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
CreatePrefixPayload,
|
||||
CreateSuffixPayload,
|
||||
prefixSuffixService,
|
||||
} from "@/user-management/services/api/prefixSuffixService";
|
||||
|
||||
export const usePrefixesList = (
|
||||
unitId: string,
|
||||
recordTypeKey: string,
|
||||
skip = 0,
|
||||
take = 10
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: ["prefixes", unitId, recordTypeKey, { cc: false }],
|
||||
queryFn: () => prefixSuffixService.getPrefix(unitId, recordTypeKey, skip, take),
|
||||
enabled: !!unitId && !!recordTypeKey,
|
||||
});
|
||||
|
||||
export const useCCPrefixesList = (
|
||||
unitId: string,
|
||||
recordTypeKey: string,
|
||||
skip = 0,
|
||||
take = 10
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: ["prefixes", unitId, recordTypeKey, { cc: true }],
|
||||
queryFn: () =>
|
||||
prefixSuffixService.getPrefixCC(unitId, recordTypeKey, skip, take),
|
||||
enabled: !!unitId && !!recordTypeKey,
|
||||
});
|
||||
|
||||
export const usePositionPrefixesList = (
|
||||
unitId: string,
|
||||
recordTypeKey: string,
|
||||
skip = 0,
|
||||
take = 10
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: ["prefixes-by-position", unitId, recordTypeKey],
|
||||
queryFn: () =>
|
||||
prefixSuffixService.getPrefixByPosition(unitId, recordTypeKey, skip, take),
|
||||
enabled: !!unitId && !!recordTypeKey,
|
||||
});
|
||||
|
||||
export const usePrefixDetail = (id: string) =>
|
||||
useQuery({
|
||||
queryKey: ["prefix", id],
|
||||
queryFn: () => prefixSuffixService.getPrefixById(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
export const useCreatePrefix = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (payload: CreatePrefixPayload) =>
|
||||
prefixSuffixService.createPrefix(payload),
|
||||
onSuccess: (_, payload) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [
|
||||
"prefixes",
|
||||
payload.unitId,
|
||||
payload.recordTypeKey,
|
||||
{ cc: payload.isForCC },
|
||||
],
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdatePrefix = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ id, payload }: { id: string; payload: CreatePrefixPayload }) =>
|
||||
prefixSuffixService.editPrefix(id, payload),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [
|
||||
"prefixes",
|
||||
variables.payload.unitId,
|
||||
variables.payload.recordTypeKey,
|
||||
{ cc: variables.payload.isForCC },
|
||||
],
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: ["prefix", variables.id] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeletePrefix = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
}: {
|
||||
id: string;
|
||||
unitId: string;
|
||||
recordTypeKey: string;
|
||||
isForCC: boolean;
|
||||
}) => prefixSuffixService.deletePrefix(id),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [
|
||||
"prefixes",
|
||||
variables.unitId,
|
||||
variables.recordTypeKey,
|
||||
{ cc: variables.isForCC },
|
||||
],
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: ["prefix", variables.id] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useSuffixesList = (
|
||||
unitId: string,
|
||||
recordTypeKey: string,
|
||||
skip = 0,
|
||||
take = 10
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: ["suffixes", unitId, recordTypeKey, { cc: false }],
|
||||
queryFn: () => prefixSuffixService.getSuffix(unitId, recordTypeKey, skip, take),
|
||||
enabled: !!unitId && !!recordTypeKey,
|
||||
});
|
||||
|
||||
export const useCCSuffixesList = (
|
||||
unitId: string,
|
||||
recordTypeKey: string,
|
||||
skip = 0,
|
||||
take = 10
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: ["suffixes", unitId, recordTypeKey, { cc: true }],
|
||||
queryFn: () =>
|
||||
prefixSuffixService.getSuffixCC(unitId, recordTypeKey, skip, take),
|
||||
enabled: !!unitId && !!recordTypeKey,
|
||||
});
|
||||
|
||||
export const useSuffixDetail = (id: string) =>
|
||||
useQuery({
|
||||
queryKey: ["suffix", id],
|
||||
queryFn: () => prefixSuffixService.getSuffixById(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
|
||||
export const useCreateSuffix = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (payload: CreateSuffixPayload) =>
|
||||
prefixSuffixService.createSuffix(payload),
|
||||
onSuccess: (_, payload) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [
|
||||
"suffixes",
|
||||
payload.unitId,
|
||||
payload.recordTypeKey,
|
||||
{ cc: payload.isForCC },
|
||||
],
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateSuffix = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ id, payload }: { id: string; payload: CreateSuffixPayload }) =>
|
||||
prefixSuffixService.editSuffix(id, payload),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [
|
||||
"suffixes",
|
||||
variables.payload.unitId,
|
||||
variables.payload.recordTypeKey,
|
||||
{ cc: variables.payload.isForCC },
|
||||
],
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: ["suffix", variables.id] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteSuffix = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
}: {
|
||||
id: string;
|
||||
unitId: string;
|
||||
recordTypeKey: string;
|
||||
isForCC: boolean;
|
||||
}) => prefixSuffixService.deleteSuffix(id),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [
|
||||
"suffixes",
|
||||
variables.unitId,
|
||||
variables.recordTypeKey,
|
||||
{ cc: variables.isForCC },
|
||||
],
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: ["suffix", variables.id] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,106 +1,106 @@
|
||||
// hooks/useRecordTagPrefixes.ts
|
||||
"use client";
|
||||
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
|
||||
import {
|
||||
CreatePrefixPayload,
|
||||
PrefixSuffixListResponseDto,
|
||||
prefixSuffixService,
|
||||
} from "../services/api/prefixSuffixService";
|
||||
|
||||
export interface UseRecordTagPrefixesParams {
|
||||
unitId: string;
|
||||
recordTagId?: string;
|
||||
skip?: number;
|
||||
take?: number;
|
||||
}
|
||||
|
||||
export const useRecordTagPrefixes = ({
|
||||
unitId,
|
||||
recordTagId,
|
||||
skip = 0,
|
||||
take = 10,
|
||||
}: UseRecordTagPrefixesParams) => {
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
// --- Get Prefixes by Record Tag ---
|
||||
const {
|
||||
data: prefixesResponse,
|
||||
isLoading: isLoadingPrefixes,
|
||||
isError: isErrorPrefixes,
|
||||
refetch: refetchPrefixes,
|
||||
} = useQuery<PrefixSuffixListResponseDto>({
|
||||
queryKey: ["recordTagPrefixes", unitId, recordTagId, skip, take],
|
||||
queryFn: async () => {
|
||||
const { data } = await prefixSuffixService.getPrefixByRecordTagId(
|
||||
unitId,
|
||||
recordTagId!,
|
||||
skip,
|
||||
take,
|
||||
);
|
||||
return data;
|
||||
},
|
||||
enabled: !!unitId && !!recordTagId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
// --- Create Prefix for Tag ---
|
||||
const { mutate: createPrefix, isPending: isCreatingPrefix } = useMutation({
|
||||
mutationFn: async (payload: CreatePrefixPayload) => {
|
||||
const { data } = await prefixSuffixService.createPrefix(payload);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success(
|
||||
t("prefixes.createdSuccess") || "Prefix created successfully ✅",
|
||||
);
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["recordTagPrefixes", unitId, recordTagId],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// --- Delete Prefix ---
|
||||
const { mutate: deletePrefix, isPending: isDeletingPrefix } = useMutation({
|
||||
mutationFn: async (prefixId: string) => {
|
||||
const { data } = await prefixSuffixService.deletePrefix(prefixId);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success(
|
||||
t("prefixes.deletedSuccess") || "Prefix deleted successfully 🗑️",
|
||||
);
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["recordTagPrefixes", unitId, recordTagId],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
// queries
|
||||
prefixes: prefixesResponse?.items ?? [],
|
||||
total: prefixesResponse?.count ?? 0,
|
||||
isLoadingPrefixes,
|
||||
isErrorPrefixes,
|
||||
refetchPrefixes,
|
||||
|
||||
// mutations
|
||||
createPrefix,
|
||||
isCreatingPrefix,
|
||||
deletePrefix,
|
||||
isDeletingPrefix,
|
||||
};
|
||||
};
|
||||
// hooks/useRecordTagPrefixes.ts
|
||||
"use client";
|
||||
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
|
||||
import {
|
||||
CreatePrefixPayload,
|
||||
PrefixSuffixListResponseDto,
|
||||
prefixSuffixService,
|
||||
} from "../services/api/prefixSuffixService";
|
||||
|
||||
export interface UseRecordTagPrefixesParams {
|
||||
unitId: string;
|
||||
recordTagId?: string;
|
||||
skip?: number;
|
||||
take?: number;
|
||||
}
|
||||
|
||||
export const useRecordTagPrefixes = ({
|
||||
unitId,
|
||||
recordTagId,
|
||||
skip = 0,
|
||||
take = 10,
|
||||
}: UseRecordTagPrefixesParams) => {
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
// --- Get Prefixes by Record Tag ---
|
||||
const {
|
||||
data: prefixesResponse,
|
||||
isLoading: isLoadingPrefixes,
|
||||
isError: isErrorPrefixes,
|
||||
refetch: refetchPrefixes,
|
||||
} = useQuery<PrefixSuffixListResponseDto>({
|
||||
queryKey: ["recordTagPrefixes", unitId, recordTagId, skip, take],
|
||||
queryFn: async () => {
|
||||
const { data } = await prefixSuffixService.getPrefixByRecordTagId(
|
||||
unitId,
|
||||
recordTagId!,
|
||||
skip,
|
||||
take,
|
||||
);
|
||||
return data;
|
||||
},
|
||||
enabled: !!unitId && !!recordTagId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
// --- Create Prefix for Tag ---
|
||||
const { mutate: createPrefix, isPending: isCreatingPrefix } = useMutation({
|
||||
mutationFn: async (payload: CreatePrefixPayload) => {
|
||||
const { data } = await prefixSuffixService.createPrefix(payload);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success(
|
||||
t("prefixes.createdSuccess") || "Prefix created successfully ✅",
|
||||
);
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["recordTagPrefixes", unitId, recordTagId],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// --- Delete Prefix ---
|
||||
const { mutate: deletePrefix, isPending: isDeletingPrefix } = useMutation({
|
||||
mutationFn: async (prefixId: string) => {
|
||||
const { data } = await prefixSuffixService.deletePrefix(prefixId);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success(
|
||||
t("prefixes.deletedSuccess") || "Prefix deleted successfully 🗑️",
|
||||
);
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["recordTagPrefixes", unitId, recordTagId],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
// queries
|
||||
prefixes: prefixesResponse?.items ?? [],
|
||||
total: prefixesResponse?.count ?? 0,
|
||||
isLoadingPrefixes,
|
||||
isErrorPrefixes,
|
||||
refetchPrefixes,
|
||||
|
||||
// mutations
|
||||
createPrefix,
|
||||
isCreatingPrefix,
|
||||
deletePrefix,
|
||||
isDeletingPrefix,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,134 +1,134 @@
|
||||
import { useQuery, useMutation } from "@tanstack/react-query";
|
||||
import { toast } from "sonner"; // ✅ shadcn sonner toast
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
|
||||
import {
|
||||
CreateRecordTagPayload,
|
||||
RecordTag,
|
||||
RecordTagResponse,
|
||||
UpdateRecordTagPayload,
|
||||
} from "@/user-management/dto/recordTags/recordTags.type";
|
||||
import { recordTagService } from "../services/api/recordTagsService";
|
||||
|
||||
export const useRecordTags = ({
|
||||
unitId,
|
||||
recordTagId,
|
||||
}: {
|
||||
unitId?: string | null;
|
||||
recordTagId?: string;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
// --- Get Record Tags List by Unit ---
|
||||
const {
|
||||
data: recordTagsList,
|
||||
isLoading: isLoadingRecordTagsList,
|
||||
isError: isErrorRecordTagsList,
|
||||
refetch: refetchRecordTagsList,
|
||||
} = useQuery<RecordTagResponse>({
|
||||
queryKey: ["recordTagsList", unitId],
|
||||
queryFn: async () => {
|
||||
const { data } = await recordTagService.getRecordTagsListWithUnitById(
|
||||
unitId!
|
||||
);
|
||||
return data;
|
||||
},
|
||||
enabled: !!unitId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
// --- Get Record Tag by Id ---
|
||||
const {
|
||||
data: recordTag,
|
||||
isLoading: isLoadingRecordTag,
|
||||
isError: isErrorRecordTag,
|
||||
refetch: refetchRecordTag,
|
||||
} = useQuery<RecordTag>({
|
||||
queryKey: ["recordTag", recordTagId],
|
||||
queryFn: async () => {
|
||||
const { data } = await recordTagService.getRecordTags(recordTagId!);
|
||||
return data;
|
||||
},
|
||||
enabled: !!recordTagId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
// --- Create Record Tag ---
|
||||
const { mutate: createRecordTag, isPending: isCreatingRecordTag } =
|
||||
useMutation({
|
||||
mutationFn: async (payload: CreateRecordTagPayload) => {
|
||||
const { data } = await recordTagService.createRecordTags(payload);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success("Record Tag created successfully ✅");
|
||||
refetchRecordTagsList();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// --- Update Record Tag ---
|
||||
const { mutate: updateRecordTag, isPending: isUpdatingRecordTag } =
|
||||
useMutation({
|
||||
mutationFn: async ({
|
||||
id,
|
||||
payload,
|
||||
}: {
|
||||
id: string;
|
||||
payload: UpdateRecordTagPayload;
|
||||
}) => {
|
||||
const { data } = await recordTagService.updateEmployee(id, payload);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success("Record Tag updated successfully ✨");
|
||||
refetchRecordTagsList();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// --- Delete Record Tag ---
|
||||
const { mutate: deleteRecordTag, isPending: isDeletingRecordTag } =
|
||||
useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
const { data } = await recordTagService.deleteEmployee(id);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success("Record Tag deleted successfully 🗑️");
|
||||
refetchRecordTagsList();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
// list
|
||||
recordTagsList,
|
||||
isLoadingRecordTagsList,
|
||||
isErrorRecordTagsList,
|
||||
refetchRecordTagsList,
|
||||
|
||||
// single
|
||||
recordTag,
|
||||
isLoadingRecordTag,
|
||||
isErrorRecordTag,
|
||||
refetchRecordTag,
|
||||
|
||||
// mutations
|
||||
createRecordTag,
|
||||
isCreatingRecordTag,
|
||||
updateRecordTag,
|
||||
isUpdatingRecordTag,
|
||||
deleteRecordTag,
|
||||
isDeletingRecordTag,
|
||||
};
|
||||
};
|
||||
import { useQuery, useMutation } from "@tanstack/react-query";
|
||||
import { toast } from "sonner"; // ✅ shadcn sonner toast
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
|
||||
import {
|
||||
CreateRecordTagPayload,
|
||||
RecordTag,
|
||||
RecordTagResponse,
|
||||
UpdateRecordTagPayload,
|
||||
} from "@/user-management/dto/recordTags/recordTags.type";
|
||||
import { recordTagService } from "../services/api/recordTagsService";
|
||||
|
||||
export const useRecordTags = ({
|
||||
unitId,
|
||||
recordTagId,
|
||||
}: {
|
||||
unitId?: string | null;
|
||||
recordTagId?: string;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
// --- Get Record Tags List by Unit ---
|
||||
const {
|
||||
data: recordTagsList,
|
||||
isLoading: isLoadingRecordTagsList,
|
||||
isError: isErrorRecordTagsList,
|
||||
refetch: refetchRecordTagsList,
|
||||
} = useQuery<RecordTagResponse>({
|
||||
queryKey: ["recordTagsList", unitId],
|
||||
queryFn: async () => {
|
||||
const { data } = await recordTagService.getRecordTagsListWithUnitById(
|
||||
unitId!
|
||||
);
|
||||
return data;
|
||||
},
|
||||
enabled: !!unitId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
// --- Get Record Tag by Id ---
|
||||
const {
|
||||
data: recordTag,
|
||||
isLoading: isLoadingRecordTag,
|
||||
isError: isErrorRecordTag,
|
||||
refetch: refetchRecordTag,
|
||||
} = useQuery<RecordTag>({
|
||||
queryKey: ["recordTag", recordTagId],
|
||||
queryFn: async () => {
|
||||
const { data } = await recordTagService.getRecordTags(recordTagId!);
|
||||
return data;
|
||||
},
|
||||
enabled: !!recordTagId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
// --- Create Record Tag ---
|
||||
const { mutate: createRecordTag, isPending: isCreatingRecordTag } =
|
||||
useMutation({
|
||||
mutationFn: async (payload: CreateRecordTagPayload) => {
|
||||
const { data } = await recordTagService.createRecordTags(payload);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success("Record Tag created successfully ✅");
|
||||
refetchRecordTagsList();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// --- Update Record Tag ---
|
||||
const { mutate: updateRecordTag, isPending: isUpdatingRecordTag } =
|
||||
useMutation({
|
||||
mutationFn: async ({
|
||||
id,
|
||||
payload,
|
||||
}: {
|
||||
id: string;
|
||||
payload: UpdateRecordTagPayload;
|
||||
}) => {
|
||||
const { data } = await recordTagService.updateEmployee(id, payload);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success("Record Tag updated successfully ✨");
|
||||
refetchRecordTagsList();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// --- Delete Record Tag ---
|
||||
const { mutate: deleteRecordTag, isPending: isDeletingRecordTag } =
|
||||
useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
const { data } = await recordTagService.deleteEmployee(id);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success("Record Tag deleted successfully 🗑️");
|
||||
refetchRecordTagsList();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
// list
|
||||
recordTagsList,
|
||||
isLoadingRecordTagsList,
|
||||
isErrorRecordTagsList,
|
||||
refetchRecordTagsList,
|
||||
|
||||
// single
|
||||
recordTag,
|
||||
isLoadingRecordTag,
|
||||
isErrorRecordTag,
|
||||
refetchRecordTag,
|
||||
|
||||
// mutations
|
||||
createRecordTag,
|
||||
isCreatingRecordTag,
|
||||
updateRecordTag,
|
||||
isUpdatingRecordTag,
|
||||
deleteRecordTag,
|
||||
isDeletingRecordTag,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,153 +1,153 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
sealService,
|
||||
CreateSealPayload,
|
||||
SealListResponse,
|
||||
SealResponseDto,
|
||||
SealStatusUpdatePayload,
|
||||
} from "../services/api/sealService";
|
||||
|
||||
export const useSeal = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
// Query for fetching all seals
|
||||
const {
|
||||
data: sealsData,
|
||||
isLoading: isLoadingSeals,
|
||||
isError: isSealsError,
|
||||
refetch: refetchSeals,
|
||||
} = useQuery<SealListResponse>({
|
||||
queryKey: ["seals"],
|
||||
queryFn: async () => {
|
||||
const response = await sealService.getSeals();
|
||||
return response.data;
|
||||
},
|
||||
enabled: false,
|
||||
});
|
||||
|
||||
// Query for fetching a single seal
|
||||
const getSealsByUnitId = (id: string | null) => {
|
||||
return useQuery({
|
||||
queryKey: ["seal", id],
|
||||
queryFn: async () => {
|
||||
if (id) {
|
||||
const response = await sealService.getSealListsByUnitId(id);
|
||||
return response.data;
|
||||
}
|
||||
},
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
// Query for fetching a single seal
|
||||
const getSealsById = (id: string | null) => {
|
||||
return useQuery({
|
||||
queryKey: ["seal", id],
|
||||
queryFn: async () => {
|
||||
if (id) {
|
||||
const response = await sealService.getSeal(id);
|
||||
return response.data;
|
||||
}
|
||||
},
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
// Mutation for creating a seal
|
||||
const createSealMutation = useMutation<
|
||||
SealResponseDto,
|
||||
Error,
|
||||
CreateSealPayload
|
||||
>({
|
||||
mutationFn: async (payload) => {
|
||||
const response = await sealService.createSeal(payload);
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["seals"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// Mutation for updating a seal
|
||||
const updateSealMutation = useMutation({
|
||||
mutationFn: async ({
|
||||
id,
|
||||
payload,
|
||||
}: {
|
||||
id: string;
|
||||
payload: Partial<CreateSealPayload>;
|
||||
}) => {
|
||||
const response = await sealService.updateSeal(id, payload);
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["seal"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// Mutation for deleting a seal (actually deactivates via change-status)
|
||||
const deleteSealMutation = useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
await sealService.changeSealStatus(id, { isCurrent: false });
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["seals"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// Mutation for updating seal upload status
|
||||
const updateSealStatusMutation = useMutation({
|
||||
mutationFn: async ({
|
||||
id,
|
||||
updateSealStatusPayload,
|
||||
}: {
|
||||
id: string;
|
||||
updateSealStatusPayload: SealStatusUpdatePayload;
|
||||
}) => {
|
||||
const response = await sealService.updateSealUploadStatus(
|
||||
id,
|
||||
updateSealStatusPayload
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["seals"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
// Queries
|
||||
seals: sealsData?.items || [],
|
||||
totalSeals: sealsData?.count || 0,
|
||||
isLoadingSeals,
|
||||
isSealsError,
|
||||
refetchSeals,
|
||||
getSealsByUnitId,
|
||||
getSealsById,
|
||||
|
||||
// Mutations
|
||||
createSeal: createSealMutation.mutateAsync,
|
||||
isCreatingSeal: createSealMutation.isPending,
|
||||
updateSeal: updateSealMutation.mutate,
|
||||
isUpdatingSeal: updateSealMutation.isPending,
|
||||
deleteSeal: deleteSealMutation.mutate,
|
||||
isDeletingSeal: deleteSealMutation.isPending,
|
||||
updateSealStatus: updateSealStatusMutation.mutateAsync,
|
||||
isUpdatingStatus: updateSealStatusMutation.isPending,
|
||||
};
|
||||
};
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import {
|
||||
sealService,
|
||||
CreateSealPayload,
|
||||
SealListResponse,
|
||||
SealResponseDto,
|
||||
SealStatusUpdatePayload,
|
||||
} from "../services/api/sealService";
|
||||
|
||||
export const useSeal = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
|
||||
// Query for fetching all seals
|
||||
const {
|
||||
data: sealsData,
|
||||
isLoading: isLoadingSeals,
|
||||
isError: isSealsError,
|
||||
refetch: refetchSeals,
|
||||
} = useQuery<SealListResponse>({
|
||||
queryKey: ["seals"],
|
||||
queryFn: async () => {
|
||||
const response = await sealService.getSeals();
|
||||
return response.data;
|
||||
},
|
||||
enabled: false,
|
||||
});
|
||||
|
||||
// Query for fetching a single seal
|
||||
const getSealsByUnitId = (id: string | null) => {
|
||||
return useQuery({
|
||||
queryKey: ["seal", id],
|
||||
queryFn: async () => {
|
||||
if (id) {
|
||||
const response = await sealService.getSealListsByUnitId(id);
|
||||
return response.data;
|
||||
}
|
||||
},
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
// Query for fetching a single seal
|
||||
const getSealsById = (id: string | null) => {
|
||||
return useQuery({
|
||||
queryKey: ["seal", id],
|
||||
queryFn: async () => {
|
||||
if (id) {
|
||||
const response = await sealService.getSeal(id);
|
||||
return response.data;
|
||||
}
|
||||
},
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
// Mutation for creating a seal
|
||||
const createSealMutation = useMutation<
|
||||
SealResponseDto,
|
||||
Error,
|
||||
CreateSealPayload
|
||||
>({
|
||||
mutationFn: async (payload) => {
|
||||
const response = await sealService.createSeal(payload);
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["seals"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// Mutation for updating a seal
|
||||
const updateSealMutation = useMutation({
|
||||
mutationFn: async ({
|
||||
id,
|
||||
payload,
|
||||
}: {
|
||||
id: string;
|
||||
payload: Partial<CreateSealPayload>;
|
||||
}) => {
|
||||
const response = await sealService.updateSeal(id, payload);
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["seal"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// Mutation for deleting a seal (actually deactivates via change-status)
|
||||
const deleteSealMutation = useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
await sealService.changeSealStatus(id, { isCurrent: false });
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["seals"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
// Mutation for updating seal upload status
|
||||
const updateSealStatusMutation = useMutation({
|
||||
mutationFn: async ({
|
||||
id,
|
||||
updateSealStatusPayload,
|
||||
}: {
|
||||
id: string;
|
||||
updateSealStatusPayload: SealStatusUpdatePayload;
|
||||
}) => {
|
||||
const response = await sealService.updateSealUploadStatus(
|
||||
id,
|
||||
updateSealStatusPayload
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["seals"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
// Queries
|
||||
seals: sealsData?.items || [],
|
||||
totalSeals: sealsData?.count || 0,
|
||||
isLoadingSeals,
|
||||
isSealsError,
|
||||
refetchSeals,
|
||||
getSealsByUnitId,
|
||||
getSealsById,
|
||||
|
||||
// Mutations
|
||||
createSeal: createSealMutation.mutateAsync,
|
||||
isCreatingSeal: createSealMutation.isPending,
|
||||
updateSeal: updateSealMutation.mutate,
|
||||
isUpdatingSeal: updateSealMutation.isPending,
|
||||
deleteSeal: deleteSealMutation.mutate,
|
||||
isDeletingSeal: deleteSealMutation.isPending,
|
||||
updateSealStatus: updateSealStatusMutation.mutateAsync,
|
||||
isUpdatingStatus: updateSealStatusMutation.isPending,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,198 +1,198 @@
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import { useAuth } from "@/shared/context/AuthContext";
|
||||
|
||||
import {
|
||||
getUnitList,
|
||||
getMyAdminUnits,
|
||||
getUnitById,
|
||||
getUnitHierarchy,
|
||||
getCurrentUnitEmployees,
|
||||
createUnit,
|
||||
updateUnit,
|
||||
softDeleteUnit,
|
||||
relateUnitToUnit,
|
||||
getChildUnits,
|
||||
RelateUnitToUnitPayload,
|
||||
UnitPayload,
|
||||
UnitQueryParams,
|
||||
} from "@/user-management/services/api/unitService";
|
||||
|
||||
export const useUnit = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
const { user } = useAuth();
|
||||
const isOrganizationAdmin =
|
||||
user?.roles?.some((role) => role.key === "organization_admin") ?? false;
|
||||
|
||||
const getList = (
|
||||
organizationId: string,
|
||||
params?: UnitQueryParams,
|
||||
enabled: boolean = true,
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: ["unitList", organizationId, params ?? {}],
|
||||
queryFn: () => getUnitList(organizationId, params ?? {}),
|
||||
enabled: enabled && !!organizationId,
|
||||
staleTime: 0,
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
};
|
||||
|
||||
const getAccessibleList = (
|
||||
organizationId: string,
|
||||
params?: UnitQueryParams,
|
||||
enabled: boolean = true,
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: [
|
||||
"accessibleUnitList",
|
||||
organizationId,
|
||||
params ?? {},
|
||||
isOrganizationAdmin ? "all" : "my-admin-units",
|
||||
],
|
||||
queryFn: async () => {
|
||||
const response = isOrganizationAdmin
|
||||
? await getUnitList(organizationId, params ?? {})
|
||||
: await getMyAdminUnits(organizationId);
|
||||
const responseData = response.data;
|
||||
const items = Array.isArray(responseData)
|
||||
? responseData
|
||||
: (responseData?.items ?? []);
|
||||
|
||||
return {
|
||||
...response,
|
||||
data: {
|
||||
...(Array.isArray(responseData) ? {} : responseData),
|
||||
count: responseData?.count ?? items.length,
|
||||
items,
|
||||
},
|
||||
};
|
||||
},
|
||||
enabled: enabled && !!organizationId,
|
||||
staleTime: 0,
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
};
|
||||
|
||||
const getById = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["unit", id],
|
||||
queryFn: () => getUnitById(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
const getHierarchy = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["unitHierarchy", id],
|
||||
queryFn: () => getUnitHierarchy(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
const getEmployees = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["unitEmployees", id],
|
||||
queryFn: () => getCurrentUnitEmployees(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
const getChildren = (parentUnitId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["unitChildren", parentUnitId],
|
||||
queryFn: () => getChildUnits(parentUnitId),
|
||||
enabled: !!parentUnitId,
|
||||
staleTime: 0,
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
};
|
||||
|
||||
const create = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
payload: UnitPayload;
|
||||
successCallback: () => void;
|
||||
}) => createUnit(payload),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["unitList"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["unitChildren"] });
|
||||
variables.successCallback();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const update = useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
id: string;
|
||||
payload: UnitPayload;
|
||||
successCallback: () => void;
|
||||
}) => updateUnit(id, payload),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["unitList"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["unitChildren"] });
|
||||
variables.successCallback();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const remove = useMutation({
|
||||
mutationFn: (id: string) => softDeleteUnit(id),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["unitList"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["unitChildren"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const relate = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
}: {
|
||||
payload: RelateUnitToUnitPayload;
|
||||
successCallback?: () => void;
|
||||
}) => relateUnitToUnit(payload),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["unitList"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["unitChildren"] });
|
||||
variables.successCallback?.();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
return {
|
||||
getList,
|
||||
getAccessibleList,
|
||||
getById,
|
||||
getHierarchy,
|
||||
getEmployees,
|
||||
getChildren,
|
||||
createUnit: create.mutateAsync,
|
||||
isCreating: create.isPending,
|
||||
updateUnit: update.mutateAsync,
|
||||
isUpdating: update.isPending,
|
||||
removeUnit: remove.mutateAsync,
|
||||
isDeleting: remove.isPending,
|
||||
relateUnit: relate.mutateAsync,
|
||||
isRelating: relate.isPending,
|
||||
};
|
||||
};
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useErrorHandler } from "@/shared/hooks/useErrorHandler";
|
||||
import { useAuth } from "@/shared/context/AuthContext";
|
||||
|
||||
import {
|
||||
getUnitList,
|
||||
getMyAdminUnits,
|
||||
getUnitById,
|
||||
getUnitHierarchy,
|
||||
getCurrentUnitEmployees,
|
||||
createUnit,
|
||||
updateUnit,
|
||||
softDeleteUnit,
|
||||
relateUnitToUnit,
|
||||
getChildUnits,
|
||||
RelateUnitToUnitPayload,
|
||||
UnitPayload,
|
||||
UnitQueryParams,
|
||||
} from "@/user-management/services/api/unitService";
|
||||
|
||||
export const useUnit = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const { handleError } = useErrorHandler(t);
|
||||
const { user } = useAuth();
|
||||
const isOrganizationAdmin =
|
||||
user?.roles?.some((role) => role.key === "organization_admin") ?? false;
|
||||
|
||||
const getList = (
|
||||
organizationId: string,
|
||||
params?: UnitQueryParams,
|
||||
enabled: boolean = true,
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: ["unitList", organizationId, params ?? {}],
|
||||
queryFn: () => getUnitList(organizationId, params ?? {}),
|
||||
enabled: enabled && !!organizationId,
|
||||
staleTime: 0,
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
};
|
||||
|
||||
const getAccessibleList = (
|
||||
organizationId: string,
|
||||
params?: UnitQueryParams,
|
||||
enabled: boolean = true,
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: [
|
||||
"accessibleUnitList",
|
||||
organizationId,
|
||||
params ?? {},
|
||||
isOrganizationAdmin ? "all" : "my-admin-units",
|
||||
],
|
||||
queryFn: async () => {
|
||||
const response = isOrganizationAdmin
|
||||
? await getUnitList(organizationId, params ?? {})
|
||||
: await getMyAdminUnits(organizationId);
|
||||
const responseData = response.data;
|
||||
const items = Array.isArray(responseData)
|
||||
? responseData
|
||||
: (responseData?.items ?? []);
|
||||
|
||||
return {
|
||||
...response,
|
||||
data: {
|
||||
...(Array.isArray(responseData) ? {} : responseData),
|
||||
count: responseData?.count ?? items.length,
|
||||
items,
|
||||
},
|
||||
};
|
||||
},
|
||||
enabled: enabled && !!organizationId,
|
||||
staleTime: 0,
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
};
|
||||
|
||||
const getById = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["unit", id],
|
||||
queryFn: () => getUnitById(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
const getHierarchy = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["unitHierarchy", id],
|
||||
queryFn: () => getUnitHierarchy(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
const getEmployees = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["unitEmployees", id],
|
||||
queryFn: () => getCurrentUnitEmployees(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
const getChildren = (parentUnitId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ["unitChildren", parentUnitId],
|
||||
queryFn: () => getChildUnits(parentUnitId),
|
||||
enabled: !!parentUnitId,
|
||||
staleTime: 0,
|
||||
refetchOnMount: "always",
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
};
|
||||
|
||||
const create = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
payload: UnitPayload;
|
||||
successCallback: () => void;
|
||||
}) => createUnit(payload),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["unitList"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["unitChildren"] });
|
||||
variables.successCallback();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const update = useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
payload,
|
||||
successCallback,
|
||||
}: {
|
||||
id: string;
|
||||
payload: UnitPayload;
|
||||
successCallback: () => void;
|
||||
}) => updateUnit(id, payload),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["unitList"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["unitChildren"] });
|
||||
variables.successCallback();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const remove = useMutation({
|
||||
mutationFn: (id: string) => softDeleteUnit(id),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["unitList"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["unitChildren"] });
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
|
||||
const relate = useMutation({
|
||||
mutationFn: ({
|
||||
payload,
|
||||
}: {
|
||||
payload: RelateUnitToUnitPayload;
|
||||
successCallback?: () => void;
|
||||
}) => relateUnitToUnit(payload),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: ["unitList"] });
|
||||
queryClient.invalidateQueries({ queryKey: ["unitChildren"] });
|
||||
variables.successCallback?.();
|
||||
},
|
||||
onError: (error) => {
|
||||
handleError(error);
|
||||
},
|
||||
});
|
||||
return {
|
||||
getList,
|
||||
getAccessibleList,
|
||||
getById,
|
||||
getHierarchy,
|
||||
getEmployees,
|
||||
getChildren,
|
||||
createUnit: create.mutateAsync,
|
||||
isCreating: create.isPending,
|
||||
updateUnit: update.mutateAsync,
|
||||
isUpdating: update.isPending,
|
||||
removeUnit: remove.mutateAsync,
|
||||
isDeleting: remove.isPending,
|
||||
relateUnit: relate.mutateAsync,
|
||||
isRelating: relate.isPending,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
approveUserPosition,
|
||||
fetchUserPositionApprovals,
|
||||
rejectUserPosition,
|
||||
type UserPositionApprovalParams,
|
||||
type UserPositionDecisionPayload,
|
||||
} from "@/user-management/services/api/userPositionApprovalService";
|
||||
|
||||
interface DecisionVariables extends UserPositionDecisionPayload {
|
||||
id: string;
|
||||
}
|
||||
|
||||
const QUERY_KEY = "user-position-approvals";
|
||||
|
||||
export const useUserPositionApprovals = (
|
||||
params: UserPositionApprovalParams = {},
|
||||
) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const approvalsQuery = useQuery({
|
||||
queryKey: [QUERY_KEY, params],
|
||||
queryFn: () => fetchUserPositionApprovals(params),
|
||||
});
|
||||
|
||||
const invalidateList = () =>
|
||||
queryClient.invalidateQueries({ queryKey: [QUERY_KEY] });
|
||||
|
||||
const approveMutation = useMutation({
|
||||
mutationFn: ({ id, comment }: DecisionVariables) =>
|
||||
approveUserPosition(id, { comment }),
|
||||
onSuccess: () => {
|
||||
toast.success("User position approved successfully");
|
||||
invalidateList();
|
||||
},
|
||||
onError: () => toast.error("Failed to approve user position"),
|
||||
});
|
||||
|
||||
const rejectMutation = useMutation({
|
||||
mutationFn: ({ id, comment }: DecisionVariables) =>
|
||||
rejectUserPosition(id, { comment }),
|
||||
onSuccess: () => {
|
||||
toast.success("User position rejected successfully");
|
||||
invalidateList();
|
||||
},
|
||||
onError: () => toast.error("Failed to reject user position"),
|
||||
});
|
||||
|
||||
return { approvalsQuery, approveMutation, rejectMutation };
|
||||
};
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
approveUserPosition,
|
||||
fetchUserPositionApprovals,
|
||||
rejectUserPosition,
|
||||
type UserPositionApprovalParams,
|
||||
type UserPositionDecisionPayload,
|
||||
} from "@/user-management/services/api/userPositionApprovalService";
|
||||
|
||||
interface DecisionVariables extends UserPositionDecisionPayload {
|
||||
id: string;
|
||||
}
|
||||
|
||||
const QUERY_KEY = "user-position-approvals";
|
||||
|
||||
export const useUserPositionApprovals = (
|
||||
params: UserPositionApprovalParams = {},
|
||||
) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const approvalsQuery = useQuery({
|
||||
queryKey: [QUERY_KEY, params],
|
||||
queryFn: () => fetchUserPositionApprovals(params),
|
||||
});
|
||||
|
||||
const invalidateList = () =>
|
||||
queryClient.invalidateQueries({ queryKey: [QUERY_KEY] });
|
||||
|
||||
const approveMutation = useMutation({
|
||||
mutationFn: ({ id, comment }: DecisionVariables) =>
|
||||
approveUserPosition(id, { comment }),
|
||||
onSuccess: () => {
|
||||
toast.success("User position approved successfully");
|
||||
invalidateList();
|
||||
},
|
||||
onError: () => toast.error("Failed to approve user position"),
|
||||
});
|
||||
|
||||
const rejectMutation = useMutation({
|
||||
mutationFn: ({ id, comment }: DecisionVariables) =>
|
||||
rejectUserPosition(id, { comment }),
|
||||
onSuccess: () => {
|
||||
toast.success("User position rejected successfully");
|
||||
invalidateList();
|
||||
},
|
||||
onError: () => toast.error("Failed to reject user position"),
|
||||
});
|
||||
|
||||
return { approvalsQuery, approveMutation, rejectMutation };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user