- call form fields are editable (according to the list of keys); - some parts of the form are editable;
277 lines
11 KiB
JavaScript
277 lines
11 KiB
JavaScript
import React, { useEffect, useState, useCallback } from 'react';
|
|
import { classNames } from 'primereact/utils';
|
|
import { __ } from '@wordpress/i18n';
|
|
import { head, isEmpty } from 'ramda';
|
|
import { diff } from 'deep-object-diff';
|
|
|
|
// components
|
|
import { Button } from 'primereact/button';
|
|
import { Dropdown } from 'primereact/dropdown';
|
|
import { Accordion, AccordionTab } from 'primereact/accordion';
|
|
import { Dialog } from 'primereact/dialog';
|
|
import { InputSwitch } from 'primereact/inputswitch';
|
|
import renderHtmlContent from '../../helpers/renderHtmlContent';
|
|
import { Editor } from 'primereact/editor';
|
|
import DOMPurify from 'dompurify';
|
|
|
|
const FormFieldRepeaterFaq = ({
|
|
data,
|
|
setDataFn,
|
|
fieldName,
|
|
options = [],
|
|
errors,
|
|
register,
|
|
label,
|
|
config = {},
|
|
disabled = false
|
|
}) => {
|
|
const [stateFieldData, setStateFieldData] = useState([]);
|
|
const [stateOptionsData, setStateOptionsData] = useState([]);
|
|
const [question, setQuestion] = useState('');
|
|
const [answer, setAnswer] = useState('');
|
|
const [title, setTitle] = useState('');
|
|
const [isVisible, setIsVisible] = useState(false);
|
|
const [editDataIndex, setEditDataIndex] = useState(null);
|
|
const [isVisibleEditDialog, setIsVisibleEditDialog] = useState(false);
|
|
|
|
const removeItem = (index) => {
|
|
const newData = stateFieldData.toSpliced(index, 1);
|
|
setStateFieldData(newData);
|
|
}
|
|
|
|
const selectItem = (e) => {
|
|
const targetedOption = head(stateOptionsData.filter(o => o.value === e.value));
|
|
if (targetedOption) {
|
|
setStateFieldData([...stateFieldData, { ...targetedOption, isVisible: true }]);
|
|
}
|
|
}
|
|
|
|
const addNewItem = () => {
|
|
const newItem = { id: null, lookUpDataId: null, title: '', value: '', response: '', isVisible: true };
|
|
setStateFieldData([...stateFieldData, newItem]);
|
|
}
|
|
|
|
const editItem = (e, index) => {
|
|
e.stopPropagation();
|
|
setTitle(stateFieldData[index].title);
|
|
setQuestion(stateFieldData[index].value);
|
|
setAnswer(stateFieldData[index].response);
|
|
setIsVisible(stateFieldData[index].isVisible);
|
|
setEditDataIndex(index);
|
|
setIsVisibleEditDialog(true);
|
|
}
|
|
|
|
const hideEditDialog = () => {
|
|
setIsVisibleEditDialog(false);
|
|
setQuestion('');
|
|
setAnswer('');
|
|
setTitle('');
|
|
setIsVisible(false);
|
|
setEditDataIndex(null);
|
|
}
|
|
|
|
const onChangeEditItem = (value, key) => {
|
|
if (key === 'title') {
|
|
setTitle(value);
|
|
} else if (key === 'value') {
|
|
setQuestion(value);
|
|
} else if (key === 'response') {
|
|
setAnswer(value)
|
|
} else {
|
|
setIsVisible(value);
|
|
}
|
|
}
|
|
|
|
const saveEditDialog = () => {
|
|
const newData = stateFieldData.map((o, i) => {
|
|
if (i === editDataIndex) {
|
|
o.title = title;
|
|
o.value = question;
|
|
o.response = answer;
|
|
o.isVisible = isVisible;
|
|
return o
|
|
} else {
|
|
return o;
|
|
}
|
|
});
|
|
setStateFieldData(newData);
|
|
setIsVisibleEditDialog(false);
|
|
setQuestion('');
|
|
setAnswer('');
|
|
setTitle('');
|
|
setIsVisible(false);
|
|
setEditDataIndex(null);
|
|
}
|
|
|
|
const headerEditDialog = () => {
|
|
return <span>{__('Aggiungi/modifica FAQ', 'gepafin')}</span>
|
|
}
|
|
|
|
const footerEditDialog = () => {
|
|
return <div>
|
|
<Button type="button" disabled={disabled} label={__('Anulla', 'gepafin')} onClick={hideEditDialog}
|
|
outlined/>
|
|
<Button
|
|
type="button"
|
|
disabled={isEmpty(title) || isEmpty(question) || isEmpty(answer) || disabled}
|
|
label={__('Salva', 'gepafin')} onClick={saveEditDialog}/>
|
|
</div>
|
|
}
|
|
|
|
const usedExistingValues = useCallback(() => {
|
|
return stateFieldData
|
|
.filter(o => o.lookUpDataId)
|
|
.map(o => o.title)
|
|
}, [stateFieldData]);
|
|
|
|
const renderHeader = () => {
|
|
return (
|
|
<span className="ql-formats">
|
|
<button className="ql-bold" aria-label="Bold"></button>
|
|
<button className="ql-italic" aria-label="Italic"></button>
|
|
<button className="ql-underline" aria-label="Underline"></button>
|
|
<button className="ql-link" aria-label="Link"></button>
|
|
<button className="ql-list" value="ordered"></button>
|
|
<button className="ql-header" value="2"></button>
|
|
<button className="ql-header" value="3"></button>
|
|
<button className="ql-blockquote"></button>
|
|
<button className="ql-list" value="bullet"></button>
|
|
<button className="ql-indent" value="-1"></button>
|
|
<button className="ql-indent" value="+1"></button>
|
|
</span>
|
|
);
|
|
};
|
|
|
|
const header = renderHeader();
|
|
|
|
const faqOptionTemplate = (option) => {
|
|
return DOMPurify.sanitize(option.title, {ALLOWED_TAGS: ['#text']});
|
|
}
|
|
|
|
useEffect(() => {
|
|
const storeFieldData = data ?? [];
|
|
setStateFieldData(storeFieldData);
|
|
setStateOptionsData([...options, ...storeFieldData]);
|
|
register(fieldName, config)
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const diffData = diff(data, stateFieldData);
|
|
|
|
if (!isEmpty(diffData)) {
|
|
const storeFieldData = data ?? [];
|
|
setStateFieldData(storeFieldData);
|
|
}
|
|
}, [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] })}>
|
|
{label}
|
|
</label>
|
|
<div className="appForm__faqHeaderControls">
|
|
<Button type="button" iconPos="left" label={__('Aggiungi', 'gepafin')}
|
|
disabled={disabled}
|
|
icon="pi pi-plus" onClick={addNewItem}/>
|
|
<Dropdown onChange={(e) => selectItem(e)}
|
|
filter
|
|
disabled={disabled}
|
|
optionDisabled={(opt) => usedExistingValues().includes(opt.title)}
|
|
options={stateOptionsData}
|
|
itemTemplate={faqOptionTemplate}
|
|
placeholder={__('Scegli tra quelli pre-creati', 'gepafin')}
|
|
optionLabel="title"/>
|
|
</div>
|
|
<Accordion activeIndex={0}>
|
|
{stateFieldData.map((o, i) =>
|
|
<AccordionTab key={i} tabIndex={i}
|
|
header={
|
|
<div className="appForm__faqTab">
|
|
<div className="appForm__faqTabItem">
|
|
<span>
|
|
{renderHtmlContent(o.value)}
|
|
</span>
|
|
</div>
|
|
<div className="appForm__faqTabItem">
|
|
{o.isVisible
|
|
? <i className="pi pi-eye"
|
|
style={{ fontSize: '1.5rem' }}></i> : null}
|
|
{!o.isVisible
|
|
? <i className="pi pi-eye-slash"
|
|
style={{ fontSize: '1.5rem' }}></i> : null}
|
|
<Button icon="pi pi-pencil" severity="success"
|
|
disabled={disabled}
|
|
className="actionBtn"
|
|
type="button"
|
|
aria-label={__('Modifica', 'gepafin')}
|
|
onClick={(e) => editItem(e, i)}/>
|
|
<Button icon="pi pi-times" severity="danger"
|
|
disabled={disabled}
|
|
className="actionBtn"
|
|
type="button"
|
|
aria-label={__('Cancella', 'gepafin')}
|
|
onClick={() => removeItem(i)}/>
|
|
</div>
|
|
</div>
|
|
}
|
|
>
|
|
<span className="m-0">
|
|
{renderHtmlContent(o.response)}
|
|
</span>
|
|
</AccordionTab>)}
|
|
</Accordion>
|
|
<Dialog
|
|
visible={isVisibleEditDialog}
|
|
modal header={headerEditDialog}
|
|
footer={footerEditDialog}
|
|
style={{ maxWidth: '600px', width: '100%' }}
|
|
onHide={hideEditDialog}>
|
|
<div className="appForm__field">
|
|
<label for="faqTitle">{__('Titolo FAQ', 'gepafin')}</label>
|
|
<Editor
|
|
id="faqTitle"
|
|
value={title}
|
|
headerTemplate={header}
|
|
onTextChange={(e) => onChangeEditItem(e.htmlValue, 'title')}
|
|
style={{ height: 80 * 1 }}
|
|
/>
|
|
</div>
|
|
<div className="appForm__field">
|
|
<label for="faqValue">{__('Domanda', 'gepafin')}</label>
|
|
<Editor
|
|
id="faqValue"
|
|
value={question}
|
|
headerTemplate={header}
|
|
onTextChange={(e) => onChangeEditItem(e.htmlValue, 'value')}
|
|
style={{ height: 80 * 1 }}
|
|
/>
|
|
</div>
|
|
<div className="appForm__field">
|
|
<label for="faqResponse">{__('Risposta', 'gepafin')}</label>
|
|
<Editor
|
|
id="faqResponse"
|
|
value={answer}
|
|
headerTemplate={header}
|
|
onTextChange={(e) => onChangeEditItem(e.htmlValue, 'response')}
|
|
style={{ height: 80 * 2 }}
|
|
/>
|
|
</div>
|
|
<div className="appForm__field">
|
|
<label>{__('Pubblicato?', 'gepafin')}</label>
|
|
<InputSwitch checked={isVisible}
|
|
onChange={(e) => onChangeEditItem(e.value, 'isVisible')}/>
|
|
</div>
|
|
</Dialog>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default FormFieldRepeaterFaq; |