Merge pull request #49 from Kitzanos/feature-163/re-admit-rejected-application

Re-admit functionality
This commit is contained in:
Vitalii Kiiko
2025-05-14 15:41:19 +02:00
committed by GitHub
9 changed files with 194 additions and 78 deletions

View File

@@ -295,8 +295,9 @@
.appPageSection__message {
display: flex;
align-items: center;
width: 100%;
gap: 20px;
background: rgba(255, 242, 226, 0.7);
background: rgba(242, 242, 242, 0.7);
border-style: solid;
border-width: 0 0 0 6px;
padding: 1.25rem 1.75rem;
@@ -409,10 +410,14 @@
.appPageSection__actions {
display: flex;
gap: 24px;
padding: 24px 0 48px;
padding: 24px 0 0;
flex-wrap: wrap;
}
.appPageSection .appPageSection__actions:last-of-type {
padding-bottom: 48px;
}
.appPageSection__actions:empty {
display: none;
}

View File

@@ -27,6 +27,7 @@ import { Button } from 'primereact/button';
import { Link, useNavigate } from 'react-router-dom';
import getQueryParamsForPaginatedEndpoint from '../../../../helpers/getQueryParamsForPaginatedEndpoint';
import SoccorsoResendEmails from '../../../SoccorsoEditPreInstructor/components/SoccorsoResendEmails';
import EvaluationReAdmit from '../../../DomandaEditPreInstructor/components/EvaluationReAdmit';
const APP_HUB_ID = process.env.REACT_APP_HUB_ID;
@@ -166,6 +167,7 @@ const MieDomandeTableInstructorManagerAsync = ({ userId = null, statuses = [] })
to={`/mie-domande/${rowData.applicationId}`}>
<Button severity="info" label={label} icon="pi pi-eye" size="small" iconPos="right"/>
</Link>
<EvaluationReAdmit id={rowData.applicationId} status={rowData.applicationStatus}/>
<SoccorsoResendEmails
emailsData={rowData.emailSendResponse}
setDataEmailsSoccorso={(updateResponse) => updateRowData(rowData.id, updateResponse)}/>

View File

@@ -15,6 +15,7 @@ import { useStoreValue } from '../../../../store';
import getFormattedDateString from '../../../../helpers/getFormattedDateString';
import getBandoLabel from '../../../../helpers/getBandoLabel';
import getBandoSeverity from '../../../../helpers/getBandoSeverity';
import getQueryParamsForPaginatedEndpoint from '../../../../helpers/getQueryParamsForPaginatedEndpoint';
// components
import { DataTable } from 'primereact/datatable';
@@ -25,8 +26,8 @@ import { Tag } from 'primereact/tag';
import { Calendar } from 'primereact/calendar';
import { Button } from 'primereact/button';
import { Link, useNavigate } from 'react-router-dom';
import getQueryParamsForPaginatedEndpoint from '../../../../helpers/getQueryParamsForPaginatedEndpoint';
import SoccorsoResendEmails from '../../../SoccorsoEditPreInstructor/components/SoccorsoResendEmails';
import EvaluationReAdmit from '../../../DomandaEditPreInstructor/components/EvaluationReAdmit';
const APP_HUB_ID = process.env.REACT_APP_HUB_ID;
@@ -166,15 +167,11 @@ const DomandeTablePreInstructorAsync = ({ userId = null, statuses = [] }) => {
<Link to={`/domande/${rowData.applicationId}`}>
<Button severity="info" label={label} icon="pi pi-eye" size="small" iconPos="right"/>
</Link>
{rowData.applicationStatus === 'REJECTED' && (
<Button
severity="success"
label={__('Riammetti', 'gepafin')}
icon="pi pi-arrow-circle-up"
size="small"
iconPos="right"
/>
)}
<Link to={`/domande/${rowData.applicationId}/preview`}>
<Button severity="info" label={__('Anteprima', 'gepafin')} icon="pi pi-eye" size="small"
iconPos="right"/>
</Link>
<EvaluationReAdmit id={rowData.applicationId} status={rowData.applicationStatus}/>
<SoccorsoResendEmails
emailsData={rowData.emailSendResponse}
setDataEmailsSoccorso={(updateResponse) => updateRowData(rowData.id, updateResponse)}/>

View File

@@ -53,6 +53,7 @@ import ApplicationInfo from '../DomandaEditPreInstructor/components/ApplicationI
import ApplicationDownloadFiles from '../DomandaEditPreInstructor/components/ApplicationDownloadFiles';
import FormField from '../../components/FormField';
import SoccorsoResendEmails from '../SoccorsoEditPreInstructor/components/SoccorsoResendEmails';
import EvaluationReAdmit from '../DomandaEditPreInstructor/components/EvaluationReAdmit';
const APP_EVALUATION_FLOW_ID = process.env.REACT_APP_EVALUATION_FLOW_ID;
const APP_HUB_ID = process.env.REACT_APP_HUB_ID;
@@ -875,11 +876,29 @@ const DomandaEditInstructorManager = () => {
</div>
}
const auxActions = () => {
return <div className="appPageSection__actions">
<SoccorsoResendEmails
emailsData={emailSendResponse}
setDataEmailsSoccorso={updateEmailSendResponses}/>
<EvaluationReAdmit id={data.applicationId} status={data.applicationStatus}/>
</div>
}
const updateEmailSendResponses = useCallback((newEmailData) => {
const newData = wrap(data).set(['emailSendResponse'], newEmailData).value();
setData(newData);
}, [data]);
const motivationMsg = () => {
return data.motivation && !isEmpty(data.motivation) && ['REJECTED', 'APPROVED'].includes(data.applicationStatus)
? <div className="appPageSection__message info">
<i className="pi pi-info-circle"></i>
<span className="summary">{__('Motivazione:', 'gepafin')}</span>
<span>{renderHtmlContent(data.motivation)}</span>
</div> : null
}
useEffect(() => {
let updatedFormValues = klona(formValues);
let context = {};
@@ -971,19 +990,21 @@ const DomandaEditInstructorManager = () => {
? <div className="appPage__content">
<ApplicationInfo data={data}/>
<div className="appPageSection">
{motivationMsg()}
</div>
<div className="appPageSection__hr">
<span>{__('Azioni rapide', 'gepafin')}</span>
</div>
<div className="appPageSection">
{actionBtns()}
<div className="appPageSection__actions">
<SoccorsoResendEmails
emailsData={emailSendResponse}
setDataEmailsSoccorso={updateEmailSendResponses}/>
</div>
{auxActions()}
</div>
<div className="appPageSection__hr"></div>
<ApplicationDownloadFiles id={id}/>
<div className="appPageSection">
@@ -1008,6 +1029,23 @@ const DomandaEditInstructorManager = () => {
sourceName="evaluation"/>
</div>
<div className="appPageSection">
<h2>{__('Note', 'gepafin')}</h2>
<div translate="no" style={{ 'width': '100%' }}>
<Editor
value={data.note}
readOnly={shouldDisableField('note') || evaluationBlockedForUser(data)}
placeholder={__('Digita qui il messagio', 'gepafin')}
headerTemplate={header}
onTextChange={(e) => updateEvaluationValue(
e.htmlValue,
['note']
)}
style={{ height: 80 * 3, width: '100%' }}
/>
</div>
</div>
{data.evaluationVersion === 'V2'
? <div className="appPageSection">
<h2>{__('Documenti allegati', 'gepafin')}</h2>
@@ -1120,21 +1158,6 @@ const DomandaEditInstructorManager = () => {
</div>)}
</div>
</div>
<h3>{__('Note', 'gepafin')}</h3>
<div translate="no">
<Editor
value={data.note}
readOnly={shouldDisableField('note') || evaluationBlockedForUser(data)}
placeholder={__('Digita qui il messagio', 'gepafin')}
headerTemplate={header}
onTextChange={(e) => updateEvaluationValue(
e.htmlValue,
['note']
)}
style={{ height: 80 * 3, width: '100%' }}
/>
</div>
</div>
<div>
<h3>{__('Documenti allegati', 'gepafin')}</h3>
@@ -1253,11 +1276,7 @@ const DomandaEditInstructorManager = () => {
<div className="appPageSection">
{actionBtns()}
<div className="appPageSection__actions">
<SoccorsoResendEmails
emailsData={emailSendResponse}
setDataEmailsSoccorso={updateEmailSendResponses}/>
</div>
{auxActions()}
</div>
<Dialog
@@ -1265,7 +1284,7 @@ const DomandaEditInstructorManager = () => {
visible={isVisibleCriterionData !== 0}
style={{ width: '50vw' }}
onHide={hideCriterionData}>
{criterionDataContent}
{criterionDataContent}
</Dialog>
<Dialog

View File

@@ -0,0 +1,68 @@
import React, { useRef, useState } from 'react';
import { __ } from '@wordpress/i18n';
// tools
import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
// api
import ApplicationService from '../../../../service/application-service';
// store
import { useStoreValue } from '../../../../store';
import { Toast } from 'primereact/toast';
import { Button } from 'primereact/button';
const EvaluationReAdmit = ({ id, status }) => {
const [isSendingRequest, setIsSendingRequest] = useState(false);
const toast = useRef(null);
const role = useStoreValue('getRole');
const doReAdmit = () => {
setIsSendingRequest(true);
ApplicationService.reAdmitApplication(id, reAdmitCallback, errReAdmitCallback);
}
const reAdmitCallback = (resp) => {
if (resp.status === 'SUCCESS') {
if (toast.current && resp.message) {
toast.current.show({
severity: 'success',
summary: '',
detail: resp.message
});
}
window.location.reload();
}
setIsSendingRequest(false);
}
const errReAdmitCallback = (resp) => {
if (toast.current && resp.message) {
toast.current.show({
severity: resp.status === 'SUCCESS' ? 'info' : 'error',
summary: '',
detail: resp.message
});
}
set404FromErrorResponse(resp);
setIsSendingRequest(false);
}
return (
['ROLE_SUPER_ADMIN', 'ROLE_INSTRUCTOR_MANAGER'].includes(role) && ['REJECTED'].includes(status)
? <>
<Toast ref={toast}/>
<Button
type="button"
disabled={isSendingRequest}
severity="warning"
onClick={doReAdmit}
label={__('Riammetti', 'gepafin')}
icon="pi pi-arrow-circle-up" iconPos="right"/>
</> : null
)
}
export default EvaluationReAdmit;

View File

@@ -54,6 +54,7 @@ import ApplicationInfo from './components/ApplicationInfo';
import ApplicationDownloadFiles from './components/ApplicationDownloadFiles';
import FormField from '../../components/FormField';
import SoccorsoResendEmails from '../SoccorsoEditPreInstructor/components/SoccorsoResendEmails';
import EvaluationReAdmit from './components/EvaluationReAdmit';
const APP_EVALUATION_FLOW_ID = process.env.REACT_APP_EVALUATION_FLOW_ID;
const APP_HUB_ID = process.env.REACT_APP_HUB_ID;
@@ -594,7 +595,7 @@ const DomandaEditPreInstructor = () => {
const shouldDisableField = useCallback((fieldName) => {
return !['EVALUATION', 'ADMISSIBLE'].includes(data.applicationStatus)
|| (['ADMISSIBLE'].includes(data.applicationStatus) && fieldName !== 'criteria')
|| (['ADMISSIBLE'].includes(data.applicationStatus) && !['criteria', 'note'].includes(fieldName))
|| (fieldName === 'files' && !isEmpty(data.amendmentDetails))
}, [data.applicationStatus]);
@@ -876,11 +877,29 @@ const DomandaEditPreInstructor = () => {
</div>
}
const auxActions = () => {
return <div className="appPageSection__actions">
<SoccorsoResendEmails
emailsData={emailSendResponse}
setDataEmailsSoccorso={updateEmailSendResponses}/>
<EvaluationReAdmit id={data.applicationId} status={data.applicationStatus}/>
</div>
}
const updateEmailSendResponses = useCallback((newEmailData) => {
const newData = wrap(data).set(['emailSendResponse'], newEmailData).value();
setData(newData);
}, [data]);
const motivationMsg = () => {
return data.motivation && !isEmpty(data.motivation) && ['REJECTED', 'APPROVED'].includes(data.applicationStatus)
? <div className="appPageSection__message info">
<i className="pi pi-info-circle"></i>
<span className="summary">{__('Motivazione:', 'gepafin')}</span>
<span>{renderHtmlContent(data.motivation)}</span>
</div> : null
}
useEffect(() => {
let updatedFormValues = klona(formValues);
let context = {};
@@ -973,19 +992,21 @@ const DomandaEditPreInstructor = () => {
? <div className="appPage__content">
<ApplicationInfo data={data}/>
<div className="appPageSection">
{motivationMsg()}
</div>
<div className="appPageSection__hr">
<span>{__('Azioni rapide', 'gepafin')}</span>
</div>
<div className="appPageSection">
{actionBtns()}
<div className="appPageSection__actions">
<SoccorsoResendEmails
emailsData={emailSendResponse}
setDataEmailsSoccorso={updateEmailSendResponses}/>
</div>
{auxActions()}
</div>
<div className="appPageSection__hr"></div>
<ApplicationDownloadFiles id={id}/>
<div className="appPageSection">
@@ -1010,6 +1031,23 @@ const DomandaEditPreInstructor = () => {
sourceName="evaluation"/>
</div>
<div className="appPageSection">
<h2>{__('Note', 'gepafin')}</h2>
<div translate="no" style={{ 'width': '100%' }}>
<Editor
value={data.note}
readOnly={shouldDisableField('note') || evaluationBlockedForUser(data)}
placeholder={__('Digita qui il messagio', 'gepafin')}
headerTemplate={header}
onTextChange={(e) => updateEvaluationValue(
e.htmlValue,
['note']
)}
style={{ height: 80 * 3, width: '100%' }}
/>
</div>
</div>
{data.evaluationVersion === 'V2'
? <div className="appPageSection">
<h2>{__('Documenti allegati', 'gepafin')}</h2>
@@ -1122,21 +1160,6 @@ const DomandaEditPreInstructor = () => {
</div>)}
</div>
</div>
<h3>{__('Note', 'gepafin')}</h3>
<div translate="no">
<Editor
value={data.note}
readOnly={shouldDisableField('note') || evaluationBlockedForUser(data)}
placeholder={__('Digita qui il messagio', 'gepafin')}
headerTemplate={header}
onTextChange={(e) => updateEvaluationValue(
e.htmlValue,
['note']
)}
style={{ height: 80 * 3, width: '100%' }}
/>
</div>
</div>
<div>
<h3>{__('Documenti allegati', 'gepafin')}</h3>
@@ -1255,11 +1278,7 @@ const DomandaEditPreInstructor = () => {
<div className="appPageSection">
{actionBtns()}
<div className="appPageSection__actions">
<SoccorsoResendEmails
emailsData={emailSendResponse}
setDataEmailsSoccorso={updateEmailSendResponses}/>
</div>
{auxActions()}
</div>
<Dialog
@@ -1267,7 +1286,7 @@ const DomandaEditPreInstructor = () => {
visible={isVisibleCriterionData !== 0}
style={{ width: '50vw' }}
onHide={hideCriterionData}>
{criterionDataContent}
{criterionDataContent}
</Dialog>
<Dialog

View File

@@ -65,18 +65,20 @@ const SoccorsoResendEmails = ({ emailsData = [], setDataEmailsSoccorso }) => {
setIsResendingRequest(false);
}
return(
['ROLE_SUPER_ADMIN', 'ROLE_INSTRUCTOR_MANAGER'].includes(role) && filtered.length > 0 ? <>
<Toast ref={toast}/>
{filtered
.map(o => <Button
severity="warning"
type="button"
disabled={isResendingRequest}
onClick={() => resendEmail(o)}
label={pathOr('Re-inivia email', ['emailScenario'], resendEmailLabelsByType)}
icon="pi pi-send" iconPos="right"/>)}
</> : null
return (
['ROLE_SUPER_ADMIN', 'ROLE_INSTRUCTOR_MANAGER'].includes(role) && filtered.length > 0
? <>
<Toast ref={toast}/>
{filtered
.map(o => <Button
key={o.userActionId}
severity="warning"
type="button"
disabled={isResendingRequest}
onClick={() => resendEmail(o)}
label={pathOr('Re-inivia email', ['emailScenario'], resendEmailLabelsByType)}
icon="pi pi-send" iconPos="right"/>)}
</> : null
)
}

View File

@@ -139,7 +139,7 @@ const routes = ({ role, chosenCompanyId }) => {
{'ROLE_INSTRUCTOR_MANAGER' === role ? <DomandeInstructorManager/> : null}
</DefaultLayout>}/>
<Route path="/domande/:id/" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <BandoApplicationPreview/> : null}
{'ROLE_SUPER_ADMIN' === role ? <DomandaEditPreInstructor/> : null}
{'ROLE_BENEFICIARY' === role ? <SoccorsoEditBeneficiario/> : null}
{'ROLE_CONFIDI' === role ? <SoccorsoEditBeneficiario/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <DomandaEditPreInstructor/> : null}

View File

@@ -63,4 +63,8 @@ export default class ApplicationService {
static downloadCsvReport = (id, callback, errCallback, queryParams) => {
NetworkService.getBlob(`${API_BASE_URL}/application/call/${id}/csv`, callback, errCallback, queryParams);
};
static reAdmitApplication = (id, callback, errCallback) => {
NetworkService.put(`${API_BASE_URL}/application/${id}/readmit`, {}, callback, errCallback);
};
}