Files
bflows-bandi-fe/src/pages/SoccorsoEditBeneficiario/index.js
Vitalii Kiiko 9c92d95a0e - added new role;
- added logic of statuses for amendment;
2024-12-20 17:09:49 +01:00

465 lines
20 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState, useEffect, useRef, useMemo } from 'react';
import { __, sprintf } from '@wordpress/i18n';
import { useNavigate, useParams } from 'react-router-dom';
import { is, isEmpty } from 'ramda';
import { useForm } from 'react-hook-form';
import { klona } from 'klona';
import { wrap } from 'object-path-immutable';
// store
import { storeSet, useStore } from '../../store';
// api
import AmendmentsService from '../../service/amendments-service';
import ApplicationService from '../../service/application-service';
// tools
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
import getBandoLabel from '../../helpers/getBandoLabel';
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
import renderHtmlContent from '../../helpers/renderHtmlContent';
// components
import { Button } from 'primereact/button';
import BlockingOverlay from '../../components/BlockingOverlay';
import { Toast } from 'primereact/toast';
import { Dialog } from 'primereact/dialog';
import FormField from '../../components/FormField';
import SoccorsoComunications from '../SoccorsoEditPreInstructor/components/SoccorsoComunications';
import { Editor } from 'primereact/editor';
const SoccorsoEditBeneficiario = () => {
const isAsyncRequest = useStore().main.isAsyncRequest();
const { id } = useParams();
const navigate = useNavigate();
const [data, setData] = useState({});
const [dataAppl, setDataAppl] = useState({});
const [isVisibleEmailDialog, setIsVisibleEmailDialog] = useState(false);
const toast = useRef(null);
const [formInitialData, setFormInitialData] = useState({});
const {
control,
handleSubmit,
formState: { errors },
setValue,
register,
trigger,
getValues
} = useForm({
defaultValues: useMemo(() => {
return formInitialData;
}, [formInitialData]), mode: 'onChange'
});
const goToArchivePage = () => {
navigate(`/domande`);
}
useEffect(() => {
const parsedId = parseInt(id);
const entityId = !isNaN(parsedId) ? parsedId : 0;
AmendmentsService.getSoccorsoByApplId(entityId, getCallback, errGetCallback, [
['statuses', 'AWAITING']
]);
}, [id]);
const getCallback = (data) => {
if (data.status === 'SUCCESS') {
if (data.data.length) {
const amendmentObj = data.data[0];
setData(getFormattedData(amendmentObj));
let formDataInitial = amendmentObj.applicationFormFields.reduce((acc, cur) => {
if (cur.fieldValue) {
acc[cur.fieldId] = cur.fieldValue;
}
return acc;
}, {});
formDataInitial = {
...formDataInitial,
amendmentDocuments: amendmentObj.amendmentDocuments
}
setFormInitialData(formDataInitial);
storeSet.main.unsetAsyncRequest();
} else {
ApplicationService.getApplication(id, getApplCallback, errGetCallback)
}
}
}
const errGetCallback = (data) => {
if (toast.current && data.message) {
toast.current.show({
severity: 'error',
summary: '',
detail: data.message
});
}
set404FromErrorResponse(data);
storeSet.main.unsetAsyncRequest();
}
const getApplCallback = (data) => {
if (data.status === 'SUCCESS') {
setDataAppl(getFormattedData(data.data));
}
storeSet.main.unsetAsyncRequest();
}
const getFormattedData = (data) => {
data.evaluationEndDate = is(String, data.evaluationEndDate) ? new Date(data.evaluationEndDate) : (data.evaluationEndDate ? data.evaluationEndDate : '');
data.startDate = is(String, data.startDate) ? new Date(data.startDate) : (data.startDate ? data.startDate : '');
data.expirationDate = is(String, data.expirationDate) ? new Date(data.expirationDate) : (data.expirationDate ? data.expirationDate : '');
return data;
};
const onSubmit = () => {
};
const doUpdateAmendment = (doClose = false) => {
trigger();
let formValues = klona(getValues());
const newFormValues = Object.keys(formValues)
.filter(v => v !== 'amendmentDocuments')
.reduce((acc, cur) => {
let fieldVal = formValues[cur];
fieldVal = isEmpty(fieldVal) ? null : fieldVal;
fieldVal = is(Array, fieldVal) ? fieldVal.map(o => o.id).join(',') : null;
acc.push({
'fieldId': cur,
'fieldValue': fieldVal
});
return acc;
}, []);
const newAmendDocs = formValues.amendmentDocuments
? formValues.amendmentDocuments.map(o => o.id).join(',')
: '';
const submitData = {
applicationFormFields: newFormValues,
amendmentDocuments: newAmendDocs,
amendmentNotes: data.amendmentNotes
}
const amendmentId = data.id;
storeSet.main.setAsyncRequest();
AmendmentsService.updateSoccorso(
amendmentId,
submitData,
(resp) => updateAmendmentCallback(resp, doClose),
errUpdateAmendmentCallback
);
}
const doUpdateAmendmentAndCompleteTask = () => {
doUpdateAmendment(true);
}
const updateAmendmentCallback = (data, doClose = false) => {
if (data.status === 'SUCCESS') {
setData(getFormattedData(data.data));
if (doClose) {
AmendmentsService.updateStatusSoccorso(data.data.id, updateAmendmentCallback, errUpdateAmendmentCallback, [
['status', 'RESPONSE_RECEIVED']
]);
} else {
if (toast.current) {
toast.current.show({
severity: 'success',
summary: '',
detail: data.message
});
}
let formDataInitial = data.data.applicationFormFields.reduce((acc, cur) => {
if (cur.fieldValue) {
acc[cur.fieldId] = cur.fieldValue;
}
return acc;
}, {});
formDataInitial = {
...formDataInitial,
amendmentDocuments: data.data.amendmentDocuments
}
setFormInitialData(formDataInitial);
}
}
storeSet.main.unsetAsyncRequest();
}
const errUpdateAmendmentCallback = (data) => {
if (toast.current && data.message) {
toast.current.show({
severity: 'error',
summary: '',
detail: data.message
});
}
//set404FromErrorResponse(data);
storeSet.main.unsetAsyncRequest();
}
const updateNewAmendmentData = (value, path) => {
const newData = wrap(data).set(path, value).value();
setData(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();
useEffect(() => {
if (formInitialData) {
//reset();
Object.keys(formInitialData).map(k => setValue(k, formInitialData[k]));
trigger();
}
}, [formInitialData]);
return (
<div className="appPage">
<div className="appPage__pageHeader">
{data.id
? <h1>
{sprintf(__('Soccorso Istruttorio: richiesta integrazione documenti per domanda #%s', 'gepafin'), id)}
</h1> : null}
{dataAppl.id
? <h1>
{sprintf(__('Dettagli: domanda #%s', 'gepafin'), dataAppl.id)}
</h1> : null}
</div>
<div className="appPage__spacer"></div>
<Toast ref={toast}/>
<BlockingOverlay shouldDisplay={isAsyncRequest}/>
<div className="appPageSection__row">
<Button
type="button"
outlined
onClick={goToArchivePage}
label={__('Indietro', 'gepafin')}
icon="pi pi-arrow-left" iconPos="left"/>
</div>
<div className="appPage__spacer"></div>
<div className="appPage__content">
{data.id
? <div className="appPageSection__withBorder columns">
<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>{__('Beneficiario', 'gepafin')}</span>
<span>{data.beneficiaryName}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Azienda', 'gepafin')}</span>
<span></span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Inizio', 'gepafin')}</span>
<span>{getDateFromISOstring(data.startDate)}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Scadenza', 'gepafin')}</span>
<span>{getDateFromISOstring(data.expirationDate)}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Stato', 'gepafin')}</span>
<span>{getBandoLabel(data.status)}</span>
</p>
</div> : null}
{dataAppl.id
? <div className="appPageSection__withBorder columns">
<p className="appPageSection__pMeta">
<span>{__('ID domanda', 'gepafin')}</span>
<span>{dataAppl.id}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Bando', 'gepafin')}</span>
<span>{dataAppl.callTitle}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Azienda', 'gepafin')}</span>
<span>{dataAppl.companyName}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Inviato', 'gepafin')}</span>
<span>{getDateFromISOstring(dataAppl.submissionDate)}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Protocolo', 'gepafin')}</span>
<span>{dataAppl.protocolNumber}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Stato', 'gepafin')}</span>
<span>{getBandoLabel(dataAppl.status)}</span>
</p>
</div> : null}
{data.id
? <div className="appPageSection">
<h2>{__('Dettagli Richiesta', 'gepafin')}</h2>
<h3>{__('Note e spiegazioni', 'gepafin')}</h3>
<div className="appPageSection__withBorder grey ql-editor"
style={{ minHeight: '100px' }}>
{renderHtmlContent(data.note)}
</div>
</div> : null}
{data.id
? <div className="appPageSection">
<h2>{__('Comunicazioni', 'gepafin')}</h2>
<SoccorsoComunications amendmentId={data.id} soccorsoStatus={data.status}/>
</div> : null}
{data.id
? <div className="appPageSection">
<h3>{__('Documenti Richiesti', 'gepafin')}</h3>
<form className="appForm" onSubmit={handleSubmit(onSubmit)}>
{data.formFields
? data.formFields.map((o, i) => {
return <FormField
key={o.fieldId}
disabled={data.status !== 'AWAITING'}
type="fileupload"
setDataFn={setValue}
saveFormCallback={doUpdateAmendment}
fieldName={o.fieldId}
label={o.label}
control={control}
register={register}
errors={errors}
defaultValue={formInitialData[o.fieldId] ? formInitialData[o.fieldId] : []}
accept={[]}
source="AMENDMENT"
sourceId={data.id}
multiple={true}
/>
}) : null}
</form>
<ol className="appPageSection__list">
{data.formFields
? data.formFields.map((o, i) => <li key={o.fieldId}
style={{ flexDirection: 'row' }}>
<span>{o.label}</span>
</li>) : null}
</ol>
</div> : null}
{data.id
? <div className="appPageSection">
<h2>{__('Documenti aggiuntivi', 'gepafin')}</h2>
<div className="appPageSection">
<h3>{__('Notes', 'gepafin')}</h3>
<div style={{ marginBottom: '30px', width: '100%', position: 'relative' }}>
<BlockingOverlay shouldDisplay={data.status !== 'AWAITING'}/>
<Editor
value={data.amendmentNotes}
readOnly={data.status !== 'AWAITING'}
placeholder={__('Digita qui il messagio', 'gepafin')}
headerTemplate={header}
onTextChange={(e) => updateNewAmendmentData(
e.htmlValue,
'amendmentNotes'
)}
style={{ height: 80 * 3, width: '100%' }}
/>
</div>
<FormField
type="fileupload"
disabled={data.status !== 'AWAITING'}
setDataFn={setValue}
saveFormCallback={doUpdateAmendment}
fieldName="amendmentDocuments"
label={__('I file', 'gepafin')}
control={control}
register={register}
errors={errors}
defaultValue={formInitialData.amendmentDocuments ? formInitialData.amendmentDocuments : []}
accept={[]}
source="amendment"
sourceId={data.id}
multiple={true}
/>
</div>
</div> : null}
{data.id
? <div className="appPageSection__message warning">
<i className="pi pi-exclamation-triangle"></i>
<span className="summary">{__('Attenzione', 'gepafin')}</span>
<span>{__('Inviare la documentazione richiesta completa delle integrazioni esclusivamente via PEC. In caso contarrio lintegrazione non può essere ritenuta valida.', 'gepafin')}</span>
</div> : null}
<div className="appPageSection">
<div className="appPageSection__actions">
{data.id
? <Button
type="button"
disabled={isAsyncRequest || data.status !== 'AWAITING'}
onClick={doUpdateAmendmentAndCompleteTask}
label={__('Invia documenti', 'gepafin')}
icon="pi pi-save" iconPos="right"/> : null}
{data.id
? <Button
type="button"
outlined
disabled={isAsyncRequest || data.status !== 'AWAITING'}
onClick={() => doUpdateAmendment()}
label={__('Salva bozza', 'gepafin')}
icon="pi pi-save" iconPos="right"/> : null}
<Button
type="button"
outlined
onClick={goToArchivePage}
label={__('Indietro', 'gepafin')}
icon="pi pi-times" iconPos="right"/>
</div>
</div>
</div>
<Dialog
header={__('Invia documenti', 'gepafin')}
visible={isVisibleEmailDialog}
style={{ width: '50vw' }}
onHide={() => {
if (!isVisibleEmailDialog) return;
setIsVisibleEmailDialog(false);
}}>
<p className="m-0">
{data.callEmail}
</p>
</Dialog>
</div>
)
}
export default SoccorsoEditBeneficiario;