diff --git a/apps/edr-freight-web/portal/src/components/dynamic-select/DynamicSelect.tsx b/apps/edr-freight-web/portal/src/components/dynamic-select/DynamicSelect.tsx
new file mode 100644
index 000000000..2003457f0
--- /dev/null
+++ b/apps/edr-freight-web/portal/src/components/dynamic-select/DynamicSelect.tsx
@@ -0,0 +1,99 @@
+import { useQuery } from "@tanstack/react-query";
+import { cn } from "@/lib/utils";
+import { api } from "@/services/api";
+import { Loader2, AlertCircle } from "lucide-react";
+import * as React from "react";
+
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@edr/ui-common";
+
+export interface DynamicSelectProps {
+ code: string;
+ placeholder?: string;
+ value?: string;
+ onValueChange?: (value: string) => void;
+ disabled?: boolean;
+ className?: string;
+}
+
+export function DynamicSelect({
+ code,
+ placeholder,
+ value,
+ onValueChange,
+ disabled,
+ className,
+}: DynamicSelectProps) {
+ const { data, isLoading, isError } = useQuery(
+ api.dropdownSettings.getByCode.queryOptions({ input: { code } }),
+ );
+
+ if (isLoading) {
+ return (
+
+
+ Loading...
+
+ );
+ }
+
+ if (isError || !data) {
+ return (
+
+
+ Failed to load options
+
+ );
+ }
+
+ const options = [...data.children].sort((a, b) => a.order - b.order);
+
+ return (
+
+ );
+}
diff --git a/apps/edr-freight-web/portal/src/components/dynamic-select/index.ts b/apps/edr-freight-web/portal/src/components/dynamic-select/index.ts
new file mode 100644
index 000000000..4e6c58b62
--- /dev/null
+++ b/apps/edr-freight-web/portal/src/components/dynamic-select/index.ts
@@ -0,0 +1,2 @@
+export { DynamicSelect } from "./DynamicSelect";
+export type { DynamicSelectProps } from "./DynamicSelect";
diff --git a/apps/edr-freight-web/portal/src/services/api.ts b/apps/edr-freight-web/portal/src/services/api.ts
index 999bf6ced..e368ed675 100644
--- a/apps/edr-freight-web/portal/src/services/api.ts
+++ b/apps/edr-freight-web/portal/src/services/api.ts
@@ -12,6 +12,15 @@ import { bookingsService } from "./bookings.service";
import { consignmentsService } from "./consignments.service";
import { trackingService } from "./tracking.service";
import { fileUploadSettingsService } from "./fileUploadSettings.service";
+import { dropdownSettingsService } from "./dropdownSettings.service";
+import {
+ CreateDropdownOptionDto,
+ CreateDropdownSettingDto,
+ DropdownOption,
+ DropdownSetting,
+ UpdateDropdownOptionDto,
+ UpdateDropdownSettingDto,
+} from "@/types/dropdownSettings";
// ---------------------------------------------------------------------------
// API definition
@@ -135,4 +144,69 @@ export const api = {
({ fieldId }) => fileUploadSettingsService.removeField(fieldId),
),
},
+
+ dropdownSettings: {
+ list: endpoint(
+ "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(
+ "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),
+ ),
+ },
};