webapp/pages/feedback/buyer/feedback.js

/* eslint-disable no-prototype-builtins */
import React, {useState} from 'react';
import {styled} from '@mui/material/styles';
import MobileStepper from '@mui/material/MobileStepper';
import Button from '@mui/material/Button';
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
import UnitFeedBack from '/components/feedback/unitFeedBack';
import FinalFeedBack from './finalFeedback';
import Grid from '@mui/material/Grid';
import {Meteor} from 'meteor/meteor';
import PropTypes from 'prop-types';
import Input from '/components/forms/Input';
import UnitSummary from '/components/unit/summary';

const PREFIX = 'feedback';

const classes = {
	mTop: `${PREFIX}-mTop`,
	margin: `${PREFIX}-margin`,
	unitSummary: `${PREFIX}-unitSummary`,
};

const StyledGrid = styled(Grid)(({theme}) => ({
	[`& .${classes.mTop}`]: {
		marginTop: '0.5rem',
	},
	[`& .${classes.margin}`]: {
		marginTop: '1rem',
	},
	[`& .${classes.unitSummary}`]: {
		boxShadow: '0 0 4px rgba(0,0,0,.14), 0 4px 8px rgba(0,0,0,.08)',
		[theme.breakpoints.up('md')]: {
			height: '168px',
		},
		[theme.breakpoints.between('xm', 'lg')]: {
			height: 'auto',
		},
	},
}));

const buyerFeedbackDefaultProps = {unitAccToReq: null, unitQueryResolved: '', unitDecision: '', amenitiesTour: '', locationAssistance: '', basicInfoExplained: ''};
/**
 * This fuction validate the unit specific data in form.
 * @param {object} {unit} form data specific to particular unit visited.
 * @returns {boolean} if all the fields in unit is not null returns true.
 */
const validateEachSlide = ({unit}) => {
	if (!unit) return null;
	for (const key in buyerFeedbackDefaultProps) {
		if (buyerFeedbackDefaultProps.hasOwnProperty(key)) {
			if (key === 'amenitiesTour' && !unit.showAmenitiesQues) continue;
			if (typeof unit[key] !== 'boolean' &&  !unit[key]) {
				Log.info(typeof unit[key], key);
				Log.info('Please give feedback for all questions');
				return false;
			}
		}
	}
	return true;
};

function Summary({field}) {
	return (
		<StyledGrid>
			<UnitSummary className={classes.unitSummary} unit={field.value}/>
		</StyledGrid>
	);
}
Summary.propTypes = {
	field: PropTypes.object,
};


/**
 *This component renders Mobile Stepper to handle rendering of unit secific form
 * @param {object}  props=>{length, unitsVisited, updateFeedbackSubmitted}
 * @return {JSX} returns Feedback Component
 */

// eslint-disable-next-line react/no-multi-comp
export default function Feedback({length, visitIds, unitsVisited, defaultValue, updateFeedbackSubmitted, scrollToTop}) {
	const [page, setPage] = useState(0);
	const maxSteps = length;

	/**
 * Validate the visitRating and visitPunctuality in data before sending OTP to the buyer.
 * @param  {object} data object containing form data.
 * @returns {boolean} if visitRating and visitPunctuality have not null value it returns true.
 */
	const validateForm = (data) => {
		const {visitRating, visitPunctuality} = data;
		if (!visitRating) {
			Log.error('Please give overall rating for the visits');
			setPage(page - 1);
			scrollToTop();
			return null;
		}
		if (!visitPunctuality) {
			Log.error('Please give answer for \'Was our visit representative on time?\'');
			setPage(page - 1);
			scrollToTop();
			return null;
		}
		return true;
	};
	/**
	 * This function calls Meteor method feedback.buyer.create and sets the flag for formSubmitted in index.js
	 * @param {object} data -completed form data
	 * @returns {null} -returns nothing
	 */

	const hFinalSubmit = ({values: data, params}) => {
		const {visitPunctuality, visitRating, group, individual} = data;
		Meteor.call('feedback.buyer.create', {visitIds, visitRating: parseInt(visitRating, 10), visitPunctuality: visitPunctuality === 'yes', unitsVisited, group, individual, token: (data.urlParams || {}).token, url: window.location.href}, (err) => {
			if (err) Log.fatal('Unable to submit your feedback', err, data);
			else {
				Log.success('Thank you for your feedback');
				if (params.cb) params.cb({verified: true, tick: 'clear'});
				updateFeedbackSubmitted(true);
			}
		});
	};
	/**
	 * This function handles Next Button
	 * and simultaneously calls validateEachSlide function to validate data before going to next step(unit specific form) in stepper
	 * @returns {null} -return null
	 */
	const handleNext = () => {
		if (validateEachSlide({unit: unitsVisited[page]})) { setPage(prevActiveStep => prevActiveStep + 1); }
	};


	/**
	 * This function handles Back Button
	 * @returns {null} -return null
	 */
	const handleBack = () => {
		setPage(prevActiveStep => prevActiveStep - 1);
	};

	return (
		<StyledGrid>
			{page !== length - 1 && (
				<Grid>
					<Grid container justifyContent='center'>
						<Grid className={classes.margin} item lg={8} md={8} sm={7} xs={11}>
							<Input base components={{input: Summary}} container={{className: classes.uSContainer}} name={`unitsVisited[${page}].unit`}/>
						</Grid>
					</Grid>
					<UnitFeedBack page={page} unit={unitsVisited[page].unit} unitDecision={defaultValue.unitsVisited[page]?.unitDecision}/>
				</Grid>
			)}
			{page === length - 1 && <FinalFeedBack finalSubmit={hFinalSubmit} page={page} validateForm={validateForm}/>}
			<MobileStepper
				activeStep={page}
				backButton={(
					<Button disabled={page === 0} onClick={handleBack} size='small'>
						<KeyboardArrowLeft/>
						Back
					</Button>
				)}
				className={classes.mTop}
				nextButton={(
					<Button disabled={page === maxSteps - 1} onClick={handleNext} size='small'>
						Next
						<KeyboardArrowRight/>
					</Button>
				)}
				position='static'
				steps={maxSteps}
				variant='dots'
			/>
		</StyledGrid>
	);
}
Feedback.propTypes = {
	defaultValue: PropTypes.object,
	length: PropTypes.number,
	scrollToTop: PropTypes.func,
	unitsVisited: PropTypes.array,
	updateFeedbackSubmitted: PropTypes.func,
	visitIds: PropTypes.array,
};