diff --git a/src/App.js b/src/App.js index 1063464..876cce0 100644 --- a/src/App.js +++ b/src/App.js @@ -4,11 +4,34 @@ import Routes from './routes'; import { createI18n, setLocaleData } from '@wordpress/i18n'; import { I18nProvider } from '@wordpress/react-i18n'; import './assets/scss/theme.scss'; +import AuthenticationService from './service/authentication-service'; + +// store +import { useStore, storeSet } from './store'; const i18n = createI18n({}, 'gepafin'); function App() { + const role = useStore().main.getRole(); + + const callback = (data) => { + if (data.status === 'SUCCESS') { + storeSet.main.userData(data.data); + } else { + storeSet.main.doLogout(); + } + storeSet.main.unsetAsyncRequest(); + } + + const errCallback = (data) => { + storeSet.main.doLogout(); + storeSet.main.unsetAsyncRequest(); + } + useEffect(() => { + storeSet.main.setAsyncRequest(); + AuthenticationService.me(callback, errCallback); + fetch('/languages/en_US.json') .then((res) => res.json()) .then(res => { @@ -19,7 +42,7 @@ function App() { return ( - + ); diff --git a/src/assets/scss/components/appPage.scss b/src/assets/scss/components/appPage.scss index 5bc3d58..167ef56 100644 --- a/src/assets/scss/components/appPage.scss +++ b/src/assets/scss/components/appPage.scss @@ -100,6 +100,8 @@ padding: 17px; border-radius: 6px; border: 1px solid var(--card-borderColor-color); + container-name: section_with_border; + container-type: inline-size; &.disabled { filter: grayscale(1); @@ -140,6 +142,15 @@ } } +@container section_with_border (max-width: 600px) { + .appPageSection__withBorder { + .row { + flex-direction: column; + align-items: flex-start; + } + } +} + .appPageSection__hero { display: flex; height: 172px; @@ -198,4 +209,5 @@ display: flex; gap: 24px; padding: 24px 0 48px; + flex-wrap: wrap; } \ No newline at end of file diff --git a/src/assets/scss/components/formBuilder.scss b/src/assets/scss/components/formBuilder.scss index 1989538..4d8a512 100644 --- a/src/assets/scss/components/formBuilder.scss +++ b/src/assets/scss/components/formBuilder.scss @@ -12,9 +12,9 @@ h2 { color: #404D5B; - font-size: 21px; + font-size: 14px; font-style: normal; - font-weight: 600; + font-weight: 700; line-height: normal; } } @@ -58,7 +58,7 @@ .actions { display: flex; - gap: 1rem; + gap: 0.5rem; } } @@ -69,9 +69,9 @@ h2 { color: #404D5B; - font-size: 21px; + font-size: 14px; font-style: normal; - font-weight: 600; + font-weight: 700; line-height: normal; } } @@ -113,4 +113,24 @@ display: flex; flex-direction: column; gap: 0.5rem; +} + +.formElementSettings__tabs { + width: 100%; + + .p-tabview-nav-link[aria-selected="true"] { + background-color: var(--message-info-background); + } + + .p-tabview-panel { + display: flex; + flex-direction: column; + gap: 1rem; + } +} + +.formElementSettings__repeater { + display: flex; + flex-direction: column; + gap: 0.5rem; } \ No newline at end of file diff --git a/src/assets/scss/components/layout.scss b/src/assets/scss/components/layout.scss index 70704e4..9b246f2 100644 --- a/src/assets/scss/components/layout.scss +++ b/src/assets/scss/components/layout.scss @@ -86,6 +86,7 @@ body { padding: 0 24px 20px; display: flex; flex-direction: column; + width: calc(100% - 320px); > footer { margin-top: auto; diff --git a/src/assets/scss/components/misc.scss b/src/assets/scss/components/misc.scss index d71840d..e7e498c 100644 --- a/src/assets/scss/components/misc.scss +++ b/src/assets/scss/components/misc.scss @@ -36,16 +36,39 @@ } .p-message.p-message-error { - background: #ffdbdb; - border-left: 5px solid #C2504D; + background: var(--message-error-background); + border-left: 5px solid var(--message-error-color); + + span.p-message-detail, span.p-message-summary { + color: var(--message-error-color); + } svg { path { - fill: var(--global-textColor); + fill: var(--message-error-color); } } } +.p-message.p-message-info { + background: var(--message-info-background); + border-left: 5px solid var(--message-info-color); + + span.p-message-detail, span.p-message-summary { + color: var(--message-info-color); + } + + svg { + path { + fill: var(--message-info-color); + } + } +} + +.p-dropdown-panel .p-dropdown-items .p-dropdown-item.p-highlight { + background: #C9E3CC; +} + .p-accordion { width: 100%; } diff --git a/src/assets/scss/components/statsBigBadges.scss b/src/assets/scss/components/statsBigBadges.scss index 102f51e..92a806f 100644 --- a/src/assets/scss/components/statsBigBadges.scss +++ b/src/assets/scss/components/statsBigBadges.scss @@ -1,13 +1,18 @@ .statsBigBadges { } + .statsBigBadges__grid { display: grid; - align-items: center; - grid-template-columns: repeat(auto-fit, minmax(460px, 1fr)); - gap: 24px; + align-items: stretch; + grid-template-columns: repeat(2, 1fr); + gap: 1rem; width: 100%; } +.statsBigBadges__grid .statsBigBadges__gridItem span { + color: #FFF; +} + .statsBigBadges__gridItem { display: flex; justify-content: space-between; @@ -42,4 +47,10 @@ border: 1px solid var(--yellow-500); background: var(--card-full-background-color-1); } +} + +@media (max-width: 1240px) { + .statsBigBadges__grid { + grid-template-columns: 1fr; + } } \ No newline at end of file diff --git a/src/assets/scss/theme.scss b/src/assets/scss/theme.scss index 37289c3..5e9e607 100644 --- a/src/assets/scss/theme.scss +++ b/src/assets/scss/theme.scss @@ -15,6 +15,10 @@ --global-textColor: #4B5563; --theme-highlight-background: #BADEBE; --primary-text: #3B7C43; + --message-error-background: #ffdbdb; + --message-error-color: #C2504D; + --message-info-background: rgba(219, 234, 254, 0.70); + --message-info-color: #3B82F6; --card-full-background-color-2: #EEC137; --card-full-background-color-3: #FA8E42; diff --git a/src/components/FormField/components/DatepickerRange/index.js b/src/components/FormField/components/DatepickerRange/index.js index dc4987b..7cf0d83 100644 --- a/src/components/FormField/components/DatepickerRange/index.js +++ b/src/components/FormField/components/DatepickerRange/index.js @@ -34,7 +34,7 @@ const DatepickerRange = ({ { const [stateFieldData, setStateFieldData] = useState([]); + const [acceptFormats, setAcceptFormats] = useState(''); const inputRef = useRef(); const customBase64Uploader = (event) => { @@ -31,14 +33,10 @@ const Fileupload = ({ for (const file of event.files) { formData.append('file', file) } - /*for (const pair of formData.entries()) { - console.log(pair[0], pair[1]); - }*/ - FileUploadService.uploadFile(formData, callback, errorCallback, [['documentType', doctype.toUpperCase()]]); + FileUploadService.uploadFile(callId, formData, callback, errorCallback, [['documentType', doctype.toUpperCase()]]); }; const callback = (data) => { - console.log('data', data); if (data.status === 'SUCCESS') { setStateFieldData(data.data); const files = inputRef.current.getFiles(); @@ -86,7 +84,6 @@ const Fileupload = ({ setStateFieldData(prevState => { const newFiles = prevState.filter(o => o.id !== id); inputRef.current.setUploadedFiles(newFiles); - console.log('newFiles', newFiles); return newFiles; }); } @@ -96,39 +93,61 @@ const Fileupload = ({ console.log('err', err); } + const onBeforeDrop = (e) => { + return validateFileInputType(e.dataTransfer.files); + } + + const validateFileInputType = ( files ) => { + const MIMEtype = new RegExp( acceptFormats ); + + return Array.prototype.every.call( files, function passesAcceptedFormat( file ){ + return MIMEtype.test( file.type ); + } ); + } + useEffect(() => { setStateFieldData(defaultValue); register(fieldName, config) }, []); + useEffect(() => { + // eslint-disable-next-line no-useless-escape + setAcceptFormats(accept.replace( /\*/g, '.\*' ).replace( /,/g, '|' )); + }, [accept]); + useEffect(() => { inputRef.current.setUploadedFiles(stateFieldData); setDataFn(fieldName, [...stateFieldData], { shouldValidate: true }); }, [stateFieldData]) return ( - <> - - {emptyText}

} - chooseLabel={chooseLabel} - cancelLabel={__('Cancella', 'gepafin')} - uploadLabel={__('Carica', 'gepafin')} - className={classNames({ 'p-invalid': errors[fieldName] })} - itemTemplate={itemTemplate} - customUpload - uploadHandler={customBase64Uploader}/> - {infoText ? {infoText} : null} - ) + callId && callId !== 0 + ? <> + + {emptyText}

} + chooseLabel={chooseLabel} + cancelLabel={__('Cancella', 'gepafin')} + uploadLabel={__('Carica', 'gepafin')} + className={classNames({ 'p-invalid': errors[fieldName] })} + itemTemplate={itemTemplate} + customUpload + onBeforeDrop={onBeforeDrop} + uploadHandler={customBase64Uploader}/> + {infoText ? {infoText} : null} + + : null + ) } export default Fileupload; \ No newline at end of file diff --git a/src/components/FormFieldRepeater/index.js b/src/components/FormFieldRepeater/index.js index d2d4e07..6f4045e 100644 --- a/src/components/FormFieldRepeater/index.js +++ b/src/components/FormFieldRepeater/index.js @@ -1,7 +1,7 @@ -import React, { useRef, useEffect, useState } from 'react'; +import React, { useRef, useEffect, useState, useCallback } from 'react'; import { classNames } from 'primereact/utils'; import { __ } from '@wordpress/i18n'; -import { isEmpty } from 'ramda'; +import { head, isNil, pluck } from 'ramda'; // components import { InputText } from 'primereact/inputtext'; @@ -22,19 +22,20 @@ const FormFieldRepeater = ({ }) => { const forMenu = useRef(null); const [stateFieldData, setStateFieldData] = useState([]); + const [stateOptionsData, setStateOptionsData] = useState([]); const menuItems = [ { type: 'existing', label: __('Esistente', 'gepafin'), command: (data) => { - setStateFieldData([...stateFieldData, { id: null, value: '', status: data.item.type }]); + setStateFieldData([...stateFieldData, { id: null, value: '', lookUpDataId: 0 }]); } }, { type: 'new', label: __('Nuovo', 'gepafin'), command: (data) => { - setStateFieldData([...stateFieldData, { id: null, value: '', status: data.item.type }]); + setStateFieldData([...stateFieldData, { id: null, value: '', lookUpDataId: null }]); } } ] @@ -45,14 +46,14 @@ const FormFieldRepeater = ({ } const selectItem = (e, index) => { - const newData = stateFieldData.map((o, i) => { - if (i === index) { - o.value = e.value; - o.id = e.id; - } - return o; - }) - setStateFieldData(newData); + const targetedOption = head(stateOptionsData.filter(o => o.value === e.value)); + + if (targetedOption) { + const newData = stateFieldData.map((o, i) => { + return i === index ? targetedOption : o; + }) + setStateFieldData(newData); + } } const onInputChange = (e, index) => { @@ -67,24 +68,30 @@ const FormFieldRepeater = ({ } const properField = (item, i) => { - return item.status === 'new' - ? onInputChange(e, i)}/> - : selectItem(e, i)} - optionDisabled={(opt) => usedExistingValues.includes(opt.value)} - options={options} optionLabel="value"/> + optionDisabled={(opt) => usedExistingValues().includes(opt.value)} + options={stateOptionsData} + optionLabel="value"/> + : onInputChange(e, i)}/> } - const usedExistingValues = stateFieldData - .filter(o => o.status === 'existing') - .map(o => o.value); + const usedExistingValues = useCallback(() => { + return stateFieldData + .filter(o => o.lookUpDataId > 0) + .map(o => o.value) + }, [stateFieldData]); useEffect(() => { const storeFieldData = data[fieldName] ?? []; - const newData = storeFieldData.map(o => ({ ...o, status: o.id ? 'existing' : 'new' })); - setStateFieldData(newData); + setStateFieldData(storeFieldData); register(fieldName, config); - }, []) + }, []); + + useEffect(() => { + setStateOptionsData([...options]); + }, [options]); useEffect(() => { setDataFn(fieldName, [...stateFieldData], { shouldValidate: true }); @@ -100,7 +107,7 @@ const FormFieldRepeater = ({ {properField(o, i)}