blocked services form

This commit is contained in:
Ildar Kamalov
2025-01-14 16:20:51 +03:00
parent 8b40fe97a6
commit aeab662335
3 changed files with 100 additions and 37 deletions

View File

@@ -1,30 +1,41 @@
import React from 'react';
import { Field, reduxForm } from 'redux-form';
import { Trans, withTranslation } from 'react-i18next';
import flow from 'lodash/flow';
import { Trans } from 'react-i18next';
import { toggleAllServices } from '../../../helpers/helpers';
import { Controller, useForm } from 'react-hook-form';
import { renderServiceField } from '../../../helpers/form';
import { FORM_NAME } from '../../../helpers/constants';
import { ServiceField } from './ServiceField';
interface FormProps {
blockedServices: unknown[];
pristine: boolean;
handleSubmit: (...args: unknown[]) => string;
change: (...args: unknown[]) => unknown;
submitting: boolean;
processing: boolean;
processingSet: boolean;
t: (...args: unknown[]) => string;
type BlockedService = {
id: string;
name: string;
icon_svg: string;
}
const Form = (props: FormProps) => {
const { blockedServices, handleSubmit, change, pristine, submitting, processing, processingSet } = props;
type FormValues = {
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 (
<form onSubmit={handleSubmit}>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form__group">
<div className="row mb-4">
<div className="col-6">
@@ -32,7 +43,8 @@ const Form = (props: FormProps) => {
type="button"
className="btn btn-secondary btn-block"
disabled={processing || processingSet}
onClick={() => toggleAllServices(blockedServices, change, true)}>
onClick={() => handleToggleAllServices(true)}
>
<Trans>block_all</Trans>
</button>
</div>
@@ -42,7 +54,8 @@ const Form = (props: FormProps) => {
type="button"
className="btn btn-secondary btn-block"
disabled={processing || processingSet}
onClick={() => toggleAllServices(blockedServices, change, false)}>
onClick={() => handleToggleAllServices(false)}
>
<Trans>unblock_all</Trans>
</button>
</div>
@@ -50,14 +63,18 @@ const Form = (props: FormProps) => {
<div className="services">
{blockedServices.map((service: any) => (
<Field
<Controller
key={service.id}
icon={service.icon_svg}
name={`blocked_services.${service.id}`}
type="checkbox"
component={renderServiceField}
placeholder={service.name}
disabled={processing || processingSet}
control={control}
render={({ field }) => (
<ServiceField
{...field}
placeholder={service.name}
disabled={processing || processingSet}
icon={service.icon_svg}
/>
)}
/>
))}
</div>
@@ -67,18 +84,10 @@ const Form = (props: FormProps) => {
<button
type="submit"
className="btn btn-success btn-standard btn-large"
disabled={submitting || pristine || processing || processingSet}>
disabled={isSubmitting || !isDirty || processing || processingSet}>
<Trans>save_btn</Trans>
</button>
</div>
</form>
);
};
export default flow([
withTranslation(),
reduxForm({
form: FORM_NAME.SERVICES,
enableReinitialize: true,
}),
])(Form);

View 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';

View File

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import Form from './Form';
import { Form } from './Form';
import Card from '../../ui/Card';
import { getBlockedServices, getAllBlockedServices, updateBlockedServices } from '../../../actions/services';
@@ -86,7 +86,8 @@ const Services = () => {
<Card
title={t('schedule_services')}
subtitle={t('schedule_services_desc')}
bodyType="card-body box-body--settings">
bodyType="card-body box-body--settings"
>
<ScheduleForm schedule={services.list.schedule} onScheduleSubmit={handleScheduleSubmit} />
</Card>
</>