import { usePage } from "@inertiajs/react"; import { CheckIcon, ChevronsUpDownIcon, SearchIcon, XIcon } from "lucide-react"; import { useState } from "react"; import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip"; import InputError from "@/back/Components/InputError"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import str from "@/hooks/use-string"; import trans from "@/hooks/use-translations"; import { cn } from "@/lib/utils"; interface EnumSelectProps { name: string; label: string; options?: Record< string, { label: string; name: string; value: number | string } >; placeholder?: string; exclude?: (number | string)[]; selected?: number | string | null; required?: boolean; disabled?: boolean; parentErrors?: Record | null; setData: (name: string, value: number | string | null) => void; onSelectValue?: (value: number | string | null) => void; } export default function EnumSelect({ name, label, options = {}, placeholder = "ex: John Doe", exclude = [], selected = null, required = true, disabled = false, parentErrors = null, setData, onSelectValue, }: Readonly) { const { locale } = usePage().props.appEnv as AppEnv; const { errors } = usePage().props; const localErrors = { ...errors, ...parentErrors }; // Model key selected. const initial = selected && selected !== 0 && selected !== "" ? selected : null; const [selectedEnum, setSelectedEnum] = useState( initial, ); // String research in models collection. const [search, setSearch] = useState(""); // List of options. const initalOptions = Object.fromEntries( Object.entries(options).filter(([, item]) => !exclude.includes(item.value)), ); const currentOptions = search.length === 0 ? initalOptions : Object.fromEntries( Object.entries(initalOptions).filter(([, item]) => item.label.toLowerCase().includes(search), ), ); // Component states. const [open, setOpen] = useState(false); const transNoResults = trans("uwil-backend::back.table_no_results"); const transDelete = trans("uwil-backend::crud.actions.delete"); /** * Get the identification field of specific option. * @param value number | string * @return string */ const getEnumLabel = (value: number | string): string => { const targetEnum = Object.values(initalOptions).find( (option) => option.value === value, ); if (!targetEnum) return String(value); if (typeof value === "object") return String( targetEnum.label[locale as keyof typeof targetEnum.label] ?? "", ); return targetEnum.label; }; /** * Updates when selecting new value. * @param value number | string * @return void */ const handleSelect = (value: number | string) => { setSelectedEnum(value); setData(name, value); onSelectValue?.(value); setOpen(false); }; /** * Updates when clear the selected value. * @return void */ const handleClear = () => { setSelectedEnum(null); setData(name, null); onSelectValue?.(null); }; /** * Reset the search. * @return void */ const handleClearSearch = () => { setSearch(""); }; return (
{ setSearch(e.target.value); }} className="w-[calc(100%-2.5rem-40px)] border-0 mx-9" /> } tooltipContent={

{str(trans("uwil-backend::crud.actions.delete")) .ucFirst() .value()}

} type="button" variant="ghost" size="icon" className="absolute top-1/2 right-0 transform -translate-y-1/2 text-muted-foreground" onClick={handleClearSearch} disabled={search.length < 1 || disabled} />
5 ? "h-[225px]" : "h-auto"}`, )} > {Object.values(currentOptions).length === 0 && (

{transNoResults}

)}
{Object.values(currentOptions).map((option) => ( ))}
{!required && selectedEnum !== null && ( } tooltipContent={

{str(transDelete).ucFirst().value()}

} type="button" variant="destructive" size="icon" onClick={handleClear} /> )}
); }