import * as React from "react"; import { Search, X } from "lucide-react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Checkbox } from "@/components/ui/checkbox"; import { Spinner } from "@/components/ui/spinner"; import { Table, TableHeader, TableHead, TableBody, TableRow, TableCell, } from "@/components/ui/table"; import { TablePagination } from "@/components/ui/pagination"; import { cn } from "@/lib/utils"; export interface LeadContact { id: string; name: string; email?: string; phone?: string; } export interface AddLeadModalProps { open: boolean; onOpenChange: (open: boolean) => void; /** Contacts for the current page — server-side pagination, parent slices. */ contacts: LeadContact[]; /** Total contacts matching the current search (drives pagination). */ total: number; isLoading?: boolean; isSubmitting?: boolean; searchValue?: string; onSearchChange?: (value: string) => void; /** 0-indexed current page. */ page?: number; pageSize?: number; pageSizeOptions?: number[]; onPageChange?: (page: number) => void; onPageSizeChange?: (pageSize: number) => void; onAdd?: (selectedIds: string[]) => void; className?: string; } function toggleInSet(prev: Set, value: T): Set { const next = new Set(prev); next.has(value) ? next.delete(value) : next.add(value); return next; } export function AddLeadModal({ open, onOpenChange, contacts, total, isLoading = false, isSubmitting = false, searchValue = "", onSearchChange, page = 0, pageSize = 10, pageSizeOptions, onPageChange, onPageSizeChange, onAdd, className, }: AddLeadModalProps) { const [selectedIds, setSelectedIds] = React.useState>(new Set()); React.useEffect(() => { if (open) setSelectedIds(new Set()); }, [open]); const allPageSelected = contacts.length > 0 && contacts.every((c) => selectedIds.has(c.id)); const somePageSelected = contacts.some((c) => selectedIds.has(c.id)); function toggleAll() { setSelectedIds((prev) => { const next = new Set(prev); if (allPageSelected) { contacts.forEach((c) => next.delete(c.id)); } else { contacts.forEach((c) => next.add(c.id)); } return next; }); } const totalPages = Math.max(1, Math.ceil(total / pageSize)); return ( Add Lead
onSearchChange?.(e.target.value)} className="pl-8 pr-8" disabled={isSubmitting} /> {searchValue && ( )}
{isLoading && (
)} e.stopPropagation()}> Name Email Phone {contacts.length === 0 && !isLoading ? ( No clients found. ) : ( contacts.map((contact) => { const isSelected = selectedIds.has(contact.id); return ( !isSubmitting && setSelectedIds((prev) => toggleInSet(prev, contact.id)) } > e.stopPropagation()}> setSelectedIds((prev) => toggleInSet(prev, contact.id), ) } disabled={isSubmitting} /> {contact.name} {contact.email ?? "—"} {contact.phone ?? "—"} ); }) )}
{/* TablePagination is 1-indexed; props are 0-indexed — converted here */}
onPageChange?.(p - 1)} onPageSizeChange={(size) => { onPageSizeChange?.(size); onPageChange?.(0); }} />
); }