- added new role;

- added logic of statuses for amendment;
This commit is contained in:
Vitalii Kiiko
2024-12-20 17:09:49 +01:00
parent d38616fc48
commit 9c92d95a0e
17 changed files with 385 additions and 130 deletions

View File

@@ -0,0 +1,465 @@
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;