'use client' import { useState, useCallback } from 'react' import { Trash2 } from 'lucide-react' import { useLanguage } from '@/lib/i18n' import { type DatabaseBlockData, randomDefaultCover, } from '@/lib/editor/database-block-types' interface DatabaseBlockEditorProps { data: DatabaseBlockData readOnly?: boolean onChange: (data: DatabaseBlockData) => void } export function DatabaseBlockEditor({ data, readOnly, onChange }: DatabaseBlockEditorProps) { const { t } = useLanguage() const { dbId, dbView, dbAuthors, dbBooks } = data const [newBookTitle, setNewBookTitle] = useState('') const [newBookAuthor, setNewBookAuthor] = useState('') const [newBookTag, setNewBookTag] = useState('') const [newBookCover, setNewBookCover] = useState('') const [newAuthorName, setNewAuthorName] = useState('') const patch = useCallback((partial: Partial) => { onChange({ ...data, ...partial }) }, [data, onChange]) const handleAddAuthor = useCallback(() => { const name = newAuthorName.trim() if (!name) return if (dbAuthors.some((a) => a.name.toLowerCase() === name.toLowerCase())) return patch({ dbAuthors: [...dbAuthors, { id: `auth-${Date.now()}`, name }], }) setNewAuthorName('') }, [dbAuthors, newAuthorName, patch]) const handleAddBook = useCallback((e: React.FormEvent) => { e.preventDefault() const title = newBookTitle.trim() let author = newBookAuthor.trim() if (!title || !author) return let nextAuthors = [...dbAuthors] if (author === '__new__') return if (!nextAuthors.some((a) => a.name.toLowerCase() === author.toLowerCase())) { nextAuthors = [...nextAuthors, { id: `auth-${Date.now()}`, name: author }] } patch({ dbAuthors: nextAuthors, dbBooks: [ ...dbBooks, { id: `bk-${Date.now()}`, title, author, cover: newBookCover.trim() || randomDefaultCover(), tag: newBookTag.trim() || t('databaseBlock.defaultTag'), }, ], }) setNewBookTitle('') setNewBookAuthor('') setNewBookTag('') setNewBookCover('') }, [dbAuthors, dbBooks, newBookAuthor, newBookCover, newBookTag, newBookTitle, patch, t]) const handleDeleteBook = useCallback((id: string) => { patch({ dbBooks: dbBooks.filter((b) => b.id !== id) }) }, [dbBooks, patch]) const handleDeleteAuthor = useCallback((id: string) => { patch({ dbAuthors: dbAuthors.filter((a) => a.id !== id) }) }, [dbAuthors, patch]) return (
📚
{t('databaseBlock.title')} id: {dbId}
{!readOnly && (
)}

{t('databaseBlock.hint')}

{dbView === 'table' ? (
{!readOnly && {dbAuthors.map((auth) => { const authorBooks = dbBooks.filter( (b) => b.author.toLowerCase() === auth.name.toLowerCase(), ) const worksStr = authorBooks.map((b) => b.title).join(', ') || t('databaseBlock.noLinkedWorks') return ( {!readOnly && ( )} ) })}
{t('databaseBlock.colAuthor')} {t('databaseBlock.colWorks')} {t('databaseBlock.colRollup')}}
{auth.name} {worksStr} {authorBooks.length}
{!readOnly && (
{t('databaseBlock.addAuthor')} setNewAuthorName(e.target.value)} className="database-block__input flex-1" />
)}
) : (
{dbBooks.map((book) => (
{!readOnly && ( )}
{book.title}

{book.title}

{book.author} {book.tag}
))}
📖 {t('databaseBlock.worksBase')} {t('databaseBlock.storedCount', { count: dbBooks.length })}
)} {!readOnly && (
{t('databaseBlock.addWork')}
setNewBookTitle(e.target.value)} className="database-block__input" required />
setNewBookTag(e.target.value)} className="database-block__input" /> setNewBookCover(e.target.value)} className="database-block__input" />
)}
) }