feat(schemas): picker 3-card blank/template/clone per nuovo schema rendicontazione

Sostituisce il vecchio flusso che proponeva solo 'Inizializza con template RE-START'.
Quando il bando non ha ancora uno schema, mostra un picker a 3 card:

1. 'Nuovo schema' -> inizializzazione blank (scheletro vuoto da popolare)
2. 'Da template'  -> dropdown con template predefiniti + descrizione
3. 'Clona da bando' -> dropdown bandi con schema esistente

Nuovo componente: components/SchemaTemplatePicker.js (200 righe).
Gestisce:
- loading parallelo di templates + clonable-calls
- selezione card con border highlight primary-color
- dropdown espanso solo sulla card attiva (stopPropagation su click)
- bottone Inizia disabilitato finche la selezione non e completa
- spinner durante init, callback onInitialized con schema_json per aggiornare
  il form dell'editor senza reload pagina

Nuovo service esportato: schemaPickerService { listTemplates, listClonableCalls,
initializeSchema(callId, payload) }.

BandoRendicontazioneSchemaEdit.js: rimosso il box 'Inizializza con template RE-START',
sostituito con <SchemaTemplatePicker /> quando !hasSchema. onInitialized popola
setSchemaRecord + setForm + mostra toast di conferma. Funzione handleInitializeRestart
resta nel file (non ancora chiamata, per sicurezza rollback).
This commit is contained in:
BFLOWS
2026-04-18 18:51:57 +02:00
parent 381fd64fef
commit 8988bed952
3 changed files with 251 additions and 9 deletions

View File

@@ -22,6 +22,7 @@ import BlockingOverlay from '../../../components/BlockingOverlay';
// api
import RendicontazioneService from '../service/rendicontazioneService';
import SchemaTemplatePicker from '../components/SchemaTemplatePicker';
import BandoService from '../../../service/bando-service';
// ---------- costanti ----------
@@ -343,15 +344,25 @@ const BandoRendicontazioneSchemaEdit = () => {
)}
{!schemaLoading && !hasSchema && (
<div className="appPageSection" style={{ alignItems: 'center', padding: '3rem 2rem' }}>
<i className="pi pi-file-edit" style={{ fontSize: '3rem', color: 'var(--text-color-secondary)', marginBottom: '1rem' }} />
<h2 style={{ marginBottom: '0.5rem' }}>{__('Nessuno schema di rendicontazione per questo bando','gepafin')}</h2>
<p style={{ color: 'var(--text-color-secondary)', marginBottom: '1.5rem', textAlign: 'center' }}>
{__('Puoi inizializzarlo con un template predefinito. Per ora è disponibile il template RE-START (fondo prestiti con remissione del debito).','gepafin')}
</p>
<Button icon="pi pi-plus-circle" iconPos="right"
label={__('Inizializza con template RE-START','gepafin')}
onClick={handleInitializeRestart} severity="success" />
<div className="appPageSection">
<SchemaTemplatePicker
callId={callId}
onInitialized={(data) => {
setSchemaRecord(data);
setForm(schemaJsonToForm(data.schema_json));
setDirty(false);
toast.current?.show({
severity: 'success',
summary: __('Schema inizializzato', 'gepafin'),
detail: __('Puoi ora configurare le sezioni e salvare come bozza.', 'gepafin')
});
}}
onError={(err) => toast.current?.show({
severity: 'error',
summary: __('Inizializzazione fallita', 'gepafin'),
detail: err?.detail || err?.message
})}
/>
</div>
)}