'use client' import { useMemo, useState } from 'react' import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog' import type { Note } from '@/lib/types' import type { ColumnFilter, ColumnSort, NotebookSchemaPayload, NotePropertyValues, } from '@/lib/structured-views/types' import { filterNotesWithProperties, sortNotesWithProperties, } from '@/lib/structured-views/property-utils' import { PropertyValueEditor } from './property-value-editor' import { getNoteDisplayTitle } from '@/lib/note-preview' import { useLanguage } from '@/lib/i18n' import { formatAbsoluteDateLocalized } from '@/lib/utils/format-localized-date' import { ChevronDown, ChevronUp, Filter, Trash2 } from 'lucide-react' type NotesStructuredTableProps = { notes: Note[] schema: NotebookSchemaPayload noteValues: Record onOpen: (note: Note) => void onPropertyChange: (noteId: string, propertyId: string, value: unknown) => void onDeleteProperty?: (propertyId: string) => Promise } export function NotesStructuredTable({ notes, schema, noteValues, onOpen, onPropertyChange, onDeleteProperty, }: NotesStructuredTableProps) { const { t, language } = useLanguage() const untitled = t('notes.untitled') const [sort, setSort] = useState({ propertyId: 'updatedAt', direction: 'desc' }) const [filterPropId, setFilterPropId] = useState(null) const [filterOp, setFilterOp] = useState('contains') const [filterValue, setFilterValue] = useState('') const [propertyToDelete, setPropertyToDelete] = useState<{ id: string; name: string } | null>(null) const [deletingProperty, setDeletingProperty] = useState(false) const filters: ColumnFilter[] = useMemo(() => { if (!filterPropId) return [] return [{ propertyId: filterPropId, operator: filterOp, value: filterValue }] }, [filterPropId, filterOp, filterValue]) const displayed = useMemo(() => { const filtered = filterNotesWithProperties(notes, noteValues, filters, schema.properties) return sortNotesWithProperties(filtered, noteValues, sort, schema.properties) }, [notes, noteValues, filters, sort, schema.properties]) const toggleSort = (propertyId: ColumnSort['propertyId']) => { setSort((prev) => prev.propertyId === propertyId ? { propertyId, direction: prev.direction === 'asc' ? 'desc' : 'asc' } : { propertyId, direction: 'asc' }, ) } const SortIcon = ({ field }: { field: ColumnSort['propertyId'] }) => sort.propertyId !== field ? null : sort.direction === 'asc' ? ( ) : ( ) return (
{filterPropId && ( <> {filterOp !== 'empty' && ( setFilterValue(e.target.value)} className="rounded-lg border border-border bg-background px-2 py-1 min-w-[120px]" placeholder={t('structuredViews.filterValue')} /> )} )}
{schema.properties.map((p) => ( ))} {displayed.map((note) => { const vals = noteValues[note.id] ?? {} return ( {schema.properties.map((p) => ( ))} ) })}
toggleSort('title')} > {t('notes.tableTitle')} {onDeleteProperty && ( )} toggleSort('updatedAt')} > {t('notes.tableModified')}
e.stopPropagation()} >
onPropertyChange(note.id, p.id, v)} />
{formatAbsoluteDateLocalized(new Date(note.updatedAt), language, 'MMM d, yyyy')}
{displayed.length === 0 && (

{t('structuredViews.noMatchingNotes')}

)}
{ if (!open) setPropertyToDelete(null) }} > {t('structuredViews.deletePropertyTitle')} {t('structuredViews.deletePropertyConfirm', { name: propertyToDelete?.name ?? '' })} {t('general.cancel')} { e.preventDefault() if (!propertyToDelete || !onDeleteProperty) return setDeletingProperty(true) try { await onDeleteProperty(propertyToDelete.id) if (filterPropId === propertyToDelete.id) setFilterPropId(null) setPropertyToDelete(null) } finally { setDeletingProperty(false) } }} > {t('structuredViews.deleteProperty')}
) }