refactor(api): Introduce unified API layer for freight backoffice

This commit is contained in:
ghost2023
2026-06-02 14:43:18 +03:00
parent 169e49faae
commit 34bf4ade48
12 changed files with 376 additions and 230 deletions

View File

@@ -1,16 +0,0 @@
import { useQuery } from "@tanstack/react-query";
import { bookingsService } from "../services/bookings.service";
export const useBookings = () =>
useQuery({
queryKey: ["bookings"],
queryFn: bookingsService.list,
});
export const useBooking = (id: string) =>
useQuery({
queryKey: ["bookings", id],
queryFn: () => bookingsService.get(id),
enabled: Boolean(id),
});

View File

@@ -1,16 +0,0 @@
import { useQuery } from "@tanstack/react-query";
import { consignmentsService } from "../services/consignments.service";
export const useConsignments = () =>
useQuery({
queryKey: ["consignments"],
queryFn: consignmentsService.list,
});
export const useConsignment = (id: string) =>
useQuery({
queryKey: ["consignments", id],
queryFn: () => consignmentsService.get(id),
enabled: Boolean(id),
});

View File

@@ -1,50 +0,0 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { customersService } from "@/services/customers.service";
import type {
CreateCustomerDto,
UpdateCustomerDto,
} from "@/types/customers";
const KEY = ["customers"] as const;
export const useCustomers = () =>
useQuery({
queryKey: KEY,
queryFn: customersService.list,
});
export const useCustomer = (id: string | undefined) =>
useQuery({
queryKey: [...KEY, "id", id],
queryFn: () => customersService.getById(id!),
enabled: Boolean(id),
});
export const useCreateCustomer = () => {
const qc = useQueryClient();
return useMutation({
mutationFn: (dto: CreateCustomerDto) => customersService.create(dto),
onSuccess: () => qc.invalidateQueries({ queryKey: KEY }),
});
};
export const useUpdateCustomer = () => {
const qc = useQueryClient();
return useMutation({
mutationFn: ({ id, dto }: { id: string; dto: UpdateCustomerDto }) =>
customersService.update(id, dto),
onSuccess: (_data, { id }) => {
qc.invalidateQueries({ queryKey: KEY });
qc.invalidateQueries({ queryKey: [...KEY, "id", id] });
},
});
};
export const useDeleteCustomer = () => {
const qc = useQueryClient();
return useMutation({
mutationFn: (id: string) => customersService.remove(id),
onSuccess: () => qc.invalidateQueries({ queryKey: KEY }),
});
};

View File

@@ -1,10 +0,0 @@
import { useQuery } from "@tanstack/react-query";
import { trackingService } from "../services/tracking.service";
export const useTracking = (consignmentId: string) =>
useQuery({
queryKey: ["tracking", consignmentId],
queryFn: () => trackingService.forConsignment(consignmentId),
enabled: Boolean(consignmentId),
});

View File

