updated form fields and application logic;

This commit is contained in:
Vitalii Kiiko
2024-09-12 17:17:48 +02:00
parent 19e17ec2d7
commit a8471ba7aa
42 changed files with 1423 additions and 231 deletions

View File

@@ -0,0 +1,57 @@
import React, { useState, useCallback } from 'react';
import { classNames } from 'primereact/utils';
import { Controller } from 'react-hook-form';
import { Checkbox } from 'primereact/checkbox';
const Checkboxes = ({
fieldName,
label,
control,
errors,
defaultValue = [],
config = {},
infoText = null,
options = []
}) => {
const [fieldVal, setFieldVal] = useState(defaultValue);
const onCheckboxesChange = useCallback((e, updateFn) => {
let data = [...fieldVal];
if (e.checked) {
data.push(e.value);
} else {
data.splice(data.indexOf(e.value), 1);
}
setFieldVal(data);
updateFn(data);
}, [fieldVal]);
const input = <Controller
name={fieldName}
control={control}
defaultValue={fieldVal}
rules={config}
render={({ field, fieldState }) =>
options.map(o => <div className="appForm__fieldItem" key={o.name}>
<Checkbox
inputId={`${fieldName}_${o.name}`}
name={fieldName}
value={o.name}
onChange={(e) => onCheckboxesChange(e, field.onChange)}
checked={field.value.includes(o.name)}
className={classNames({ 'p-invalid': fieldState.invalid })}/>
<label htmlFor={`${fieldName}_${o.name}`}>{o.label}</label>
</div>)}/>
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? '*' : null}
</label>
{input}
{infoText ? <small>{infoText}</small> : null}
</>)
}
export default Checkboxes;

View File

@@ -18,7 +18,7 @@ const Datepicker = ({
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required ? '*' : null}
{label}{config.required || config.isRequired ? '*' : null}
</label>
<Controller
name={fieldName}

View File

@@ -15,8 +15,8 @@ const NumberInput = ({
inputgroup = false,
icon = null,
locale = 'it-IT',
minFractionDigits = 2,
step = 1,
minFractionDigits = 0,
maxFractionDigits = 1,
min,
max
}) => {
@@ -31,13 +31,14 @@ const NumberInput = ({
onValueChange={(e) => field.onChange(e.value)}
min={min}
max={max}
locale={locale} minFractionDigits={minFractionDigits} step={step}
locale={locale}
minFractionDigits={minFractionDigits}
className={classNames({ 'p-invalid': fieldState.invalid })}/>
)}/>
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required ? '*' : null}
{label}{config.required || config.isRequired ? '*' : null}
</label>
{inputgroup
? <div className="p-inputgroup flex-1">

View File

@@ -4,34 +4,35 @@ import { Controller } from 'react-hook-form';
import { RadioButton } from 'primereact/radiobutton';
const Radio = ({
fieldName,
label,
control,
errors,
defaultValue,
config = {},
infoText = null,
options = []
}) => {
fieldName,
label,
control,
errors,
defaultValue,
config = {},
infoText = null,
options = []
}) => {
const input = <Controller
name={fieldName}
control={control}
defaultValue={defaultValue}
rules={config}
render={({ field, fieldState }) =>
options.map(o => <div className="appForm__fieldItem" key={o.name}>
<RadioButton
id={`${fieldName}_${o.name}`}
name={fieldName}
value={o.name}
onChange={(e) => field.onChange(e.value)}
checked={field.value === o.name}/>
<label htmlFor={`${fieldName}_${o.name}`}>{o.label}</label>
</div>)}/>
options.map(o => <div className="appForm__fieldItem" key={o.name}>
<RadioButton
inputId={`${fieldName}_${o.name}`}
name={fieldName}
value={o.name}
onChange={(e) => field.onChange(e.value)}
checked={field.value === o.name}
className={classNames({ 'p-invalid': fieldState.invalid })}/>
<label htmlFor={`${fieldName}_${o.name}`}>{o.label}</label>
</div>)}/>
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required ? '*' : null}
{label}{config.required || config.isRequired ? '*' : null}
</label>
{input}
{infoText ? <small>{infoText}</small> : null}

View File

@@ -27,13 +27,14 @@ const Select = ({
onChange={(e) => field.onChange(e.value)}
options={options}
optionLabel="label"
optionValue="name"
placeholder={placeholder}
className={classNames({ 'p-invalid': fieldState.invalid })}/>
)}/>
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required ? '*' : null}
{label}{config.required || config.isRequired ? '*' : null}
</label>
{inputgroup
? <div className="p-inputgroup flex-1">

View File

@@ -34,7 +34,7 @@ const Switch = ({
<>
<div className="appForm__row">
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] }, 'mr-8')}>
{label}{config.required ? '*' : null}
{label}{config.required || config.isRequired ? '*' : null}
</label>
<div className="appForm__row">
{offLabel ? <span>{offLabel}</span> : null}

View File

@@ -16,7 +16,7 @@ const TextArea = ({
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required ? '*' : null}
{label}{config.required || config.isRequired ? '*' : null}
</label>
<Controller
name={fieldName}

View File

@@ -31,7 +31,7 @@ const TextInput = ({
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required ? '*' : null}
{label}{config.required || config.isRequired ? '*' : null}
</label>
{inputgroup
? <div className="p-inputgroup flex-1">

View File

@@ -0,0 +1,54 @@
import React from 'react';
import { classNames } from 'primereact/utils';
import { Controller } from 'react-hook-form';
import { Editor } from 'primereact/editor';
const Wysiwyg = ({
fieldName,
label,
control,
rows = 3,
errors,
defaultValue,
config = {},
infoText = null
}) => {
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>
</span>
);
};
const header = renderHeader();
return (
<>
<label htmlFor={fieldName} className={classNames({ 'p-error': errors[fieldName] })}>
{label}{config.required || config.isRequired ? '*' : null}
</label>
<Controller
name={fieldName}
control={control}
defaultValue={defaultValue}
rules={config}
render={({ field, fieldState }) => (
<Editor
id={field.name}
{...field}
headerTemplate={header}
onTextChange={(e) => field.onChange(e.htmlValue)}
style={{ height: 80 * rows }}
className={classNames({ 'p-invalid': fieldState.invalid })}
/>
)}/>
{infoText ? <small>{infoText}</small> : null}
</>)
}
export default Wysiwyg;

View File

@@ -12,6 +12,8 @@ import NumberInput from './components/NumberInput';
import Switch from './components/Switch';
import Select from './components/Select';
import Radio from './components/Radio';
import Wysiwyg from './components/Wysiwyg';
import Checkboxes from './components/Checkboxes';
const FormField = (props) => {
const fields = {
@@ -23,7 +25,9 @@ const FormField = (props) => {
numberinput: NumberInput,
switch: Switch,
select: Select,
radio: Radio
radio: Radio,
wysiwyg: Wysiwyg,
checkboxes: Checkboxes
}
const Comp = !isNil(fields[props.type]) ? fields[props.type] : null;