docv/components/ui/member-autocomplete.tsx

111 lines
4.0 KiB
TypeScript

"use client"
import * as React from "react"
import { Check, ChevronsUpDown, X } 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 { Badge } from "@/components/ui/badge"
interface MemberAutocompleteProps {
allMembers: string[];
selectedMembers: string[];
onChange: (selectedMembers: string[]) => void;
}
export function MemberAutocomplete({
allMembers,
selectedMembers,
onChange,
}: MemberAutocompleteProps) {
const [open, setOpen] = React.useState(false)
// Liste des membres qui ne sont PAS encore sélectionnés
const availableMembers = allMembers.filter(
(member) => !selectedMembers.includes(member)
)
// Gère la sélection d'un membre dans la liste
const handleSelect = (memberId: string) => {
onChange([...selectedMembers, memberId])
setOpen(false) // Ferme le popover après sélection
}
// Gère la suppression d'un membre (clic sur le 'X' du badge)
const handleRemove = (memberId: string) => {
onChange(selectedMembers.filter((m) => m !== memberId))
}
return (
<div className="space-y-2">
{/* 1. Affichage des membres déjà sélectionnés (Badges) */}
<div className="flex flex-wrap gap-1">
{selectedMembers.map((member) => (
<Badge
key={member}
variant="secondary"
className="flex items-center gap-1"
>
<span className="truncate max-w-[200px]" title={member}>{member}</span>
<button
type="button"
onClick={() => handleRemove(member)}
className="rounded-full hover:bg-red-500/20 p-0.5"
>
<X className="h-3 w-3" />
</button>
</Badge>
))}
</div>
{/* 2. Le Popover avec le bouton de recherche */}
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
type="button" // Important pour ne pas soumettre le formulaire
variant="outline"
role="combobox"
aria-expanded={open}
className="w-full justify-between bg-gray-100 dark:bg-gray-700"
>
Ajouter un membre...
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[--radix-popover-trigger-width] p-0">
<Command>
<CommandInput placeholder="Rechercher un membre..." />
<CommandList>
<CommandEmpty>Aucun membre trouvé.</CommandEmpty>
<CommandGroup>
{availableMembers.map((member) => (
<CommandItem
key={member}
value={member} // 'value' est utilisé pour la recherche
onSelect={() => handleSelect(member)}
className="truncate"
>
{member}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
</div>
)
}