quivr/frontend/lib/components/ui/Select.tsx
Mamadou DICKO 87458d8de1
Feat/brain access rights (#705)
* refactor(BrainUsers)

* feat: give brain share access to EDITORs

* feat(RBAC): add role enum and supports multiple roles check

* feat: make owner right read only for other permissions
2023-07-19 13:36:23 +02:00

128 lines
4.0 KiB
TypeScript

/* eslint-disable max-lines */
import { BsCheckCircleFill } from "react-icons/bs";
import Popover from "@/lib/components/ui/Popover";
type SelectOptionProps<T> = {
label: string;
value: T;
};
type SelectProps<T> = {
options: SelectOptionProps<T>[];
value?: T;
onChange: (option: T) => void;
label?: string;
readOnly?: boolean;
};
const selectedStyle = "rounded-lg bg-black text-white";
export const Select = <T extends string | number>({
onChange,
options,
value,
label,
readOnly = false,
}: SelectProps<T>): JSX.Element => {
const selectedValueLabel = options.find(
(option) => option.value === value
)?.label;
if (readOnly) {
return (
<div>
{label !== undefined && (
<label
id="listbox-label"
className="block text-sm font-medium leading-6 text-gray-900 mb-2"
>
{label}
</label>
)}
<div className="relative">
<button
type="button"
className="relative w-full cursor-default rounded-md bg-white py-1.5 px-3 text-left text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 sm:text-sm sm:leading-6"
aria-haspopup="listbox"
disabled
>
<span className="flex items-center">
<span className="mx-4 block truncate">
{selectedValueLabel ?? label ?? "Select"}
</span>
</span>
</button>
</div>
</div>
);
}
return (
<div>
{label !== undefined && (
<label
id="listbox-label"
className="block text-sm font-medium leading-6 text-gray-900 mb-2"
>
{label}
</label>
)}
<div className="relative">
<Popover
Trigger={
<button
type="button"
className="relative w-full cursor-default rounded-md bg-white py-1.5 pl-3 pr-10 text-left text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 sm:text-sm sm:leading-6"
aria-haspopup="listbox"
>
<span className="flex items-center">
<span className="ml-3 block truncate">
{selectedValueLabel ?? label ?? "Select"}
</span>
</span>
<span className="pointer-events-none absolute inset-y-0 right-0 ml-3 flex items-center pr-2">
<svg
className="h-5 w-5 text-gray-400"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M10 3a.75.75 0 01.55.24l3.25 3.5a.75.75 0 11-1.1 1.02L10 4.852 7.3 7.76a.75.75 0 01-1.1-1.02l3.25-3.5A.75.75 0 0110 3zm-3.76 9.2a.75.75 0 011.06.04l2.7 2.908 2.7-2.908a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 01.04-1.06z"
clip-rule="evenodd"
/>
</svg>
</span>
</button>
}
CloseTrigger={<div />}
>
<ul role="listbox">
{options.map((option) => (
<li
className="text-gray-900 relative cursor-pointer select-none py-2"
id="listbox-option-0"
key={option.value}
onClick={() => onChange(option.value)}
>
<div
className={`flex items-center px-3 py-2 ${
value === option.value && selectedStyle
}`}
>
<span className="font-bold block truncate mr-2">
{option.label}
</span>
{value === option.value && <BsCheckCircleFill />}
</div>
</li>
))}
</ul>
</Popover>
</div>
</div>
);
};