- updated users table;

This commit is contained in:
Vitalii Kiiko
2024-10-21 12:31:49 +02:00
30 changed files with 1157 additions and 196 deletions

View File

@@ -7,6 +7,7 @@
"@babel/preset-react": "7.24.7", "@babel/preset-react": "7.24.7",
"@date-fns/tz": "1.1.2", "@date-fns/tz": "1.1.2",
"@emotion/styled": "11.13.0", "@emotion/styled": "11.13.0",
"@number-flow/react": "^0.2.0",
"@tanstack/react-table": "^8.20.5", "@tanstack/react-table": "^8.20.5",
"@wordpress/i18n": "5.8.0", "@wordpress/i18n": "5.8.0",
"@wordpress/react-i18n": "4.8.0", "@wordpress/react-i18n": "4.8.0",

View File

@@ -157,6 +157,18 @@
flex: 0 0 auto; flex: 0 0 auto;
} }
} }
&.columns {
gap: 2em;
column-count: 2;
column-width: 4em;
display: block;
padding-bottom: 0;
.appPageSection__pMeta {
margin-bottom: 1em;
}
}
} }
@container section_with_border (max-width: 600px) { @container section_with_border (max-width: 600px) {
@@ -212,6 +224,10 @@
font-weight: 600; font-weight: 600;
line-height: normal; line-height: normal;
} }
span:nth-of-type(2) {
font-weight: 400;
}
} }
.appPageSection__table { .appPageSection__table {

View File

@@ -12,7 +12,7 @@ body {
margin: 0; margin: 0;
font-family: "Montserrat", sans-serif; font-family: "Montserrat", sans-serif;
p, span:not(.p-button-label, .p-button-icon, .p-badge, .p-message-detail, .p-highlight, .p-inline-message-text), p, span:not(.p-button-label, .p-button-icon, .p-badge, .p-message-detail, .p-highlight, .p-inline-message-text, .p-tag, .p-tag-icon),
input, label:not(.p-error), textarea, a, li, h1, h2, h3, h4, h5, h6, div:not(.p-inline-message, .p-toast-detail), th, td { input, label:not(.p-error), textarea, a, li, h1, h2, h3, h4, h5, h6, div:not(.p-inline-message, .p-toast-detail), th, td {
color: var(--global-textColor); color: var(--global-textColor);
} }

View File

@@ -0,0 +1,39 @@
.myTable {
border-spacing: 0px;
width: 100%;
}
.myThead {
th {
text-align: left;
padding: 1rem 1rem;
border: 1px solid #e5e7eb;
border-width: 0 0 1px 0;
font-weight: 700;
color: #374151;
background: #f9fafb;
transition: box-shadow 0.2s;
}
}
.myTbody {
td {
text-align: left;
border: 1px solid #e5e7eb;
border-width: 0 0 1px 0;
padding: 1rem 1rem;
}
}
.myTfoot {
td {
text-align: left;
padding: 1rem 1rem;
border: 1px solid #e5e7eb;
border-width: 0 0 1px 0;
font-weight: 700;
color: #374151;
background: #f9fafb;
transition: box-shadow 0.2s;
}
}

View File

@@ -41,3 +41,4 @@
@import "./components/login.scss"; @import "./components/login.scss";
@import "./components/flowBuilder.scss"; @import "./components/flowBuilder.scss";
@import "./components/error404.scss"; @import "./components/error404.scss";
@import "./components/myTable.scss";

View File

@@ -55,7 +55,7 @@ const TopBarProfileMenu = ({ menuLeftRef }) => {
command: () => { command: () => {
navigate('/profilo-aziendale') navigate('/profilo-aziendale')
}, },
enable: !intersection(permissions, ['MANAGE_TENDERS']).length && companies.length > 0 enable: intersection(permissions, ['APPLY_CALLS']).length && companies.length > 0
}, },
{ {
label: __('Seleziona azienda', 'gepafin'), label: __('Seleziona azienda', 'gepafin'),
@@ -67,7 +67,7 @@ const TopBarProfileMenu = ({ menuLeftRef }) => {
command: () => { command: () => {
navigate('/agguingi-azienda') navigate('/agguingi-azienda')
}, },
enable: !intersection(permissions, ['MANAGE_TENDERS']).length enable: intersection(permissions, ['APPLY_CALLS']).length
}, },
{ {
separator: true, separator: true,

View File

@@ -2,6 +2,9 @@ import { __ } from '@wordpress/i18n';
const getBandoLabel = (status) => { const getBandoLabel = (status) => {
switch (status) { switch (status) {
case 'ACTIVE':
return __('Attivo', 'gepafin');
case 'SUBMIT': case 'SUBMIT':
return __('Inviato', 'gepafin'); return __('Inviato', 'gepafin');
@@ -17,6 +20,9 @@ const getBandoLabel = (status) => {
case 'DRAFT': case 'DRAFT':
return __('Bozza', 'gepafin'); return __('Bozza', 'gepafin');
case 'AWAITING':
return __('In attesa', 'gepafin');
case 'EXPIRED': case 'EXPIRED':
return __('Scaduto', 'gepafin'); return __('Scaduto', 'gepafin');

View File

@@ -2,6 +2,9 @@ import { __ } from '@wordpress/i18n';
const getBandoSeverity = (status) => { const getBandoSeverity = (status) => {
switch (status) { switch (status) {
case 'ACTIVE':
return 'success';
case 'SUBMIT': case 'SUBMIT':
return 'success'; return 'success';
@@ -17,6 +20,9 @@ const getBandoSeverity = (status) => {
case 'DRAFT': case 'DRAFT':
return 'warning'; return 'warning';
case 'AWAITING':
return 'warning';
case 'EXPIRED': case 'EXPIRED':
return 'closed'; return 'closed';

View File

@@ -40,6 +40,13 @@ const AppSidebar = () => {
id: 4, id: 4,
enable: intersection(permissions, ['VIEW_CALLS']).length enable: intersection(permissions, ['VIEW_CALLS']).length
}, },
{
label: __('Domande da valutare', 'gepafin'),
icon: 'pi pi-calendar-clock',
href: '/valutazioni',
id: 4,
enable: intersection(permissions, ['EVALUATE_APPLICATIONS']).length
},
{ {
label: __('Gestione Utenti', 'gepafin'), label: __('Gestione Utenti', 'gepafin'),
icon: 'pi pi-users', icon: 'pi pi-users',

View File

@@ -27,9 +27,10 @@ const AppTopbar = () => {
<i className="pi pi-bell p-overlay-badge topBar__icon"> <i className="pi pi-bell p-overlay-badge topBar__icon">
<Badge value="0"></Badge> <Badge value="0"></Badge>
</i> </i>
<i className="pi pi-envelope p-overlay-badge topBar__icon"> <i className="pi pi-envelope topBar__icon"></i>
{/*<i className="pi pi-envelope p-overlay-badge topBar__icon">
<Badge severity="danger"></Badge> <Badge severity="danger"></Badge>
</i> </i>*/}
<Button <Button
className="topBar__profileBtn" className="topBar__profileBtn"
outlined outlined
@@ -40,7 +41,7 @@ const AppTopbar = () => {
<TopBarProfileMenu menuLeftRef={menuLeft}/> <TopBarProfileMenu menuLeftRef={menuLeft}/>
</div> </div>
return( return (
<Toolbar start={startContent} end={endContent} className="topBar"/> <Toolbar start={startContent} end={endContent} className="topBar"/>
) )
} }

View File

@@ -31,12 +31,12 @@ import { Link } from 'react-router-dom';
const AllBandiTable = () => { const AllBandiTable = () => {
const [items, setItems] = useState(null); const [items, setItems] = useState(null);
const [filters, setFilters] = useState(null); const [filters, setFilters] = useState(null);
const [loading, setLoading] = useState(false); const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
const [globalFilterValue, setGlobalFilterValue] = useState(''); const [globalFilterValue, setGlobalFilterValue] = useState('');
const [statuses, setStatuses] = useState([]); const [statuses, setStatuses] = useState([]);
useEffect(() => { useEffect(() => {
storeSet.main.setAsyncRequest(); setLocalAsyncRequest(true);
BandoService.getBandi(getCallback, errGetCallbacks); BandoService.getBandi(getCallback, errGetCallbacks);
}, []); }, []);
@@ -46,12 +46,11 @@ const AllBandiTable = () => {
setStatuses(uniq(data.data.map(o => o.status))) setStatuses(uniq(data.data.map(o => o.status)))
initFilters(); initFilters();
} }
storeSet.main.unsetAsyncRequest(); setLocalAsyncRequest(false);
} }
const errGetCallbacks = (data) => { const errGetCallbacks = (data) => {
console.log('errGetCallbacks', data) setLocalAsyncRequest(false);
storeSet.main.unsetAsyncRequest();
} }
const getFormattedBandiData = (data) => { const getFormattedBandiData = (data) => {
@@ -136,7 +135,7 @@ const AllBandiTable = () => {
return( return(
<div className="appPageSection__table"> <div className="appPageSection__table">
<DataTable value={items} paginator showGridlines rows={10} loading={loading} dataKey="id" <DataTable value={items} paginator showGridlines rows={10} loading={localAsyncRequest} dataKey="id"
filters={filters} filters={filters}
globalFilterFields={['name', 'status']} globalFilterFields={['name', 'status']}
header={header} header={header}

View File

@@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
import { head, isEmpty, isNil } from 'ramda'; import { head, isEmpty, isNil } from 'ramda';
import { __, sprintf } from '@wordpress/i18n'; import { __, sprintf } from '@wordpress/i18n';
import { klona } from 'klona'; import { klona } from 'klona';
import { wrap } from 'object-path-immutable';
// store // store
import { storeSet, useStore } from '../../../../store'; import { storeSet, useStore } from '../../../../store';
@@ -14,13 +15,17 @@ import { TabView, TabPanel } from 'primereact/tabview';
import { InputSwitch } from 'primereact/inputswitch'; import { InputSwitch } from 'primereact/inputswitch';
import ElementSetting from './components/ElementSetting'; import ElementSetting from './components/ElementSetting';
import { Dropdown } from 'primereact/dropdown'; import { Dropdown } from 'primereact/dropdown';
import { MultiSelect } from 'primereact/multiselect';
const BuilderElementSettings = ({ closeSettings }) => { const BuilderElementSettings = ({ closeSettingsFn }) => {
const elements = useStore().main.formElements(); const elements = useStore().main.formElements();
const activeElement = useStore().main.activeElement(); const activeElement = useStore().main.activeElement();
const criteriaOptions = useStore().main.bandoCriteria();
const [activeElementData, setActiveElementData] = useState({}); const [activeElementData, setActiveElementData] = useState({});
const [settings, setSettings] = useState([]); const [settings, setSettings] = useState([]);
const [validators, setValidators] = useState({}); const [validators, setValidators] = useState({});
const [dynamicData, setDynamicData] = useState('');
const [criteria, setCriteria] = useState([]);
const textBasedValidatorFields = ['min', 'max', 'minLength', 'maxLength', 'pattern']; const textBasedValidatorFields = ['min', 'max', 'minLength', 'maxLength', 'pattern'];
const customValidationOptions = [ const customValidationOptions = [
{ value: 'isPIVA', label: 'isPIVA' }, { value: 'isPIVA', label: 'isPIVA' },
@@ -63,11 +68,14 @@ const BuilderElementSettings = ({ closeSettings }) => {
} }
const saveSettings = () => { const saveSettings = () => {
activeElementData.settings = settings; let newActiveElementData = klona(activeElementData);
activeElementData.validators = validators; newActiveElementData = wrap(newActiveElementData).set(['settings'], settings).value();
const newElements = elements.map(o => o.id === activeElementData.id ? activeElementData : o); newActiveElementData = wrap(newActiveElementData).set(['validators'], validators).value();
newActiveElementData = wrap(newActiveElementData).set(['dynamicData'], dynamicData).value();
newActiveElementData = wrap(newActiveElementData).set(['criteria'], criteria).value();
const newElements = elements.map(o => o.id === newActiveElementData.id ? newActiveElementData : o);
storeSet.main.formElements(newElements); storeSet.main.formElements(newElements);
closeSettings(); closeSettingsFn();
} }
const showField = (value, key) => { const showField = (value, key) => {
@@ -92,17 +100,56 @@ const BuilderElementSettings = ({ closeSettings }) => {
setValidators(newValidators); setValidators(newValidators);
} }
const onChangeCriteriaData = (value) => {
setCriteria(value);
}
const getDynamicDataOptions = (type) => {
switch (type) {
case 'datepicker' :
return [
{ label: 'user dateOfBirth', value: 'user.dateOfBirth' }
]
default :
return [
{ label: 'company name', value: 'company.companyName' },
{ label: 'company piva', value: 'company.vatNumber' },
{ label: 'company codiceFiscale', value: 'company.codiceFiscale' },
{ label: 'company address', value: 'company.address' },
{ label: 'company phoneNumber', value: 'company.phoneNumber' },
{ label: 'company city', value: 'company.city' },
{ label: 'company province', value: 'company.province' },
{ label: 'company cap', value: 'company.cap' },
{ label: 'company country', value: 'company.country' },
{ label: 'company pec', value: 'company.pec' },
{ label: 'company email', value: 'company.email' },
{ label: 'company contactName', value: 'company.contactName' },
{ label: 'company contactEmail', value: 'company.contactEmail' },
{ label: 'user email', value: 'user.email' },
{ label: 'user firstName', value: 'user.firstName' },
{ label: 'user lastName', value: 'user.lastName' },
{ label: 'user phoneNumber', value: 'user.phoneNumber' },
{ label: 'user codiceFiscale', value: 'user.codiceFiscale' }
]
}
}
useEffect(() => { useEffect(() => {
const chosen = head(elements.filter(o => o.id === activeElement)); const chosen = head(elements.filter(o => o.id === activeElement));
if (chosen) { if (chosen) {
setActiveElementData(klona(chosen)); setActiveElementData(klona(chosen));
setSettings(klona(chosen.settings)); setSettings(klona(chosen.settings));
setValidators(klona(chosen.validators)) setValidators(klona(chosen.validators));
setDynamicData(chosen.dynamicData ? chosen.dynamicData : '');
setCriteria(chosen.criteria ? chosen.criteria : []);
} else { } else {
setActiveElementData({}); setActiveElementData({});
setSettings([]); setSettings([]);
setValidators({}) setValidators({});
setDynamicData('');
setCriteria([]);
} }
}, [activeElement]); }, [activeElement]);
@@ -118,6 +165,18 @@ const BuilderElementSettings = ({ closeSettings }) => {
changeFn={onChange} changeFn={onChange}
updateDataFn={onUpdateOptions}/>) updateDataFn={onUpdateOptions}/>)
: null} : null}
{['textinput', 'datepicker'].includes(activeElementData.name)
? <div className="formElementSettings__field">
<label htmlFor="dynamicData">{__('Dati dinamici', 'gepafin')}</label>
<Dropdown
id="dynamicData"
value={dynamicData}
onChange={(e) => setDynamicData(e.value)}
options={getDynamicDataOptions(activeElementData.name)}
optionLabel="label"
optionValue="value"
placeholder={__('Scegli', 'gepafin')}/>
</div> : null}
</TabPanel> </TabPanel>
{!isEmpty(validators) {!isEmpty(validators)
? <TabPanel header={__('Validation', 'gepafin')}> ? <TabPanel header={__('Validation', 'gepafin')}>
@@ -162,6 +221,20 @@ const BuilderElementSettings = ({ closeSettings }) => {
</div> : null} </div> : null}
</div>) : null} </div>) : null}
</TabPanel> : null} </TabPanel> : null}
<TabPanel header={__('Criteri', 'gepafin')}>
<div className="formElementSettings__field">
<label htmlFor="criteria">{__('Criteri di valutazione', 'gepafin')}</label>
<MultiSelect
id="criteria"
value={criteria}
onChange={(e) => onChangeCriteriaData(e.value)}
options={criteriaOptions}
optionLabel="label"
optionValue="value"
display="chip"
placeholder={__('Scegli', 'gepafin')}/>
</div>
</TabPanel>
</TabView> </TabView>
<Button label={__('Salva', 'gepafin')} onClick={saveSettings}/> <Button label={__('Salva', 'gepafin')} onClick={saveSettings}/>

View File

@@ -57,7 +57,7 @@ const FormBuilder = () => {
<> <>
<Sidebar visible={!isEmpty(activeElement)} onHide={closeSettings} className="formBuilder__elementSettings"> <Sidebar visible={!isEmpty(activeElement)} onHide={closeSettings} className="formBuilder__elementSettings">
<h2>{__('Impostazioni del campo modulo', 'gepafin')}</h2> <h2>{__('Impostazioni del campo modulo', 'gepafin')}</h2>
{!isEmpty(activeElement) ? <BuilderElementSettings closeSettings={closeSettings}/> : null} {!isEmpty(activeElement) ? <BuilderElementSettings closeSettingsFn={closeSettings}/> : null}
</Sidebar> </Sidebar>
<div className="formBuilder"> <div className="formBuilder">
<div className="formBuilder__main"> <div className="formBuilder__main">

View File

@@ -4,7 +4,7 @@ import { useNavigate, useParams } from 'react-router-dom';
import { DndProvider } from 'react-dnd'; import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend'; import { HTML5Backend } from 'react-dnd-html5-backend';
import { klona } from 'klona'; import { klona } from 'klona';
import { isEmpty } from 'ramda'; import { isEmpty, pathOr } from 'ramda';
// store // store
import { storeSet, storeGet, useStore } from '../../store'; import { storeSet, storeGet, useStore } from '../../store';
@@ -21,6 +21,7 @@ import { Messages } from 'primereact/messages';
// api // api
import FormsService from '../../service/forms-service'; import FormsService from '../../service/forms-service';
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse'; import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
import BandoService from '../../service/bando-service';
// TODO temp data // TODO temp data
//import { elementItems } from '../../tempData'; //import { elementItems } from '../../tempData';
@@ -243,7 +244,20 @@ const BandoFormsEdit = () => {
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} }
const getBandoCallback = (data) => {
if (data.status === 'SUCCESS') {
const criteria = pathOr([], ['data', 'criteria'], data);
const criteriaOptions = criteria.map(o => ({value: o.id, label: o.value}));
storeSet.main.bandoCriteria(criteriaOptions);
}
}
const errGetBandoCallback = (data) => {
set404FromErrorResponse(data);
}
useEffect(() => { useEffect(() => {
const bandoId = getBandoId();
const parsedFormId = parseInt(formId) const parsedFormId = parseInt(formId)
const bandoFormId = !isNaN(parsedFormId) ? parsedFormId : 0; const bandoFormId = !isNaN(parsedFormId) ? parsedFormId : 0;
@@ -253,12 +267,14 @@ const BandoFormsEdit = () => {
if (bandoFormId) { if (bandoFormId) {
storeSet.main.setAsyncRequest(); storeSet.main.setAsyncRequest();
FormsService.getFormById(bandoFormId, getFormCallback, errGetFormCallbacks); FormsService.getFormById(bandoFormId, getFormCallback, errGetFormCallbacks);
BandoService.getBando(bandoId, getBandoCallback, errGetBandoCallback);
} }
return () => { return () => {
storeSet.main.formId(0); storeSet.main.formId(0);
storeSet.main.formLabel(''); storeSet.main.formLabel('');
storeSet.main.formElements([]); storeSet.main.formElements([]);
storeSet.main.bandoCriteria([]);
} }
}, [id, formId]); }, [id, formId]);

View File

@@ -31,44 +31,12 @@ import { Link } from 'react-router-dom';
const LatestBandiTable = () => { const LatestBandiTable = () => {
const [items, setItems] = useState(null); const [items, setItems] = useState(null);
const [filters, setFilters] = useState(null); const [filters, setFilters] = useState(null);
const [loading, setLoading] = useState(false); const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
const [globalFilterValue, setGlobalFilterValue] = useState(''); const [globalFilterValue, setGlobalFilterValue] = useState('');
const [statuses, setStatuses] = useState([]); const [statuses, setStatuses] = useState([]);
useEffect(() => { useEffect(() => {
// TODO setLocalAsyncRequest(true);
/*const items = [
{
name: 'Bando Innovazione 2024',
start_date: '2024-08-08T00:00:00+00:00',
end_date: '2024-08-30T00:00:00+00:00',
submissions: 24,
status: 'PUBLISH',
id: 11
},
{
name: 'Bando Sostenibilità 2024',
start_date: '2024-07-28T00:00:00+00:00',
end_date: '2024-08-15T00:00:00+00:00',
submissions: 35,
status: 'PUBLISH',
id: 9
},
{
name: 'Bando A',
start_date: '2024-06-28T00:00:00+00:00',
end_date: '2024-06-15T00:00:00+00:00',
submissions: 2,
status: 'EXPIRED',
id: 2
}
]
setItems(getFormattedBandiData(items));
setStatuses(uniq(items.map(o => o.status)))
setLoading(false);
initFilters();*/
storeSet.main.setAsyncRequest();
BandoService.getBandi(getCallback, errGetCallbacks); BandoService.getBandi(getCallback, errGetCallbacks);
}, []); }, []);
@@ -79,12 +47,11 @@ const LatestBandiTable = () => {
setStatuses(uniq(data.data.map(o => o.status))) setStatuses(uniq(data.data.map(o => o.status)))
initFilters(); initFilters();
} }
storeSet.main.unsetAsyncRequest(); setLocalAsyncRequest(false);
} }
const errGetCallbacks = (data) => { const errGetCallbacks = (data) => {
console.log('errGetCallbacks', data) setLocalAsyncRequest(false);
storeSet.main.unsetAsyncRequest();
} }
const getFormattedBandiData = (data) => { const getFormattedBandiData = (data) => {
@@ -179,13 +146,13 @@ const LatestBandiTable = () => {
return( return(
<div className="appPageSection__table"> <div className="appPageSection__table">
<DataTable value={items} paginator showGridlines rows={10} loading={loading} dataKey="id" <DataTable value={items} paginator showGridlines rows={10} loading={localAsyncRequest} dataKey="id"
filters={filters} filters={filters}
globalFilterFields={['name', 'status']} globalFilterFields={['name', 'status']}
header={header} header={header}
emptyMessage={__('Nessun dato disponibile', 'gepafin')} emptyMessage={__('Nessun dato disponibile', 'gepafin')}
onFilter={(e) => setFilters(e.filters)}> onFilter={(e) => setFilters(e.filters)}>
<Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder="Search by name" <Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder={__('Cerca il nome', 'gepafin')}
style={{ minWidth: '12rem' }}/> style={{ minWidth: '12rem' }}/>
<Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date" <Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date"
style={{ minWidth: '10rem' }} style={{ minWidth: '10rem' }}

View File

@@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { pathOr } from 'ramda'; import { pathOr } from 'ramda';
import NumberFlow from '@number-flow/react';
// store // store
//import { storeSet } from '../../store'; //import { storeSet } from '../../store';
@@ -13,6 +14,7 @@ import DashboardService from '../../service/dashboard-service';
import LatestBandiTable from './components/LatestBandiTable'; import LatestBandiTable from './components/LatestBandiTable';
//import LatestUsersActivityTable from './components/LatestUsersActivityTable'; //import LatestUsersActivityTable from './components/LatestUsersActivityTable';
import { Button } from 'primereact/button'; import { Button } from 'primereact/button';
import MyEvaluationsTable from '../DashboardInstructor/components/MyEvaluationsTable';
const Dashboard = () => { const Dashboard = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -67,27 +69,52 @@ const Dashboard = () => {
<div className="statsBigBadges__grid"> <div className="statsBigBadges__grid">
<div className="statsBigBadges__gridItem"> <div className="statsBigBadges__gridItem">
<span>{__('Bandi attivi', 'gepafin')}</span> <span>{__('Bandi attivi', 'gepafin')}</span>
<span>{getStatValue('numberOfActiveCalls', 0)}</span> <span><NumberFlow
value={getStatValue('numberOfActiveCalls', 0)}
format={{ notation: 'compact' }}
locales="it-IT" /></span>
</div> </div>
<div className="statsBigBadges__gridItem"> <div className="statsBigBadges__gridItem">
<span>{__('Utenti registrati', 'gepafin')}</span> <span>{__('Utenti registrati', 'gepafin')}</span>
<span>{getStatValue('numberOfResgisteredUsers', 0)}</span> <span><NumberFlow
value={getStatValue('numberOfResgisteredUsers', 0)}
format={{ notation: 'compact' }}
locales="it-IT" /></span>
</div> </div>
<div className="statsBigBadges__gridItem"> <div className="statsBigBadges__gridItem">
<span>{__('Domande in pre-istruttoria', 'gepafin')}</span> <span>{__('Domande in pre-istruttoria', 'gepafin')}</span>
<span>{getStatValue('numberOfSubmittedApplications', 0)}</span> <span><NumberFlow
value={getStatValue('numberOfSubmittedApplications', 0)}
format={{ notation: 'compact' }}
locales="it-IT" /></span>
</div> </div>
<div className="statsBigBadges__gridItem"> <div className="statsBigBadges__gridItem">
<span>{__('Domande in bozza', 'gepafin')}</span> <span>{__('Domande in bozza', 'gepafin')}</span>
<span>{getStatValue('numberOfDraftApplications', 0)}</span> <span><NumberFlow
value={getStatValue('numberOfDraftApplications', 0)}
format={{ notation: 'compact' }}
locales="it-IT" /></span>
</div> </div>
<div className="statsBigBadges__gridItem"> <div className="statsBigBadges__gridItem">
<span>{__('Aziende', 'gepafin')}</span> <span>{__('Aziende', 'gepafin')}</span>
<span>{getStatValue('numberOfCompany', 0)}</span> <span><NumberFlow
value={getStatValue('numberOfCompany', 0)}
format={{ notation: 'compact' }}
locales="it-IT" /></span>
</div> </div>
<div className="statsBigBadges__gridItem"> <div className="statsBigBadges__gridItem">
<span>{__('Totale finanziamenti attivi', 'gepafin')}</span> <span>{__('Totale finanziamenti attivi', 'gepafin')}</span>
<span>{formatToMillions(getStatValue('totalActiveFinancing', 0))}</span> <span><NumberFlow
value={getStatValue('totalActiveFinancing', 0)}
format={{
notation: 'compact',
compactDisplay: 'short',
roundingMode: 'trunc',
style: 'currency',
currency: 'EUR',
currencyDisplay: 'symbol'
}}
locales="en-US" /></span>
</div> </div>
</div> </div>
</div> </div>
@@ -95,10 +122,17 @@ const Dashboard = () => {
<div className="appPage__spacer"></div> <div className="appPage__spacer"></div>
<div className="appPageSection"> <div className="appPageSection">
<h2>{__('Ultimi Bandi Pubblicati', 'gepafin')}</h2> <h2>{__('Ultimi bandi pubblicati', 'gepafin')}</h2>
<LatestBandiTable/> <LatestBandiTable/>
</div> </div>
<div className="appPage__spacer"></div>
<div className="appPageSection">
<h2>{__('Ultime domande pubblicate', 'gepafin')}</h2>
<MyEvaluationsTable/>
</div>
{/*<div className="appPage__spacer"></div> {/*<div className="appPage__spacer"></div>
<div className="appPageSection"> <div className="appPageSection">

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect} from 'react'; import React, { useState, useEffect} from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { uniq } from 'ramda'; import { uniq } from 'ramda';
import { Link } from 'react-router-dom';
// tools // tools
import getBandoLabel from '../../../../helpers/getBandoLabel'; import getBandoLabel from '../../../../helpers/getBandoLabel';
@@ -25,7 +26,6 @@ import { Button } from 'primereact/button';
import { Calendar } from 'primereact/calendar'; import { Calendar } from 'primereact/calendar';
import { Tag } from 'primereact/tag'; import { Tag } from 'primereact/tag';
import ProperBandoLabel from '../../../../components/ProperBandoLabel'; import ProperBandoLabel from '../../../../components/ProperBandoLabel';
import { Link } from 'react-router-dom';
const LatestBandiTable = () => { const LatestBandiTable = () => {
@@ -43,7 +43,7 @@ const LatestBandiTable = () => {
const getCallback = (data) => { const getCallback = (data) => {
if (data.status === 'SUCCESS') { if (data.status === 'SUCCESS') {
const newItems = data.data.filter(o => o.status === 'PUBLISH'); const newItems = data.data.filter(o => o.status === 'PUBLISH');
setItems(getFormattedBandiData(newItems)); setItems(getFormattedData(newItems));
setStatuses(uniq(data.data.map(o => o.status))) setStatuses(uniq(data.data.map(o => o.status)))
initFilters(); initFilters();
} }
@@ -55,7 +55,7 @@ const LatestBandiTable = () => {
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} }
const getFormattedBandiData = (data) => { const getFormattedData = (data) => {
return [...(data || [])].map((d) => { return [...(data || [])].map((d) => {
d.start_date = new Date(d.dates[0]); d.start_date = new Date(d.dates[0]);
d.end_date = new Date(d.dates[1]); d.end_date = new Date(d.dates[1]);
@@ -121,18 +121,10 @@ const LatestBandiTable = () => {
return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)} dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999" />; return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)} dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999" />;
}; };
const balanceFilterTemplate = (options) => {
return <InputNumber value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)} />;
};
const statusBodyTemplate = (rowData) => { const statusBodyTemplate = (rowData) => {
return <ProperBandoLabel status={rowData.status}/>; return <ProperBandoLabel status={rowData.status}/>;
}; };
const statusFilterTemplate = (options) => {
return <Dropdown value={options.value} options={statuses} onChange={(e) => options.filterCallback(e.value, options.index)} itemTemplate={statusItemTemplate} placeholder="Select One" className="p-column-filter" showClear />;
};
const statusItemTemplate = (option) => { const statusItemTemplate = (option) => {
return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)} />; return <Tag value={getBandoLabel(option)} severity={getBandoSeverity(option)} />;
}; };
@@ -153,7 +145,7 @@ const LatestBandiTable = () => {
header={header} header={header}
emptyMessage={__('Nessun dato disponibile', 'gepafin')} emptyMessage={__('Nessun dato disponibile', 'gepafin')}
onFilter={(e) => setFilters(e.filters)}> onFilter={(e) => setFilters(e.filters)}>
<Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder="Search by name" <Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder={__('Cerca il nome', 'gepafin')}
style={{ minWidth: '12rem' }}/> style={{ minWidth: '12rem' }}/>
<Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date" <Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date"
style={{ minWidth: '10rem' }} style={{ minWidth: '10rem' }}

View File

@@ -26,14 +26,14 @@ import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse
const MyLatestSubmissionsTable = () => { const MyLatestSubmissionsTable = () => {
const isAsyncRequest = useStore().main.isAsyncRequest(); const [localAsyncRequest, setLocalAsyncRequest] = useState(false);
const [items, setItems] = useState(null); const [items, setItems] = useState(null);
const [filters, setFilters] = useState(null); const [filters, setFilters] = useState(null);
const [globalFilterValue, setGlobalFilterValue] = useState(''); const [globalFilterValue, setGlobalFilterValue] = useState('');
const [statuses, setStatuses] = useState([]); const [statuses, setStatuses] = useState([]);
useEffect(() => { useEffect(() => {
storeSet.main.setAsyncRequest(); setLocalAsyncRequest(true);
ApplicationService.getApplications(getApplCallback, errGetApplCallback) ApplicationService.getApplications(getApplCallback, errGetApplCallback)
}, []); }, []);
@@ -45,12 +45,11 @@ const MyLatestSubmissionsTable = () => {
initFilters(); initFilters();
} }
} }
storeSet.main.unsetAsyncRequest(); setLocalAsyncRequest(false);
} }
const errGetApplCallback = (data) => { const errGetApplCallback = (data) => {
set404FromErrorResponse(data); setLocalAsyncRequest(false);
storeSet.main.unsetAsyncRequest();
} }
const getFormattedBandiData = (data) => { const getFormattedBandiData = (data) => {
@@ -164,13 +163,13 @@ const MyLatestSubmissionsTable = () => {
return ( return (
<div className="appPageSection__table"> <div className="appPageSection__table">
<DataTable value={items} paginator showGridlines rows={10} loading={isAsyncRequest} dataKey="id" <DataTable value={items} paginator showGridlines rows={10} loading={localAsyncRequest} dataKey="id"
filters={filters} filters={filters}
globalFilterFields={['name', 'status']} globalFilterFields={['name', 'status']}
header={header} header={header}
emptyMessage={__('Nessun dato disponibile', 'gepafin')} emptyMessage={__('Nessun dato disponibile', 'gepafin')}
onFilter={(e) => setFilters(e.filters)}> onFilter={(e) => setFilters(e.filters)}>
<Column field="callTitle" header={__('Bando', 'gepafin')} filter filterPlaceholder="Search by name" <Column field="callTitle" header={__('Bando', 'gepafin')} filter filterPlaceholder={__('Cerca il nome', 'gepafin')}
style={{ minWidth: '12rem' }}/> style={{ minWidth: '12rem' }}/>
<Column header={__('Scadenza', 'gepafin')} filterField="callEndDate" dataType="date" <Column header={__('Scadenza', 'gepafin')} filterField="callEndDate" dataType="date"
style={{ minWidth: '10rem' }} style={{ minWidth: '10rem' }}

View File

@@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { head, pathOr } from 'ramda'; import { head, pathOr } from 'ramda';
import NumberFlow from '@number-flow/react';
// store // store
import { useStore } from '../../store'; import { useStore } from '../../store';
@@ -57,15 +58,24 @@ const DashboardBeneficiario = () => {
<div className="statsBigBadges__grid"> <div className="statsBigBadges__grid">
<div className="statsBigBadges__gridItem"> <div className="statsBigBadges__gridItem">
<span>{__('Domande attive', 'gepafin')}</span> <span>{__('Domande attive', 'gepafin')}</span>
<span>{getStatValue('numberOfApplications', 0)}</span> <span><NumberFlow
value={getStatValue('numberOfApplications', 0)}
format={{ notation: 'compact' }}
locales="it-IT" /></span>
</div> </div>
<div className="statsBigBadges__gridItem"> <div className="statsBigBadges__gridItem">
<span>{__('Bandi osservati', 'gepafin')}</span> <span>{__('Bandi osservati', 'gepafin')}</span>
<span>{getStatValue('numberOfCalls', 0)}</span> <span><NumberFlow
value={getStatValue('numberOfCalls', 0)}
format={{ notation: 'compact' }}
locales="it-IT" /></span>
</div> </div>
<div className="statsBigBadges__gridItem"> <div className="statsBigBadges__gridItem">
<span>{__('Documenti da integrare', 'gepafin')}</span> <span>{__('Documenti da integrare', 'gepafin')}</span>
<span>{getStatValue('numberOfIntegratedDocuments', 0)}</span> <span><NumberFlow
value={getStatValue('numberOfIntegratedDocuments', 0)}
format={{ notation: 'compact' }}
locales="it-IT" /></span>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,189 @@
import React, { useState, useEffect } from 'react';
import { __ } from '@wordpress/i18n';
import { Link } from 'react-router-dom';
// store
import { useStore } from '../../../../store';
// tools
//import set404FromErrorResponse from '../../../../helpers/set404FromErrorResponse';
import ProperBandoLabel from '../../../../components/ProperBandoLabel';
// api
//import ApplicationService from '../../../../service/application-service';
// components
import { FilterMatchMode, FilterOperator } from 'primereact/api';
import { DataTable } from 'primereact/datatable';
import { Column } from 'primereact/column';
import { InputText } from 'primereact/inputtext';
import { IconField } from 'primereact/iconfield';
import { InputIcon } from 'primereact/inputicon';
import { Button } from 'primereact/button';
import { Calendar } from 'primereact/calendar';
const MyEvaluationsTable = () => {
const isAsyncRequest = useStore().main.isAsyncRequest();
const [items, setItems] = useState(null);
const [filters, setFilters] = useState(null);
const [globalFilterValue, setGlobalFilterValue] = useState('');
useEffect(() => {
const demoItems = [
{
id: 1,
callTitle: 'Bando 1',
appliedDate: '2024-10-01',
callEndDate: '2025-11-25',
status: 'AWAITING'
},
{
id: 2,
callTitle: 'Bando 2',
appliedDate: '2024-08-11',
callEndDate: '2027-09-23',
status: 'AWAITING'
}
];
setItems(getFormattedData(demoItems));
/*storeSet.main.setAsyncRequest();
ApplicationService.getApplications(getApplCallback, errGetApplCallback)*/
}, []);
/*const getApplCallback = (data) => {
if (data.status === 'SUCCESS') {
if (data.data.length) {
setItems(getFormattedBandiData(data.data));
setStatuses(uniq(items.map(o => o.status)))
initFilters();
}
}
storeSet.main.unsetAsyncRequest();
}
const errGetApplCallback = (data) => {
set404FromErrorResponse(data);
storeSet.main.unsetAsyncRequest();
}*/
const getFormattedData = (data) => {
return [...(data || [])].map((d) => {
d.appliedDate = new Date(d.appliedDate);
d.callEndDate = new Date(d.callEndDate);
return d;
});
};
const formatDate = (value) => {
return value.toLocaleDateString('it-IT', {
day: '2-digit',
month: '2-digit',
year: 'numeric'
});
};
const clearFilter = () => {
initFilters();
};
const onGlobalFilterChange = (e) => {
const value = e.target.value;
let _filters = { ...filters };
_filters['global'].value = value;
setFilters(_filters);
setGlobalFilterValue(value);
};
const initFilters = () => {
setFilters({
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
callTitle: {
operator: FilterOperator.AND,
constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
},
appliedDate: {
operator: FilterOperator.AND,
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
},
callEndDate: {
operator: FilterOperator.AND,
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
}
});
setGlobalFilterValue('');
};
const renderHeader = () => {
return (
<div className="appTableHeader">
<Button type="button" icon="pi pi-filter-slash" label={__('Pulisci', 'gepafin')} outlined
onClick={clearFilter}/>
<IconField iconPosition="left">
<InputIcon className="pi pi-search"/>
<InputText value={globalFilterValue} onChange={onGlobalFilterChange}
placeholder={__('Cerca', 'gepafin')}/>
</IconField>
</div>
);
};
const dateAppliedBodyTemplate = (rowData) => {
return formatDate(rowData.appliedDate);
};
const dateEndBodyTemplate = (rowData) => {
return formatDate(rowData.callEndDate);
};
const dateFilterTemplate = (options) => {
return <Calendar value={options.value} onChange={(e) => options.filterCallback(e.value, options.index)}
dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" mask="99/99/9999"/>;
};
const statusBodyTemplate = (rowData) => {
return <ProperBandoLabel status={rowData.status}/>;
};
const actionsBodyTemplate = (rowData) => {
return <Link to={`/valutazioni/${rowData.id}`}>
<Button type="button"
severity="info"
label={__('Valuta', 'gepafin')}
size="small"/>
</Link>
}
const header = renderHeader();
return (
<div className="appPageSection__table">
<DataTable value={items} paginator showGridlines rows={10} loading={isAsyncRequest} dataKey="id"
filters={filters}
globalFilterFields={['name', 'status']}
header={header}
emptyMessage={__('Nessun dato disponibile', 'gepafin')}
onFilter={(e) => setFilters(e.filters)}>
<Column field="id" header={__('ID domanda', 'gepafin')}
style={{ minWidth: '2rem' }}/>
<Column field="callTitle" header={__('Bando', 'gepafin')} filter filterPlaceholder={__('Cerca il nome', 'gepafin')}
style={{ minWidth: '12rem' }}/>
<Column header={__('Data Ricezione', 'gepafin')} filterField="modifiedDate" dataType="date"
style={{ minWidth: '10rem' }}
body={dateAppliedBodyTemplate} filter filterElement={dateFilterTemplate}/>
<Column header={__('Scadenza', 'gepafin')} filterField="callEndDate" dataType="date"
style={{ minWidth: '10rem' }}
body={dateEndBodyTemplate} filter filterElement={dateFilterTemplate}/>
<Column field="status" header={__('Stato', 'gepafin')}
style={{ width: '120px' }} body={statusBodyTemplate} />
<Column header={__('Azioni', 'gepafin')}
body={actionsBodyTemplate}/>
</DataTable>
</div>
)
}
export default MyEvaluationsTable;

View File

@@ -0,0 +1,76 @@
import React, { useEffect, useState } from 'react';
import { __ } from '@wordpress/i18n';
import { useNavigate } from 'react-router-dom';
import { head, pathOr } from 'ramda';
// store
import { useStore } from '../../store';
// api
//import DashboardService from '../../service/dashboard-service';
// components
//import LatestBandiTable from './components/LatestBandiTable';
//import MyLatestSubmissionsTable from './components/MyLatestSubmissionsTable';
import { Button } from 'primereact/button';
import MyEvaluationsTable from './components/MyEvaluationsTable';
const DashboardInstructor = () => {
const navigate = useNavigate();
//const [mainStats, setMainStats] = useState({});
const goToAllEvaluations = () => {
navigate('/valutazioni');
}
return(
<div className="appPage">
<div className="appPage__pageHeader">
<h1>{__('Dashboard', 'gepafin')}</h1>
</div>
{/*<div className="appPage__spacer"></div>
<div className="appPageSection statsBigBadges">
<h2>{__('Panoramica di Sistema', 'gepafin')}</h2>
<div className="statsBigBadges__grid">
<div className="statsBigBadges__gridItem">
<span>{__('Domande attive', 'gepafin')}</span>
<span>{getStatValue('numberOfApplications', 0)}</span>
</div>
<div className="statsBigBadges__gridItem">
<span>{__('Bandi osservati', 'gepafin')}</span>
<span>{getStatValue('numberOfCalls', 0)}</span>
</div>
<div className="statsBigBadges__gridItem">
<span>{__('Documenti da integrare', 'gepafin')}</span>
<span>{getStatValue('numberOfIntegratedDocuments', 0)}</span>
</div>
</div>
</div>*/}
<div className="appPage__spacer"></div>
<div className="appPageSection">
<h2>{__('Coda di lavoro', 'gepafin')}</h2>
<MyEvaluationsTable/>
</div>
<div className="appPage__spacer"></div>
<div className="appPageSection__hr">
<span>{__('Azioni rapide', 'gepafin')}</span>
</div>
<div className="appPageSection">
<div className="appPageSection__actions">
<Button
onClick={goToAllEvaluations}
label={__('Tutti valutazioni', 'gepafin')} icon="pi pi-arrow-right" iconPos="right"/>
</div>
</div>
</div>
)
}
export default DashboardInstructor;

View File

@@ -0,0 +1,227 @@
import React, { useState, useEffect, useRef } from 'react';
import { __, sprintf } from '@wordpress/i18n';
import { useNavigate, useParams } from 'react-router-dom';
import { is, isEmpty, isNil } from 'ramda';
// store
import { storeSet, useStore } from '../../store';
// tools
import getNumberWithCurrency from '../../helpers/getNumberWithCurrency';
//import getDateFromISOstring from '../../helpers/getDateFromISOstring';
// components
import { Skeleton } from 'primereact/skeleton';
import { Button } from 'primereact/button';
import { Messages } from 'primereact/messages';
import { Tag } from 'primereact/tag';
const EvaluationEdit = () => {
const isAsyncRequest = useStore().main.isAsyncRequest();
const { id } = useParams();
const navigate = useNavigate();
const [data, setData] = useState({});
const pageMsgs = useRef(null);
const goToEvaluationsPage = () => {
navigate('/valutazioni');
}
/*const getCallback = (data) => {
if (data.status === 'SUCCESS') {
setData(getFormattedBandiData(data.data));
}
storeSet.main.unsetAsyncRequest();
}
const errGetCallback = (data) => {
if (pageMsgs.current && data.message) {
pageMsgs.current.show([
{
sticky: true, severity: 'error', summary: '',
detail: data.message,
closable: true
}
]);
}
set404FromErrorResponse(data);
storeSet.main.unsetAsyncRequest();
}*/
/*const getFormattedBandiData = (data) => {
data.dates = data.dates.map(v => is(String, v) ? new Date(v) : (v ? v : ''));
return data;
};*/
useEffect(() => {
const parsed = parseInt(id)
const entityId = !isNaN(parsed) ? parsed : 0;
setData({
id: 'DOM_2024_001',
callTitle: 'Innovazione 2024',
beneficiario: 'Azienda Alpha SRL',
createdAt: '2024-08-01',
scadenzaAt: '2024-08-05',
status: 'In Valutazione',
criteria: [
{ title: 'Innovatività del progetto', score: 25, id: 12 },
{ title: 'Innovatività del progetto2', score: 35, id: 13 },
{ title: 'Innovatività del progetto3', score: 15, id: 14 }
],
minScore: 60
});
//BandoService.getBando(entityId, getCallback, errGetCallback);
}, [id]);
return (
<div className="appPage">
<div className="appPage__pageHeader">
<h1>{__('Valuta domanda', 'gepafin')}</h1>
</div>
<div className="appPage__spacer"></div>
<Messages ref={pageMsgs}/>
<div className="appPageSection__row">
<Button
type="button"
outlined
onClick={goToEvaluationsPage}
label={__('Indietro', 'gepafin')}
icon="pi pi-arrow-left" iconPos="left"/>
</div>
<div className="appPage__spacer"></div>
{!isAsyncRequest && !isEmpty(data)
? <div className="appPage__content">
<div className="appPageSection__withBorder columns">
<p className="appPageSection__pMeta">
<span>{__('ID domanda', 'gepafin')}</span>
<span>{data.id}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Bando', 'gepafin')}</span>
<span>{data.callTitle}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Beneficiario', 'gepafin')}</span>
<span>{data.beneficiario}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Data ricezione', 'gepafin')}</span>
<span>{data.createdAt}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Scadenza Valutazione', 'gepafin')}</span>
<span>{data.scadenzaAt}</span>
</p>
<p className="appPageSection__pMeta">
<span>{__('Stato', 'gepafin')}</span>
<span>{data.status}</span>
</p>
</div>
<div className="appPageSection">
<h2>{__('Punteggi di valutazione', 'gepafin')}</h2>
{data.criteria
? <table className="myTable">
<thead className="myThead">
<tr>
<th>{__('Parametro', 'gepafin')}</th>
<th>{__('Punteggio', 'gepafin')}</th>
<th>{__('Stato', 'gepafin')}</th>
</tr>
</thead>
<tbody className="myTbody">
{data.criteria.map(o => <tr key={o.id}>
<td>{o.title}</td>
<td>{o.score}</td>
<td></td>
</tr>)}
<tr>
<td>{__('Punteggio:', 'gepafin')}</td>
<td>{68}</td>
<td><Tag icon="pi pi-check" severity="success" value={__('Ammissibile')}></Tag></td>
</tr>
</tbody>
<tfoot className="myTfoot">
<tr>
<td colSpan="3">{sprintf(__('Punteggio minimo per l\'ammissione: %d'), data.minScore)}</td>
</tr>
</tfoot>
</table> : null}
</div>
<div className="appPageSection">
<h2>{__('Checklist Valutazione', 'gepafin')}</h2>
</div>
<div className="appPage__spacer"></div>
<div className="appPageSection__hr">
<span>{__('Azioni rapide', 'gepafin')}</span>
</div>
<div className="appPageSection">
<div className="appPageSection__actions">
<Button
type="button"
outlined
label={<>
{__('Richiedi Soccorso Istruttorio', 'gepafin')}
<i style={{marginLeft: 7}}>
<svg width="15" height="14" viewBox="0 0 15 14" fill="none"
xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0_1665_1656)">
<path
d="M7.50129 14C6.53308 14 5.62302 13.8163 4.7711 13.4488C3.91919 13.0814 3.17818 12.5827 2.54805 11.9529C1.91793 11.323 1.41903 10.5823 1.05134 9.73074C0.683781 8.87919 0.5 7.96938 0.5 7.00129C0.5 6.03308 0.683719 5.12302 1.05116 4.2711C1.4186 3.41919 1.91725 2.67818 2.54713 2.04805C3.17701 1.41793 3.91772 0.919026 4.76926 0.551342C5.62081 0.183781 6.53062 0 7.49871 0C8.46692 0 9.37698 0.183719 10.2289 0.551158C11.0808 0.918596 11.8218 1.41725 12.4519 2.04713C13.0821 2.67701 13.581 3.41772 13.9487 4.26926C14.3162 5.12081 14.5 6.03062 14.5 6.99871C14.5 7.96692 14.3163 8.87698 13.9488 9.72889C13.5814 10.5808 13.0827 11.3218 12.4529 11.9519C11.823 12.5821 11.0823 13.081 10.2307 13.4487C9.37919 13.8162 8.46938 14 7.50129 14ZM5.36316 12.4895L6.44576 10.0238C5.98585 9.86147 5.58888 9.60977 5.25484 9.26874C4.92081 8.92758 4.66598 8.52747 4.49037 8.06842L1.99634 9.1C2.28359 9.88596 2.72195 10.5737 3.31142 11.1632C3.90089 11.7526 4.58481 12.1947 5.36316 12.4895ZM4.49037 5.93158C4.65665 5.47253 4.90816 5.07555 5.24489 4.74066C5.58163 4.40576 5.97719 4.15567 6.43158 3.99037L5.4 1.49634C4.60937 1.79587 3.91932 2.24037 3.32984 2.82984C2.74037 3.41932 2.29587 4.10937 1.99634 4.9L4.49037 5.93158ZM7.49834 9.09724C8.08045 9.09724 8.57579 8.8935 8.98437 8.48603C9.39295 8.07855 9.59724 7.58376 9.59724 7.00166C9.59724 6.41955 9.3935 5.92421 8.98603 5.51563C8.57855 5.10705 8.08376 4.90276 7.50166 4.90276C6.91955 4.90276 6.42421 5.1065 6.01563 5.51397C5.60705 5.92145 5.40276 6.41624 5.40276 6.99834C5.40276 7.58045 5.6065 8.07579 6.01397 8.48437C6.42145 8.89295 6.91624 9.09724 7.49834 9.09724ZM9.63684 12.4895C10.4105 12.1947 11.089 11.7557 11.6724 11.1724C12.2557 10.589 12.6947 9.91053 12.9895 9.13684L10.5238 8.05424C10.368 8.50862 10.1209 8.90302 9.78274 9.23742C9.44453 9.57182 9.05203 9.82923 8.60526 10.0096L9.63684 12.4895ZM10.5096 5.89474L12.9895 4.86316C12.6947 4.08947 12.2557 3.41096 11.6724 2.82763C11.089 2.2443 10.4105 1.80526 9.63684 1.51053L8.60526 4.01303C9.04258 4.18299 9.4242 4.43051 9.75013 4.75558C10.0761 5.08053 10.3292 5.46025 10.5096 5.89474Z"
fill="#3B7C43"/>
</g>
<defs>
<clipPath id="clip0_1665_1656">
<rect width="14" height="14" fill="white"
transform="translate(0.5)"/>
</clipPath>
</defs>
</svg>
</i>
</>}
/>
<Button
type="button"
outlined
label={__('Salva Bozza Valutazione', 'gepafin')}
icon="pi pi-save" iconPos="right"/>
<Button
type="button"
label={__('Richiedi Soccorso Istruttorio', 'gepafin')}
icon="pi pi-check" iconPos="right"/>
<Button
type="button"
label={__('Richiedi Soccorso Istruttorio', 'gepafin')}
icon="pi pi-times" iconPos="right"/>
</div>
</div>
</div>
: <>
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
<Skeleton width="100%" height="2rem" className="mb-8"></Skeleton>
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
<Skeleton width="100%" height="4rem" className="mb-8"></Skeleton>
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
<Skeleton width="100%" height="2rem" className="mb-8"></Skeleton>
<Skeleton width="20%" height="1rem" className="mb-2"></Skeleton>
<Skeleton width="100%" height="4rem"></Skeleton>
</>}
</div>
)
}
export default EvaluationEdit;

View File

@@ -0,0 +1,23 @@
import React from 'react';
import { __ } from '@wordpress/i18n';
// components
import MyEvaluationsTable from '../DashboardInstructor/components/MyEvaluationsTable';
const Bandi = () => {
return(
<div className="appPage">
<div className="appPage__pageHeader">
<h1>{__('Domande da valutare', 'gepafin')}</h1>
</div>
<div className="appPage__spacer"></div>
<div className="appPageSection">
<MyEvaluationsTable/>
</div>
</div>
)
}
export default Bandi;

View File

@@ -114,9 +114,9 @@ const LoginAdmin = () => {
label={__('Accedi', 'gepafin')} label={__('Accedi', 'gepafin')}
disabled={loading}/> disabled={loading}/>
<Button {/*<Button
label={__('Password dimenticata?', 'gepafin')} label={__('Password dimenticata?', 'gepafin')}
link onClick={gotToResetPassword}/> link onClick={gotToResetPassword}/>*/}
</form> </form>
</div> </div>
</div> </div>

View File

@@ -129,88 +129,7 @@ const Profile = () => {
</div> </div>
<div className="appPageSection"> <div className="appPageSection">
<h2>{__('Consensi', 'gepafin')}</h2> <h2>{__('Impostazioni', 'gepafin')}</h2>
<div className="appForm__switchFieldWrapper">
<FormField
type="switch"
disabled={true}
fieldName="privacy"
label={''}
control={control}
errors={errors}
onLabel={''}
offLabel={''}
/>
<div>
{__('Dichiaro di aver preso visione, prima dell\'accesso al portale https://bandi.gepafin.it, dell\' "Informativa Privacy" all\'interno dell\'Appendice 10 dell\'Avviso secondo il Regolamento UE 2016/679 relativo alla protezione delle persone fisiche con riguardo al trattamento dei dati personale, nonché alla libera circolazione di tali dati e che abroga la Direttiva 95/46 CE.', 'gepafin')}
</div>
</div>
<div className="appForm__switchFieldWrapper">
<FormField
type="switch"
disabled={true}
fieldName="terms"
label={''}
control={control}
errors={errors}
onLabel={''}
offLabel={''}
/>
<div>
{__('Termini e condizioni', 'gepafin')}
</div>
</div>
<div className="appForm__switchFieldWrapper">
<FormField
type="switch"
fieldName="marketing"
label={''}
control={control}
errors={errors}
onLabel={''}
offLabel={''}
/>
<div>
{__('Invio di materiale pubblicitario, vendita diretta, compimento di ricerche di mercato o comunicazione commerciale riguardanti promozione e vendita di prodotti e servizi della Gepafin, mediante modalità di contatto automatizzate (posta elettronica, PEC, messaggi tramite canali informatici, network ed applicazioni web) e tradizionali (come posta cartacea e chiamate telefoniche con operatore)', 'gepafin')}
</div>
</div>
<div className="appForm__switchFieldWrapper">
<FormField
type="switch"
fieldName="offers"
label={''}
control={control}
errors={errors}
onLabel={''}
offLabel={''}
/>
<div>
{__('Elaborazione, in forma elettronica, dei dati relativi ai rapporti e servizi forniti, per lanalisi di comportamenti e preferenze della clientela, da utilizzare a scopo commerciale, per la individuazione ed offerta di prodotti e servizi di suo interesse', 'gepafin')}
</div>
</div>
<div className="appForm__switchFieldWrapper">
<FormField
type="switch"
fieldName="thirdParty"
label={''}
control={control}
errors={errors}
onLabel={''}
offLabel={''}
/>
<div>
{__('Comunicazione dei miei dati ad altre società in ambito bancario, finanziario od assicurativo e enti pubblici che li tratteranno per invio di materiale pubblicitario, vendita diretta, compimento di ricerche di mercato o comunicazione commerciale riguardanti loro prodotti o servizi, mediante le modalità automatizzate e tradizionali di comunicazione sopra indicate', 'gepafin')}
</div>
</div>
</div>
<div className="appPageSection">
<h2>{__('Utenti Associati', 'gepafin')}</h2>
<div className="appForm__cols"> <div className="appForm__cols">
<FormField <FormField
type="select" type="select"

View File

@@ -0,0 +1,288 @@
import React, { useMemo, useRef } from 'react';
import { __ } from '@wordpress/i18n';
import { useForm } from 'react-hook-form';
// store
import { storeSet, useStore } from '../../store';
// components
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
import FormField from '../../components/FormField';
import { Button } from 'primereact/button';
import { Toast } from 'primereact/toast';
// api
import UserService from '../../service/user-service';
// tools
import getDateFromISOstring from '../../helpers/getDateFromISOstring';
const ProfileBeneficiario = () => {
const isAsyncRequest = useStore().main.isAsyncRequest();
const userData = useStore().main.userData();
const toast = useRef(null);
const {
control,
handleSubmit,
formState: { errors }
} = useForm({
defaultValues: useMemo(() => {
return userData;
}, [userData]),
mode: 'onChange'
});
const onSubmit = (formData) => {
storeSet.main.setAsyncRequest();
UserService.updateUser(userData.id, formData, updateCallback, updateError);
};
const updateCallback = (data) => {
if (data.status === 'SUCCESS') {
storeSet.main.userData(data.data);
if (toast.current) {
toast.current.show({
severity: 'success',
summary: '',
detail: __('L\'utente è stato aggiornato!', 'gepafin')
});
}
}
storeSet.main.unsetAsyncRequest();
}
const updateError = (data) => {
set404FromErrorResponse(data);
storeSet.main.unsetAsyncRequest();
}
return (
<div className="appPage">
<div className="appPage__pageHeader">
<h1>{__('Profilo utente', 'gepafin')}</h1>
</div>
<div className="appPage__spacer"></div>
<Toast ref={toast}/>
<form className="appForm" onSubmit={handleSubmit(onSubmit)}>
<div className="appPageSection">
<h2>{__('Informazioni personali', 'gepafin')}</h2>
<div className="appForm__cols">
<FormField
type="textinput"
disabled={true}
fieldName="firstName"
label={__('Nome', 'gepafin')}
control={control}
errors={errors}
config={{ required: __('È obbligatorio', 'gepafin') }}
placeholder="Francesco"
/>
<FormField
type="textinput"
disabled={true}
fieldName="lastName"
label={__('Cognome', 'gepafin')}
control={control}
errors={errors}
config={{ required: __('È obbligatorio', 'gepafin') }}
placeholder="Moli"
/>
<FormField
type="textinput"
disabled={true}
fieldName="codiceFiscale"
label={__('Codice fiscale', 'gepafin')}
control={control}
errors={errors}
config={{ required: __('È obbligatorio', 'gepafin') }}
placeholder="XXXXXXXX"
/>
</div>
<div className="appForm__cols">
<FormField
type="textinput"
fieldName="email"
label={__('Email', 'gepafin')}
control={control}
errors={errors}
config={{ required: __('È obbligatorio', 'gepafin') }}
placeholder="user@example.com"
/>
<FormField
type="textinput"
fieldName="phoneNumber"
label={__('Telefono', 'gepafin')}
control={control}
errors={errors}
config={{ required: __('È obbligatorio', 'gepafin') }}
placeholder="1234567"
/>
</div>
</div>
<div className="appPageSection">
<h2>{__('Consensi', 'gepafin')}</h2>
<div className="appForm__switchFieldWrapper">
<FormField
type="switch"
disabled={true}
fieldName="privacy"
label={''}
control={control}
errors={errors}
onLabel={''}
offLabel={''}
/>
<div>
{__('Dichiaro di aver preso visione, prima dell\'accesso al portale https://bandi.gepafin.it, dell\' "Informativa Privacy" all\'interno dell\'Appendice 10 dell\'Avviso secondo il Regolamento UE 2016/679 relativo alla protezione delle persone fisiche con riguardo al trattamento dei dati personale, nonché alla libera circolazione di tali dati e che abroga la Direttiva 95/46 CE.', 'gepafin')}
</div>
</div>
<div className="appForm__switchFieldWrapper">
<FormField
type="switch"
disabled={true}
fieldName="terms"
label={''}
control={control}
errors={errors}
onLabel={''}
offLabel={''}
/>
<div>
{__('Termini e condizioni', 'gepafin')}
</div>
</div>
<div className="appForm__switchFieldWrapper">
<FormField
type="switch"
fieldName="marketing"
label={''}
control={control}
errors={errors}
onLabel={''}
offLabel={''}
/>
<div>
{__('Invio di materiale pubblicitario, vendita diretta, compimento di ricerche di mercato o comunicazione commerciale riguardanti promozione e vendita di prodotti e servizi della Gepafin, mediante modalità di contatto automatizzate (posta elettronica, PEC, messaggi tramite canali informatici, network ed applicazioni web) e tradizionali (come posta cartacea e chiamate telefoniche con operatore)', 'gepafin')}
</div>
</div>
<div className="appForm__switchFieldWrapper">
<FormField
type="switch"
fieldName="offers"
label={''}
control={control}
errors={errors}
onLabel={''}
offLabel={''}
/>
<div>
{__('Elaborazione, in forma elettronica, dei dati relativi ai rapporti e servizi forniti, per lanalisi di comportamenti e preferenze della clientela, da utilizzare a scopo commerciale, per la individuazione ed offerta di prodotti e servizi di suo interesse', 'gepafin')}
</div>
</div>
<div className="appForm__switchFieldWrapper">
<FormField
type="switch"
fieldName="thirdParty"
label={''}
control={control}
errors={errors}
onLabel={''}
offLabel={''}
/>
<div>
{__('Comunicazione dei miei dati ad altre società in ambito bancario, finanziario od assicurativo e enti pubblici che li tratteranno per invio di materiale pubblicitario, vendita diretta, compimento di ricerche di mercato o comunicazione commerciale riguardanti loro prodotti o servizi, mediante le modalità automatizzate e tradizionali di comunicazione sopra indicate', 'gepafin')}
</div>
</div>
</div>
<div className="appPageSection">
<h2>{__('Impostazioni', 'gepafin')}</h2>
<div className="appForm__cols">
<FormField
type="select"
disabled={true}
fieldName="language"
defaultValue={'it'}
label={__('Lingua predefinita', 'gepafin')}
control={control}
errors={errors}
config={{ required: __('È obbligatorio', 'gepafin') }}
options={[
{ label: __('Italiano', 'gepafin'), name: 'it' }
]}
/>
<FormField
type="select"
disabled={true}
fieldName="timezone"
defaultValue={'Europe/Rome'}
label={__('Fuso Orario', 'gepafin')}
control={control}
errors={errors}
config={{ required: __('È obbligatorio', 'gepafin') }}
options={[
{ label: __('Europe/Rome', 'gepafin'), name: 'Europe/Rome' }
]}
/>
<FormField
type="select"
disabled={true}
fieldName="dateformat"
defaultValue={'DD/MM/YY'}
label={__('Formato Data', 'gepafin')}
control={control}
errors={errors}
config={{ required: __('È obbligatorio', 'gepafin') }}
options={[
{ label: __('DD/MM/YY', 'gepafin'), name: 'DD/MM/YY' }
]}
/>
</div>
</div>
<div className="appPageSection">
<h2>{__('Sicurezza', 'gepafin')}</h2>
<div className="appForm__row">
<label>{__('Ultimo accesso', 'gepafin')}</label>
<span>{getDateFromISOstring(userData.lastLogin)}</span>
</div>
</div>
<div className="appPage__spacer"></div>
<div className="appPageSection__hr">
<span>{__('Azioni rapide', 'gepafin')}</span>
</div>
<div className="appPageSection">
<div className="appPageSection__actions">
<Button
disabled={isAsyncRequest}
label={__('Salva modifiche', 'gepafin')}
icon="pi pi-check" iconPos="right"/>
</div>
</div>
</form>
</div>
)
}
export default ProfileBeneficiario;

View File

@@ -143,7 +143,7 @@ const ResetPassword = () => {
type="textinput" type="textinput"
inputtype="password" inputtype="password"
fieldName="confirmPassword" fieldName="confirmPassword"
label={__('Conferma Password', 'gepafin')} label={__('Conferma password', 'gepafin')}
control={control} control={control}
errors={errors} errors={errors}
config={{ config={{

View File

@@ -11,6 +11,7 @@ import UserService from '../../service/user-service';
// tools // tools
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse'; import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
import { isEmail } from '../../helpers/validators';
// components // components
import AllUsersTable from './components/AllUsersTable'; import AllUsersTable from './components/AllUsersTable';
@@ -31,7 +32,9 @@ const Users = () => {
lastName: '', lastName: '',
email: '', email: '',
phoneNumber: '', phoneNumber: '',
role: '' password: '',
confPassword: '',
roleId: 0
}); });
const [roles, setRoles] = useState([]); const [roles, setRoles] = useState([]);
const toast = useRef(null); const toast = useRef(null);
@@ -51,18 +54,24 @@ const Users = () => {
lastName: '', lastName: '',
email: '', email: '',
phoneNumber: '', phoneNumber: '',
role: '' password: '',
confPassword: '',
roleId: 0
}); });
} }
const saveEditDialog = () => { const saveEditDialog = () => {
setLoading(true); const emptyValues = Object.values(newUserData).filter(v => isEmpty(v));
const body = {
...newUserData,
hubUuid: APP_HUB_ID
}
UserService.createUser(body, createUserCallback, errCreateUserCallback); if (isEmpty(emptyValues) && newUserData.password === newUserData.confPassword && !loading) {
setLoading(true);
const body = {
...newUserData,
hubUuid: APP_HUB_ID
}
UserService.createUser(body, createUserCallback, errCreateUserCallback);
}
} }
const createUserCallback = (data) => { const createUserCallback = (data) => {
@@ -118,6 +127,8 @@ const Users = () => {
storeSet.main.unsetAsyncRequest(); storeSet.main.unsetAsyncRequest();
} }
const isInvalidField = (data, key) => isEmpty(data[key]) || isNil(data[key])
useEffect(() => { useEffect(() => {
if (isVisibleEditDialog) { if (isVisibleEditDialog) {
UserService.getRoles(getRolesCallback, errGetRolesCallback) UserService.getRoles(getRolesCallback, errGetRolesCallback)
@@ -153,42 +164,73 @@ const Users = () => {
<div className="appForm__cols"> <div className="appForm__cols">
<div className="appForm__field"> <div className="appForm__field">
<label <label
className={classNames({ 'p-error': isEmpty(newUserData.firstName) || isNil(newUserData.firstName) })}>{__('Nome', 'gepafin')}*</label> className={classNames({ 'p-error': isInvalidField(newUserData, 'firstName') })}>
{__('Nome', 'gepafin')}*
</label>
<InputText value={newUserData.firstName} <InputText value={newUserData.firstName}
invalid={isEmpty(newUserData.firstName) || isNil(newUserData.firstName)} invalid={isInvalidField(newUserData, 'firstName')}
onChange={(e) => onChangeEditItem(e.target.value, 'firstName')}/> onChange={(e) => onChangeEditItem(e.target.value, 'firstName')}/>
</div> </div>
<div className="appForm__field"> <div className="appForm__field">
<label <label
className={classNames({ 'p-error': isEmpty(newUserData.lastName) || isNil(newUserData.lastName) })}>{__('Cognome', 'gepafin')}*</label> className={classNames({ 'p-error': isInvalidField(newUserData, 'lastName') })}>
{__('Cognome', 'gepafin')}*
</label>
<InputText value={newUserData.lastName} <InputText value={newUserData.lastName}
invalid={isEmpty(newUserData.lastName) || isNil(newUserData.lastName)} invalid={isInvalidField(newUserData, 'lastName')}
onChange={(e) => onChangeEditItem(e.target.value, 'lastName')}/> onChange={(e) => onChangeEditItem(e.target.value, 'lastName')}/>
</div> </div>
</div> </div>
<div className="appForm__cols"> <div className="appForm__cols">
<div className="appForm__field"> <div className="appForm__field">
<label <label
className={classNames({ 'p-error': isEmpty(newUserData.email) || isNil(newUserData.email) })}>{__('Email', 'gepafin')}*</label> className={classNames({ 'p-error': isEmpty(newUserData.email) || isNil(newUserData.email) || !isEmail(newUserData.email) })}>
{__('Email', 'gepafin')}*
</label>
<InputText value={newUserData.email} <InputText value={newUserData.email}
invalid={isEmpty(newUserData.email) || isNil(newUserData.email)} invalid={isEmpty(newUserData.email) || isNil(newUserData.email) || !isEmail(newUserData.email)}
onChange={(e) => onChangeEditItem(e.target.value, 'email')}/> onChange={(e) => onChangeEditItem(e.target.value, 'email')}/>
</div> </div>
<div className="appForm__field"> <div className="appForm__field">
<label <label
className={classNames({ 'p-error': isEmpty(newUserData.phoneNumber) || isNil(newUserData.phoneNumber) })}>{__('Telefono', 'gepafin')}</label> className={classNames({ 'p-error': isInvalidField(newUserData, 'phoneNumber') })}>
{__('Telefono', 'gepafin')}
</label>
<InputText value={newUserData.phoneNumber} <InputText value={newUserData.phoneNumber}
invalid={isEmpty(newUserData.phoneNumber) || isNil(newUserData.phoneNumber)} keyfilter="int"
invalid={isInvalidField(newUserData, 'phoneNumber')}
onChange={(e) => onChangeEditItem(e.target.value, 'phoneNumber')}/> onChange={(e) => onChangeEditItem(e.target.value, 'phoneNumber')}/>
</div> </div>
</div> </div>
<div className="appForm__cols">
<div className="appForm__field">
<label
className={classNames({ 'p-error': isEmpty(newUserData.password) || isNil(newUserData.password) || newUserData.password !== newUserData.confPassword })}>
{__('Password', 'gepafin')}*
</label>
<InputText value={newUserData.password}
invalid={isEmpty(newUserData.password) || isNil(newUserData.password) || newUserData.password !== newUserData.confPassword}
onChange={(e) => onChangeEditItem(e.target.value, 'password')}/>
</div>
<div className="appForm__field">
<label
className={classNames({ 'p-error': isEmpty(newUserData.confPassword) || isNil(newUserData.confPassword) || newUserData.password !== newUserData.confPassword })}>
{__('Conferma password', 'gepafin')}*
</label>
<InputText value={newUserData.confPassword}
invalid={isEmpty(newUserData.confPassword) || isNil(newUserData.confPassword) || newUserData.password !== newUserData.confPassword}
onChange={(e) => onChangeEditItem(e.target.value, 'confPassword')}/>
</div>
</div>
<div className="appForm__field"> <div className="appForm__field">
<label <label
className={classNames({ 'p-error': isEmpty(newUserData.role) || isNil(newUserData.role) })}>{__('Ruolo', 'gepafin')}</label> className={classNames({ 'p-error': isEmpty(newUserData.roleId) || isNil(newUserData.roleId) || newUserData.roleId === 0 })}>
{__('Ruolo', 'gepafin')}*
</label>
<Dropdown <Dropdown
value={newUserData.role} value={newUserData.roleId}
invalid={isEmpty(newUserData.role) || isNil(newUserData.role)} invalid={isEmpty(newUserData.roleId) || isNil(newUserData.roleId) || newUserData.roleId === 0}
onChange={(e) => onChangeEditItem(e.value, 'role')} onChange={(e) => onChangeEditItem(e.value, 'roleId')}
options={roles} options={roles}
optionLabel="name" optionLabel="name"
optionValue="value"/> optionValue="value"/>

View File

@@ -25,6 +25,10 @@ import ProfileCompany from './pages/ProfileCompany';
import Users from './pages/Users'; import Users from './pages/Users';
import AddCompany from './pages/AddCompany'; import AddCompany from './pages/AddCompany';
import ResetPassword from './pages/ResetPassword'; import ResetPassword from './pages/ResetPassword';
import DashboardInstructor from './pages/DashboardInstructor';
import ProfileBeneficiario from './pages/ProfileBeneficiario';
import Evaluations from './pages/Evaluations';
import EvaluationEdit from './pages/EvaluationEdit';
const routes = ({ role, chosenCompanyId }) => { const routes = ({ role, chosenCompanyId }) => {
@@ -34,62 +38,87 @@ const routes = ({ role, chosenCompanyId }) => {
<Route path="/" element={<DefaultLayout> <Route path="/" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <Dashboard/> : null} {'ROLE_SUPER_ADMIN' === role ? <Dashboard/> : null}
{'ROLE_BENEFICIARY' === role ? <DashboardBeneficiario/> : null} {'ROLE_BENEFICIARY' === role ? <DashboardBeneficiario/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <DashboardInstructor/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/bandi" element={<DefaultLayout> <Route path="/bandi" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <Bandi/> : null} {'ROLE_SUPER_ADMIN' === role ? <Bandi/> : null}
{'ROLE_BENEFICIARY' === role ? <BandiBeneficiario/> : null} {'ROLE_BENEFICIARY' === role ? <BandiBeneficiario/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/bandi/:id" element={<DefaultLayout> <Route path="/bandi/:id" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <BandoEdit/> : null} {'ROLE_SUPER_ADMIN' === role ? <BandoEdit/> : null}
{'ROLE_BENEFICIARY' === role ? <BandoViewBeneficiario/> : null} {'ROLE_BENEFICIARY' === role ? <BandoViewBeneficiario/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/bandi/:id/preview" element={<DefaultLayout> <Route path="/bandi/:id/preview" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <BandoView/> : null} {'ROLE_SUPER_ADMIN' === role ? <BandoView/> : null}
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null} {'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/bandi/:id/preview-evaluation" element={<DefaultLayout> <Route path="/bandi/:id/preview-evaluation" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <BandoView/> : null} {'ROLE_SUPER_ADMIN' === role ? <BandoView/> : null}
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null} {'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/bandi/:id/forms" element={<DefaultLayout> <Route path="/bandi/:id/forms" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <BandoForms/> : null} {'ROLE_SUPER_ADMIN' === role ? <BandoForms/> : null}
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null} {'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/bandi/:id/forms/:formId" element={<DefaultLayout> <Route path="/bandi/:id/forms/:formId" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <BandoFormsEdit/> : null} {'ROLE_SUPER_ADMIN' === role ? <BandoFormsEdit/> : null}
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null} {'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/bandi/:id/forms/:formId/preview" element={<DefaultLayout> <Route path="/bandi/:id/forms/:formId/preview" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <BandoFormsPreview/> : null} {'ROLE_SUPER_ADMIN' === role ? <BandoFormsPreview/> : null}
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null} {'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/bandi/:id/flow" element={<DefaultLayout> <Route path="/bandi/:id/flow" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <BandoFlowEdit/> : null} {'ROLE_SUPER_ADMIN' === role ? <BandoFlowEdit/> : null}
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null} {'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/imieibandi" element={<DefaultLayout> <Route path="/imieibandi" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null} {'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
{'ROLE_BENEFICIARY' === role ? <Applications/> : null} {'ROLE_BENEFICIARY' === role ? <Applications/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/imieibandi/:id/" element={<DefaultLayout> <Route path="/imieibandi/:id/" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null} {'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
{'ROLE_BENEFICIARY' === role ? <BandoApplication/> : null} {'ROLE_BENEFICIARY' === role ? <BandoApplication/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/>
<Route path="/valutazioni" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <Evaluations/> : null}
</DefaultLayout>}/>
<Route path="/valutazioni/:id/" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <EvaluationEdit/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/profilo" element={<DefaultLayout> <Route path="/profilo" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <Profile/> : null} {'ROLE_SUPER_ADMIN' === role ? <Profile/> : null}
{'ROLE_BENEFICIARY' === role ? <Profile/> : null} {'ROLE_BENEFICIARY' === role ? <ProfileBeneficiario/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <Profile/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/profilo-aziendale" element={<DefaultLayout> <Route path="/profilo-aziendale" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null} {'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
{'ROLE_BENEFICIARY' === role && chosenCompanyId > 0 ? <ProfileCompany/> : <PageNotFound/>} {'ROLE_BENEFICIARY' === role && chosenCompanyId > 0 ? <ProfileCompany/> : <PageNotFound/>}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/agguingi-azienda" element={<DefaultLayout> <Route path="/agguingi-azienda" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null} {'ROLE_SUPER_ADMIN' === role ? <PageNotFound/> : null}
{'ROLE_BENEFICIARY' === role ? <AddCompany/> : null} {'ROLE_BENEFICIARY' === role ? <AddCompany/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
<Route path="/utenti" element={<DefaultLayout> <Route path="/utenti" element={<DefaultLayout>
{'ROLE_SUPER_ADMIN' === role ? <Users/> : null} {'ROLE_SUPER_ADMIN' === role ? <Users/> : null}
{'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null} {'ROLE_BENEFICIARY' === role ? <PageNotFound/> : null}
{'ROLE_PRE_INSTRUCTOR' === role ? <PageNotFound/> : null}
</DefaultLayout>}/> </DefaultLayout>}/>
</Route> </Route>
<Route exact path="/reset-password" element={<ResetPassword/>}/> <Route exact path="/reset-password" element={<ResetPassword/>}/>

View File

@@ -17,6 +17,7 @@ const initialStore = {
elementItems: [], elementItems: [],
activeElement: '', activeElement: '',
draggingElementId: 0, draggingElementId: 0,
bandoCriteria: [],
// flow // flow
flowData: [], flowData: [],
flowForms: [], flowForms: [],