'use client' import { Check, ChevronsUpDown, Star } from 'lucide-react' import { useMemo, useState } from 'react' import { Button } from '@/components/ui/button' import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from '@/components/ui/command' import { Label } from '@/components/ui/label' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { Switch } from '@/components/ui/switch' import { cn } from '@/lib/utils' // ── Toggle field ────────────────────────────────────────────── export function ToggleField({ label, checked, value, onChange, disabled, }: { label: string /** Boolean checked state */ checked?: boolean /** Number or string (0/1 or '0'/'1') — converted to boolean automatically */ value?: number | string onChange: (v: boolean) => void disabled?: boolean }) { const isChecked = checked ?? (value === 1 || value === '1') return (
) } // ── Interaction Type Combobox ────────────────────────────────── export function InteractionTypeCombobox({ value, onChange, types, disabled, }: { value: string onChange: (v: string) => void types: string[] disabled?: boolean }) { const [open, setOpen] = useState(false) const [inputValue, setInputValue] = useState('') const filtered = useMemo(() => { if (!inputValue.trim()) return types.slice(0, 50) const q = inputValue.toLowerCase() return types.filter((t) => t.toLowerCase().includes(q)).slice(0, 50) }, [types, inputValue]) return ( {inputValue.trim() ? ( ) : ( 'No types found.' )} {filtered.map((t) => ( { onChange(t) setOpen(false) setInputValue('') }} > {t} ))} ) } // ── Move Page Combobox with smart suggestions ───────────────── export function MovePageCombobox({ value, onChange, pages, currentPageId, suggestedPageIds, }: { value: number | null onChange: (id: number | null) => void pages: { id: number; caption: string }[] currentPageId: number /** Page IDs to show first as suggestions (from move-suggestions.ts) */ suggestedPageIds?: number[] }) { const [open, setOpen] = useState(false) const options = useMemo(() => pages.filter((p) => p.id !== currentPageId), [pages, currentPageId]) const selectedPage = value ? pages.find((p) => p.id === value) : null // Build suggested pages list const suggested = useMemo(() => { if (!suggestedPageIds?.length) return [] const pageMap = new Map(options.map((p) => [p.id, p])) return suggestedPageIds.map((id) => pageMap.get(id)).filter(Boolean) as { id: number caption: string }[] }, [suggestedPageIds, options]) // Non-suggested pages (exclude those already in suggestions) const suggestedSet = useMemo(() => new Set(suggested.map((s) => s.id)), [suggested]) const remaining = useMemo( () => options.filter((p) => !suggestedSet.has(p.id)), [options, suggestedSet], ) return ( No page found. {/* Suggested pages */} {suggested.length > 0 && ( {suggested.map((page) => ( { onChange(page.id) setOpen(false) }} > #{page.id} {page.caption} ))} )} {/* All pages */} 0 ? 'All pages' : undefined}> {remaining.map((page) => ( { onChange(page.id) setOpen(false) }} > #{page.id} {page.caption} ))} ) }