Files
bflows-bandi-fe/src/components/FormFieldRepeaterCriteria/index.js
Vitalii Kiiko b08e2d46c0 Make some call fields editable after publishing the call
- call form fields are editable (according to the list of keys);
- some parts of the form are editable;
2024-11-14 14:27:19 +01:00

176 lines
6.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useRef, useEffect, useState, useCallback } from 'react';
import { classNames } from 'primereact/utils';
import { __ } from '@wordpress/i18n';
import { head, isEmpty, isNil, pluck } from 'ramda';
// components
import { InputText } from 'primereact/inputtext';
import { Button } from 'primereact/button';
import { Menu } from 'primereact/menu';
import { Dropdown } from 'primereact/dropdown';
import { InputNumber } from 'primereact/inputnumber';
import { diff } from 'deep-object-diff';
import { klona } from 'klona';
const FormFieldRepeaterCriteria = ({
data,
setDataFn,
fieldName,
options = [],
errors,
register,
label,
infoText,
config = {},
disabled = false
}) => {
const forMenu = useRef(null);
const [stateFieldData, setStateFieldData] = useState([]);
const [stateOptionsData, setStateOptionsData] = useState([]);
const [threshold, setThreshold] = useState(0);
const menuItems = [
{
type: 'existing',
label: __('Esistente', 'gepafin'),
command: (data) => {
setStateFieldData([...stateFieldData, { id: null, value: '', lookUpDataId: 0 }]);
}
},
{
type: 'new',
label: __('Nuovo', 'gepafin'),
command: (data) => {
setStateFieldData([...stateFieldData, { id: null, value: '', lookUpDataId: null }]);
}
}
]
const removeItem = (index) => {
const newData = stateFieldData.toSpliced(index, 1);
setStateFieldData(newData);
}
const selectItem = (e, index) => {
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 = (value, index, name) => {
const newData = stateFieldData.map((o, i) => {
if (i === index) {
o[name] = value;
}
return o;
})
setStateFieldData(newData);
}
const onThresholdChange = (value) => {
setThreshold(value);
setDataFn('threshold', value, { shouldValidate: true });
}
const properField = (item, i) => {
return !isNil(item.lookUpDataId)
? <Dropdown value={item.value}
filter
disabled={disabled}
onChange={(e) => selectItem(e, i)}
optionDisabled={(opt) => usedExistingValues().includes(opt.value)}
options={stateOptionsData} optionLabel="value"/>
: <InputText disabled={disabled} value={item.value}
onInput={(e) => onInputChange(e.target.value, i, 'value')}/>
}
const usedExistingValues = useCallback(() => {
return stateFieldData
.filter(o => o.lookUpDataId > 0)
.map(o => o.value)
}, [stateFieldData]);
useEffect(() => {
const storeFieldData = data[fieldName] ?? [];
setStateFieldData(storeFieldData);
setStateOptionsData([...options, ...storeFieldData]);
setThreshold(data['threshold'])
register(fieldName, config)
register('threshold', {
required: __('È obbligatorio', 'gepafin')
})
}, []);
useEffect(() => {
const diffData = diff(data[fieldName], stateFieldData);
if (!isEmpty(diffData)) {
const storeFieldData = data[fieldName] ?? [];
setStateFieldData(storeFieldData);
setStateOptionsData(prevState => {
const ids = pluck('lookUpDataId', prevState)
const objectsToAdd = klona(storeFieldData)
.filter(o => !ids.includes(o.lookUpDataId))
.map(o => ({ ...o, id: null, score: 0 }));
return [...prevState, ...objectsToAdd];
});
}
}, [data]);
useEffect(() => {
setStateOptionsData([...options]);
}, [options]);
useEffect(() => {
setDataFn(fieldName, [...stateFieldData], { shouldValidate: true });
}, [stateFieldData]);
return (
<div className={classNames(['appForm__field', 'formfieldrepeater'])}>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] || errors['threshold'] })}>
{label}
</label>
<div className="appForm__col">
<label htmlFor="criterionThreshold">{__('Punteggio minimo per lammissione', 'gepafin')}</label>
<InputNumber inputId="criterionThreshold"
disabled={disabled}
value={threshold}
showButtons
onValueChange={(e) => onThresholdChange(e.value)}/>
</div>
{stateFieldData.map((o, i) => <div key={i}
className={classNames('appForm__field', 'appForm__repeaterItem')}>
<div className="appForm__cols">
<div>
<label>{__('Nome criterio di valutazione', 'gepafin')}</label>
<div className="p-inputgroup flex-1">
{properField(o, i)}
<Button disabled={disabled} type="button" icon="pi pi-times" className="p-button-danger"
onClick={() => removeItem(i)}/>
</div>
{isNil(o.lookUpDataId) && infoText ? <small>{infoText}</small> : null}
</div>
<div>
<label htmlFor="criterionMin">{__('Punteggio', 'gepafin')}</label>
<InputNumber inputId="criterionMin"
disabled={disabled}
value={o.score}
showButtons
onValueChange={(e) => onInputChange(e.value, i, 'score')}/>
</div>
</div>
</div>)}
<Menu model={menuItems} popup ref={forMenu} id="aimedForMenu"/>
<Button type="button" iconPos="right" label={__('Aggiungi', 'gepafin')}
disabled={disabled}
icon="pi pi-chevron-down" onClick={(event) => forMenu.current.toggle(event)}
aria-controls="aimedForMenu" aria-haspopup/>
</div>
)
}
export default FormFieldRepeaterCriteria;