UNPKG

@shopgate/engage

Version:
210 lines (204 loc) • 7.69 kB
import 'react-phone-number-input/style.css'; import React, { useState, useContext, useMemo, useRef, useLayoutEffect, useCallback, Fragment } from 'react'; import { TextField, RippleButton, RadioGroup, RadioGroupItem, ProgressBar } from '@shopgate/engage/components'; import { i18n } from '@shopgate/engage/core/helpers'; import { useFormState } from "../../../core/hooks/useFormState"; import { FulfillmentContext } from "../../locations.context"; import { ReserveFormPhone } from "./ReserveFormPhone"; import { constraints } from "./ReserveForm.constraints"; import { form, fieldset, formField, formHeading, pickerSwitch, pickerItem, button, progressBar } from "./ReserveForm.style"; // eslint-disable-next-line max-len /** @typedef {import('@shopgate/engage/locations/locations.types').ReservationFormValues} ReservationFormValues */ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; const PICKUP_PERSON_ME = 'me'; const PICKUP_PERSON_OTHER = 'someoneelse'; /** * Determines the pick up person. * @param {ReservationFormValues|null} userInput The current user input * @return {string} */ const determinePickupPerson = userInput => { if (!userInput) { return PICKUP_PERSON_ME; } const meFields = ['firstName', 'lastName', 'email', 'cellPhone']; const otherFields = ['firstName2', 'lastName2', 'email2', 'cellPhone2']; const hasMeFields = meFields.every(field => typeof userInput[field] !== 'undefined'); const hasOtherFields = otherFields.every(field => typeof userInput[field] !== 'undefined'); if (!hasOtherFields || !hasMeFields) { return PICKUP_PERSON_ME; } const valuesEqual = meFields.every((field, index) => userInput[field] === userInput[otherFields[index]]); return valuesEqual ? PICKUP_PERSON_ME : PICKUP_PERSON_OTHER; }; /** * Renders the quick reservation form. * @returns {JSX.Element} */ function ReserveFormUnwrapped() { const { sendReservation, userInput } = useContext(FulfillmentContext); const [picker, setPicker] = useState(determinePickupPerson(userInput)); /** @type {ReservationFormValues} */ const defaultState = { firstName: '', lastName: '', cellPhone: '', email: '', firstName2: '', lastName2: '', cellPhone2: '', email2: '' }; const validationConstraints = useMemo(() => ({ ...constraints, ...(picker === PICKUP_PERSON_OTHER && { firstName2: constraints.firstName, lastName2: constraints.lastName, cellPhone2: constraints.cellPhone, email2: constraints.email }) }), [picker]); /** @type {ReservationFormValues} */ const initialState = userInput ? { ...defaultState, ...userInput } : defaultState; /** * @param {Object} values The form values. */ /** @param {ReservationFormValues} values */ const complete = useCallback(async values => { const response = values; if (picker === PICKUP_PERSON_ME) { response.firstName2 = response.firstName; response.lastName2 = response.lastName; response.cellPhone2 = response.cellPhone; response.email2 = response.email; } else { response.firstName2 = response.firstName2 || response.firstName; response.lastName2 = response.lastName2 || response.lastName; response.cellPhone2 = response.cellPhone2 || response.cellPhone; response.email2 = response.email2 || response.email; } await sendReservation(response); }, [picker, sendReservation]); const { values, handleChange, handleSubmit, changed, valid, validationErrors = {}, isSubmitting } = useFormState(initialState, complete, validationConstraints); const someoneElseRef = useRef(null); useLayoutEffect(() => { if (someoneElseRef.current && picker === PICKUP_PERSON_OTHER) { someoneElseRef.current.scrollIntoView({ behavior: 'smooth' }); } }, [picker, someoneElseRef]); return /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx("div", { className: progressBar, children: /*#__PURE__*/_jsx(ProgressBar, { isVisible: isSubmitting }) }), /*#__PURE__*/_jsxs("form", { onSubmit: handleSubmit, className: form, children: [/*#__PURE__*/_jsxs("fieldset", { className: fieldset, children: [/*#__PURE__*/_jsx(TextField, { name: "firstName", value: values.firstName, onChange: handleChange, label: i18n.text('locations.firstName'), className: formField, errorText: i18n.text(validationErrors.firstName) }), /*#__PURE__*/_jsx(TextField, { name: "lastName", value: values.lastName, onChange: handleChange, label: i18n.text('locations.lastName'), className: formField, errorText: i18n.text(validationErrors.lastName) }), /*#__PURE__*/_jsx(ReserveFormPhone, { name: "cellPhone", value: values.cellPhone, onChange: handleChange, label: i18n.text('locations.cellPhone'), errorText: i18n.text(validationErrors.cellPhone) }), /*#__PURE__*/_jsx(TextField, { name: "email", value: values.email, onChange: handleChange, label: i18n.text('locations.emailAddress'), className: formField, errorText: i18n.text(validationErrors.email) })] }), /*#__PURE__*/_jsx("p", { className: formHeading, children: i18n.text('locations.who_will_pickup') }), /*#__PURE__*/_jsx("div", { className: pickerSwitch, children: /*#__PURE__*/_jsxs(RadioGroup, { name: "picker", direction: "row", value: picker, onChange: setPicker, children: [/*#__PURE__*/_jsx(RadioGroupItem, { label: i18n.text('locations.me'), name: PICKUP_PERSON_ME, className: pickerItem }), /*#__PURE__*/_jsx(RadioGroupItem, { label: i18n.text('locations.someone_else'), name: PICKUP_PERSON_OTHER, className: pickerItem })] }) }), picker === PICKUP_PERSON_OTHER && /*#__PURE__*/_jsxs("fieldset", { className: fieldset, ref: someoneElseRef, children: [/*#__PURE__*/_jsx(TextField, { name: "firstName2", value: values.firstName2, onChange: handleChange, label: i18n.text('locations.firstName'), className: formField, errorText: i18n.text(validationErrors.firstName2) }), /*#__PURE__*/_jsx(TextField, { name: "lastName2", value: values.lastName2, onChange: handleChange, label: i18n.text('locations.lastName'), className: formField, errorText: i18n.text(validationErrors.lastName2) }), /*#__PURE__*/_jsx(ReserveFormPhone, { name: "cellPhone2", value: values.cellPhone2, onChange: handleChange, label: i18n.text('locations.cellPhone'), errorText: i18n.text(validationErrors.cellPhone2) }), /*#__PURE__*/_jsx(TextField, { name: "email2", value: values.email2, onChange: handleChange, label: i18n.text('locations.emailAddress'), className: formField, errorText: i18n.text(validationErrors.email2) })] }), /*#__PURE__*/_jsx(RippleButton, { type: "secondary", disabled: changed || valid === false || isSubmitting, className: button, children: i18n.text('locations.place_reservation') })] })] }); } export const ReserveForm = ReserveFormUnwrapped;