Files
bflows-bandi-fe/src/pages/SoccorsoAddInstructorManager/index.js
Vitalii Kiiko 61389f6c43 - updated page of adding ammendment;
- updated communication form;
2025-10-14 16:40:00 +02:00

429 lines
19 KiB
JavaScript

import React, { useState, useEffect, useRef } from 'react';
import { __ } from '@wordpress/i18n';
import { useNavigate, useParams } from 'react-router-dom';
import { isEmpty } from 'ramda';
import { wrap } from 'object-path-immutable';
// store
import { storeSet, useStoreValue } from '../../store';
// api
import AmendmentsService from '../../service/amendments-service';
// tools
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
import getFormatedFileSizeText from '../../helpers/getFormatedFileSizeText';
// components
import { Skeleton } from 'primereact/skeleton';
import { Button } from 'primereact/button';
import { Checkbox } from 'primereact/checkbox';
import { Editor } from 'primereact/editor';
import { InputNumber } from 'primereact/inputnumber';
import BlockingOverlay from '../../components/BlockingOverlay';
import { Toast } from 'primereact/toast';
import { InputSwitch } from 'primereact/inputswitch';
import ApplicationEvaluationService from '../../service/application-evaluation-service';
import { Dialog } from 'primereact/dialog';
import { FileUpload } from 'primereact/fileupload';
import { defaultMaxFileSize, mimeTypes } from '../../configData';
const SoccorsoAddInstructorManager = () => {
const isAsyncRequest = useStoreValue('isAsyncRequest');
const { id } = useParams();
const navigate = useNavigate();
const [data, setData] = useState({});
const [evaluationId, setEvaluationId] = useState(0);
const [formData, setFormData] = useState({});
const [isVisibleConfirmDialog, setIsVisibleConfirmDialog] = useState(false);
const toast = useRef(null);
const ammendmentFilesRef = useRef(null);
const goToEvaluationPage = () => {
navigate(`/mie-domande/${id}`);
}
useEffect(() => {
const parsed = parseInt(id)
const entityId = !isNaN(parsed) ? parsed : 0;
storeSet('setAsyncRequest');
ApplicationEvaluationService.getEvaluationByApplId(getCallbackEvaluation, errGetCallback, [
['applicationId', entityId]
]);
}, [id]);
const getCallbackEvaluation = (data) => {
if (data.status === 'SUCCESS') {
setEvaluationId(data.data.id);
AmendmentsService.getSoccorsoByApplEvalId(data.data.id, getCallback, errGetCallback)
}
}
const getCallback = (data) => {
if (data.status === 'SUCCESS') {
setData(data.data);
setFormData(getFormattedFormData(data.data));
}
storeSet('unsetAsyncRequest');
}
const errGetCallback = (data) => {
if (toast.current && data.message) {
toast.current.show({
severity: 'error',
summary: '',
detail: data.message
});
}
set404FromErrorResponse(data);
storeSet('unsetAsyncRequest');
}
const getFormattedFormData = (data) => {
let newData = {};
newData.formFields = data.formFields;
newData.responseDays = 10;
newData.note = '';
newData.isSendNotification = true;
newData.isSendEmail = true;
return newData;
};
const renderHeader = () => {
return (
<span className="ql-formats">
<button className="ql-bold" aria-label="Bold"></button>
<button className="ql-italic" aria-label="Italic"></button>
<button className="ql-underline" aria-label="Underline"></button>
<button className="ql-link" aria-label="Link"></button>
<button className="ql-list" value="ordered"></button>
<button className="ql-header" value="2"></button>
<button className="ql-header" value="3"></button>
<button className="ql-blockquote"></button>
<button className="ql-list" value="bullet"></button>
<button className="ql-indent" value="-1"></button>
<button className="ql-indent" value="+1"></button>
</span>
);
};
const header = renderHeader();
const updateEvaluationValue = (value, path, maxValue) => {
let finalValue = value;
if (maxValue) {
finalValue = value > maxValue ? maxValue : value;
}
const newData = wrap(formData).set(path.split('.'), finalValue).value();
setFormData(newData);
}
const doCreate = () => {
storeSet('setAsyncRequest');
const updatedFormData = { ...formData };
delete updatedFormData.files;
delete updatedFormData.formFields;
const formDataToSend = new FormData();
const jsonBlob = new Blob([JSON.stringify(updatedFormData)], {
type: 'application/json'
});
formDataToSend.append('applicationAmendmentRequest', jsonBlob);
if (formData.files && formData.files.length > 0) {
formData.files.forEach((file) => {
formDataToSend.append('files', file);
});
}
AmendmentsService.createSoccorso(formDataToSend, createCallback, errCreateCallback, [
['applicationEvaluationId', evaluationId]
]);
}
const createCallback = (data) => {
if (data.status === 'SUCCESS') {
if (toast.current) {
toast.current.show({
severity: 'success',
summary: '',
detail: data.message
});
}
setTimeout(() => {
navigate(`/mie-domande/${id}/soccorso/${data.data.id}`);
}, 1000)
}
storeSet('unsetAsyncRequest');
}
const errCreateCallback = (data) => {
if (toast.current && data.message) {
toast.current.show({
severity: 'error',
summary: '',
detail: data.message
});
}
set404FromErrorResponse(data);
storeSet('unsetAsyncRequest');
}
const initCreationProcess = () => {
setIsVisibleConfirmDialog(true);
}
const headerConfirmDialog = () => {
return <span>{__('Richiesta di conferma', 'gepafin')}</span>;
}
const hideConfirmDialog = () => {
setIsVisibleConfirmDialog(false);
}
const footerConfirmDialog = () => {
return <div>
<Button type="button" label={__('No', 'gepafin')} onClick={goToEvaluationPage} outlined/>
<Button
type="button"
label={__('Si', 'gepafin')} onClick={doConfirm}/>
</div>
}
const doConfirm = () => {
setIsVisibleConfirmDialog(false);
doCreate();
}
return (
<div className="appPage">
<div className="appPage__pageHeader">
<h1>{__('Richiesta Integrazione Documentale', 'gepafin')}</h1>
</div>
<div className="appPage__spacer"></div>
<Toast ref={toast}/>
<BlockingOverlay shouldDisplay={isAsyncRequest}/>
<div className="appPageSection__row">
<Button
type="button"
outlined
onClick={goToEvaluationPage}
label={__('Indietro', 'gepafin')}
icon="pi pi-arrow-left" iconPos="left"/>
</div>
<div className="appPage__spacer"></div>
{!isAsyncRequest && !isEmpty(data)
? <div className="appPage__content">
<div className="appPageSection__withBorder column">
<p className="appPageSection__pMeta">
<span>{__('ID domanda', 'gepafin')}</span>
<span>{data.applicationId}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Bando', 'gepafin')}</span>
<span>{data.callName}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Referente Aziendale', 'gepafin')}</span>
<span>{data.beneficiaryName}</span>
</p>
</div>
<div className="appPageSection">
<div className="appPageSection columns">
<div>
<h3>{__('Pec/Email', 'gepafin')}</h3>
<div style={{marginBottom: '30px'}} translate="no">
<Editor
value={formData.note}
placeholder={__('Digita qui il messagio', 'gepafin')}
headerTemplate={header}
onTextChange={(e) => updateEvaluationValue(
e.htmlValue,
'note'
)}
style={{ height: 80 * 3, width: '100%' }}
/>
</div>
<div style={{marginBottom: '30px'}}>
<div className="appForm__field">
<label>
{__('Allegati PEC', 'gepafin')}
</label>
<FileUpload
ref={ammendmentFilesRef}
name="files[]"
multiple
accept={mimeTypes.map(o => o.code).join(',')}
maxFileSize={defaultMaxFileSize}
auto={false}
customUpload={true}
onSelect={(e) => {
updateEvaluationValue(e.files, 'files');
}}
onRemove={(e) => {
const updatedFiles = ammendmentFilesRef.current.getFiles();
updateEvaluationValue(updatedFiles, 'files');
}}
headerTemplate={(options) => {
const { chooseButton } = options;
return (
<div className="p-fileupload-buttonbar" data-pc-section="buttonbar">
{chooseButton}
</div>
);
}}
chooseOptions={{
label: __('Aggiungi i file', 'gepafin'),
icon: 'pi pi-plus'
}}
itemTemplate={(file, props) => {
return(
<div className="p-fileupload-row" data-pc-section="file">
<div data-pc-section="details" style={{display: 'flex', flexDirection: 'column', gap: '10px', textAlign: 'left'}}>
<div className="p-fileupload-filename" data-pc-section="filename">
{file.name}
</div>
<span data-pc-section="filesize">{getFormatedFileSizeText(file.size)}</span>
</div>
<div data-pc-section="actions">
<Button
type="button"
icon="pi pi-times"
className="p-button-rounded p-button-danger p-button-text"
onClick={() => props.onRemove()}
/>
</div>
</div>
)
}}
emptyTemplate={<p className="m-0">{__('Trascina i file qua')}</p>}
/>
</div>
</div>
<h3>{__('Tempo per la Risposta (giorni)', 'gepafin')}</h3>
<div style={{marginBottom: '30px'}}>
<InputNumber
keyfilter="int"
value={formData.responseDays}
showButtons
onChange={(e) => updateEvaluationValue(
e.value,
'responseDays',
9999
)}/>
</div>
<h3>{__('Notifica', 'gepafin')}</h3>
<div className="appPageSection__withBorder grey">
<div className="appForm__field row">
<InputSwitch
inputId="notify_email"
checked={formData.isSendEmail}
onChange={(e) => updateEvaluationValue(
e.value,
'isSendEmail'
)}/>
<label htmlFor="notify_email">{__('Notifiche Email', 'gepafin')}</label>
</div>
<div className="appForm__field row">
<InputSwitch
inputId="notify_push"
checked={formData.isSendNotification}
onChange={(e) => updateEvaluationValue(
e.value,
'isSendNotification'
)}/>
<label htmlFor="notify_push">{__('Notifiche Push', 'gepafin')}</label>
</div>
</div>
</div>
{formData.formFields
? <div>
<h3>{__('Documenti da Integrare', 'gepafin')}</h3>
<div className="appPageSection__withBorder grey">
<div className="appPageSection__checklist">
{formData.formFields.map((o, i) => <div key={o.fieldId}>
<Checkbox
inputId={`checklist_${o.fieldId}`}
onChange={(e) => updateEvaluationValue(
e.checked,
`formFields.${i}.selected`
)}
checked={o.selected}></Checkbox>
<label htmlFor={`checklist_${o.fieldId}`}>{o.label}</label>
</div>)}
</div>
</div>
</div>
: null}
</div>
</div>
<div className="appPageSection__message warning">
<i className="pi pi-exclamation-triangle"></i>
<span className="summary">{__('Attenzione', 'gepafin')}</span>
<span>{__('L\'invio della richiesta di integrazione sospenderà il termine di valutazione della domanda.', 'gepafin')}</span>
</div>
<div className="appPageSection__hr">
<span>{__('Azioni', 'gepafin')}</span>
</div>
<div className="appPageSection">
<div className="appPageSection__actions">
<Button
type="button"
outlined
onClick={goToEvaluationPage}
label={__('Annulla', 'gepafin')}
icon="pi pi-times" iconPos="right"/>
<Button
type="button"
onClick={initCreationProcess}
label={__('Invia richiesta', 'gepafin')}
icon="pi pi-check" iconPos="right"/>
</div>
</div>
<Dialog
visible={isVisibleConfirmDialog}
modal
header={headerConfirmDialog}
footer={footerConfirmDialog}
style={{ maxWidth: '600px', width: '100%' }}
onHide={hideConfirmDialog}>
<div className="appForm__field">
<p>{__('Soccorso istruttorio autorizzato dal direttore e autorizzazione caricata su portale a seguito del quale parte l\'email?', 'gepafin')}</p>
</div>
</Dialog>
</div>
: <>
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
<Skeleton width="100%" height="2rem" className="mb-8"></Skeleton>
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
<Skeleton width="100%" height="4rem" className="mb-8"></Skeleton>
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
<Skeleton width="100%" height="2rem" className="mb-8"></Skeleton>
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
<Skeleton width="100%" height="4rem"></Skeleton>
</>}
</div>
)
}
export default SoccorsoAddInstructorManager;