feat(ar1-admin): riscrittura italiana + 5 tab con Testi PEC + editor form-based

Riscrittura completa di Ar1AdminConfig.js (490 -> 888 LOC) con UI italianizzata,
labels parlanti, editor form-based per layout template, tab 'Testi comunicazioni'
con editor dei 5 template email + anteprima server-side.

CAMBIAMENTI FUNZIONALI:

Tab 1 Template:
  - 'In uso' (ACTIVE/DRAFT) vs 'Archiviati' ora in DUE Card separate, non mescolati
  - Nomi varianti in italiano ('A1 — Persona Giuridica (societa, ente)', ecc)
  - Status tag italiano ('In uso', 'Archiviato', 'Bozza')
  - Editor layout: DEFAULT modalita form (Brand/Header/Intro/Privacy con campi
    espliciti nome, logo_url, colori primario+accento, titoli, saluto, corpo
    introduttivo, URL privacy, testo piede). Toggle 'Modalita avanzata (JSON raw)'
    per chi vuole editare tutto il layout_config.
  - Bottone 'Anteprima PDF' presente (placeholder toast TODO — endpoint BE da wirare)
  - Bottone 'Nuova versione' eredita automaticamente layout_config da ACTIVE corrente

Tab 2 Policy:
  - Tutti i label tradotti in italiano con help text inline per ogni campo
  - Dropdown 'Categoria documento aziendale' da GET /admin/document-categories
    (cross-schema read a gepafin_schema.document_category) invece di InputNumber
    raw. Mostra 'DURC — Documento Unico...', 'ANTIRICICLAGGIO — Dichiarazione...'
  - Switch con descrizioni espanse (cosa fa, quando si attiva)
  - Divider visivo tra campi numerici e switch booleani

Tab 3 Regole reminder:
  - Colonna 'Regola' con label italiano parlante + kind tecnico in sottotitolo
  - Colonna 'Quando parte' calcolata dinamicamente: '30 giorni PRIMA',
    'Il giorno della scadenza', '5 giorni DOPO', ecc
  - Colonna 'Ricorrenza' formattata ('una tantum' vs 'ogni 30 giorni')
  - Dialog edit: Dropdown PEC_KIND_OPTIONS con 5 etichette italiane (kind
    disabled se editing esistente), help text inline sul campo offset_days
    che cambia live ('3 giorni prima della scadenza' / 'giorno della scadenza'
    / '3 giorni dopo la scadenza')

Tab 4 Invio massivo:
  - Label italiano 'Solo aziende con AR1 scaduta' / 'Solo aziende senza AR1'
  - Pulsante 'Anteprima (non invia)' con toast descrittivo
  - Pulsante 'Invia PEC' richiede ConfirmDialog
  - Messaggio warning giallo chiarisce che la PEC sara dispatchata dal BE Gepafin
  - Box esito con matched / marked_for_pec / company_ids (trimmato a 30+…)

Tab 5 Testi comunicazioni (NUOVO):
  - Banner info + elenco variabili supportate come Tag cliccabili (7 variabili)
  - DataTable 5 righe: Tipo comunicazione (label IT + kind mono) / Oggetto /
    Versione (Tag 'v1', 'v2', ...) / Aggiornato il / Azione 'Modifica'
  - Dialog edit massimizzabile: subject + body_html (textarea monospace 10
    righe) + body_text fallback (5 righe) + note interne
  - Bottone 'Anteprima (dati di esempio)' chiama POST /admin/ar1-email-templates/
    {kind}/preview e mostra rendering HTML interpolato (dangerouslySetInnerHTML)
    con subject renderizzato + body in box stile email
  - Save bump version lato BE (toast 'Testo aggiornato (version N)')

SERVICE:
  ar1Service.js esteso da 213 -> 247 LOC:
    + listDocumentCategories (GET /admin/document-categories)
    + listEmailTemplates / getEmailTemplate / updateEmailTemplate /
      previewEmailTemplate (4 metodi admin email)

VALIDAZIONE:
  Parse-check @babel/parser plugin JSX: 2/2 OK (service + Ar1AdminConfig).
  Hot-reload CRA webpack compiled with 1 warning (solo unused-vars pre-esistenti).

COSE NON ANCORA FATTE (next):
  - Endpoint BE POST /admin/ar1-templates/:id/preview per anteprima PDF
    (wiring FE: rimuovere toast TODO dentro openEditLayout/tplActiveActionsTpl)
  - Test manuale dal browser con hard-refresh
This commit is contained in:
BFLOWS
2026-04-23 14:32:34 +02:00
parent 2028239759
commit 4a719ded5b
2 changed files with 585 additions and 153 deletions

View File

@@ -208,6 +208,40 @@ const Ar1Service = {
body: JSON.stringify(payload)
}).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
},
// ---------- ADMIN: document categories (per dropdown) ----------
listDocumentCategories(onSuccess, onError) {
fetch(`${BASE_URL}/admin/document-categories`, {
method: 'GET', mode: 'cors', headers: buildHeaders()
}).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
},
// ---------- ADMIN: email templates (Opzione 3 — tenant-agnostic, BE Gepafin pull) ----------
listEmailTemplates(onSuccess, onError) {
fetch(`${BASE_URL}/admin/ar1-email-templates`, {
method: 'GET', mode: 'cors', headers: buildHeaders()
}).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
},
getEmailTemplate(kind, onSuccess, onError) {
fetch(`${BASE_URL}/admin/ar1-email-templates/${kind}`, {
method: 'GET', mode: 'cors', headers: buildHeaders()
}).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
},
updateEmailTemplate(kind, payload, onSuccess, onError) {
fetch(`${BASE_URL}/admin/ar1-email-templates/${kind}`, {
method: 'PUT', mode: 'cors', headers: buildHeaders(),
body: JSON.stringify(payload)
}).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
},
previewEmailTemplate(kind, mockVars, onSuccess, onError) {
fetch(`${BASE_URL}/admin/ar1-email-templates/${kind}/preview`, {
method: 'POST', mode: 'cors', headers: buildHeaders(),
body: JSON.stringify(mockVars || {})
}).then(r => handleResponse(r, onSuccess, onError)).catch(e => handleError(e, onError));
},
};
export default Ar1Service;