- updated flow edit page;

- fixed issues on application form page;
This commit is contained in:
Vitalii Kiiko
2024-09-24 17:25:41 +02:00
parent 2341b9ff62
commit b008fcd37a
11 changed files with 103 additions and 75 deletions

View File

@@ -4,13 +4,11 @@
.statsBigBadges__grid { .statsBigBadges__grid {
display: grid; display: grid;
align-items: stretch; align-items: stretch;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 1rem; gap: 1rem;
width: 100%; width: 100%;
container-name: big-badges-grid;
&.grid-3 { container-type: inline-size;
grid-template-columns: repeat(3, 1fr);
}
} }
.statsBigBadges__grid .statsBigBadges__gridItem span { .statsBigBadges__grid .statsBigBadges__gridItem span {
@@ -53,8 +51,15 @@
} }
} }
@media (max-width: 1240px) { @container big-badges-grid (max-width: 700px) {
.statsBigBadges__grid { .statsBigBadges__gridItem {
grid-template-columns: 1fr; padding: 12px;
span {
font-size: 16px;
}
span:nth-last-of-type(1) {
font-size: 16px;
}
} }
} }

View File

@@ -8,41 +8,8 @@ import { __ } from '@wordpress/i18n';
const NodeInitialForm = ({ data: { id, label = '' } }) => { const NodeInitialForm = ({ data: { id, label = '' } }) => {
const flowData = storeGet.main.flowData(); const flowData = storeGet.main.flowData();
//const [options, setOptions] = useState([]);
const [value, setValue] = useState(''); const [value, setValue] = useState('');
/*const onChangeFn = (e) => {
const { value } = e.target;
const data = {
formId: String(id),
chosenField: value,
chosenValue: ''
}
setValue(value);
storeSet.main.addFlowData(data);
}*/
/*useEffect(() => {
const flowForms = storeGet.main.flowForms();
const flowData = storeGet.main.flowData();
if (flowForms.length > 2) {
const form = head(flowForms.filter(o => String(o.id) === String(id)))
const relevantFields = form
? form.content
.filter(o => ['radio', 'select'].includes(o.name))
.map(o => ({ name: o.id, label: o.label }))
: [];
setOptions(relevantFields);
}
const flowDataForm = head(flowData.filter(o => String(o.formId) === String(id)));
if (flowDataForm) {
setValue(flowDataForm.chosenField);
}
}, [id]);*/
useEffect(() => { useEffect(() => {
const flowForms = storeGet.main.flowForms(); const flowForms = storeGet.main.flowForms();
const form = head(flowForms.filter(o => String(o.id) === String(id))); const form = head(flowForms.filter(o => String(o.id) === String(id)));

View File

@@ -8,7 +8,7 @@ import { isEmpty } from 'ramda';
import '@xyflow/react/dist/style.css'; import '@xyflow/react/dist/style.css';
// store // store
import { useStore, storeSet } from '../../store'; import { useStore, storeSet, storeGet } from '../../store';
// nodes // nodes
import NodeInitialForm from './components/NodeInitialForm'; import NodeInitialForm from './components/NodeInitialForm';
@@ -104,15 +104,6 @@ const FlowBuilder = ({ initialForm = 0, finalForm = 0, mainField = '' }) => {
setNodes(initialNodes); setNodes(initialNodes);
setEdges(edges); setEdges(edges);
storeSet.main.flowEdges(edges); storeSet.main.flowEdges(edges);
if (!isEmpty(mainField)) {
const data = {
formId: String(initialForm),
chosenField: mainField,
chosenValue: ''
}
storeSet.main.addFlowData(data);
}
} else { } else {
setNodes([]); setNodes([]);
setEdges([]); setEdges([]);

View File

@@ -19,7 +19,8 @@ const NumberInput = ({
maxFractionDigits = 1, maxFractionDigits = 1,
min, min,
max, max,
disabled = false disabled = false,
useGrouping = true
}) => { }) => {
const input = <Controller const input = <Controller
name={fieldName} name={fieldName}
@@ -34,6 +35,7 @@ const NumberInput = ({
min={min} min={min}
max={max} max={max}
locale={locale} locale={locale}
useGrouping={useGrouping}
minFractionDigits={minFractionDigits} minFractionDigits={minFractionDigits}
className={classNames({ 'p-invalid': fieldState.invalid })}/> className={classNames({ 'p-invalid': fieldState.invalid })}/>
)}/> )}/>

View File

@@ -3,7 +3,8 @@ import { match, isEmpty } from 'ramda';
import CodiceFiscale from 'codice-fiscale-js'; import CodiceFiscale from 'codice-fiscale-js';
export const isPIVA = (v) => { export const isPIVA = (v) => {
return false; const regexp = new RegExp(/^[0-9]{11}$/);
return !isEmpty(match(regexp, String(v)));
} }
// example: DSDDSD99P23B352G // example: DSDDSD99P23B352G
@@ -14,8 +15,8 @@ export const isCodiceFiscale = (v) => {
} }
export const isCAP = (v) => { export const isCAP = (v) => {
const regexp = new RegExp(/^[0-9]{5}$/) const regexp = new RegExp(/^[0-9]{5}$/);
return !isEmpty(match(regexp, v)); return !isEmpty(match(regexp, String(v)));
} }
export const isIBAN = (v) => { export const isIBAN = (v) => {
@@ -54,5 +55,6 @@ export const isUrl = (v) => {
} }
export const isMarcaDaBollo = (v) => { export const isMarcaDaBollo = (v) => {
return true; const regexp = new RegExp(/^[0-9]{14}$/);
return !isEmpty(match(regexp, String(v)));
} }

View File

@@ -2,7 +2,7 @@ import React, { useState, useEffect, useCallback, useRef } from 'react';
import { __, sprintf } from '@wordpress/i18n'; import { __, sprintf } from '@wordpress/i18n';
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { klona } from 'klona'; import { klona } from 'klona';
import { head, range } from 'ramda'; import { head, range, is, isNil } from 'ramda';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
// store // store
@@ -31,11 +31,12 @@ import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
import { Steps } from 'primereact/steps'; import { Steps } from 'primereact/steps';
import { Toast } from 'primereact/toast'; import { Toast } from 'primereact/toast';
import { TZDate } from '@date-fns/tz'; import { TZDate } from '@date-fns/tz';
import { Messages } from 'primereact/messages';
const BandoApplication = () => { const BandoApplication = () => {
const { id } = useParams(); const { id } = useParams();
const navigate = useNavigate();
const [formData, setFormData] = useState([]); const [formData, setFormData] = useState([]);
const [formInitialData, setFormInitialData] = useState([]);
const [bandoTitle, setBandoTitle] = useState(''); const [bandoTitle, setBandoTitle] = useState('');
const [formId, setFormId] = useState(''); const [formId, setFormId] = useState('');
const [totalSteps, setTotalSteps] = useState(0); const [totalSteps, setTotalSteps] = useState(0);
@@ -43,6 +44,7 @@ const BandoApplication = () => {
const [stepItems, setStepItems] = useState([{ label: 'Passo' }]); const [stepItems, setStepItems] = useState([{ label: 'Passo' }]);
const isAsyncRequest = useStore().main.isAsyncRequest(); const isAsyncRequest = useStore().main.isAsyncRequest();
const toast = useRef(null); const toast = useRef(null);
const formMsgs = useRef(null);
const { const {
control, control,
handleSubmit, handleSubmit,
@@ -69,15 +71,20 @@ const BandoApplication = () => {
const saveDraft = useCallback(() => { const saveDraft = useCallback(() => {
trigger(); trigger();
const formData = getValues(); const formValues = getValues();
const newFormData = Object.keys(formData).reduce((acc, cur) => { const newFormValues = Object.keys(formValues).reduce((acc, cur) => {
let fieldVal = formData[cur]; const formField = head(formData.filter(o => o.id === cur));
if (formData[cur] && formData[cur].toISOString) { let fieldVal = formValues[cur];
const tzAwareDate = new TZDate(formData[cur], 'Europe/Berlin');
if (formValues[cur] && formValues[cur].toISOString) {
const tzAwareDate = new TZDate(formValues[cur], 'Europe/Berlin');
fieldVal = tzAwareDate.toISOString().substring(0, 19); fieldVal = tzAwareDate.toISOString().substring(0, 19);
} }
fieldVal = !fieldVal ? null : fieldVal; fieldVal = !fieldVal ? null : fieldVal;
if (formField && formField.name === 'fileupload') {
fieldVal = is(Array, fieldVal) ? fieldVal.map(o => o.id).join(',') : fieldVal;
}
acc.push({ acc.push({
'fieldId': cur, 'fieldId': cur,
'fieldValue': fieldVal 'fieldValue': fieldVal
@@ -85,12 +92,17 @@ const BandoApplication = () => {
return acc; return acc;
}, []); }, []);
const submitData = { const submitData = {
formFields: newFormData formFields: newFormValues
} }
if (formId) { if (formId) {
const applId = getApplicationId(); const applId = getApplicationId();
storeSet.main.setAsyncRequest(); storeSet.main.setAsyncRequest();
if (formMsgs.current) {
formMsgs.current.clear();
}
ApplicationService.submitForm(applId, submitData, submitFormCallback, errSubmitFormCallback, [ ApplicationService.submitForm(applId, submitData, submitFormCallback, errSubmitFormCallback, [
['formId', formId] ['formId', formId]
]); ]);
@@ -117,8 +129,21 @@ const BandoApplication = () => {
} }
const errSubmitFormCallback = (data) => { const errSubmitFormCallback = (data) => {
set404FromErrorResponse(data);
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
if (data.status === 'VALIDATION_ERROR') {
if (formMsgs.current) {
formMsgs.current.show([
{
id: '99',
sticky: true, severity: 'error', summary: '',
detail: data.data.join(', '),
closable: true
}
]);
}
} else {
set404FromErrorResponse(data);
}
} }
const goBackward = () => { const goBackward = () => {
@@ -147,6 +172,15 @@ const BandoApplication = () => {
if (data.status === 'SUCCESS') { if (data.status === 'SUCCESS') {
setBandoTitle(data.data.callTitle); setBandoTitle(data.data.callTitle);
setFormData(data.data.applicationFormResponse.content); setFormData(data.data.applicationFormResponse.content);
if (data.data.applicationFormResponse.formFields) {
const submitData = data.data.applicationFormResponse.formFields.map((o) => ({
fieldId: o.fieldId,
fieldValue: o.fieldValue
}));
setFormInitialData(submitData)
}
setFormId(data.data.formId); setFormId(data.data.formId);
setTotalSteps(data.data.totalFormSteps); setTotalSteps(data.data.totalFormSteps);
setActiveStep(data.data.currentStep) setActiveStep(data.data.currentStep)
@@ -169,6 +203,12 @@ const BandoApplication = () => {
} }
} }
useEffect(() => {
const newFormData = klona(formInitialData);
console.log('newFormData', newFormData);
newFormData.map(o => setValue(o.fieldId, o.fieldValue));
}, [formInitialData]);
useEffect(() => { useEffect(() => {
const rangeArr = range(1, totalSteps + 1); const rangeArr = range(1, totalSteps + 1);
setStepItems(rangeArr.map(() => ({ label: 'Passo' }))); setStepItems(rangeArr.map(() => ({ label: 'Passo' })));
@@ -201,6 +241,7 @@ const BandoApplication = () => {
<div className="appPage__spacer"></div> <div className="appPage__spacer"></div>
<Messages ref={formMsgs}/>
<Toast ref={toast}/> <Toast ref={toast}/>
{!isAsyncRequest {!isAsyncRequest
? <div className="appPage__content"> ? <div className="appPage__content">
@@ -252,6 +293,7 @@ const BandoApplication = () => {
options={options ? options.value : []} options={options ? options.value : []}
setDataFn={setValue} setDataFn={setValue}
sourceId={getApplicationId()} sourceId={getApplicationId()}
useGrouping={false}
/> />
})} })}

View File

@@ -253,10 +253,9 @@ const BandoEdit = () => {
} }
} else { } else {
BandoService.getBando(id, getCallback, errGetCallback); BandoService.getBando(id, getCallback, errGetCallback);
FormsService.getFormsForCall(id, getFormsCallback, () => { FormsService.getFormsForCall(id, getFormsCallback, () => {});
});
} }
}, []); }, [id]);
return ( return (
<div className="appPage"> <div className="appPage">

View File

@@ -31,6 +31,7 @@ const BandoFlowEdit = () => {
const [initialForm, setInitialForm] = useState(0); const [initialForm, setInitialForm] = useState(0);
const [mainFieldOptions, setMainFieldOptions] = useState([]); const [mainFieldOptions, setMainFieldOptions] = useState([]);
const [mainField, setMainField] = useState(''); const [mainField, setMainField] = useState('');
const [bandoStatus, setBandoStatus] = useState('');
const [isFlowAllowed, setIsFlowAllowed] = useState(false); const [isFlowAllowed, setIsFlowAllowed] = useState(false);
const [finalForm, setFinalForm] = useState(0); const [finalForm, setFinalForm] = useState(0);
const flowMsgs = useRef(null); const flowMsgs = useRef(null);
@@ -85,7 +86,8 @@ const BandoFlowEdit = () => {
const shoudDisableSaving = useCallback(() => { const shoudDisableSaving = useCallback(() => {
return forms.length > 2 return forms.length > 2
? isEmpty(flowData) || isEmpty(flowEdges) || isEmpty(initialForm) || isEmpty(finalForm) ? isEmpty(flowData) || isEmpty(flowEdges) || isEmpty(initialForm) || isEmpty(finalForm)
: isEmpty(flowEdges) || isEmpty(initialForm); || flowData.length < forms.length - 1 || 'PUBLISH' === bandoStatus
: isEmpty(flowEdges) || isEmpty(initialForm) || 'PUBLISH' === bandoStatus;
}, [flowData, flowEdges]); }, [flowData, flowEdges]);
const doSave = () => { const doSave = () => {
@@ -100,6 +102,7 @@ const BandoFlowEdit = () => {
if (flowMsgs.current) { if (flowMsgs.current) {
flowMsgs.current.clear(); flowMsgs.current.clear();
} }
FlowService.createFlow(bandoId, body, getFlowCreateCallback, errGetFlowCreateCallback); FlowService.createFlow(bandoId, body, getFlowCreateCallback, errGetFlowCreateCallback);
} }
@@ -141,6 +144,7 @@ const BandoFlowEdit = () => {
storeSet.main.flowEdges(data.data.flowEdges); storeSet.main.flowEdges(data.data.flowEdges);
setInitialForm(data.data.initialForm); setInitialForm(data.data.initialForm);
setFinalForm(data.data.finalForm); setFinalForm(data.data.finalForm);
setBandoStatus(data.data.callStatus);
const flowDataItem = head(data.data.flowData.filter(o => !isEmpty(o.chosenField))); const flowDataItem = head(data.data.flowData.filter(o => !isEmpty(o.chosenField)));
if (flowDataItem) { if (flowDataItem) {
@@ -167,6 +171,12 @@ const BandoFlowEdit = () => {
if (field && options.value && options.value.length === flowForms.length - 2) { if (field && options.value && options.value.length === flowForms.length - 2) {
setIsFlowAllowed(true); setIsFlowAllowed(true);
const data = {
formId: String(initialForm),
chosenField: mainField,
chosenValue: ''
}
storeSet.main.addFlowData(data);
} else { } else {
setIsFlowAllowed(false); setIsFlowAllowed(false);
let msg = 'Non è possibile creare il flusso. Il campo principale deve avere esattamente %s opzioni.'; let msg = 'Non è possibile creare il flusso. Il campo principale deve avere esattamente %s opzioni.';
@@ -263,6 +273,7 @@ const BandoFlowEdit = () => {
<label htmlFor="initialForm">{__('Scegli form iniziale', 'gepafin')}</label> <label htmlFor="initialForm">{__('Scegli form iniziale', 'gepafin')}</label>
<Dropdown <Dropdown
id="initialForm" id="initialForm"
disabled={'PUBLISH' === bandoStatus}
value={initialForm} value={initialForm}
onChange={(e) => updateInitialForm(e.value)} onChange={(e) => updateInitialForm(e.value)}
optionDisabled={(opt) => finalForm === opt.value || isEmpty(opt.value)} optionDisabled={(opt) => finalForm === opt.value || isEmpty(opt.value)}
@@ -277,6 +288,7 @@ const BandoFlowEdit = () => {
<label htmlFor="mainField">{__('Scegli il campo principale', 'gepafin')}</label> <label htmlFor="mainField">{__('Scegli il campo principale', 'gepafin')}</label>
<Dropdown <Dropdown
id="mainField" id="mainField"
disabled={'PUBLISH' === bandoStatus}
value={mainField} value={mainField}
onChange={(e) => setMainField(e.value)} onChange={(e) => setMainField(e.value)}
optionDisabled={(opt) => isEmpty(opt.value)} optionDisabled={(opt) => isEmpty(opt.value)}
@@ -291,6 +303,7 @@ const BandoFlowEdit = () => {
<label htmlFor="finalForm">{__('Scegli form finale', 'gepafin')}</label> <label htmlFor="finalForm">{__('Scegli form finale', 'gepafin')}</label>
<Dropdown <Dropdown
id="finalForm" id="finalForm"
disabled={'PUBLISH' === bandoStatus}
value={finalForm} value={finalForm}
onChange={(e) => setFinalForm(e.value)} onChange={(e) => setFinalForm(e.value)}
optionDisabled={(opt) => initialForm === opt.value || isEmpty(opt.value)} optionDisabled={(opt) => initialForm === opt.value || isEmpty(opt.value)}
@@ -307,7 +320,10 @@ const BandoFlowEdit = () => {
<div className="appPageSection"> <div className="appPageSection">
<Messages ref={flowMsgs}/> <Messages ref={flowMsgs}/>
{forms.length >= 2 && isFlowAllowed {forms.length >= 2 && isFlowAllowed
? <FlowBuilder initialForm={initialForm} finalForm={finalForm} mainField={mainField}/> : null} ? <FlowBuilder
initialForm={initialForm}
finalForm={finalForm}
mainField={mainField}/> : null}
</div> </div>
<div className="appPage__spacer"></div> <div className="appPage__spacer"></div>
@@ -328,6 +344,7 @@ const BandoFlowEdit = () => {
<ConfirmPopup/> <ConfirmPopup/>
<Button <Button
onClick={confirmDelete} onClick={confirmDelete}
disabled={'PUBLISH' === bandoStatus}
severity="warning" severity="warning"
label={__('Reset', 'gepafin')} icon="pi pi-refresh" iconPos="right"/> label={__('Reset', 'gepafin')} icon="pi pi-refresh" iconPos="right"/>
</div> </div>

View File

@@ -28,6 +28,7 @@ const BandoFormsEdit = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [formName, setFormName] = useState(''); const [formName, setFormName] = useState('');
const [visibleConfirmation, setVisibleConfirmation] = useState(false); const [visibleConfirmation, setVisibleConfirmation] = useState(false);
const [bandoStatus, setBandoStatus] = useState('');
const isAsyncRequest = useStore().main.isAsyncRequest(); const isAsyncRequest = useStore().main.isAsyncRequest();
const formMsgs = useRef(null); const formMsgs = useRef(null);
const toast = useRef(null); const toast = useRef(null);
@@ -221,6 +222,7 @@ const BandoFormsEdit = () => {
storeSet.main.formId(data.data.id); storeSet.main.formId(data.data.id);
storeSet.main.formLabel(data.data.label); storeSet.main.formLabel(data.data.label);
setFormName(data.data.label); setFormName(data.data.label);
setBandoStatus(data.data.callStatus);
const elements = klona(data.data.content); const elements = klona(data.data.content);
storeSet.main.formElements(elements); storeSet.main.formElements(elements);
} }
@@ -304,7 +306,7 @@ const BandoFormsEdit = () => {
label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" iconPos="left"/> label={__('Indietro', 'gepafin')} icon="pi pi-arrow-left" iconPos="left"/>
<Button <Button
onClick={() => doSave()} onClick={() => doSave()}
disabled={isAsyncRequest} disabled={isAsyncRequest || 'PUBLISH' === bandoStatus}
label={__('Salva progressi', 'gepafin')} icon="pi pi-save" iconPos="right"/> label={__('Salva progressi', 'gepafin')} icon="pi pi-save" iconPos="right"/>
<Button <Button
outlined outlined
@@ -320,7 +322,7 @@ const BandoFormsEdit = () => {
<ConfirmPopup /> <ConfirmPopup />
<Button <Button
onClick={confirmDelete} onClick={confirmDelete}
disabled={isAsyncRequest} disabled={isAsyncRequest || 'PUBLISH' === bandoStatus}
severity="danger" severity="danger"
label={__('Cancella', 'gepafin')} icon="pi pi-trash" iconPos="right"/> label={__('Cancella', 'gepafin')} icon="pi pi-trash" iconPos="right"/>
</div> </div>

View File

@@ -24,7 +24,7 @@ const DashboardBeneficiario = () => {
<div className="appPageSection statsBigBadges"> <div className="appPageSection statsBigBadges">
<h2>{__('Panoramica di Sistema', 'gepafin')}</h2> <h2>{__('Panoramica di Sistema', 'gepafin')}</h2>
<div className="statsBigBadges__grid grid-3"> <div className="statsBigBadges__grid">
<div className="statsBigBadges__gridItem"> <div className="statsBigBadges__gridItem">
<span>{__('Domande attivi', 'gepafin')}</span> <span>{__('Domande attivi', 'gepafin')}</span>
<span>3</span> <span>3</span>

View File

@@ -45,9 +45,10 @@ export const actionsBeta = (set, get, api) => ({
}, },
addFlowData: (data) => { addFlowData: (data) => {
const initial = get.flowData(); const initial = get.flowData();
const exists = initial ? initial.filter(o => o.formId === data.formId) : []; const exists = initial ? initial.filter(o => parseInt(o.formId) === parseInt(data.formId)) : [];
if (exists.length) { if (exists.length) {
const newData = initial.map(o => o.formId === data.formId ? data : o); const newData = initial.map(o => parseInt(o.formId) === parseInt(data.formId) ? data : o);
set.flowData(newData); set.flowData(newData);
} else { } else {
set.flowData([...initial, data]); set.flowData([...initial, data]);