@@ -1,11 +1,8 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { QUERY_KEYS } from "@/constants/TANSTACK_QUEY_KEY"; import { api } from "@/services/api";
import { import type { RuleEngineListParams } from "@/services/ruleEngine/ruleEngine.service";
ruleEngineService,
type RuleEngineListParams,
} from "@/services/ruleEngine/ruleEngine.service";
import { RULE_ENGINE_SELECT_NONE } from "@/pages/ruleEngine/config/resources"; import { RULE_ENGINE_SELECT_NONE } from "@/pages/ruleEngine/config/resources";
import type { import type {
ApproveRatePayload, ApproveRatePayload,
@@ -15,26 +12,29 @@ import type {
const CARGO_TYPE_PARENT_PAGE_SIZE = 500; const CARGO_TYPE_PARENT_PAGE_SIZE = 500;
const listKey = (resource: RuleEngineResourceSlug) =>
["rule-engine", resource] as const;
export const useRuleEngineList = ( export const useRuleEngineList = (
resource: RuleEngineResourceSlug, resource: RuleEngineResourceSlug,
params: RuleEngineListParams, params: RuleEngineListParams,
) => ) =>
useQuery({ useQuery(
queryKey: [...QUERY_KEYS.RULE_ENGINE.list(resource), params], api.ruleEngine.list.queryOptions({
queryFn: () => ruleEngineService.list<RuleEngineRecord>(resource, params), input: { resource, params },
}); }),
);
export const useCargoTypeParentOptions = (excludeId?: string, enabled = true) => export const useCargoTypeParentOptions = (excludeId?: string, enabled = true) =>
useQuery({ useQuery({
queryKey: [ queryKey: api.ruleEngine.list.queryKey({
...QUERY_KEYS.RULE_ENGINE.list("cargo-types"), resource: "cargo-types",
"parent-options", params: { page: 1, pageSize: CARGO_TYPE_PARENT_PAGE_SIZE },
excludeId ?? "", }),
],
queryFn: () => queryFn: () =>
ruleEngineService.list<RuleEngineRecord>("cargo-types", { api.ruleEngine.list.call({
page: 1, resource: "cargo-types",
pageSize: CARGO_TYPE_PARENT_PAGE_SIZE, params: { page: 1, pageSize: CARGO_TYPE_PARENT_PAGE_SIZE },
}), }),
enabled, enabled,
select: (result) => { select: (result) => {
@@ -45,7 +45,9 @@ export const useCargoTypeParentOptions = (excludeId?: string, enabled = true) =>
const name = String(row.cargoTypeName ?? "").trim(); const name = String(row.cargoTypeName ?? "").trim();
const code = String(row.code ?? "").trim(); const code = String(row.code ?? "").trim();
const label = const label =
name && code ? `${name} (${code})` : name || code || String(row.id); name && code
? `${name} (${code})`
: name || code || String(row.id);
return { label, value: String(row.id) }; return { label, value: String(row.id) };
}); });
return [noneOption, ...parents]; return [noneOption, ...parents];
@@ -53,20 +55,20 @@ export const useCargoTypeParentOptions = (excludeId?: string, enabled = true) =>
}); });
export const useApprovalChain = (enabled: boolean) => export const useApprovalChain = (enabled: boolean) =>
useQuery({ useQuery(
queryKey: QUERY_KEYS.RULE_ENGINE.chain, api.ruleEngine.getApprovalChain.queryOptions({
queryFn: () => ruleEngineService.getApprovalChain(), enabled,
enabled, }),
}); );
export const useRuleEngineMutations = (resource: RuleEngineResourceSlug) => { export const useRuleEngineMutations = (resource: RuleEngineResourceSlug) => {
const qc = useQueryClient(); const qc = useQueryClient();
const invalidate = () => const invalidate = () =>
qc.invalidateQueries({ queryKey: QUERY_KEYS.RULE_ENGINE.list(resource) }); qc.invalidateQueries({ queryKey: listKey(resource) });
const create = useMutation({ const create = useMutation({
mutationFn: (payload: Record<string, unknown>) => mutationFn: (payload: Record<string, unknown>) =>
ruleEngineService.create(resource, payload), api.ruleEngine.create.call({ resource, payload }),
onSuccess: () => { onSuccess: () => {
toast.success("Created successfully"); toast.success("Created successfully");
invalidate(); invalidate();
@@ -81,7 +83,7 @@ export const useRuleEngineMutations = (resource: RuleEngineResourceSlug) => {
}: { }: {
id: string; id: string;
payload: Record<string, unknown>; payload: Record<string, unknown>;
}) => ruleEngineService.update(resource, id, payload), }) => api.ruleEngine.update.call({ resource, id, payload }),
onSuccess: () => { onSuccess: () => {
toast.success("Updated successfully"); toast.success("Updated successfully");
invalidate(); invalidate();
@@ -90,7 +92,8 @@ export const useRuleEngineMutations = (resource: RuleEngineResourceSlug) => {
}); });
const remove = useMutation({ const remove = useMutation({
mutationFn: (id: string) => ruleEngineService.remove(resource, id), mutationFn: (id: string) =>
api.ruleEngine.remove.call({ resource, id }),
onSuccess: () => { onSuccess: () => {
toast.success("Deleted successfully"); toast.success("Deleted successfully");
invalidate(); invalidate();
@@ -104,10 +107,10 @@ export const useRuleEngineMutations = (resource: RuleEngineResourceSlug) => {
export const useRateWorkflow = () => { export const useRateWorkflow = () => {
const qc = useQueryClient(); const qc = useQueryClient();
const invalidate = () => const invalidate = () =>
qc.invalidateQueries({ queryKey: QUERY_KEYS.RULE_ENGINE.list("rates") }); qc.invalidateQueries({ queryKey: listKey("rates") });
const submit = useMutation({ const submit = useMutation({
mutationFn: (id: string) => ruleEngineService.submitRate(id), mutationFn: (id: string) => api.ruleEngine.submitRate.call({ id }),
onSuccess: () => { onSuccess: () => {
toast.success("Rate submitted for approval"); toast.success("Rate submitted for approval");
invalidate(); invalidate();
@@ -116,8 +119,13 @@ export const useRateWorkflow = () => {
}); });
const approve = useMutation({ const approve = useMutation({
mutationFn: ({ id, payload }: { id: string; payload: ApproveRatePayload }) => mutationFn: ({
ruleEngineService.approveRate(id, payload), id,
payload,
}: {
id: string;
payload: ApproveRatePayload;
}) => api.ruleEngine.approveRate.call({ id, payload }),
onSuccess: () => { onSuccess: () => {
toast.success("Rate approved"); toast.success("Rate approved");
invalidate(); invalidate();

View File

@@ -1,6 +1,6 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQueryClient } from "@tanstack/react-query";
import { dropdownSettingsService } from "@/services/dropdownSettings.service"; import { api } from "@/services/api";
import type { import type {
CreateDropdownOptionDto, CreateDropdownOptionDto,
CreateDropdownSettingDto, CreateDropdownSettingDto,
@@ -8,38 +8,15 @@ import type {
UpdateDropdownSettingDto, UpdateDropdownSettingDto,
} from "@/types/dropdownSettings"; } from "@/types/dropdownSettings";
const KEY = ["dropdown-settings"] as const;
/* ------------------------------ Queries ------------------------------ */
export const useDropdownSettings = () =>
useQuery({
queryKey: KEY,
queryFn: dropdownSettingsService.list,
});
export const useDropdownSetting = (id: string) =>
useQuery({
queryKey: [...KEY, "id", id],
queryFn: () => dropdownSettingsService.getById(id),
enabled: Boolean(id),
});
export const useDropdownSettingByCode = (code: string) =>
useQuery({
queryKey: [...KEY, "code", code],
queryFn: () => dropdownSettingsService.getByCode(code),
enabled: Boolean(code),
});
/* ----------------------------- Mutations ----------------------------- */ /* ----------------------------- Mutations ----------------------------- */
export const useCreateDropdownSetting = () => { export const useCreateDropdownSetting = () => {
const qc = useQueryClient(); const qc = useQueryClient();
return useMutation({ return useMutation({
mutationFn: (dto: CreateDropdownSettingDto) => mutationFn: (dto: CreateDropdownSettingDto) =>
dropdownSettingsService.create(dto), api.dropdownSettings.create.call(dto),
onSuccess: () => qc.invalidateQueries({ queryKey: KEY }), onSuccess: () =>
qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() }),
}); });
}; };
@@ -52,10 +29,12 @@ export const useUpdateDropdownSetting = () => {
}: { }: {
id: string; id: string;
dto: UpdateDropdownSettingDto; dto: UpdateDropdownSettingDto;
}) => dropdownSettingsService.update(id, dto), }) => api.dropdownSettings.update.call({ id, dto }),
onSuccess: (_data, { id }) => { onSuccess: (_data, { id }) => {
qc.invalidateQueries({ queryKey: KEY }); qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() });
qc.invalidateQueries({ queryKey: [...KEY, "id", id] }); qc.invalidateQueries({
queryKey: api.dropdownSettings.getById.queryKey({ id }),
});
}, },
}); });
}; };
@@ -63,8 +42,9 @@ export const useUpdateDropdownSetting = () => {
export const useDeleteDropdownSetting = () => { export const useDeleteDropdownSetting = () => {
const qc = useQueryClient(); const qc = useQueryClient();
return useMutation({ return useMutation({
mutationFn: (id: string) => dropdownSettingsService.remove(id), mutationFn: (id: string) => api.dropdownSettings.remove.call({ id }),
onSuccess: () => qc.invalidateQueries({ queryKey: KEY }), onSuccess: () =>
qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() }),
}); });
}; };
@@ -77,10 +57,12 @@ export const useReplaceDropdownOptions = () => {
}: { }: {
settingId: string; settingId: string;
options: CreateDropdownOptionDto[]; options: CreateDropdownOptionDto[];
}) => dropdownSettingsService.replaceOptions(settingId, options), }) => api.dropdownSettings.replaceOptions.call({ id: settingId, options }),
onSuccess: (_data, { settingId }) => { onSuccess: (_data, { settingId }) => {
qc.invalidateQueries({ queryKey: KEY }); qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() });
qc.invalidateQueries({ queryKey: [...KEY, "id", settingId] }); qc.invalidateQueries({
queryKey: api.dropdownSettings.getById.queryKey({ id: settingId }),
});
}, },
}); });
}; };
@@ -94,10 +76,12 @@ export const useAddDropdownOption = () => {
}: { }: {
settingId: string; settingId: string;
dto: CreateDropdownOptionDto; dto: CreateDropdownOptionDto;
}) => dropdownSettingsService.addOption(settingId, dto), }) => api.dropdownSettings.addOption.call({ id: settingId, dto }),
onSuccess: (_data, { settingId }) => { onSuccess: (_data, { settingId }) => {
qc.invalidateQueries({ queryKey: KEY }); qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() });
qc.invalidateQueries({ queryKey: [...KEY, "id", settingId] }); qc.invalidateQueries({
queryKey: api.dropdownSettings.getById.queryKey({ id: settingId }),
});
}, },
}); });
}; };
@@ -111,8 +95,9 @@ export const useUpdateDropdownOption = () => {
}: { }: {
optionId: string; optionId: string;
dto: UpdateDropdownOptionDto; dto: UpdateDropdownOptionDto;
}) => dropdownSettingsService.updateOption(optionId, dto), }) => api.dropdownSettings.updateOption.call({ optionId, dto }),
onSuccess: () => qc.invalidateQueries({ queryKey: KEY }), onSuccess: () =>
qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() }),
}); });
}; };
@@ -120,7 +105,8 @@ export const useRemoveDropdownOption = () => {
const qc = useQueryClient(); const qc = useQueryClient();
return useMutation({ return useMutation({
mutationFn: (optionId: string) => mutationFn: (optionId: string) =>
dropdownSettingsService.removeOption(optionId), api.dropdownSettings.removeOption.call({ optionId }),
onSuccess: () => qc.invalidateQueries({ queryKey: KEY }), onSuccess: () =>
qc.invalidateQueries({ queryKey: api.dropdownSettings.list.queryKey() }),
}); });
}; };

