mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
Merge pull request #27 from Tria-plc/freight/feature/dynamic-dropdown
Implemented the dynamic dropdown
This commit is contained in:
@@ -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 (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex h-9 w-full items-center gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm text-muted-foreground",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Loader2 className="size-4 animate-spin" />
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isError || !data) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex h-9 w-full items-center gap-2 rounded-md border border-destructive/50 bg-destructive/10 px-3 py-2 text-sm text-destructive",
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<AlertCircle className="size-4 shrink-0" />
|
||||||
|
Failed to load options
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = [...data.children].sort((a, b) => a.order - b.order);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
value={value}
|
||||||
|
onValueChange={onValueChange}
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
|
<SelectTrigger className={cn("w-full", className)}>
|
||||||
|
<SelectValue placeholder={placeholder ?? `Select ${data.label}`} />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{options.length === 0 ? (
|
||||||
|
<div className="p-2 text-center text-sm text-muted-foreground">
|
||||||
|
No options available
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
options.map((option) => (
|
||||||
|
<SelectItem
|
||||||
|
key={option.id}
|
||||||
|
value={option.value}
|
||||||
|
disabled={option.disabled}
|
||||||
|
>
|
||||||
|
{option.label}
|
||||||
|
{option.note ? (
|
||||||
|
<span className="ml-1 text-xs text-muted-foreground">
|
||||||
|
{option.note}
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
</SelectItem>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export { DynamicSelect } from "./DynamicSelect";
|
||||||
|
export type { DynamicSelectProps } from "./DynamicSelect";
|
||||||
@@ -12,6 +12,15 @@ import { bookingsService } from "./bookings.service";
|
|||||||
import { consignmentsService } from "./consignments.service";
|
import { consignmentsService } from "./consignments.service";
|
||||||
import { trackingService } from "./tracking.service";
|
import { trackingService } from "./tracking.service";
|
||||||
import { fileUploadSettingsService } from "./fileUploadSettings.service";
|
import { fileUploadSettingsService } from "./fileUploadSettings.service";
|
||||||
|
import { dropdownSettingsService } from "./dropdownSettings.service";
|
||||||
|
import {
|
||||||
|
CreateDropdownOptionDto,
|
||||||
|
CreateDropdownSettingDto,
|
||||||
|
DropdownOption,
|
||||||
|
DropdownSetting,
|
||||||
|
UpdateDropdownOptionDto,
|
||||||
|
UpdateDropdownSettingDto,
|
||||||
|
} from "@/types/dropdownSettings";
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// API definition
|
// API definition
|
||||||
@@ -135,4 +144,69 @@ export const api = {
|
|||||||
({ fieldId }) => fileUploadSettingsService.removeField(fieldId),
|
({ 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),
|
||||||
|
),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user