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 = () => {
{
- navigate('/tenders/preview/11');
+ navigate(`/tenders/${values.id}/preview`);
}
const openPreviewEvaluation = () => {
- navigate('/tenders/preview-evaluation/11');
+ navigate(`/tenders/${values.id}/preview-evaluation`);
}
useImperativeHandle(
@@ -231,6 +231,7 @@ const BandoEditFormStep2 = forwardRef(function ({ initialData, getFormErrors },
diff --git a/src/pages/BandoView/index.js b/src/pages/BandoView/index.js
index de8c212..8f094c1 100644
--- a/src/pages/BandoView/index.js
+++ b/src/pages/BandoView/index.js
@@ -180,7 +180,9 @@ const BandoView = () => {
{__('FAQ', 'gepafin')}
- {data.faq.map((o, i) =>
+ {data.faq
+ .filter(o => o.isVisible)
+ .map((o, i) =>
{o.response}
diff --git a/src/pages/BandoViewBeneficiario/index.js b/src/pages/BandoViewBeneficiario/index.js
index d57bcb4..fcc87ee 100644
--- a/src/pages/BandoViewBeneficiario/index.js
+++ b/src/pages/BandoViewBeneficiario/index.js
@@ -19,6 +19,7 @@ import { Button } from 'primereact/button';
import BandoService from '../../service/bando-service';
import { Messages } from 'primereact/messages';
import set404FromErrorResponse from '../../helpers/set404FromErrorResponse';
+import FaqItemService from '../../service/faq-item-service';
const BandoViewBeneficiario = () => {
const isAsyncRequest = useStore().main.isAsyncRequest();
@@ -48,6 +49,57 @@ const BandoViewBeneficiario = () => {
}
+ const submitNewQuestion = () => {
+ if (newQuestion) {
+ if (bandoMsgs.current) {
+ bandoMsgs.current.clear();
+ }
+ const obj = {
+ "id": null,
+ "lookUpDataId": null,
+ "title": newQuestion,
+ "value": newQuestion,
+ "response": "",
+ "isVisible": false
+ }
+ storeSet.main.setAsyncRequest();
+ FaqItemService.addQuestion(id, obj, createCallBack, errCreateCallback)
+ }
+ }
+
+ const createCallBack = (data) => {
+ if (data.status === 'SUCCESS') {
+ setNewQuestion('');
+ if (bandoMsgs.current && data.message) {
+ bandoMsgs.current.show([
+ {
+ sticky: true, severity: 'success', summary: '',
+ detail: data.message,
+ closable: true
+ }
+ ]);
+
+ setTimeout(() => {
+ bandoMsgs.current.clear();
+ }, 5000);
+ }
+ }
+ storeSet.main.unsetAsyncRequest();
+ }
+
+ const errCreateCallback = (data) => {
+ if (bandoMsgs.current && data.message) {
+ bandoMsgs.current.show([
+ {
+ sticky: true, severity: 'error', summary: '',
+ detail: data.message,
+ closable: true
+ }
+ ]);
+ }
+ storeSet.main.unsetAsyncRequest();
+ }
+
const getCallback = (data) => {
if (data.status === 'SUCCESS') {
setData(getFormattedBandiData(data.data));
@@ -77,7 +129,7 @@ const BandoViewBeneficiario = () => {
useEffect(() => {
const parsed = parseInt(id)
const bandoId = !isNaN(parsed) ? parsed : 0;
-
+ storeSet.main.setAsyncRequest();
BandoService.getBando(bandoId, getCallback, errGetCallback);
}, [id]);
@@ -187,7 +239,9 @@ const BandoViewBeneficiario = () => {
{__('FAQ', 'gepafin')}
- {data.faq.map((o, i) =>
+ {data.faq
+ .filter(o => o.isVisible)
+ .map((o, i) =>
{o.response}
@@ -210,6 +264,10 @@ const BandoViewBeneficiario = () => {
{__('Riceverai una notifica quando ti risponderemo', 'gepafin')}
+
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);
+ };
+}