View File

@@ -1,6 +1,6 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQueryClient } from "@tanstack/react-query";
import { fileUploadSettingsService } from "@/services/fileUploadSettings.service"; import { api } from "@/services/api";
import type { import type {
CreateFileUploadFieldDto, CreateFileUploadFieldDto,
CreateFileUploadSettingDto, CreateFileUploadSettingDto,
@@ -8,38 +8,17 @@ import type {
UpdateFileUploadSettingDto, UpdateFileUploadSettingDto,
} from "@/types/fileUploadSettings"; } from "@/types/fileUploadSettings";
const KEY = ["file-upload-settings"] as const;
/* ------------------------------ Queries ------------------------------ */
export const useFileUploadSettings = () =>
useQuery({
queryKey: KEY,
queryFn: fileUploadSettingsService.list,
});
export const useFileUploadSetting = (id: string) =>
useQuery({
queryKey: [...KEY, "id", id],
queryFn: () => fileUploadSettingsService.getById(id),
enabled: Boolean(id),
});
export const useFileUploadSettingByCode = (code: string) =>
useQuery({
queryKey: [...KEY, "code", code],
queryFn: () => fileUploadSettingsService.getByCode(code),
enabled: Boolean(code),
});
/* ----------------------------- Mutations ----------------------------- */ /* ----------------------------- Mutations ----------------------------- */
export const useCreateFileUploadSetting = () => { export const useCreateFileUploadSetting = () => {
const qc = useQueryClient(); const qc = useQueryClient();
return useMutation({ return useMutation({
mutationFn: (dto: CreateFileUploadSettingDto) => mutationFn: (dto: CreateFileUploadSettingDto) =>
fileUploadSettingsService.create(dto), api.fileUploadSettings.create.call(dto),
onSuccess: () => qc.invalidateQueries({ queryKey: KEY }), onSuccess: () =>
qc.invalidateQueries({
queryKey: api.fileUploadSettings.list.queryKey(),
}),
}); });
}; };
@@ -52,10 +31,14 @@ export const useUpdateFileUploadSetting = () => {
}: { }: {
id: string; id: string;
dto: UpdateFileUploadSettingDto; dto: UpdateFileUploadSettingDto;
}) => fileUploadSettingsService.update(id, dto), }) => api.fileUploadSettings.update.call({ id, dto }),
onSuccess: (_data, { id }) => { onSuccess: (_data, { id }) => {
qc.invalidateQueries({ queryKey: KEY }); qc.invalidateQueries({
qc.invalidateQueries({ queryKey: [...KEY, "id", id] }); queryKey: api.fileUploadSettings.list.queryKey(),
});
qc.invalidateQueries({
queryKey: api.fileUploadSettings.getById.queryKey({ id }),
});
}, },
}); });
}; };
@@ -63,8 +46,11 @@ export const useUpdateFileUploadSetting = () => {
export const useDeleteFileUploadSetting = () => { export const useDeleteFileUploadSetting = () => {
const qc = useQueryClient(); const qc = useQueryClient();
return useMutation({ return useMutation({
mutationFn: (id: string) => fileUploadSettingsService.remove(id), mutationFn: (id: string) => api.fileUploadSettings.remove.call({ id }),
onSuccess: () => qc.invalidateQueries({ queryKey: KEY }), onSuccess: () =>
qc.invalidateQueries({
queryKey: api.fileUploadSettings.list.queryKey(),
}),
}); });
}; };
@@ -77,10 +63,14 @@ export const useReplaceFileUploadFields = () => {
}: { }: {
settingId: string; settingId: string;
fields: CreateFileUploadFieldDto[]; fields: CreateFileUploadFieldDto[];
}) => fileUploadSettingsService.replaceFields(settingId, fields), }) => api.fileUploadSettings.replaceFields.call({ id: settingId, fields }),
onSuccess: (_data, { settingId }) => { onSuccess: (_data, { settingId }) => {
qc.invalidateQueries({ queryKey: KEY }); qc.invalidateQueries({
qc.invalidateQueries({ queryKey: [...KEY, "id", settingId] }); queryKey: api.fileUploadSettings.list.queryKey(),
});
qc.invalidateQueries({
queryKey: api.fileUploadSettings.getById.queryKey({ id: settingId }),
});
}, },
}); });
}; };
@@ -94,10 +84,14 @@ export const useAddFileUploadField = () => {
}: { }: {
settingId: string; settingId: string;
dto: CreateFileUploadFieldDto; dto: CreateFileUploadFieldDto;
}) => fileUploadSettingsService.addField(settingId, dto), }) => api.fileUploadSettings.addField.call({ settingId, dto }),
onSuccess: (_data, { settingId }) => { onSuccess: (_data, { settingId }) => {
qc.invalidateQueries({ queryKey: KEY }); qc.invalidateQueries({
qc.invalidateQueries({ queryKey: [...KEY, "id", settingId] }); queryKey: api.fileUploadSettings.list.queryKey(),
});
qc.invalidateQueries({
queryKey: api.fileUploadSettings.getById.queryKey({ id: settingId }),
});
}, },
}); });
}; };
@@ -111,8 +105,11 @@ export const useUpdateFileUploadField = () => {
}: { }: {
fieldId: string; fieldId: string;
dto: UpdateFileUploadFieldDto; dto: UpdateFileUploadFieldDto;
}) => fileUploadSettingsService.updateField(fieldId, dto), }) => api.fileUploadSettings.updateField.call({ fieldId, dto }),
onSuccess: () => qc.invalidateQueries({ queryKey: KEY }), onSuccess: () =>
qc.invalidateQueries({
queryKey: api.fileUploadSettings.list.queryKey(),
}),
}); });
}; };
@@ -120,7 +117,10 @@ export const useRemoveFileUploadField = () => {
const qc = useQueryClient(); const qc = useQueryClient();
return useMutation({ return useMutation({
mutationFn: (fieldId: string) => mutationFn: (fieldId: string) =>
fileUploadSettingsService.removeField(fieldId), api.fileUploadSettings.removeField.call({ fieldId }),
onSuccess: () => qc.invalidateQueries({ queryKey: KEY }), onSuccess: () =>
qc.invalidateQueries({
queryKey: api.fileUploadSettings.list.queryKey(),
}),
}); });
}; };

