fix(erp): enable erp pages and menu items
This commit is contained in:
103
front-end-agency/components/ui/CustomSelect.tsx
Normal file
103
front-end-agency/components/ui/CustomSelect.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
"use client";
|
||||
|
||||
import { Fragment, useState } from "react";
|
||||
import { Listbox, ListboxButton, ListboxOption, ListboxOptions, Transition } from "@headlessui/react";
|
||||
import { CheckIcon, ChevronUpDownIcon } from "@heroicons/react/20/solid";
|
||||
|
||||
export interface SelectOption {
|
||||
label: string;
|
||||
value: string | number;
|
||||
icon?: React.ReactNode;
|
||||
color?: string; // Cor para badge/ponto
|
||||
}
|
||||
|
||||
interface CustomSelectProps {
|
||||
options: SelectOption[];
|
||||
value: string | number;
|
||||
onChange: (value: any) => void;
|
||||
label?: string;
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
buttonClassName?: string;
|
||||
}
|
||||
|
||||
export default function CustomSelect({
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
label,
|
||||
placeholder = "Selecione...",
|
||||
className = "",
|
||||
buttonClassName = ""
|
||||
}: CustomSelectProps) {
|
||||
const selected = options.find((opt) => opt.value === value) || null;
|
||||
|
||||
return (
|
||||
<div className={`w-full ${className}`}>
|
||||
{label && (
|
||||
<label className="block text-xs font-bold text-zinc-500 dark:text-zinc-400 uppercase tracking-wider mb-2">
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
<Listbox value={value} onChange={onChange}>
|
||||
<div className="relative">
|
||||
<ListboxButton
|
||||
className={`
|
||||
relative w-full cursor-pointer rounded-xl bg-white dark:bg-zinc-900 py-2.5 pl-4 pr-10 text-left text-sm font-semibold transition-all border
|
||||
${buttonClassName || 'border-zinc-200 dark:border-zinc-800 text-zinc-700 dark:text-zinc-300 hover:border-zinc-400'}
|
||||
focus:outline-none focus:border-zinc-400 dark:focus:border-zinc-500
|
||||
`}
|
||||
>
|
||||
<span className="flex items-center gap-2 truncate">
|
||||
{selected?.color && (
|
||||
<span className={`w-2 h-2 rounded-full ${selected.color}`} />
|
||||
)}
|
||||
{selected?.icon && <span>{selected.icon}</span>}
|
||||
{selected ? selected.label : placeholder}
|
||||
</span>
|
||||
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
||||
<ChevronUpDownIcon className="h-5 w-5 text-zinc-400" aria-hidden="true" />
|
||||
</span>
|
||||
</ListboxButton>
|
||||
|
||||
<Transition
|
||||
as={Fragment}
|
||||
leave="transition ease-in duration-100"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<ListboxOptions className="absolute z-50 mt-2 max-h-60 w-full overflow-auto rounded-xl bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 py-1 focus:outline-none sm:text-sm">
|
||||
{options.map((option, idx) => (
|
||||
<ListboxOption
|
||||
key={idx}
|
||||
className={({ active }) =>
|
||||
`relative cursor-pointer select-none py-2.5 pl-10 pr-4 transition-colors ${active ? "bg-zinc-50 dark:bg-zinc-800 text-brand-600 dark:text-brand-400" : "text-zinc-700 dark:text-zinc-300"
|
||||
}`
|
||||
}
|
||||
value={option.value}
|
||||
>
|
||||
{({ selected: isSelected }) => (
|
||||
<>
|
||||
<span className={`flex items-center gap-2 truncate ${isSelected ? "font-bold" : "font-medium"}`}>
|
||||
{option.color && (
|
||||
<span className={`w-2 h-2 rounded-full ${option.color}`} />
|
||||
)}
|
||||
{option.icon && <span>{option.icon}</span>}
|
||||
{option.label}
|
||||
</span>
|
||||
{isSelected ? (
|
||||
<span className="absolute inset-y-0 left-0 flex items-center pl-3 text-brand-600 dark:text-brand-400">
|
||||
<CheckIcon className="h-5 w-5" aria-hidden="true" />
|
||||
</span>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
</ListboxOption>
|
||||
))}
|
||||
</ListboxOptions>
|
||||
</Transition>
|
||||
</div>
|
||||
</Listbox>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user