'use client'; import { useState, useCallback, useRef } from 'react'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Download, Upload } from 'lucide-react'; import { TermEditor } from './TermEditor'; import { exportGlossaryToCsv, parseCsvToTerms } from './csvUtils'; import { useToast } from '@/components/ui/toast'; import type { Glossary, GlossaryTermInput } from './types'; import { MAX_TERMS_PER_GLOSSARY } from './types'; interface EditGlossaryDialogProps { open: boolean; onOpenChange: (open: boolean) => void; glossary: Glossary | null; onSave: (id: string, data: { name: string; terms: GlossaryTermInput[] }) => Promise; isSaving: boolean; } export function EditGlossaryDialog({ open, onOpenChange, glossary, onSave, isSaving, }: EditGlossaryDialogProps) { const [name, setName] = useState(''); const [terms, setTerms] = useState([]); const fileInputRef = useRef(null); const isInitialized = useRef(false); if (glossary && !isInitialized.current) { setName(glossary.name); setTerms(glossary.terms.map(t => ({ source: t.source, target: t.target }))); isInitialized.current = true; } if (!open && isInitialized.current) { isInitialized.current = false; } const handleSave = useCallback(async () => { if (!glossary || !name.trim()) return; const validTerms = terms.filter(t => t.source.trim() && t.target.trim()); await onSave(glossary.id, { name: name.trim(), terms: validTerms, }); }, [glossary, name, terms, onSave]); const handleExport = useCallback(() => { if (!glossary) return; const glossaryWithCurrentTerms: Glossary = { ...glossary, name, terms: terms.map((t, i) => ({ id: `temp-${i}`, source: t.source, target: t.target, translations: t.translations || {}, created_at: null, })), }; exportGlossaryToCsv(glossaryWithCurrentTerms); }, [glossary, name, terms]); const handleImportClick = useCallback(() => { fileInputRef.current?.click(); }, []); const { toast } = useToast(); const handleFileChange = useCallback((e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; const reader = new FileReader(); reader.onload = (event) => { const text = event.target?.result; if (typeof text === 'string') { const importedTerms = parseCsvToTerms(text); if (importedTerms.length > 0) { if (importedTerms.length > MAX_TERMS_PER_GLOSSARY) { toast({ variant: 'destructive', title: 'Import failed', description: `CSV contains ${importedTerms.length} terms, but maximum is ${MAX_TERMS_PER_GLOSSARY}. Please reduce the number of terms.`, }); e.target.value = ''; return; } setTerms(importedTerms); toast({ title: 'Import successful', description: `${importedTerms.length} terms imported successfully.`, }); } else { toast({ variant: 'destructive', title: 'Import failed', description: 'No valid terms found in CSV file.', }); } } }; reader.onerror = () => { toast({ variant: 'destructive', title: 'Import failed', description: 'Failed to read CSV file.', }); }; reader.readAsText(file); e.target.value = ''; }, [toast]); const validTermsCount = terms.filter(t => t.source.trim() && t.target.trim()).length; return ( Edit Glossary Update the glossary name and term pairs.
setName(e.target.value)} placeholder="Enter glossary name..." disabled={isSaving} />
); }