webapp/components/dashboard/seller/new/pages/OptionalNew.js

import React, {useEffect, useRef} from 'react';
import {styled} from '@mui/material/styles';
import Grid from '@mui/material/Grid';
import facings from '/common/info/facings';
import floorings from '/common/info/unit/floorings';
import furnishingTypes from '/common/info/furnishingTypes';
import possessionStatusTypes from '/common/info/unit/possessionStatuses';
import PropTypes from 'prop-types';
import Loader from '/components/Loader';
import {Input} from '@settlin/react-hook-form-mui';
import {useForm, FormProvider} from 'react-hook-form';
import {useSelector} from 'react-redux';
import Stepper from '/components/dashboard/seller/new/pages/MobileStepper';
import rhfOptions from '/common/utils/formikOptions';
import rhfValidation from '/components/dashboard/seller/new/pages/rhfValidation';
import clsx from 'clsx';

const PREFIX = 'Optional';

const classes = {
	largeDevices: `${PREFIX}-largeDevices`,
	smallDevices: `${PREFIX}-smallDevices`,
	stepperButton: `${PREFIX}-stepperButton`,
	chipStyle: `${PREFIX}-chipStyle`,
	showDateOfConstruction: `${PREFIX}-showDateOfConstruction`,
	hideDateOfConstruction: `${PREFIX}-hideDateOfConstruction`,
	selectChipLabel: `${PREFIX}-selectChipLabel`,
	helperTextLabel: `${PREFIX}-helperTextLabel`,
};

const StyledGrid = styled(Grid)((
	{
		theme,
	},
) => ({
	[`& .${classes.largeDevices}`]: {
		width: theme.spacing(56),
	},
	[`& .${classes.smallDevices}`]: {
		width: theme.spacing(40),
	},
	marginTop: theme.spacing(0.5),
	[`& .${classes.stepperButton}`]: {
		width: '100%',
	},
	[`& .${classes.chipStyle}`]: {
		marginBottom: '-0.2rem',
		height: '2rem',
	},
	[`& .${classes.showDateOfConstruction}`]: {
		borderBottom: 'none',
		margin: 0,
		height: '2.1rem',
	},
	[`& .${classes.hideDateOfConstruction}`]: {
		color: 'transparent',
	},
	[`& .${classes.selectChipLabel}`]: {
		marginLeft: '-14px',
	},
	[`& .${classes.helperTextLabel}`]: {
		marginRight: 0,
		marginLeft: 0,
	},
}));

/**
 * This Component renders a react hook form for adding Property with basic details.
 * @param {object} props props
 * @return {ReactElement} React component
 */
