- update to contract functionality;

This commit is contained in:
Vitalii Kiiko
2025-11-10 12:00:44 +01:00
parent afaa750f43
commit 31413399b0
4 changed files with 210 additions and 474 deletions

View File

@@ -1,12 +1,12 @@
import React, { useEffect, useState, useCallback } from 'react';
import React, { useEffect, useState, useCallback, useRef } from 'react';
import { __ } from '@wordpress/i18n';
import { is } from 'ramda';
import { is, isEmpty } from 'ramda';
import { Link } from 'react-router-dom';
import translationStrings from '../../../../translationStringsForComponents';
// store
import { useStoreValue } from '../../../../store';
import { storeSet, useStoreValue } from '../../../../store';
// api
import ApplicationService from '../../../../service/application-service';
@@ -25,8 +25,18 @@ import ProperBandoLabel from '../../../../components/ProperBandoLabel';
import { Dropdown } from 'primereact/dropdown';
import { Tag } from 'primereact/tag';
import { Calendar } from 'primereact/calendar';
import { Toast } from 'primereact/toast';
import { classNames } from 'primereact/utils';
import { FileUpload } from 'primereact/fileupload';
import { defaultMaxFileSize } from '../../../../configData';
import getFormatedFileSizeText from '../../../../helpers/getFormatedFileSizeText';
import { Dialog } from 'primereact/dialog';
import { wrap } from 'object-path-immutable';
import ApplicationContractService from '../../../../service/application-contract-service';
import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
const AllDomandeBeneficiarioTableAsync = ({ statuses }) => {
const isAsyncRequest = useStoreValue('isAsyncRequest');
const chosenCompanyId = useStoreValue('chosenCompanyId');
const companies = useStoreValue('companies');
const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
@@ -47,6 +57,13 @@ const AllDomandeBeneficiarioTableAsync = ({ statuses }) => {
applicationStatus: { value: null, matchMode: 'equals' }
}
});
const [isVisibleContractForm, setIsVisibleContractForm] = useState(false);
const [contractFormData, setContractFormData] = useState({
subject: '',
text: ''
});
const contractFormFilesRef = useRef(null);
const toast = useRef(null);
const getPaginationQuery = useCallback(() => getQueryParamsForPaginatedEndpoint(lazyState, statuses, 'id'), [lazyState]);
@@ -68,7 +85,8 @@ const AllDomandeBeneficiarioTableAsync = ({ statuses }) => {
const getCallback = (resp) => {
if (resp.status === 'SUCCESS') {
const { body, totalRecords,
const {
body, totalRecords,
//currentPage, totalPages, pageSize
} = resp.data;
setTotalRecordsNum(totalRecords);
@@ -101,6 +119,14 @@ const AllDomandeBeneficiarioTableAsync = ({ statuses }) => {
<Button severity="info" label={__('Anteprima', 'gepafin')} icon="pi pi-eye" size="small"
iconPos="right"/>
</Link>
{rowData.status === 'APPROVED'
? <Button severity="success"
label={__('Invia contratto firmato', 'gepafin')}
icon="pi pi-upload" size="small"
iconPos="right" onClick={() => {
openSendContractForm();
}}/>
: null}
</div>
}
@@ -141,6 +167,91 @@ const AllDomandeBeneficiarioTableAsync = ({ statuses }) => {
return getFormattedDateString(rowData.submissionDate);
};
const openSendContractForm = () => {
setContractFormData({
subject: '',
text: ''
});
setIsVisibleContractForm(true);
};
const headerContractDialog = () => {
return <span>{__('Invia il contratto', 'gepafin')}</span>;
}
const hideContractDialog = () => {
setIsVisibleContractForm(false);
setContractFormData({
subject: '',
text: ''
});
}
const footerContractDialog = useCallback(() => {
let isDisabled = !contractFormData.files || isEmpty(contractFormData.files) || isAsyncRequest;
return <div>
<Button type="button" label={__('Annulla', 'gepafin')} onClick={hideContractDialog} outlined/>
<Button
type="button"
disabled={isDisabled}
label={__('Invia', 'gepafin')} onClick={doSendContract}/>
</div>
}, [contractFormData]);
const updateContractFormData = (value, path) => {
const newData = wrap(contractFormData).set(path.split('.'), value).value();
setContractFormData(newData);
};
const doSendContract = useCallback(() => {
if (contractFormData.files && !isEmpty(contractFormData.files) && !isAsyncRequest) {
const formDataToSend = new FormData();
if (contractFormData.files && contractFormData.files.length > 0) {
contractFormData.files.forEach((file) => {
formDataToSend.append('beneficiaryContractDocuments', file);
});
}
storeSet('setAsyncRequest');
ApplicationContractService.updateApplicationContract(
contractFormData.id,
formDataToSend,
getUploadApplicationContractCallback,
errGetUploadApplicationContractCallback
);
}
}, [contractFormData]);
const getUploadApplicationContractCallback = (data) => {
if (data.status === 'SUCCESS') {
if (toast.current && data.message) {
toast.current.show({
severity: 'success',
summary: '',
detail: data.message
});
}
}
hideContractDialog();
storeSet('unsetAsyncRequest');
}
const errGetUploadApplicationContractCallback = (data) => {
if (toast.current && data.message) {
toast.current.show({
severity: data.status === 'SUCCESS' ? 'info' : 'error',
summary: '',
detail: data.message
});
}
hideContractDialog();
set404FromErrorResponse(data);
storeSet('unsetAsyncRequest');
}
useEffect(() => {
setLocalAsyncRequest(true);
const paginationQuery = getPaginationQuery();
@@ -193,6 +304,82 @@ const AllDomandeBeneficiarioTableAsync = ({ statuses }) => {
<Column header={__('Azioni', 'gepafin')}
body={actionsBodyTemplate}/>
</DataTable>
<Toast ref={toast}/>
<Dialog
visible={isVisibleContractForm}
modal
header={headerContractDialog}
footer={footerContractDialog}
style={{ maxWidth: '600px', width: '100%' }}
onHide={hideContractDialog}>
<div className="appForm__field">
<p>Ricarica il contratto formato digitalmente:</p>
</div>
<div className="appForm__field">
<label
className={classNames({ 'p-error': !contractFormData.files || isEmpty(contractFormData.files) })}>
{__('Files', 'gepafin')}* (p7m)
</label>
<FileUpload
ref={contractFormFilesRef}
name="files[]"
multiple
accept=".p7m,application/pkcs7-mime,application/x-pkcs7-mime"
maxFileSize={defaultMaxFileSize}
auto={false}
customUpload={true}
className={classNames({ 'p-invalid': !contractFormData.files || isEmpty(contractFormData.files) })}
onSelect={(e) => {
updateContractFormData(e.files, 'files');
}}
onRemove={(e) => {
const updatedFiles = contractFormFilesRef.current.getFiles();
updateContractFormData(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>
</Dialog>
</div>
)
}