From acd3a43d2eb9e39025dd019881e31c917b2a1c62 Mon Sep 17 00:00:00 2001 From: Vitalii Kiiko Date: Fri, 13 Sep 2024 17:05:32 +0200 Subject: [PATCH] - fixed styles for fileupload; - fixed funcionality of form fields; - added 'submit question' functionality; --- src/assets/scss/components/appForm.scss | 20 ++- src/assets/scss/components/misc.scss | 12 ++ .../FormField/components/Fileupload/index.js | 166 ++++++++++++++++++ .../components/FileuploadAsync/index.js | 64 ++++--- src/components/FormField/index.js | 2 + src/helpers/validators.js | 3 + src/pages/BandoApplication/index.js | 62 ++++++- .../components/BandoEditFormStep2/index.js | 5 +- src/pages/BandoView/index.js | 4 +- src/pages/BandoViewBeneficiario/index.js | 62 ++++++- src/service/faq-item-service.js | 10 ++ 11 files changed, 369 insertions(+), 41 deletions(-) create mode 100644 src/components/FormField/components/Fileupload/index.js create mode 100644 src/helpers/validators.js create mode 100644 src/service/faq-item-service.js diff --git a/src/assets/scss/components/appForm.scss b/src/assets/scss/components/appForm.scss index 7989898..7d77686 100644 --- a/src/assets/scss/components/appForm.scss +++ b/src/assets/scss/components/appForm.scss @@ -49,12 +49,26 @@ } .appForm__fileUploadItem { - display: flex; - justify-content: space-between; + display: grid; + grid-template-columns: 2fr 0.5fr 0.5fr; + + > div { + display: flex; + align-items: center; + + &:nth-of-type(2) { + justify-content: center; + } + + &:nth-of-type(3) { + justify-content: flex-end; + } + } } .appForm__fileUploadItemName { - + color: var(--global-textColor); + font-style: italic; } .appForm__row { diff --git a/src/assets/scss/components/misc.scss b/src/assets/scss/components/misc.scss index d2f6c23..bf17896 100644 --- a/src/assets/scss/components/misc.scss +++ b/src/assets/scss/components/misc.scss @@ -83,6 +83,18 @@ margin: 0; } +.p-fileupload .p-fileupload-content { + padding: 1rem 0.5rem; +} + +.p-fileupload .p-fileupload-row > div { + padding: 0.5rem; +} + +.p-message-detail { + color: white; +} + .blockingOverlay { position: absolute; z-index: 999; diff --git a/src/components/FormField/components/Fileupload/index.js b/src/components/FormField/components/Fileupload/index.js new file mode 100644 index 0000000..100b482 --- /dev/null +++ b/src/components/FormField/components/Fileupload/index.js @@ -0,0 +1,166 @@ +import React, { useEffect, useState, useRef } from 'react'; +import { classNames } from 'primereact/utils'; + +import FileUploadService from '../../../../service/file-upload-service'; + +import { FileUpload } from 'primereact/fileupload'; +import { __ } from '@wordpress/i18n'; +import { Tag } from 'primereact/tag'; +import { Button } from 'primereact/button'; + +const Fileupload = ({ + fieldName, + setDataFn, + label, + errors, + register, + defaultValue = [], + config = {}, + infoText = null, + accept = 'image/*', + doctype = 'images', + maxSize = 1000000, + emptyText = __('Trascina qui il tuo file', 'gepafin'), + chooseLabel = __('Aggiungi file', 'gepafin'), + multiple = false, + sourceId = 0, + source = 'application' + }) => { + const [stateFieldData, setStateFieldData] = useState([]); + const [acceptFormats, setAcceptFormats] = useState(''); + const inputRef = useRef(); + + const customBase64Uploader = (event) => { + const formData = new FormData() + for (const file of event.files) { + formData.append('file', file) + } + FileUploadService.uploadFile(sourceId, formData, callback, errorCallback, [ + ['documentType', doctype.toUpperCase()], + ['source', source] + ]); + }; + + const callback = (data) => { + if (data.status === 'SUCCESS') { + setStateFieldData(data.data); + const files = inputRef.current.getFiles(); + inputRef.current.setUploadedFiles(files); + inputRef.current.setFiles([]); + } + } + + const errorCallback = (err) => { + console.log('err', err); + } + + const itemTemplate = (file) => { + return ( +
+
+ + {file.name} + +
+
+ {file.id ? : null} + {!file.id ? : null} +
+
+
+
+ ); + }; + + const onTemplateRemove = (file) => { + if (file.id) { + FileUploadService.deleteFile( + {}, + (data) => dCallback(data, file.id), + dErrorCallback, + [['id', file.id]] + ); + } else { + const files = inputRef.current.getFiles() + const newFiles = files.filter(o => o.lastModified !== file.lastModified && o.name !== file.name); + inputRef.current.setFiles(newFiles); + } + } + + const dCallback = (data, id) => { + if (data.status === 'SUCCESS') { + setStateFieldData(prevState => { + const newFiles = prevState.filter(o => o.id !== id); + inputRef.current.setUploadedFiles(newFiles); + return newFiles; + }); + } + } + + const dErrorCallback = (err) => { + 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(() => { + if (inputRef.current) { + inputRef.current.setUploadedFiles(stateFieldData); + } + setDataFn(fieldName, [...stateFieldData], { shouldValidate: true }); + }, [stateFieldData]) + + return ( + sourceId && sourceId !== 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/FormField/components/FileuploadAsync/index.js b/src/components/FormField/components/FileuploadAsync/index.js index 6291fb5..7a1c602 100644 --- a/src/components/FormField/components/FileuploadAsync/index.js +++ b/src/components/FormField/components/FileuploadAsync/index.js @@ -9,21 +9,21 @@ import { Tag } from 'primereact/tag'; import { Button } from 'primereact/button'; const FileuploadAsync = ({ - fieldName, - setDataFn, - label, - errors, - register, - defaultValue = [], - config = {}, - infoText = null, - accept = 'image/*', - doctype = 'images', - emptyText = __('Trascina qui il tuo file', 'gepafin'), - chooseLabel = __('Aggiungi immagine', 'gepafin'), - multiple = false, - callId = 0 - }) => { + fieldName, + setDataFn, + label, + errors, + register, + defaultValue = [], + config = {}, + infoText = null, + accept = 'image/*', + doctype = 'images', + emptyText = __('Trascina qui il tuo file', 'gepafin'), + chooseLabel = __('Aggiungi immagine', 'gepafin'), + multiple = false, + callId = 0 + }) => { const [stateFieldData, setStateFieldData] = useState([]); const [acceptFormats, setAcceptFormats] = useState(''); const inputRef = useRef(); @@ -52,14 +52,20 @@ const FileuploadAsync = ({ const itemTemplate = (file) => { return (
- - {file.name} - - {file.id ? : null} - {!file.id ? : null} -
); }; @@ -97,12 +103,12 @@ const FileuploadAsync = ({ return validateFileInputType(e.dataTransfer.files); } - const validateFileInputType = ( files ) => { - const MIMEtype = new RegExp( acceptFormats ); + const validateFileInputType = (files) => { + const MIMEtype = new RegExp(acceptFormats); - return Array.prototype.every.call( files, function passesAcceptedFormat( file ){ - return MIMEtype.test( file.type ); - } ); + return Array.prototype.every.call(files, function passesAcceptedFormat(file) { + return MIMEtype.test(file.type); + }); } useEffect(() => { @@ -112,7 +118,7 @@ const FileuploadAsync = ({ useEffect(() => { // eslint-disable-next-line no-useless-escape - setAcceptFormats(accept.replace( /\*/g, '.\*' ).replace( /,/g, '|' )); + setAcceptFormats(accept.replace(/\*/g, '.\*').replace(/,/g, '|')); }, [accept]); useEffect(() => { diff --git a/src/components/FormField/index.js b/src/components/FormField/index.js index eb0839e..477ef00 100644 --- a/src/components/FormField/index.js +++ b/src/components/FormField/index.js @@ -14,6 +14,7 @@ import Select from './components/Select'; import Radio from './components/Radio'; import Wysiwyg from './components/Wysiwyg'; import Checkboxes from './components/Checkboxes'; +import Fileupload from './components/Fileupload'; const FormField = (props) => { const fields = { @@ -22,6 +23,7 @@ const FormField = (props) => { datepicker: Datepicker, datepickerrange: DatepickerRange, fileuploadasync: FileuploadAsync, + fileupload: Fileupload, numberinput: NumberInput, switch: Switch, select: Select, diff --git a/src/helpers/validators.js b/src/helpers/validators.js new file mode 100644 index 0000000..8923b2b --- /dev/null +++ b/src/helpers/validators.js @@ -0,0 +1,3 @@ +export const isVAT = (v) => { + return false; +} \ No newline at end of file diff --git a/src/pages/BandoApplication/index.js b/src/pages/BandoApplication/index.js index 81ad810..ad3e8bc 100644 --- a/src/pages/BandoApplication/index.js +++ b/src/pages/BandoApplication/index.js @@ -11,6 +11,9 @@ import { storeSet, useStore } from '../../store'; // api import FormsService from '../../service/forms-service'; +// tools +import { isVAT } from '../../helpers/validators'; + // components import { Skeleton } from 'primereact/skeleton'; import { Button } from 'primereact/button'; @@ -30,11 +33,32 @@ const BandoApplication = () => { control, handleSubmit, formState: { errors }, + setValue, + trigger, + register, getValues, } = useForm({ defaultValues: {}, mode: 'onChange' }); const values = getValues(); + const validationFns = { + isVAT + } + const onSubmit = (formData) => { + /*const newFormData = Object.keys(formData).reduce((acc, cur) => { + acc.push({ + 'fieldId': cur, + 'fieldValue': formData[cur] && formData[cur].getMonth ? formData[cur].toISOString() : formData[cur] + }); + return acc; + }, []); + console.log('newFormData', newFormData); + console.log('errors', errors);*/ + }; + + const saveDraft = () => { + trigger(); + const formData = getValues(); const newFormData = Object.keys(formData).reduce((acc, cur) => { acc.push({ 'fieldId': cur, @@ -42,7 +66,8 @@ const BandoApplication = () => { }); return acc; }, []); - console.log('newFormData', newFormData) + console.log('newFormData', newFormData); + console.log('errors', errors); }; const getBandoId = () => { @@ -98,7 +123,31 @@ const BandoApplication = () => { const placeholder = head(o.settings.filter(o => o.name === 'placeholder')); const options = head(o.settings.filter(o => o.name === 'options')); const step = head(o.settings.filter(o => o.name === 'step')); - const mime = head(o.settings.filter(o => o.name === 'mime').join(',')); + const mime = head(o.settings.filter(o => o.name === 'mime')); + let mimeValue = ''; + + if (mime) { + mimeValue = mime.value.join(','); + } + + const validations = Object.keys(o.validators).reduce((acc, cur) => { + if (o.validators[cur]) { + if (['min', 'max', 'minLength', 'maxLength', 'maxSize'].includes(cur)) { + acc[cur] = parseInt(o.validators[cur]); + } else if ('pattern' === cur) { + acc[cur] = new RegExp(o.validators[cur]) + } else if ('isRequired' === cur) { + acc[cur] = o.validators[cur] + } else if ('custom' === cur && validationFns[o.validators[cur]]) { + if (!acc.validate) { + acc.validate = {} + } + acc.validate[cur] = validationFns[o.validators[cur]] + } + } + + return acc; + }, {}); return { label={label ? label.value : ''} placeholder={placeholder ? placeholder.value : ''} control={control} + register={register} errors={errors} defaultValue={values[o.id]} maxFractionDigits={step} - accept={mime} - config={o.validators} + accept={mimeValue} + config={validations} options={options ? options.value : []} + setDataFn={setValue} + sourceId={1} /> })} @@ -125,6 +177,8 @@ const BandoApplication = () => {
diff --git a/src/service/faq-item-service.js b/src/service/faq-item-service.js new file mode 100644 index 0000000..d46aa20 --- /dev/null +++ b/src/service/faq-item-service.js @@ -0,0 +1,10 @@ +import { NetworkService } from './network-service'; + +const API_BASE_URL = process.env.REACT_APP_API_EXECUTION_ADDRESS; + +export default class FaqItemService { + + static addQuestion = (id, body, callback, errCallback) => { + NetworkService.post(`${API_BASE_URL}/faq/call/${id}`, body, callback, errCallback); + }; +}