Vitron-Front/app/components/AppSelectBox.tsx
2026-04-29 01:44:16 +03:30

113 lines
3.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Check, Loader } from "lucide-react";
import { cn } from "../lib/utils";
import { Button } from "../components/ui/button";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "../components/ui/command";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "../components/ui/popover";
import { useState } from "react";
interface Item {
value: string | number;
label: string;
}
interface AppSelectBoxProps {
items: Item[];
placeholder?: string;
haveSearchbar?: boolean;
value: string;
setValue: React.Dispatch<React.SetStateAction<string>>;
loading?: boolean; // New loading prop
width?: string; // New width prop
disabled?: boolean;
title?: string; // Add title prop
}
export default function AppSelectBox({
haveSearchbar,
items,
placeholder,
value,
setValue,
loading = false, // Default to false
width = "w-[105px]", // Default width
disabled = false,
title,
}: AppSelectBoxProps) {
const [open, setOpen] = useState(false);
return (
<div className={`w-full flex flex-col ${title ? "gap-2" : "gap-0"}`}>
{title && (
<p className="text-R14 text-foreground dark:text-gray-200">{title}</p>
)}
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
size={"lg"}
aria-expanded={open}
className={`${width} ${value ? "text-BLACK dark:text-gray-200" : "text-GRAY dark:text-gray-400"} rounded-[12px] border border-input bg-inputBg dark:bg-gray-800 dark:border-gray-600`}
disabled={disabled || loading} // Disable button when loading
>
{loading ? (
<Loader className="animate-spin" size={16} /> // Show loading spinner
) : value ? (
items.find((item: Item) => item.value.toString() === value)?.label
) : (
placeholder
)}
</Button>
</PopoverTrigger>
{!loading && ( // Only show dropdown content when not loading
<PopoverContent className={`${width} p-0`}>
<Command>
{haveSearchbar && (
<CommandInput placeholder="جستجو" className="h-9" />
)}
<CommandList>
<CommandEmpty>آیتمی وجود نداره</CommandEmpty>
<CommandGroup>
{items.map((item: Item) => (
<CommandItem
key={item.value}
value={item.value.toString()}
onSelect={() => {
setValue(
item.value === value ? "" : item.value.toString()
);
setOpen(false);
}}
>
{item.label}
<Check
className={cn(
"ml-auto",
value === item.value.toString()
? "opacity-100"
: "opacity-0"
)}
/>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
)}
</Popover>
</div>
);
}