mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 01:48:12 +00:00
implement booking flow
This commit is contained in:
@@ -1,41 +1,38 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
|
||||
import { api } from "@/services/api";
|
||||
import type { RuleEngineListParams } from "@/services/ruleEngine/ruleEngine.service";
|
||||
import { ruleEngineService, 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 {
|
||||
invalidateRuleEngineList,
|
||||
patchRuleEngineListRecord,
|
||||
} from "@/utils/queryInvalidation";
|
||||
|
||||
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 },
|
||||
}),
|
||||
);
|
||||
useQuery({
|
||||
queryKey: QUERY_KEYS.RULE_ENGINE.list(resource, params),
|
||||
queryFn: () => ruleEngineService.list(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 },
|
||||
}),
|
||||
queryKey: QUERY_KEYS.RULE_ENGINE.selectOptions("cargo-types"),
|
||||
queryFn: () =>
|
||||
api.ruleEngine.list.call({
|
||||
resource: "cargo-types",
|
||||
params: { page: 1, pageSize: CARGO_TYPE_PARENT_PAGE_SIZE },
|
||||
ruleEngineService.list<RuleEngineRecord>("cargo-types", {
|
||||
page: 1,
|
||||
pageSize: CARGO_TYPE_PARENT_PAGE_SIZE,
|
||||
}),
|
||||
enabled,
|
||||
select: (result) => {
|
||||
@@ -55,54 +52,90 @@ export const useCargoTypeParentOptions = (excludeId?: string, enabled = true) =>
|
||||
},
|
||||
});
|
||||
|
||||
export const useContainerTypeOptions = (enabled = true) =>
|
||||
export function buildContainerTypeSelectOptions(
|
||||
rows: RuleEngineRecord[],
|
||||
includeNone: boolean,
|
||||
): { label: string; value: string }[] {
|
||||
const options = rows
|
||||
.filter((row) => row.id)
|
||||
.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),
|
||||
};
|
||||
});
|
||||
|
||||
if (!includeNone) return options;
|
||||
return [{ label: "None", value: RULE_ENGINE_SELECT_NONE }, ...options];
|
||||
}
|
||||
|
||||
export const useContainerTypeOptions = (
|
||||
includeNone = true,
|
||||
enabled = true,
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: [
|
||||
...QUERY_KEYS.RULE_ENGINE.list("container-types"),
|
||||
"select-options",
|
||||
],
|
||||
queryKey: QUERY_KEYS.RULE_ENGINE.selectOptions("container-types", {
|
||||
includeNone,
|
||||
}),
|
||||
queryFn: () =>
|
||||
ruleEngineService.list<RuleEngineRecord>("container-types", {
|
||||
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);
|
||||
select: (result) =>
|
||||
buildContainerTypeSelectOptions(result.data ?? [], includeNone),
|
||||
});
|
||||
|
||||
return {
|
||||
label: parts.join(" - "),
|
||||
value: String(row.id),
|
||||
};
|
||||
});
|
||||
const LIVE_RATE_PAGE_SIZE = 500;
|
||||
|
||||
return [noneOption, ...options];
|
||||
},
|
||||
export const useLiveRateOptions = (enabled = true) =>
|
||||
useQuery({
|
||||
queryKey: QUERY_KEYS.RULE_ENGINE.selectOptions("rates", { status: "LIVE" }),
|
||||
queryFn: () =>
|
||||
ruleEngineService.list<RuleEngineRecord>("rates", {
|
||||
page: 1,
|
||||
pageSize: LIVE_RATE_PAGE_SIZE,
|
||||
status: "LIVE",
|
||||
}),
|
||||
enabled,
|
||||
select: (result) =>
|
||||
(result.data ?? [])
|
||||
.filter((row) => row.id)
|
||||
.map((row) => {
|
||||
const rateType = String(row.rateType ?? "").replace(/_/g, " ");
|
||||
const currency = String(row.currency ?? "");
|
||||
const value = row.rateValue != null ? String(row.rateValue) : "";
|
||||
const unit = row.rateUnit ? String(row.rateUnit).replace(/_/g, " ") : "";
|
||||
const parts = [rateType, currency, value, unit].filter(Boolean);
|
||||
return {
|
||||
label: parts.join(" · "),
|
||||
value: String(row.id),
|
||||
};
|
||||
}),
|
||||
});
|
||||
|
||||
export const useApprovalChain = (enabled: boolean) =>
|
||||
useQuery(
|
||||
api.ruleEngine.getApprovalChain.queryOptions({
|
||||
enabled,
|
||||
}),
|
||||
);
|
||||
useQuery({
|
||||
queryKey: QUERY_KEYS.RULE_ENGINE.chain,
|
||||
queryFn: () => ruleEngineService.getApprovalChain(),
|
||||
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: () => {
|
||||
onSuccess: async (created) => {
|
||||
toast.success("Created successfully");
|
||||
invalidate();
|
||||
patchRuleEngineListRecord(qc, resource, created);
|
||||
await invalidateRuleEngineList(qc, resource);
|
||||
},
|
||||
onError: () => toast.error("Failed to create record"),
|
||||
});
|
||||
@@ -115,9 +148,10 @@ export const useRuleEngineMutations = (resource: RuleEngineResourceSlug) => {
|
||||
id: string;
|
||||
payload: Record<string, unknown>;
|
||||
}) => api.ruleEngine.update.call({ resource, id, payload }),
|
||||
onSuccess: () => {
|
||||
onSuccess: async (updated) => {
|
||||
toast.success("Updated successfully");
|
||||
invalidate();
|
||||
patchRuleEngineListRecord(qc, resource, updated);
|
||||
await invalidateRuleEngineList(qc, resource);
|
||||
},
|
||||
onError: () => toast.error("Failed to update record"),
|
||||
});
|
||||
@@ -125,9 +159,9 @@ export const useRuleEngineMutations = (resource: RuleEngineResourceSlug) => {
|
||||
const remove = useMutation({
|
||||
mutationFn: (id: string) =>
|
||||
api.ruleEngine.remove.call({ resource, id }),
|
||||
onSuccess: () => {
|
||||
onSuccess: async () => {
|
||||
toast.success("Deleted successfully");
|
||||
invalidate();
|
||||
await invalidateRuleEngineList(qc, resource);
|
||||
},
|
||||
onError: () => toast.error("Failed to delete record"),
|
||||
});
|
||||
@@ -137,29 +171,23 @@ export const useRuleEngineMutations = (resource: RuleEngineResourceSlug) => {
|
||||
|
||||
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: () => {
|
||||
onSuccess: async (updated) => {
|
||||
toast.success("Rate submitted for approval");
|
||||
invalidate();
|
||||
patchRuleEngineListRecord(qc, "rates", updated);
|
||||
await invalidateRuleEngineList(qc, "rates");
|
||||
},
|
||||
onError: () => toast.error("Failed to submit rate"),
|
||||
});
|
||||
|
||||
const approve = useMutation({
|
||||
mutationFn: ({
|
||||
id,
|
||||
payload,
|
||||
}: {
|
||||
id: string;
|
||||
payload: ApproveRatePayload;
|
||||
}) => api.ruleEngine.approveRate.call({ id, payload }),
|
||||
onSuccess: () => {
|
||||
mutationFn: (id: string) => api.ruleEngine.approveRate.call({ id }),
|
||||
onSuccess: async (updated) => {
|
||||
toast.success("Rate approved");
|
||||
invalidate();
|
||||
patchRuleEngineListRecord(qc, "rates", updated);
|
||||
await invalidateRuleEngineList(qc, "rates");
|
||||
},
|
||||
onError: () => toast.error("Failed to approve rate"),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user