'use client'; import { useState, useTransition } from 'react'; import { MESSAGE_MAX_CHARS } from '@/lib/screen/contract'; import { deleteTemplate, saveTemplate, setTemplateTranslation, translateTemplate, } from './actions'; export type TemplateRow = { id: string; textFr: string; textEn: string | null; translationStatus: 'PENDING' | 'DONE' | 'MANUAL' | 'ERROR'; sortOrder: number; }; const STATUS: Record = { PENDING: { label: 'traduction en attente', className: 'bg-[var(--surface-muted)] text-[var(--ink-muted)]' }, DONE: { label: 'traduit', className: 'bg-[var(--success-tint)] text-[var(--success)]' }, MANUAL: { label: 'traduction manuelle', className: 'bg-[var(--accent-tint)] text-[var(--accent-ink)]' }, ERROR: { label: 'traduction en échec', className: 'bg-[var(--danger-tint)] text-[var(--danger)]' }, }; export default function TemplateManager({ canEdit, templates, }: { canEdit: boolean; templates: TemplateRow[]; }) { const [textFr, setTextFr] = useState(''); const [pending, startTransition] = useTransition(); const [message, setMessage] = useState<{ kind: 'ok' | 'error'; text: string } | null>(null); const remaining = MESSAGE_MAX_CHARS - textFr.length; function run(work: () => Promise<{ ok: true } | { ok: false; error: string }>, success: string) { setMessage(null); startTransition(async () => { const result = await work(); setMessage(result.ok ? { kind: 'ok', text: success } : { kind: 'error', text: result.error }); }); } function create() { setMessage(null); startTransition(async () => { const saved = await saveTemplate({ textFr, sortOrder: templates.length }); if (!saved.ok) { setMessage({ kind: 'error', text: saved.error }); return; } setTextFr(''); setMessage({ kind: 'ok', text: 'Modèle enregistré. Traduction en cours…' }); const translated = await translateTemplate(saved.value.id); setMessage( translated.ok ? { kind: 'ok', text: 'Modèle enregistré et traduit.' } : { kind: 'error', text: `Modèle enregistré, mais la traduction a échoué : ${translated.error}` }, ); }); } return (
{message ? (

{message.text}

) : null} {canEdit ? (

Nouveau modèle

{remaining >= 0 ? `${remaining} caractères restants.` : `${-remaining} caractères de trop : le message serait coupé sur l’écran.`}

) : null}

Modèles enregistrés

{templates.length === 0 ? (

Aucun modèle. Ceux que vous ajoutez ici seront proposés partout où l’on compose un message.

) : (
    {templates.map((row) => ( ))}
)}
); } function TemplateCard({ row, canEdit, pending, run, startTransition, setMessage, }: { row: TemplateRow; canEdit: boolean; pending: boolean; run: (work: () => Promise<{ ok: true } | { ok: false; error: string }>, success: string) => void; startTransition: (work: () => void) => void; setMessage: (value: { kind: 'ok' | 'error'; text: string } | null) => void; }) { const [draftEn, setDraftEn] = useState(row.textEn ?? ''); const badge = STATUS[row.translationStatus]; return (
  • {row.textFr}

    {badge.label}
    {canEdit ? (
    ) : row.textEn ? (

    {row.textEn}

    ) : null}
  • ); }