'use client'; import { useState, useEffect } from 'react'; import { BookText, Plus, Library, Calendar, Hash, Zap, Save, Trash2, MessageSquare, Loader2, Wrench, HardHat, Monitor, Scale, Stethoscope, BarChart3, Megaphone, Car, } from 'lucide-react'; import { useUser } from '@/app/dashboard/useUser'; import { useI18n } from '@/lib/i18n'; import { useGlossaries, useGlossary } from './useGlossaries'; import type { Glossary, GlossaryTermInput, GlossaryListItem } from './types'; import { ProUpgradePrompt } from './ProUpgradePrompt'; import { CreateGlossaryDialog } from './CreateGlossaryDialog'; import { EditGlossaryDialog } from './EditGlossaryDialog'; import { DeleteGlossaryDialog } from './DeleteGlossaryDialog'; import { useToast } from '@/components/ui/toast'; import { useTranslationStore } from '@/lib/store'; import { API_BASE } from '@/lib/config'; const PRESETS = [ { key: 'hvac', title: 'HVAC / Génie climatique', desc: 'Thermique, ventilation, climatisation', icon: Wrench, templateId: 'hvac' }, { key: 'construction', title: 'BTP / Construction', desc: 'Gros œuvre, second œuvre, normes', icon: HardHat, templateId: 'construction' }, { key: 'it', title: 'IT / Logiciel', desc: 'Développement, infrastructure, DevOps', icon: Monitor, templateId: 'technology' }, { key: 'legal', title: 'Juridique / Contrats', desc: 'Droit des affaires, contentieux', icon: Scale, templateId: 'legal' }, { key: 'medical', title: 'Médical / Santé', desc: 'Pharmacologie, chirurgie, diagnostic', icon: Stethoscope, templateId: 'medical' }, { key: 'finance', title: 'Finance / Comptabilité', desc: 'IFRS, bilans, fiscalité', icon: BarChart3, templateId: 'finance' }, { key: 'marketing', title: 'Marketing / Publicité', desc: 'Digital, branding, analytics', icon: Megaphone, templateId: 'marketing' }, { key: 'automotive', title: 'Automobile', desc: 'Motorisation, ADAS, homologation', icon: Car, templateId: 'automotive' }, ]; export default function GlossariesPage() { const { t } = useI18n(); const { data: user, isLoading: isLoadingUser } = useUser(); const { glossaries, total, isLoading: isLoadingGlossaries, isCreating, isUpdating, isDeleting, isImportingTemplate, createGlossary, updateGlossary, deleteGlossary, importTemplate, } = useGlossaries(); const { toast } = useToast(); const { settings, updateSettings } = useTranslationStore(); const [createDialogOpen, setCreateDialogOpen] = useState(false); const [editDialogOpen, setEditDialogOpen] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [selectedGlossary, setSelectedGlossary] = useState(null); const [glossaryToEdit, setGlossaryToEdit] = useState(null); const [glossaryToDelete, setGlossaryToDelete] = useState<{ id: string; name: string } | null>(null); const [systemPrompt, setSystemPrompt] = useState(settings.systemPrompt); const [isSavingPrompt, setIsSavingPrompt] = useState(false); const [creatingPreset, setCreatingPreset] = useState(null); const { glossary: fullGlossary, isLoading: isLoadingGlossaryDetail } = useGlossary( selectedGlossary?.id || null ); const isPro = user?.tier === 'pro'; const isLoading = isLoadingUser || isLoadingGlossaries; useEffect(() => { setSystemPrompt(settings.systemPrompt); }, [settings]); const handleSavePrompt = async () => { setIsSavingPrompt(true); try { updateSettings({ systemPrompt }); await new Promise(resolve => setTimeout(resolve, 300)); toast({ title: t('context.saved'), description: t('context.savedDesc') }); } finally { setIsSavingPrompt(false); } }; const handleClearPrompt = () => { updateSettings({ systemPrompt: '' }); setSystemPrompt(''); }; const handleCreatePresetGlossary = async (preset: typeof PRESETS[0]) => { setCreatingPreset(preset.key); try { const token = localStorage.getItem('token'); if (!token) return; const headers: Record = { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }; const params = new URLSearchParams({ template_id: preset.templateId }); const res = await fetch(`${API_BASE}/api/v1/glossaries/import?${params.toString()}`, { method: 'POST', headers, }); if (res.ok) { const result = await res.json(); const glossary = result.data; toast({ title: t('context.presets.created'), description: t('context.presets.createdDesc', { name: glossary?.name ?? preset.title, count: String(glossary?.terms?.length ?? 0), }), }); } else { toast({ variant: 'destructive', title: t('glossaries.toast.error'), description: t('glossaries.toast.errorCreate') }); } } catch { toast({ variant: 'destructive', title: t('glossaries.toast.error'), description: t('glossaries.toast.errorImport') }); } finally { setCreatingPreset(null); } }; const handleEditClick = (id: string) => { const glossary = glossaries.find((g: GlossaryListItem) => g.id === id); if (glossary) { setSelectedGlossary(glossary); setEditDialogOpen(true); } }; const handleDeleteClick = (id: string, name: string) => { setGlossaryToDelete({ id, name }); setDeleteDialogOpen(true); }; const handleCreateGlossary = async (data: { name: string; terms: GlossaryTermInput[] }) => { try { await createGlossary(data); setCreateDialogOpen(false); toast({ title: t('glossaries.toast.created'), description: t('glossaries.toast.createdDesc', { name: data.name }), }); } catch (error) { toast({ variant: 'destructive', title: t('glossaries.toast.error'), description: t('glossaries.toast.errorCreate'), }); throw error; } }; const handleImportTemplate = async (templateId: string, name?: string) => { try { await importTemplate(templateId, name); setCreateDialogOpen(false); toast({ title: t('glossaries.toast.imported'), description: name ? t('glossaries.toast.importedDesc', { name }) : t('glossaries.toast.importedDesc', { name: templateId }), }); } catch (error) { toast({ variant: 'destructive', title: t('glossaries.toast.error'), description: t('glossaries.toast.errorImport'), }); throw error; } }; const handleSaveGlossary = async (id: string, data: { name: string; terms: GlossaryTermInput[] }) => { try { await updateGlossary(id, data); setEditDialogOpen(false); setSelectedGlossary(null); toast({ title: t('glossaries.toast.updated'), description: t('glossaries.toast.updatedDesc', { name: data.name }), }); } catch (error) { toast({ variant: 'destructive', title: t('glossaries.toast.error'), description: t('glossaries.toast.errorUpdate'), }); throw error; } }; const handleDeleteConfirm = async () => { if (!glossaryToDelete) return; try { await deleteGlossary(glossaryToDelete.id); setDeleteDialogOpen(false); setGlossaryToDelete(null); toast({ title: t('glossaries.toast.deleted'), description: t('glossaries.toast.deletedDesc'), }); } catch (error) { toast({ variant: 'destructive', title: t('glossaries.toast.error'), description: t('glossaries.toast.errorDelete'), }); } }; if (isLoading) { return (

Loading...

); } if (!isPro) { return ; } return (
{/* ── Editorial Header ───────────────────────────────────── */}
{t('glossaries.yourGlossaries')}

{t('glossaries.title')}

{t('glossaries.description')}

{/* ── System Prompt ────────────────────────────────────── */}

{t('context.instructions.title')}

{t('context.instructions.desc')}