Files
edr-platform/apps/edr-freight-web/backoffice/src/hooks/rule-engine/useRuleEngine.ts
ghost2023 c2145b48f5 fix
2026-06-03 15:31:29 +03:00

169 lines
4.8 KiB
TypeScript

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import toast from "react-hot-toast";
import { api } from "@/services/api";
import type { RuleEngineListParams } from "@/services/ruleEngine/ruleEngine.service";
import { RULE_ENGINE_SELECT_NONE } from "@/pages/ruleEngine/config/resources";
import type {
ApproveRatePayload,
RuleEngineRecord,
RuleEngineResourceSlug,
} from "@/types/rule-engine";
import { QUERY_KEYS } from "@/constants/TANSTACK_QUEY_KEY";
const CARGO_TYPE_PARENT_PAGE_SIZE = 500;
const CONTAINER_TYPE_OPTIONS_PAGE_SIZE = 500;
const listKey = (resource: RuleEngineResourceSlug) =>
["rule-engine", resource] as const;
export const useRuleEngineList = (
resource: RuleEngineResourceSlug,
params: RuleEngineListParams,
) =>
useQuery(
api.ruleEngine.list.queryOptions({
input: { resource, params },
}),
);
export const useCargoTypeParentOptions = (excludeId?: string, enabled = true) =>
useQuery({
queryKey: api.ruleEngine.list.queryKey({
resource: "cargo-types",
params: { page: 1, pageSize: CARGO_TYPE_PARENT_PAGE_SIZE },
}),
queryFn: () =>
api.ruleEngine.list.call({
resource: "cargo-types",
params: { page: 1, pageSize: CARGO_TYPE_PARENT_PAGE_SIZE },
}),
enabled,
select: (result) => {
const noneOption = { label: "None", value: RULE_ENGINE_SELECT_NONE };
const parents = (result.data ?? [])
.filter((row) => row.id && String(row.id) !== excludeId)
.map((row) => {
const name = String(row.cargoTypeName ?? "").trim();
const code = String(row.code ?? "").trim();
const label =
name && code ? `${name} (${code})` : name || code || String(row.id);
return { label, value: String(row.id) };
});
return [noneOption, ...parents];
},
});
export const useContainerTypeOptions = (enabled = true) =>
useQuery({
queryKey: [
...QUERY_KEYS.RULE_ENGINE.list("container-types"),
"select-options",
],
queryFn: () =>
api.ruleEngine.list.call({
resource: "container-types",
params: {
page: 1,
pageSize: CONTAINER_TYPE_OPTIONS_PAGE_SIZE,
},
}),
enabled,
select: (result) => {
const noneOption = { label: "None", value: RULE_ENGINE_SELECT_NONE };
const options = (result.data ?? []).map((row) => {
const label = String(row.label ?? "").trim();
const code = String(row.code ?? "").trim();
const size = row.sizeFt ? `${String(row.sizeFt)}ft` : "";
const parts = [label || code || String(row.id), size].filter(Boolean);
return {
label: parts.join(" - "),
value: String(row.id),
};
});
return [noneOption, ...options];
},
});
export const useApprovalChain = (enabled: boolean) =>
useQuery(
api.ruleEngine.getApprovalChain.queryOptions({
enabled,
}),
);
export const useRuleEngineMutations = (resource: RuleEngineResourceSlug) => {
const qc = useQueryClient();
const invalidate = () =>
qc.invalidateQueries({ queryKey: listKey(resource) });
const create = useMutation({
mutationFn: (payload: Record<string, unknown>) =>
api.ruleEngine.create.call({ resource, payload }),
onSuccess: () => {
toast.success("Created successfully");
invalidate();
},
onError: () => toast.error("Failed to create record"),
});
const update = useMutation({
mutationFn: ({
id,
payload,
}: {
id: string;
payload: Record<string, unknown>;
}) => api.ruleEngine.update.call({ resource, id, payload }),
onSuccess: () => {
toast.success("Updated successfully");
invalidate();
},
onError: () => toast.error("Failed to update record"),
});
const remove = useMutation({
mutationFn: (id: string) => api.ruleEngine.remove.call({ resource, id }),
onSuccess: () => {
toast.success("Deleted successfully");
invalidate();
},
onError: () => toast.error("Failed to delete record"),
});
return { create, update, remove };
};
export const useRateWorkflow = () => {
const qc = useQueryClient();
const invalidate = () => qc.invalidateQueries({ queryKey: listKey("rates") });
const submit = useMutation({
mutationFn: (id: string) => api.ruleEngine.submitRate.call({ id }),
onSuccess: () => {
toast.success("Rate submitted for approval");
invalidate();
},
onError: () => toast.error("Failed to submit rate"),
});
const approve = useMutation({
mutationFn: ({
id,
payload,
}: {
id: string;
payload: ApproveRatePayload;
}) => api.ruleEngine.approveRate.call({ id, payload }),
onSuccess: () => {
toast.success("Rate approved");
invalidate();
},
onError: () => toast.error("Failed to approve rate"),
});
return { submit, approve };
};