function Optional({ruData: rawUnitData, history, submitData}) {
	const deviceType = useSelector(state => state.deviceType);
	const styleProps = (deviceType === 'extraSmall' ? classes.smallDevices : classes.largeDevices);
	const {ruData = {}, waitingForData} = rawUnitData;
	const {project, type} = ruData.propertyType || {};
	const form = useForm({defaultValues: ruData});
	const {watch, handleSubmit, reset, setError, clearErrors, formState: {errors}} = form;
	const formValue = watch();
	const {possessionStatus, flooring, furnishing, constructedOn, plotFacing, facing} = formValue;
	const commonProps = {
		container: {md: 6, xs: 12},
		inputProps: {className: 'mui'},
	};

	const validationRules = {
		constructedOn: {
			type: 'date',
			message: 'Constructed On date is required or it must not be in future',
		},
		balconies: {
			type: 'number',
		},
		plotArea: {
			type: 'number',
			length: {min: 1, max: 10000000},
		},
		floor: {
			type: 'number',
		},
		uParking: {
			type: 'number',
			message: 'Uncovered Parking must be positive number',
		},
		floors: {
			type: 'number',
		},
		cParking: {
			type: 'number',
			message: 'Covered Parking must be positive number',
		},
	};

	const ref = useRef({formValue: {}});

	useEffect(() => {
		const result = rhfValidation({ref, values: formValue, validationRules});
		result.forEach(res => (res?.message && res?.name) ? setError(res?.name, {message: res?.message}) : clearErrors(res?.name, ''));
	}, [formValue]);

	useEffect(() => {
		reset(ruData);
	}, [ruData]);

	const handleNext = (data) => {
		const {_id, balconies, cParking, plotArea, floors, floor, uParking} = formValue;
		data = {_id, balconies, cParking, plotArea, constructedOn, furnishing, flooring, floors, floor, uParking, facing, plotFacing, possessionStatus};
		if (data.constructedOn)data.constructedOn = new Date(data.constructedOn);
		if (js(ruData) === js(data)) history.push(`/dashboard/seller/listing/${ruData._id}/imageUpload`, {edit: true});
		else {
			submitData({data, page: 2, id: ruData._id, params: 'imageUpload'});
		}
	};

	const handleBack = (data) => {
		const {_id, balconies, cParking, plotArea, floors, floor, uParking} = formValue;
		data = {_id, balconies, cParking, plotArea, constructedOn, furnishing, flooring, floors, floor, uParking, facing, plotFacing, possessionStatus};
		submitData({data, page: 2, id: ruData._id, params: 'details'});
	};

	if (waitingForData) return <Loader/>;

	return (
		<FormProvider {...form}>
			<form autoComplete='off' onSubmit={handleSubmit(handleNext)}>
				<StyledGrid container spacing={2}>
					{project && (
						<Input
							helperText={formValue.floor ? '' : 'Floor on which property is located'}
							label='On Floor'
							name='floor'
							type='number'
							{...commonProps}
							className={styleProps}
						/>
					)}
					{/* Inline styling is done as it was overriding the default styling */}
					<Input
						className={styleProps}
						container={{md: 6, xs: 12}}
						format='MM/YYYY'
						helperText={constructedOn ? '' : 'Completion date of the property'}
						id='constructed-on'
						inputProps={{className: clsx('mui', constructedOn ? classes.showDateOfConstruction : classes.hideDateOfConstruction),
							style: {
								margin: '0',
								height: '2rem',
								borderBottom: 'none',
							}}}
						label='Constructed On'
						name='constructedOn'
						openTo='month'
						type='month'
						views={['year', 'month']}
					/>
					<Input
						ChipProps={classes.chipStyle}
						InputLabelProps={({required: true}, {className: [classes.selectChipLabel]})}
						className={styleProps}
						helperText={plotFacing || facing ? '' : 'Door facing of the property'}
						helperTextProps={{classes: {root: classes.helperTextLabel}}}
						label={type === 'house' ? 'Plot Facing' : 'Facing'}
						name={type === 'house' ? 'plotFacing' : 'facing'}
						options={rhfOptions(facings)}
						type='selectchip'
						{...commonProps}
					/>
					{type === 'house' && (
						<>
							<Input
								label='Plot Area(Sqft)'
								name='plotArea'
								type='number'
								{...commonProps}
								className={styleProps}
							/>
							<Input
								label='No Of Floors'
								name='floors'
								type='number'
								{...commonProps}
								className={styleProps}
							/>
						</>
					)
					}
					<Input
						label='No Of Balconies'
						name='balconies'
						type='number'
						{...commonProps}
						className={styleProps}
					/>
					<Input
						label='No Of Covered Parking'
						name='cParking'
						type='number'
						{...commonProps}
						className={styleProps}
					/>
					<Input
						label='No Of Uncovered Parking'
						name='uParking'
						type='number'
						{...commonProps}
						className={styleProps}
					/>
					<Input
						ChipProps={classes.chipStyle}
						InputLabelProps={({required: true}, {className: [classes.selectChipLabel]})}
						className={styleProps}
						label='Possession Status'
						name='possessionStatus'
						type='selectchip'
						{...commonProps}
						helperText={possessionStatus ? '' : 'Possession status of property'}
						helperTextProps={{classes: {root: classes.helperTextLabel}}}
						options={rhfOptions(possessionStatusTypes)}
					/>
					{possessionStatus === 'readyToMoveIn' && (
						<Input
							ChipProps={classes.chipStyle}
							className={styleProps}
							label='Furnishing'
							name='furnishing'
							options={rhfOptions(furnishingTypes)}
							type='selectchip'
							{...commonProps}
						/>
					)}
					{furnishing === 'furnished' && (
						<Input
							ChipProps={classes.chipStyle}
							className={styleProps}
							label='Flooring'
							name='flooring'
							options={rhfOptions(floorings)}
							type='selectchip'
							{...commonProps}
						/>
					)}
					<Stepper OtherProps={classes.stepperButton} activeStep={1} disabled={Boolean(Object.keys(errors).length)} handleBack={handleBack} totalSteps={3}/>
				</StyledGrid>
			</form>
		</FormProvider>
	);
}

Optional.propTypes = {
	history: PropTypes.object,
	location: PropTypes.object,
	ruData: PropTypes.object,
	submitData: PropTypes.func,
	waitingForData: PropTypes.bool,
};

export default Optional;