'use client' import { useEffect, useRef, useState } from 'react' import { cn } from '@/lib/utils' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { useLanguage } from '@/lib/i18n' import type { PropertyType, SchemaProperty } from '@/lib/structured-views/types' type PropertyValueEditorProps = { property: SchemaProperty value: unknown onChange: (value: unknown) => void compact?: boolean className?: string } export function PropertyValueEditor({ property, value, onChange, compact, className, }: PropertyValueEditorProps) { const base = cn( 'w-full rounded-md border border-border/60 bg-background text-sm', compact ? 'px-2 py-1 text-[12px]' : 'px-3 py-2', className, ) switch (property.type) { case 'checkbox': return ( onChange(e.target.checked)} className="h-4 w-4 accent-brand-accent" /> ) case 'number': return ( onChange(e.target.value === '' ? null : Number(e.target.value))} className={base} /> ) case 'date': return ( onChange(e.target.value || null)} className={base} /> ) case 'select': return ( ) case 'multiselect': return ( typeof v === 'string') : []} onChange={onChange} className={base} compact={compact} /> ) default: return ( onChange(e.target.value || null)} className={base} /> ) } } function MultiSelectEditor({ options, value, onChange, className, compact, }: { options: string[] value: string[] onChange: (v: string[]) => void className?: string compact?: boolean }) { const { t } = useLanguage() const [open, setOpen] = useState(false) const toggle = (opt: string) => { if (value.includes(opt)) onChange(value.filter((v) => v !== opt)) else onChange([...value, opt]) } if (compact) { return (

{t('structuredViews.multiselectPick')}

{options.map((opt) => { const active = value.includes(opt) return ( ) })}
) } return (
{options.map((opt) => { const active = value.includes(opt) return ( ) })}
) } export function useDebouncedPropertySave( noteId: string, onSaved?: (values: Record) => void, delayMs = 500, ) { const timerRef = useRef | null>(null) const pendingRef = useRef>({}) useEffect(() => () => { if (timerRef.current) clearTimeout(timerRef.current) }, []) const queueSave = (propertyId: string, value: unknown) => { pendingRef.current[propertyId] = value if (timerRef.current) clearTimeout(timerRef.current) timerRef.current = setTimeout(async () => { const payload = { ...pendingRef.current } pendingRef.current = {} try { const res = await fetch(`/api/notes/${noteId}/properties`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ properties: payload }), }) const json = await res.json() if (json.success && json.data?.values) onSaved?.(json.data.values) } catch (e) { console.error(e) } }, delayMs) } return queueSave } export function formatPropertyTypeLabel(type: PropertyType, t: (k: string) => string) { return t(`structuredViews.propertyTypes.${type}`) }