import { Button } from '@/components/ui/button'; import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { Input } from '@/components/ui/input'; import { useAppParams } from '@/hooks/useAppParams'; import { useEventProperties } from '@/hooks/useEventProperties'; import type { IChartEvent } from '@openpanel/validation'; import { AnimatePresence, motion } from 'framer-motion'; import { ArrowLeftIcon, DatabaseIcon, UserIcon } from 'lucide-react'; import VirtualList from 'rc-virtual-list'; import { type Dispatch, type SetStateAction, useEffect, useState } from 'react'; interface PropertiesComboboxProps { event?: IChartEvent; children: (setOpen: Dispatch>) => React.ReactNode; onSelect: (action: { value: string; label: string; description: string; }) => void; } function SearchHeader({ onBack, onSearch, value, }: { onBack?: () => void; onSearch: (value: string) => void; value: string; }) { return (
{!!onBack && ( )} onSearch(e.target.value)} autoFocus />
); } export function PropertiesCombobox({ event, children, onSelect, }: PropertiesComboboxProps) { const { projectId } = useAppParams(); const [open, setOpen] = useState(false); const properties = useEventProperties({ event: event?.name, projectId, }); const [state, setState] = useState<'index' | 'event' | 'profile'>('index'); const [search, setSearch] = useState(''); const [direction, setDirection] = useState<'forward' | 'backward'>('forward'); useEffect(() => { if (!open) { setState('index'); } }, [open]); // Mock data for the lists const profileActions = properties .filter((property) => property.startsWith('profile')) .map((property) => ({ value: property, label: property.split('.').pop() ?? property, description: property.split('.').slice(0, -1).join('.'), })); const eventActions = properties .filter((property) => !property.startsWith('profile')) .map((property) => ({ value: property, label: property.split('.').pop() ?? property, description: property.split('.').slice(0, -1).join('.'), })); const handleStateChange = (newState: 'index' | 'event' | 'profile') => { setDirection(newState === 'index' ? 'backward' : 'forward'); setState(newState); }; const handleSelect = (action: { value: string; label: string; description: string; }) => { setOpen(false); onSelect(action); }; const renderIndex = () => { return ( {/* {}} value={search} /> */} {/* */} { e.preventDefault(); handleStateChange('event'); }} > Event properties { e.preventDefault(); handleStateChange('profile'); }} > Profile properties ); }; const renderEvent = () => { const filteredActions = eventActions.filter( (action) => action.label.toLowerCase().includes(search.toLowerCase()) || action.description.toLowerCase().includes(search.toLowerCase()), ); return (
handleStateChange('index')} onSearch={setSearch} value={search} /> {(action) => ( handleSelect(action)} >
{action.label}
{action.description}
)}
); }; const renderProfile = () => { const filteredActions = profileActions.filter( (action) => action.label.toLowerCase().includes(search.toLowerCase()) || action.description.toLowerCase().includes(search.toLowerCase()), ); return (
handleStateChange('index')} onSearch={setSearch} value={search} /> {(action) => ( handleSelect(action)} >
{action.label}
{action.description}
)}
); }; return ( { setOpen(open); }} > {children(setOpen)} {state === 'index' && ( {renderIndex()} )} {state === 'event' && ( {renderEvent()} )} {state === 'profile' && ( {renderProfile()} )} ); }