mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
188 lines
5.7 KiB
TypeScript
188 lines
5.7 KiB
TypeScript
import { useState, type ReactNode } from "react";
|
|
import { Hash } from "lucide-react";
|
|
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from "@/components/ui/dialog";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Label } from "@/components/ui/label";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Textarea } from "@/components/ui/textarea";
|
|
|
|
import type { DropdownSetting } from "@/types/dropdownSettings";
|
|
|
|
export interface EditDropdownSettingDialogProps {
|
|
mode?: "create" | "edit";
|
|
setting?: DropdownSetting;
|
|
children: ReactNode;
|
|
}
|
|
|
|
export default function EditDropdownSettingDialog({
|
|
mode = "create",
|
|
setting,
|
|
children,
|
|
}: EditDropdownSettingDialogProps) {
|
|
const isEdit = mode === "edit";
|
|
const [multiple, setMultiple] = useState<boolean>(setting?.multiple ?? false);
|
|
const [searchable, setSearchable] = useState<boolean>(
|
|
setting?.meta?.searchable ?? false,
|
|
);
|
|
const [clearable, setClearable] = useState<boolean>(
|
|
setting?.meta?.clearable ?? false,
|
|
);
|
|
|
|
return (
|
|
<Dialog>
|
|
<DialogTrigger asChild>{children}</DialogTrigger>
|
|
|
|
<DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-2xl rounded-3xl">
|
|
<DialogHeader>
|
|
<DialogTitle className="text-2xl font-bold">
|
|
{isEdit ? "Edit Dropdown Setting" : "New Dropdown Setting"}
|
|
</DialogTitle>
|
|
<DialogDescription>
|
|
{isEdit
|
|
? "Update the metadata for this dropdown setting."
|
|
: "Define a new dynamic dropdown that admins can manage."}
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<div className="grid gap-5 py-4 md:grid-cols-2">
|
|
<div className="space-y-2">
|
|
<Label>Code *</Label>
|
|
<div className="relative">
|
|
<Hash className="absolute left-3 top-3 h-4 w-4 text-slate-400" />
|
|
<Input
|
|
defaultValue={setting?.code ?? ""}
|
|
placeholder="e.g. cargo_type"
|
|
className="pl-10 font-mono"
|
|
/>
|
|
</div>
|
|
<p className="text-xs text-slate-500">
|
|
Stable identifier used in code. Use snake_case.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Label *</Label>
|
|
<Input
|
|
defaultValue={setting?.label ?? ""}
|
|
placeholder="e.g. Cargo Type"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2 md:col-span-2">
|
|
<Label>Description</Label>
|
|
<Textarea
|
|
defaultValue={setting?.description ?? ""}
|
|
placeholder="What this dropdown represents and where it's used..."
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Icon (meta.icon)</Label>
|
|
<Input
|
|
defaultValue={setting?.meta?.icon ?? ""}
|
|
placeholder="lucide icon name, e.g. package"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Color (meta.color)</Label>
|
|
<Input
|
|
type="text"
|
|
defaultValue={setting?.meta?.color ?? ""}
|
|
placeholder="#33578D"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Permissions (comma-separated)</Label>
|
|
<Input
|
|
defaultValue={setting?.meta?.permissions?.join(", ") ?? ""}
|
|
placeholder="admin, ops"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label>Version (meta.version)</Label>
|
|
<Input
|
|
defaultValue={setting?.meta?.version ?? "1.0"}
|
|
placeholder="1.0"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2 md:col-span-2">
|
|
<Label>Behavior</Label>
|
|
<div className="flex flex-wrap gap-3">
|
|
<ToggleChip
|
|
checked={multiple}
|
|
onChange={setMultiple}
|
|
label="Multi-select"
|
|
description="Users can pick more than one option"
|
|
/>
|
|
<ToggleChip
|
|
checked={searchable}
|
|
onChange={setSearchable}
|
|
label="Searchable"
|
|
description="Show a search input in the dropdown"
|
|
/>
|
|
<ToggleChip
|
|
checked={clearable}
|
|
onChange={setClearable}
|
|
label="Clearable"
|
|
description="Allow users to clear the selection"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex justify-end gap-3">
|
|
<Button variant="outline">Cancel</Button>
|
|
<Button className="bg-[#33578D] text-white hover:bg-[#33578D]/90">
|
|
{isEdit ? "Save Changes" : "Create Setting"}
|
|
</Button>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|
|
|
|
function ToggleChip({
|
|
checked,
|
|
onChange,
|
|
label,
|
|
description,
|
|
}: {
|
|
checked: boolean;
|
|
onChange: (next: boolean) => void;
|
|
label: string;
|
|
description: string;
|
|
}) {
|
|
return (
|
|
<label
|
|
className={
|
|
checked
|
|
? "flex cursor-pointer items-start gap-2 rounded-2xl border border-[#33578D]/40 bg-[#33578D]/10 px-3 py-2 text-sm"
|
|
: "flex cursor-pointer items-start gap-2 rounded-2xl border border-slate-200 bg-white px-3 py-2 text-sm transition hover:border-[#33578D]/30 hover:bg-[#33578D]/5"
|
|
}
|
|
>
|
|
<input
|
|
type="checkbox"
|
|
checked={checked}
|
|
onChange={(e) => onChange(e.target.checked)}
|
|
className="mt-0.5 h-4 w-4 rounded border-slate-300 text-[#33578D] focus:ring-[#33578D]/20"
|
|
/>
|
|
<div>
|
|
<p className="font-medium text-slate-900">{label}</p>
|
|
<p className="text-xs text-slate-500">{description}</p>
|
|
</div>
|
|
</label>
|
|
);
|
|
}
|