import React, { useEffect, useState, useRef, useMemo, useCallback } from 'react'; import { __ } from '@wordpress/i18n'; import { useNavigate, useParams } from 'react-router-dom'; // components import { Button } from 'primereact/button'; import { Toast } from 'primereact/toast'; import { Tag } from 'primereact/tag'; import { Skeleton } from 'primereact/skeleton'; import { ConfirmPopup, confirmPopup } from 'primereact/confirmpopup'; import { Dialog } from 'primereact/dialog'; import { InputText } from 'primereact/inputtext'; import { InputNumber } from 'primereact/inputnumber'; import { Dropdown } from 'primereact/dropdown'; import { Calendar } from 'primereact/calendar'; import { InputTextarea } from 'primereact/inputtextarea'; import { DataTable } from 'primereact/datatable'; import { Column } from 'primereact/column'; // api import RendicontazioneService from '../service/rendicontazioneService'; import FileUploadCell from '../components/FileUploadCell'; import FilePreviewDialog from '../components/FilePreviewDialog'; import CompanyDocumentPicker from '../components/CompanyDocumentPicker'; // ---------- costanti ---------- const IVA_REGIME_LABELS = { ORDINARIO: 'Ordinario (IVA non rendicontabile)', FORFETTARIO: 'Forfettario (IVA rendicontabile)', ESENTE: 'Esente' }; const CONTRACT_TYPES = [ { value: 'T_IND', label: 'Tempo indeterminato' }, { value: 'T_DET', label: 'Tempo determinato' }, { value: 'APPR', label: 'Apprendistato' }, { value: 'STAGE', label: 'Tirocinio / Stage' }, { value: 'COLL', label: 'Collaborazione coordinata' }, { value: 'ALTRO', label: 'Altro' } ]; const STATUS_TAGS = { DRAFT: { severity: 'warning', label: 'In compilazione' }, SUBMITTED: { severity: 'info', label: 'Inviata' }, UNDER_REVIEW: { severity: 'info', label: 'In valutazione' }, APPROVED: { severity: 'success', label: 'Approvata' }, REJECTED: { severity: 'danger', label: 'Respinta' }, AWAITING_AMENDMENT: { severity: 'warning', label: 'Soccorso istruttorio' } }; const euro = (v) => '€ ' + Number(v || 0).toLocaleString('it-IT', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); const formatDate = (d) => d ? new Date(d).toLocaleDateString('it-IT') : '—'; // empty invoice/employee templates const emptyInvoice = (catCode) => ({ category_code: catCode || '', invoice_number: '', invoice_date: null, payment_date: null, supplier_name: '', supplier_vat: '', description: '', taxable: null, vat: 0, total: null, pdf_filename: '' }); const emptyEmployee = () => ({ codice_fiscale: '', full_name: '', contract_type: 'T_IND', role_description: '', fte_pct: 1.0, period_start_date: null, period_end_date: null, supporting_doc_type: 'LUL', supporting_doc_filename: '' }); const PraticaRendicontazioneEdit = () => { const { id: practiceId } = useParams(); const navigate = useNavigate(); const toast = useRef(null); const [practice, setPractice] = useState(null); const [loading, setLoading] = useState(true); const [gate, setGate] = useState(null); const [customChecks, setCustomChecks] = useState([]); // v2: merge schema+values dal BE const loadCustomChecks = useCallback(() => { if (!practiceId) return; RendicontazioneService.listCustomChecks(practiceId, (resp) => setCustomChecks(resp?.data?.custom_checks || []), () => {}); // eslint-disable-next-line react-hooks/exhaustive-deps }, [practiceId]); // modal fattura const [invDialog, setInvDialog] = useState({ visible: false, data: null }); // modal dipendente ULA const [empDialog, setEmpDialog] = useState({ visible: false, data: null }); // modal risposta soccorso istruttorio const [amendDialog, setAmendDialog] = useState({ visible: false, amendment: null, responseText: '' }); // preview file const [previewDialog, setPreviewDialog] = useState({ visible: false, entityType: null, entityId: null, filename: null, title: null }); const openPreview = (entityType, entityId, title, filename) => setPreviewDialog({ visible: true, entityType, entityId, title, filename }); const closePreview = () => setPreviewDialog({ visible: false, entityType: null, entityId: null, filename: null, title: null }); // update locale riga dopo upload/delete const updateInvoiceFile = (invoiceId, fileMeta) => { setPractice(p => p ? { ...p, invoices: p.invoices.map(i => i.id === invoiceId ? { ...i, pdf_filename: fileMeta ? fileMeta.filename_original : null, storage_path: fileMeta ? fileMeta.storage_path : null, size_bytes: fileMeta ? fileMeta.size_bytes : null, } : i) } : p); }; const updateUlaFile = (empId, fileMeta) => { setPractice(p => p ? { ...p, ula_employees: p.ula_employees.map(e => e.id === empId ? { ...e, supporting_doc_filename: fileMeta ? fileMeta.filename_original : null, storage_path: fileMeta ? fileMeta.storage_path : null, size_bytes: fileMeta ? fileMeta.size_bytes : null, } : e) } : p); }; const updateDocFile = (docCode, docId, fileMeta) => { setPractice(p => { if (!p) return p; const exists = p.documents.find(d => d.doc_code === docCode); const newDocs = exists ? p.documents.map(d => d.doc_code === docCode ? { ...d, filename: fileMeta ? fileMeta.filename_original : null, storage_path: fileMeta ? fileMeta.storage_path : null, size_bytes: fileMeta ? fileMeta.size_bytes : null, } : d) : p.documents; return { ...p, documents: newDocs }; }); }; // ensure doc record exists (returns id via callback) const ensureDocRecord = (docCode, onReady) => { const existing = practice?.documents?.find(d => d.doc_code === docCode); if (existing && existing.id) { onReady(existing.id); return; } RendicontazioneService.upsertDocument(practiceId, docCode, { filename: null }, (resp) => { const newDoc = resp?.data; if (newDoc && newDoc.id) { setPractice(p => p ? { ...p, documents: [...p.documents.filter(d => d.doc_code !== docCode), newDoc] } : p); onReady(newDoc.id); } }, (err) => toast.current?.show({ severity: 'error', summary: __('Errore preparazione documento', 'gepafin'), detail: err?.detail }) ); }; // --- CompanyDocument picker state + handlers --- const [repoPicker, setRepoPicker] = useState({ visible: false, docCode: null }); const openRepositoryPicker = (docCode) => setRepoPicker({ visible: true, docCode }); const closeRepositoryPicker = () => setRepoPicker({ visible: false, docCode: null }); // quando l'utente sceglie un doc dal picker: ensure record -> link-from-repository -> update state const handleRepositoryPick = (companyDoc) => { const docCode = repoPicker.docCode; if (!docCode || !companyDoc) return; ensureDocRecord(docCode, (remDocId) => { RendicontazioneService.linkDocumentFromRepository( remDocId, companyDoc.id, (resp) => { const d = resp?.data || {}; setPractice(p => p ? { ...p, documents: p.documents.map(x => x.doc_code === docCode ? { ...x, filename: d.filename ?? companyDoc.fileName, expires_at: d.expires_at ?? null, source_company_document_id: d.source_company_document_id ?? companyDoc.id, source_status: d.source_status ?? companyDoc.status, size_bytes: null, } : x) } : p); const sev = (d.source_status === 'EXPIRED') ? 'warn' : 'success'; toast.current?.show({ severity: sev, summary: __('Documento collegato dal repository', 'gepafin'), detail: companyDoc.fileName + ' · ' + (d.source_status || companyDoc.status) }); }, (err) => toast.current?.show({ severity: 'error', summary: __('Errore link repository', 'gepafin'), detail: err?.detail }) ); }); }; // ---------- load ---------- const load = useCallback(() => { setLoading(true); RendicontazioneService.getPractice(practiceId, (resp) => { setPractice(resp?.data); setLoading(false); refreshGate(resp?.data); }, (err) => { toast.current?.show({ severity: 'error', summary: __('Errore caricamento', 'gepafin'), detail: err?.detail }); setLoading(false); } ); // eslint-disable-next-line react-hooks/exhaustive-deps }, [practiceId]); const refreshGate = (p) => { RendicontazioneService.gateCheck(practiceId, (resp) => setGate(resp?.data), () => setGate(null)); }; useEffect(() => { load(); }, [load]); useEffect(() => { loadCustomChecks(); }, [loadCustomChecks]); const readOnly = practice && practice.status !== 'DRAFT'; // ---------- derived ---------- const sections = practice?.schema_snapshot?.sections || []; const categories = useMemo(() => { const s = sections.find(x => x.type === 'category_grid') || {}; return s.categories || []; }, [sections]); const ulaSection = useMemo(() => sections.find(x => x.type === 'ula_block') || {}, [sections]); const docsSection = useMemo(() => sections.find(x => x.type === 'document_checklist') || {}, [sections]); const docsRequired = useMemo(() => { const raw = docsSection.required_types || []; return raw.map(r => typeof r === 'string' ? { code: r, label: r } : r); }, [docsSection]); // v2: custom_checks definition + values (state separato con fetch dedicato) const customChecksDefs = useMemo(() => { return practice?.schema_snapshot?.custom_checks || []; }, [practice]); const ivaAllowed = useMemo(() => { const gen = sections.find(x => x.type === 'static_fields'); const ivaField = (gen?.fields || []).find(f => f.id === 'iva_regime'); const opts = ivaField?.options || []; return opts.map(o => (typeof o === 'string' ? { value: o, label: IVA_REGIME_LABELS[o] || o } : { value: o.value, label: IVA_REGIME_LABELS[o.value] || o.label || o.value })); }, [sections]); // ---------- actions ---------- const afterMutation = (successMsg) => (resp) => { toast.current?.show({ severity: 'success', summary: successMsg }); load(); }; const onMutationError = (err) => { toast.current?.show({ severity: 'error', summary: __('Operazione fallita', 'gepafin'), detail: err?.detail || JSON.stringify(err?.message || err) }); }; const updateIvaRegime = (regime) => { RendicontazioneService.updatePractice(practiceId, { iva_regime: regime }, afterMutation(__('Regime IVA aggiornato', 'gepafin')), onMutationError); }; // invoices const openAddInvoice = (catCode) => setInvDialog({ visible: true, data: emptyInvoice(catCode) }); const saveInvoice = () => { const d = invDialog.data; // validazione minima if (!d.invoice_number || !d.invoice_date || !d.payment_date || !d.supplier_name || !d.supplier_vat || !d.description || d.taxable == null || d.total == null) { toast.current?.show({ severity: 'warn', summary: __('Campi obbligatori mancanti', 'gepafin'), detail: __('Compila tutti i campi della fattura.', 'gepafin') }); return; } const payload = { ...d, invoice_date: typeof d.invoice_date === 'string' ? d.invoice_date : d.invoice_date.toISOString().slice(0, 10), payment_date: typeof d.payment_date === 'string' ? d.payment_date : d.payment_date.toISOString().slice(0, 10) }; RendicontazioneService.addInvoice(practiceId, payload, (resp) => { setInvDialog({ visible: false, data: null }); afterMutation(__('Fattura aggiunta', 'gepafin'))(resp); }, onMutationError); }; const deleteInvoice = (e, inv) => { confirmPopup({ target: e.currentTarget, message: __('Rimuovere questa fattura?', 'gepafin'), icon: 'pi pi-exclamation-triangle', acceptLabel: __('Rimuovi', 'gepafin'), rejectLabel: __('Annulla', 'gepafin'), acceptClassName: 'p-button-danger', accept: () => RendicontazioneService.deleteInvoice(practiceId, inv.id, afterMutation(__('Fattura rimossa', 'gepafin')), onMutationError) }); }; // ula const openAddEmployee = () => setEmpDialog({ visible: true, data: emptyEmployee() }); const saveEmployee = () => { const d = empDialog.data; if (!d.codice_fiscale || !d.full_name || !d.contract_type || !d.period_start_date || !d.period_end_date || d.fte_pct == null) { toast.current?.show({ severity: 'warn', summary: __('Campi obbligatori mancanti', 'gepafin') }); return; } const payload = { ...d, period_start_date: typeof d.period_start_date === 'string' ? d.period_start_date : d.period_start_date.toISOString().slice(0, 10), period_end_date: typeof d.period_end_date === 'string' ? d.period_end_date : d.period_end_date.toISOString().slice(0, 10) }; RendicontazioneService.addUlaEmployee(practiceId, payload, (resp) => { setEmpDialog({ visible: false, data: null }); afterMutation(__('Dipendente aggiunto', 'gepafin'))(resp); }, onMutationError); }; const deleteEmployee = (e, emp) => { confirmPopup({ target: e.currentTarget, message: __('Rimuovere questo dipendente?', 'gepafin'), icon: 'pi pi-exclamation-triangle', acceptLabel: __('Rimuovi', 'gepafin'), rejectLabel: __('Annulla', 'gepafin'), acceptClassName: 'p-button-danger', accept: () => RendicontazioneService.deleteUlaEmployee(practiceId, emp.id, afterMutation(__('Dipendente rimosso', 'gepafin')), onMutationError) }); }; // v2: custom_checks const declareCustomCheck = (code, declared, file) => { RendicontazioneService.declareCustomCheck(practiceId, code, declared, file, (resp) => { toast.current?.show({ severity: 'success', summary: __('Controllo aggiornato','gepafin') }); loadCustomChecks(); }, onMutationError); }; const deleteCustomCheckDoc = (code) => { RendicontazioneService.deleteCustomCheckDocument(practiceId, code, (resp) => { toast.current?.show({ severity: 'success', summary: __('Documento rimosso','gepafin') }); loadCustomChecks(); }, onMutationError); }; // documents const upsertDocument = (docCode, filename) => { RendicontazioneService.upsertDocument(practiceId, docCode, { doc_code: docCode, filename }, afterMutation(__('Documento aggiornato', 'gepafin')), onMutationError); }; const clearDocument = (docCode) => { RendicontazioneService.clearDocument(practiceId, docCode, afterMutation(__('Documento rimosso', 'gepafin')), onMutationError); }; // submit const handleSubmit = (e) => { confirmPopup({ target: e.currentTarget, message: __('Confermi l\'invio della pratica di rendicontazione? Dopo l\'invio non potrai più modificarla.', 'gepafin'), icon: 'pi pi-exclamation-triangle', acceptLabel: __('Invia', 'gepafin'), rejectLabel: __('Annulla', 'gepafin'), acceptClassName: 'p-button-success', accept: () => RendicontazioneService.submitPractice(practiceId, (resp) => { toast.current?.show({ severity: 'success', summary: __('Pratica inviata', 'gepafin') }); load(); }, onMutationError) }); }; const submitAmendmentResponse = () => { if (!amendDialog.responseText || amendDialog.responseText.trim().length < 5) { toast.current?.show({ severity: 'warn', summary: __('Risposta troppo corta', 'gepafin') }); return; } RendicontazioneService.respondAmendmentBeneficiary( practiceId, amendDialog.amendment.id, amendDialog.responseText, (resp) => { setAmendDialog({ visible: false, amendment: null, responseText: '' }); afterMutation(__('Risposta inviata all\'istruttore', 'gepafin'))(resp); }, onMutationError); }; // ---------- render guards ---------- if (loading) { return
; } if (!practice) { return

{__('Pratica non trovata', 'gepafin')}

; } const statusCfg = STATUS_TAGS[practice.status] || { severity: 'secondary', label: practice.status }; const totals = gate?.totals || {}; const remissionDue = totals.remission_due || 0; const grandTotal = totals.grand_total || 0; const maxRemission = totals.max_remission || 0; const perCategory = totals.per_category || {}; const invoicesOfCat = (code) => practice.invoices.filter(i => i.category_code === code); return (
{/* HEADER */}

{__('Rendicontazione', 'gepafin')}

{practice.schema_snapshot?.template_label || `Bando #${practice.call_id}`}

{/* ACTIONS */}
{/* RIEPILOGO FINANZIARIO */}

{__('Riepilogo', 'gepafin')}

{__('Importo erogato', 'gepafin')}
{euro(practice.amount_erogato)}
{__('Totale fatture rendicontate', 'gepafin')}
{euro(grandTotal)}
{__('Cap remissione massimo', 'gepafin')}
{euro(maxRemission)}
{__('Remissione spettante', 'gepafin')}
{euro(remissionDue)}
{/* GATE CHECKS */} {gate && (

{__('Requisiti per invio', 'gepafin')}

{gate.checks.map((c, i) => (
{c.label}
{c.detail}
))}
)} {/* SOCCORSO ISTRUTTORIO (se presente) */} {practice.amendments && practice.amendments.length > 0 && (<>

{__('Richieste di soccorso istruttorio', 'gepafin')}

{__('L\'istruttore ha chiesto integrazioni o chiarimenti. Rispondi al più presto.', 'gepafin')}

{practice.amendments.map(a => { const statusCfg = { AWAITING: { sev: 'warning', label: 'In attesa della tua risposta' }, RESPONSE_RECEIVED: { sev: 'info', label: 'Risposta inviata, in attesa di chiusura' }, CLOSED: { sev: 'success', label: 'Chiusa' }, EXPIRED: { sev: 'danger', label: 'Scaduta' } }[a.status] || { sev: 'secondary', label: a.status }; return (
{__('Scadenza:', 'gepafin')} {new Date(a.deadline).toLocaleDateString('it-IT')}
{a.status === 'AWAITING' && (
{__('Richiesta istruttore:', 'gepafin')}
{a.request_text}
{a.response_text && (<> {__('Tua risposta:', 'gepafin')}
{a.response_text}
)}
); })}
)}
{/* SEZIONE 1: REGIME IVA */}

{__('1. Regime IVA', 'gepafin')}

e.preventDefault()}>
updateIvaRegime(e.value)} options={ivaAllowed} placeholder={__('Seleziona...', 'gepafin')} disabled={readOnly} />
{/* SEZIONE 2: FATTURE PER CATEGORIA */}

{__('2. Fatture per categoria', 'gepafin')}

{__('Carica le fatture assegnandole alla categoria di spesa appropriata. I totali si aggiornano in tempo reale.', 'gepafin')}

{categories.map((cat) => { const invs = invoicesOfCat(cat.code); const catTotal = perCategory[cat.code] || 0; return (
{cat.code} — {cat.label}
{cat.description}
{euro(catTotal)}
{invs.length} {__('fatture', 'gepafin')}
{invs.length > 0 && ( formatDate(r.invoice_date)} /> {r.description.slice(0, 40)}{r.description.length > 40 ? '…' : ''}} /> euro(r.taxable)} /> euro(r.total)} /> ( openPreview('invoice', r.id, `Fattura ${r.invoice_number}`, r.pdf_filename)} onChange={(meta) => updateInvoiceFile(r.id, meta)} toastRef={toast} /> )} /> {!readOnly && ( (
)}
); })}
{/* SEZIONE 3: ULA */} {ulaSection.enabled && (<>

{__('3. Calcolo ULA — Dipendenti', 'gepafin')}

{__('Inserisci i dipendenti che contano per l\'incremento occupazionale. Soglia minima richiesta:', 'gepafin')} {ulaSection.threshold}.

{practice.ula_employees.length > 0 && ( (CONTRACT_TYPES.find(c => c.value === r.contract_type)?.label || r.contract_type)} /> Number(r.fte_pct).toFixed(2)} /> `${formatDate(r.period_start_date)} → ${formatDate(r.period_end_date)}`} /> ( openPreview('ula', r.id, r.full_name, r.supporting_doc_filename)} onChange={(meta) => updateUlaFile(r.id, meta)} toastRef={toast} /> )} /> {!readOnly && ( (
)}
{/* SEZIONE 4: DOCUMENTI */}

{__((ulaSection.enabled ? '4.' : '3.') + ' Documenti richiesti', 'gepafin')}

{__('Carica un file per ciascun documento richiesto. In questa sandbox viene registrato solo il nome del file (upload reale al prossimo sprint).', 'gepafin')}

{docsRequired.map((dr) => { const existing = practice.documents.find(d => d.doc_code === dr.code); const hasFile = !!(existing && existing.filename); return (
{dr.label}
{dr.code}
{existing && existing.id && existing.filename ? (
openPreview('document', existing.id, dr.label, existing.filename)} onChange={(meta) => updateDocFile(dr.code, existing.id, meta)} toastRef={toast} /> {existing.source_company_document_id && ( )} {!readOnly && (
) : !readOnly ? (
) : ( {__('Nessun file', 'gepafin')} )}
); })}
{/* SEZIONE 5: CONTROLLI AGGIUNTIVI (v2) */} {customChecksDefs.length > 0 && (<>

{__((ulaSection.enabled ? '5.' : '4.') + ' Controlli aggiuntivi (dichiarazioni)', 'gepafin')}

{__('Dichiarazioni richieste dal bando oltre ai documenti standard. I controlli obbligatori devono essere tutti dichiarati prima di poter inviare la pratica.', 'gepafin')}

{customChecksDefs.map((def) => { const val = customChecks.find(c => c.code === def.code) || {}; const declared = !!val.beneficiary_declared; const hasDoc = !!val.filename_original; const isMissing = def.required && !declared; return (
declareCustomCheck(def.code, e.target.checked, null)} style={{ width: '20px', height: '20px', cursor: readOnly ? 'default' : 'pointer' }} />
{__('Dichiaro', 'gepafin')}: {def.label} {def.required && ( )} {!def.required && ( )} {val.verification_status && val.verification_status !== 'PENDING' && ( )}
{def.description && (
{def.description}
)} {def.requires_document && (
{hasDoc ? (
{val.filename_original} {val.size_bytes && ({(val.size_bytes/1024).toFixed(1)} KB)} {!readOnly && (
) : ( !readOnly && (
{__('Allega documento (PDF, JPG, PNG — max 15MB):', 'gepafin')} { const f = e.target.files?.[0]; if (f) declareCustomCheck(def.code, declared, f); e.target.value = ''; }} style={{ display: 'block', marginTop: '0.4rem' }} />
) )}
)} {val.verification_notes && (
{__('Note istruttore', 'gepafin')}: {val.verification_notes}
)}
); })}
)} {/* BOTTOM ACTIONS */} {!readOnly && (
)} {/* ---------- DIALOG FATTURA ---------- */} setInvDialog({ visible: false, data: null })}> {invDialog.data && (
{ e.preventDefault(); saveInvoice(); }}>
setInvDialog(d => ({ ...d, data: { ...d.data, invoice_number: e.target.value } }))} />
setInvDialog(d => ({ ...d, data: { ...d.data, invoice_date: e.value } }))} />
setInvDialog(d => ({ ...d, data: { ...d.data, payment_date: e.value } }))} />
setInvDialog(d => ({ ...d, data: { ...d.data, supplier_name: e.target.value } }))} />
setInvDialog(d => ({ ...d, data: { ...d.data, supplier_vat: e.target.value } }))} />
setInvDialog(d => ({ ...d, data: { ...d.data, description: e.target.value } }))} />
setInvDialog(d => ({ ...d, data: { ...d.data, taxable: e.value } }))} />
setInvDialog(d => ({ ...d, data: { ...d.data, vat: e.value } }))} />
setInvDialog(d => ({ ...d, data: { ...d.data, total: e.value } }))} />
{__('Dopo aver salvato la fattura potrai caricare il PDF dalla tabella.', 'gepafin')}
)}
{/* ---------- DIALOG RISPOSTA SOCCORSO ---------- */} setAmendDialog({ visible: false, amendment: null, responseText: '' })}> {amendDialog.amendment && (
{ e.preventDefault(); submitAmendmentResponse(); }}>
{__('Richiesta istruttore:', 'gepafin')}
{amendDialog.amendment.request_text}
setAmendDialog(d => ({ ...d, responseText: e.target.value }))} placeholder={__('Descrivi le integrazioni fornite, allegati caricati, chiarimenti...', 'gepafin')} />
)}
{/* ---------- DIALOG DIPENDENTE ULA ---------- */} setEmpDialog({ visible: false, data: null })}> {empDialog.data && (
{ e.preventDefault(); saveEmployee(); }}>
setEmpDialog(d => ({ ...d, data: { ...d.data, codice_fiscale: e.target.value.toUpperCase() } }))} />
setEmpDialog(d => ({ ...d, data: { ...d.data, full_name: e.target.value } }))} />
setEmpDialog(d => ({ ...d, data: { ...d.data, contract_type: e.value } }))} />
setEmpDialog(d => ({ ...d, data: { ...d.data, role_description: e.target.value } }))} />
setEmpDialog(d => ({ ...d, data: { ...d.data, fte_pct: e.value } }))} />
setEmpDialog(d => ({ ...d, data: { ...d.data, period_start_date: e.value } }))} />
setEmpDialog(d => ({ ...d, data: { ...d.data, period_end_date: e.value } }))} />
typeof t === 'string' ? { value: t, label: t } : { value: t.code, label: t.label })} onChange={(e) => setEmpDialog(d => ({ ...d, data: { ...d.data, supporting_doc_type: e.value } }))} />
{__("Dopo aver salvato il dipendente potrai caricare il LUL o il documento di supporto dalla tabella.", 'gepafin')}
)}
d.doc_code === repoPicker.docCode) || {}).source_company_document_id || null} onHide={closeRepositoryPicker} onSelect={handleRepositoryPick} /> ); }; export default PraticaRendicontazioneEdit;