import { store } from '@/actions/App/Http/Controllers/Settings/LabelController';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
Command,
CommandEmpty,
CommandInput,
CommandItem,
CommandList,
} from '@/components/ui/command';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
import { cn } from '@/lib/utils';
import { getLabelColorClasses, LABEL_COLORS, type Label } from '@/types/label';
import { Check, ChevronsUpDown, Plus, Tag, X } from 'lucide-react';
import { useState } from 'react';
interface LabelComboboxProps {
value: string[];
onValueChange: (value: string[]) => void;
labels: Label[];
disabled?: boolean;
placeholder?: string;
triggerClassName?: string;
allowCreate?: boolean;
allowRemoveAll?: boolean;
onLabelCreated?: (label: Label) => void;
}
export function LabelCombobox({
value,
onValueChange,
labels = [],
disabled = false,
placeholder = 'Add labels...',
triggerClassName,
allowCreate = true,
allowRemoveAll = false,
onLabelCreated,
}: LabelComboboxProps) {
const [open, setOpen] = useState(false);
const [inputValue, setInputValue] = useState('');
const [isCreating, setIsCreating] = useState(false);
const selectedLabels = labels.filter((l) => value.includes(l.id));
const sortedLabels = [...labels].sort((a, b) =>
a.name.localeCompare(b.name),
);
const handleSelect = (labelId: string) => {
if (value.includes(labelId)) {
onValueChange(value.filter((id) => id !== labelId));
} else {
onValueChange([...value, labelId]);
}
};
const handleRemove = (labelId: string, e: React.MouseEvent) => {
e.stopPropagation();
onValueChange(value.filter((id) => id !== labelId));
};
const handleCreate = async () => {
if (!inputValue.trim() || isCreating) return;
const existingLabel = labels.find(
(l) => l.name.toLowerCase() === inputValue.toLowerCase(),
);
if (existingLabel) {
handleSelect(existingLabel.id);
setInputValue('');
return;
}
setIsCreating(true);
try {
const randomColor =
LABEL_COLORS[Math.floor(Math.random() * LABEL_COLORS.length)];
const response = await fetch(store.url(), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-XSRF-TOKEN': decodeURIComponent(
document.cookie
.split('; ')
.find((row) => row.startsWith('XSRF-TOKEN='))
?.split('=')[1] || '',
),
Accept: 'application/json',
},
body: JSON.stringify({
name: inputValue.trim(),
color: randomColor,
}),
});
if (!response.ok) {
throw new Error('Failed to create label');
}
const data = await response.json();
const newLabel = data.data || data;
if (newLabel) {
onValueChange([...value, newLabel.id]);
setInputValue('');
onLabelCreated?.(newLabel);
}
} catch (error) {
console.error('Failed to create label:', error);
} finally {
setIsCreating(false);
}
};
const showCreateOption =
allowCreate &&
inputValue.trim() &&
!labels.some((l) => l.name.toLowerCase() === inputValue.toLowerCase());
return (