blocked services form
This commit is contained in:
@@ -1,30 +1,41 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Field, reduxForm } from 'redux-form';
|
import { Trans } from 'react-i18next';
|
||||||
import { Trans, withTranslation } from 'react-i18next';
|
|
||||||
import flow from 'lodash/flow';
|
|
||||||
|
|
||||||
import { toggleAllServices } from '../../../helpers/helpers';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
|
|
||||||
import { renderServiceField } from '../../../helpers/form';
|
import { ServiceField } from './ServiceField';
|
||||||
import { FORM_NAME } from '../../../helpers/constants';
|
|
||||||
|
|
||||||
interface FormProps {
|
type BlockedService = {
|
||||||
blockedServices: unknown[];
|
id: string;
|
||||||
pristine: boolean;
|
name: string;
|
||||||
handleSubmit: (...args: unknown[]) => string;
|
icon_svg: string;
|
||||||
change: (...args: unknown[]) => unknown;
|
|
||||||
submitting: boolean;
|
|
||||||
processing: boolean;
|
|
||||||
processingSet: boolean;
|
|
||||||
t: (...args: unknown[]) => string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Form = (props: FormProps) => {
|
type FormValues = {
|
||||||
const { blockedServices, handleSubmit, change, pristine, submitting, processing, processingSet } = props;
|
blocked_services: Record<string, boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FormProps {
|
||||||
|
initialValues: Record<string, boolean>;
|
||||||
|
blockedServices: BlockedService[];
|
||||||
|
onSubmit: (...args: unknown[]) => void;
|
||||||
|
processing: boolean;
|
||||||
|
processingSet: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Form = ({ initialValues, blockedServices, processing, processingSet, onSubmit }: FormProps) => {
|
||||||
|
const { handleSubmit, control, setValue, formState: { isSubmitting, isDirty } } = useForm<FormValues>({
|
||||||
|
mode: 'onChange',
|
||||||
|
defaultValues: initialValues,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleToggleAllServices = (isSelected: boolean) => {
|
||||||
|
blockedServices.forEach((service: BlockedService) => setValue(`blocked_services.${service.id}`, isSelected));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="form__group">
|
<div className="form__group">
|
||||||
<div className="row mb-4">
|
<div className="row mb-4">
|
||||||
<div className="col-6">
|
<div className="col-6">
|
||||||
@@ -32,7 +43,8 @@ const Form = (props: FormProps) => {
|
|||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary btn-block"
|
className="btn btn-secondary btn-block"
|
||||||
disabled={processing || processingSet}
|
disabled={processing || processingSet}
|
||||||
onClick={() => toggleAllServices(blockedServices, change, true)}>
|
onClick={() => handleToggleAllServices(true)}
|
||||||
|
>
|
||||||
<Trans>block_all</Trans>
|
<Trans>block_all</Trans>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -42,7 +54,8 @@ const Form = (props: FormProps) => {
|
|||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary btn-block"
|
className="btn btn-secondary btn-block"
|
||||||
disabled={processing || processingSet}
|
disabled={processing || processingSet}
|
||||||
onClick={() => toggleAllServices(blockedServices, change, false)}>
|
onClick={() => handleToggleAllServices(false)}
|
||||||
|
>
|
||||||
<Trans>unblock_all</Trans>
|
<Trans>unblock_all</Trans>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -50,14 +63,18 @@ const Form = (props: FormProps) => {
|
|||||||
|
|
||||||
<div className="services">
|
<div className="services">
|
||||||
{blockedServices.map((service: any) => (
|
{blockedServices.map((service: any) => (
|
||||||
<Field
|
<Controller
|
||||||
key={service.id}
|
key={service.id}
|
||||||
icon={service.icon_svg}
|
|
||||||
name={`blocked_services.${service.id}`}
|
name={`blocked_services.${service.id}`}
|
||||||
type="checkbox"
|
control={control}
|
||||||
component={renderServiceField}
|
render={({ field }) => (
|
||||||
placeholder={service.name}
|
<ServiceField
|
||||||
disabled={processing || processingSet}
|
{...field}
|
||||||
|
placeholder={service.name}
|
||||||
|
disabled={processing || processingSet}
|
||||||
|
icon={service.icon_svg}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -67,18 +84,10 @@ const Form = (props: FormProps) => {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-success btn-standard btn-large"
|
className="btn btn-success btn-standard btn-large"
|
||||||
disabled={submitting || pristine || processing || processingSet}>
|
disabled={isSubmitting || !isDirty || processing || processingSet}>
|
||||||
<Trans>save_btn</Trans>
|
<Trans>save_btn</Trans>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default flow([
|
|
||||||
withTranslation(),
|
|
||||||
reduxForm({
|
|
||||||
form: FORM_NAME.SERVICES,
|
|
||||||
enableReinitialize: true,
|
|
||||||
}),
|
|
||||||
])(Form);
|
|
||||||
|
|||||||
53
client/src/components/Filters/Services/ServiceField.tsx
Normal file
53
client/src/components/Filters/Services/ServiceField.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import cn from 'classnames';
|
||||||
|
import { FieldValues, ControllerRenderProps } from 'react-hook-form';
|
||||||
|
|
||||||
|
interface ServiceFieldProps extends ControllerRenderProps<FieldValues> {
|
||||||
|
placeholder: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
className?: string;
|
||||||
|
icon?: string;
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ServiceField = React.forwardRef<HTMLInputElement, ServiceFieldProps>(({
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
onBlur,
|
||||||
|
placeholder,
|
||||||
|
disabled,
|
||||||
|
className,
|
||||||
|
icon,
|
||||||
|
error,
|
||||||
|
}, ref) => (
|
||||||
|
<>
|
||||||
|
<label className={cn('service custom-switch', className)}>
|
||||||
|
<input
|
||||||
|
name={name}
|
||||||
|
type="checkbox"
|
||||||
|
className="custom-switch-input"
|
||||||
|
checked={!!value}
|
||||||
|
onChange={onChange}
|
||||||
|
onBlur={onBlur}
|
||||||
|
ref={ref}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<span className="service__switch custom-switch-indicator"></span>
|
||||||
|
|
||||||
|
<span className="service__text" title={placeholder}>
|
||||||
|
{placeholder}
|
||||||
|
</span>
|
||||||
|
{icon && <div dangerouslySetInnerHTML={{ __html: window.atob(icon) }} className="service__icon" />}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
{!disabled && error && (
|
||||||
|
<span className="form__message form__message--error">
|
||||||
|
{error}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
));
|
||||||
|
|
||||||
|
ServiceField.displayName = 'ServiceField';
|
||||||
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
|
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
import Form from './Form';
|
import { Form } from './Form';
|
||||||
|
|
||||||
import Card from '../../ui/Card';
|
import Card from '../../ui/Card';
|
||||||
import { getBlockedServices, getAllBlockedServices, updateBlockedServices } from '../../../actions/services';
|
import { getBlockedServices, getAllBlockedServices, updateBlockedServices } from '../../../actions/services';
|
||||||
@@ -86,7 +86,8 @@ const Services = () => {
|
|||||||
<Card
|
<Card
|
||||||
title={t('schedule_services')}
|
title={t('schedule_services')}
|
||||||
subtitle={t('schedule_services_desc')}
|
subtitle={t('schedule_services_desc')}
|
||||||
bodyType="card-body box-body--settings">
|
bodyType="card-body box-body--settings"
|
||||||
|
>
|
||||||
<ScheduleForm schedule={services.list.schedule} onScheduleSubmit={handleScheduleSubmit} />
|
<ScheduleForm schedule={services.list.schedule} onScheduleSubmit={handleScheduleSubmit} />
|
||||||
</Card>
|
</Card>
|
||||||
</>
|
</>
|
||||||
|
|||||||
Reference in New Issue
Block a user