View File

@@ -20,12 +20,16 @@ import ManageFileUploadFieldsDialog from "./ManageFileUploadFieldsDialog";
import DeleteFileUploadSettingDialog from "./DeleteFileUploadSettingDialog"; import DeleteFileUploadSettingDialog from "./DeleteFileUploadSettingDialog";
import Breadcrumbs from "@/components/ui/Breadcrumbs"; import Breadcrumbs from "@/components/ui/Breadcrumbs";
import { getMinFiles } from "@/types/fileUploadSettings"; import { getMinFiles } from "@/types/fileUploadSettings";
import { useDeleteFileUploadSetting, useFileUploadSettings } from "@/hooks/useFileUploadSettings"; import { useQuery } from "@tanstack/react-query";
import { api } from "@/services/api";
import { useDeleteFileUploadSetting } from "@/hooks/useFileUploadSettings";
export default function FileUploadSettingsPage() { export default function FileUploadSettingsPage() {
const [query, setQuery] = useState(""); const [query, setQuery] = useState("");
const { data, isLoading, isError, error } = useFileUploadSettings(); const { data, isLoading, isError, error } = useQuery(
api.fileUploadSettings.list.queryOptions(),
);
const deleteMutation = useDeleteFileUploadSetting(); const deleteMutation = useDeleteFileUploadSetting();
const fileUploadSettings = useMemo( const fileUploadSettings = useMemo(

View File

@@ -21,10 +21,9 @@ import Breadcrumbs from "@/components/ui/Breadcrumbs";
import EditDropdownSettingDialog from "./EditDropdownSettingDialog"; import EditDropdownSettingDialog from "./EditDropdownSettingDialog";
import ManageDropdownOptionsDialog from "./ManageDropdownOptionsDialog"; import ManageDropdownOptionsDialog from "./ManageDropdownOptionsDialog";
import DeleteDropdownSettingDialog from "./DeleteDropdownSettingDialog"; import DeleteDropdownSettingDialog from "./DeleteDropdownSettingDialog";
import { import { useQuery } from "@tanstack/react-query";
useDeleteDropdownSetting, import { api } from "@/services/api";
useDropdownSettings, import { useDeleteDropdownSetting } from "@/hooks/useDropdownSettings";
} from "@/hooks/useDropdownSettings";
import type { DropdownSetting } from "@/types/dropdownSettings"; import type { DropdownSetting } from "@/types/dropdownSettings";
import { import {
DataTable, DataTable,
@@ -86,7 +85,9 @@ export default function DropdownSettingsPage() {
return () => cancelAnimationFrame(id); return () => cancelAnimationFrame(id);
}, [activeDialog]); }, [activeDialog]);
const { data, isLoading, isError, error } = useDropdownSettings(); const { data, isLoading, isError, error } = useQuery(
api.dropdownSettings.list.queryOptions(),
);
const deleteMutation = useDeleteDropdownSetting(); const deleteMutation = useDeleteDropdownSetting();
const dropdownSettings = useMemo<DropdownSetting[]>( const dropdownSettings = useMemo<DropdownSetting[]>(

View File

@@ -0,0 +1,223 @@
import { endpoint } from "@/utils/endpoint";
import type {
CreateFileUploadFieldDto,
CreateFileUploadSettingDto,
FileUploadField,
FileUploadSetting,
UpdateFileUploadFieldDto,
UpdateFileUploadSettingDto,
} from "@/types/fileUploadSettings";
import {
CreateDropdownOptionDto,
CreateDropdownSettingDto,
DropdownOption,
DropdownSetting,
UpdateDropdownOptionDto,
UpdateDropdownSettingDto,
} from "@/types/dropdownSettings";
import {
ApproveRatePayload,
RuleEngineListResult,
RuleEngineRecord,
RuleEngineResourceSlug,
} from "@/types/rule-engine";
import { fileUploadSettingsService } from "./fileUploadSettings.service";
import { dropdownSettingsService } from "./dropdownSettings.service";
import {
ruleEngineService,
RuleEngineListParams,
} from "./ruleEngine/ruleEngine.service";
export const api = {
fileUploadSettings: {
list: endpoint<void, FileUploadSetting[]>(
"file-upload-settings",
"list",
fileUploadSettingsService.list,
),
getById: endpoint<{ id: string }, FileUploadSetting>(
"file-upload-settings",
"getById",
({ id }) => fileUploadSettingsService.getById(id),
),
getByCode: endpoint<{ code: string }, FileUploadSetting>(
"file-upload-settings",
"getByCode",
({ code }) => fileUploadSettingsService.getByCode(code),
),
create: endpoint<CreateFileUploadSettingDto, FileUploadSetting>(
"file-upload-settings",
"create",
(payload) => fileUploadSettingsService.create(payload),
),
update: endpoint<
{ id: string; dto: UpdateFileUploadSettingDto },
FileUploadSetting
>("file-upload-settings", "update", ({ id, dto }) =>
fileUploadSettingsService.update(id, dto),
),
remove: endpoint<{ id: string }, void>(
"file-upload-settings",
"remove",
({ id }) => fileUploadSettingsService.remove(id),
),
replaceFields: endpoint<
{ id: string; fields: CreateFileUploadFieldDto[] },
FileUploadField[]
>("file-upload-settings", "replaceFields", ({ id, fields }) =>
fileUploadSettingsService.replaceFields(id, fields),
),
addField: endpoint<
{ settingId: string; dto: CreateFileUploadFieldDto },
FileUploadField
>("file-upload-settings", "addField", ({ settingId, dto }) =>
fileUploadSettingsService.addField(settingId, dto),
),
updateField: endpoint<
{ fieldId: string; dto: UpdateFileUploadFieldDto },
FileUploadField
>("file-upload-settings", "updateField", ({ fieldId, dto }) =>
fileUploadSettingsService.updateField(fieldId, dto),
),
removeField: endpoint<{ fieldId: string }, void>(
"file-upload-settings",
"removeField",
({ fieldId }) => fileUploadSettingsService.removeField(fieldId),
),
},
dropdownSettings: {
list: endpoint<void, DropdownSetting[]>(
"dropdown-settings",
"list",
dropdownSettingsService.list,
),
getById: endpoint<{ id: string }, DropdownSetting>(
"dropdown-settings",
"getById",
({ id }) => dropdownSettingsService.getById(id),
),
getByCode: endpoint<{ code: string }, DropdownSetting>(
"dropdown-settings",
"getByCode",
({ code }) => dropdownSettingsService.getByCode(code),
),
create: endpoint<CreateDropdownSettingDto, DropdownSetting>(
"dropdown-settings",
"create",
(payload) => dropdownSettingsService.create(payload),
),
update: endpoint<
{ id: string; dto: UpdateDropdownSettingDto },
DropdownSetting
>("dropdown-settings", "update", ({ id, dto }) =>
dropdownSettingsService.update(id, dto),
),
remove: endpoint<{ id: string }, void>(
"dropdown-settings",
"remove",
({ id }) => dropdownSettingsService.remove(id),
),
replaceOptions: endpoint<
{ id: string; options: CreateDropdownOptionDto[] },
DropdownOption[]
>("dropdown-settings", "replaceOptions", ({ id, options }) =>
dropdownSettingsService.replaceOptions(id, options),
),
addOption: endpoint<
{ id: string; dto: CreateDropdownOptionDto },
DropdownOption
>("dropdown-settings", "addOption", ({ id, dto }) =>
dropdownSettingsService.addOption(id, dto),
),
updateOption: endpoint<
{ optionId: string; dto: UpdateDropdownOptionDto },
DropdownOption
>("dropdown-settings", "updateOption", ({ optionId, dto }) =>
dropdownSettingsService.updateOption(optionId, dto),
),
removeOption: endpoint<{ optionId: string }, void>(
"dropdown-settings",
"removeOption",
({ optionId }) => dropdownSettingsService.removeOption(optionId),
),
},
ruleEngine: {
list: endpoint<
{ resource: RuleEngineResourceSlug; params?: RuleEngineListParams },
RuleEngineListResult<RuleEngineRecord>
>("rule-engine", "list", ({ resource, params }) =>
ruleEngineService.list(resource, params),
),
getById: endpoint<
{ resource: RuleEngineResourceSlug; id: string },
RuleEngineRecord
>("rule-engine", "getById", ({ resource, id }) =>
ruleEngineService.getById(resource, id),
),
create: endpoint<
{ resource: RuleEngineResourceSlug; payload: Record<string, unknown> },
RuleEngineRecord
>("rule-engine", "create", ({ resource, payload }) =>
ruleEngineService.create(resource, payload),
),
update: endpoint<
{
resource: RuleEngineResourceSlug;
id: string;
payload: Record<string, unknown>;
},
RuleEngineRecord
>("rule-engine", "update", ({ resource, id, payload }) =>
ruleEngineService.update(resource, id, payload),
),
remove: endpoint<
{ resource: RuleEngineResourceSlug; id: string },
void
>("rule-engine", "remove", ({ resource, id }) =>
ruleEngineService.remove(resource, id),
),
submitRate: endpoint<{ id: string }, RuleEngineRecord>(
"rule-engine",
"submitRate",
({ id }) => ruleEngineService.submitRate(id),
),
approveRate: endpoint<
{ id: string; payload: ApproveRatePayload },
RuleEngineRecord
>("rule-engine", "approveRate", ({ id, payload }) =>
ruleEngineService.approveRate(id, payload),
),
getApprovalChain: endpoint<void, RuleEngineRecord[]>(
"rule-engine",
"getApprovalChain",
() => ruleEngineService.getApprovalChain(),
),
},
};

View File

@@ -8,10 +8,8 @@ import type {
UpdateFileUploadFieldDto, UpdateFileUploadFieldDto,
UpdateFileUploadSettingDto, UpdateFileUploadSettingDto,
} from "@/types/fileUploadSettings"; } from "@/types/fileUploadSettings";
import { URL_CONSTANTS } from "@/constants/URLS";
import { QUERY_KEYS } from "@/constants/TANSTACK_QUEY_KEY";
import { ApiResponse } from "@/types/apiResponse"; import { ApiResponse } from "@/types/apiResponse";
import { endpoint, unwrap } from "@/utils/endpoint"; import { unwrap } from "@/utils/endpoint";
const BASE = "/file-upload-settings"; const BASE = "/file-upload-settings";
@@ -124,14 +122,3 @@ export const fileUploadSettingsService = {
await client.delete(`${BASE}/fields/${fieldId}`); await client.delete(`${BASE}/fields/${fieldId}`);
}, },
}; };
export const getFileUploadSettingByCode = endpoint<string, FileUploadSetting>(
QUERY_KEYS.FILES.FILE_UPLOAD_SETTINGS,
QUERY_KEYS.FILES.BY_CODE,
(code: any) =>
client
.get<
ApiResponse<FileUploadSetting>
>(`${URL_CONSTANTS.FILES.FILE_UPLOAD_SETTINGS_BY_CODE}/${code}`)
.then((res: any) => res.data.data),
);

View File

@@ -0,0 +1,29 @@
export type Result<T, E = { code: string; message: string; statusCode?: number }> =
| { success: true; data: T }
| { success: false; error: E };
export type ApiError = {
code: string;
message: string;
statusCode?: number;
};
export function extractApiError(err: unknown): ApiError {
if (err && typeof err === "object") {
const obj = err as Record<string, unknown>;
const response = obj.response as Record<string, unknown> | undefined;
if (response) {
const statusCode = response.status as number | undefined;
const data = response.data as Record<string, unknown> | undefined;
return {
code: (data?.error as string) || (data?.message as string) || "api_error",
message: (data?.message as string) || (data?.error as string) || "An unexpected error occurred",
statusCode,
};
}
if (obj.message && typeof obj.message === "string") {
return { code: "client_error", message: obj.message };
}
}
return { code: "unknown_error", message: "An unexpected error occurred" };
}