@merchi/cart 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +134 -0
- package/esm/Cart.js +62 -0
- package/esm/CartAlert.js +47 -0
- package/esm/CartHeader.js +29 -0
- package/esm/CartProvider.js +1101 -0
- package/esm/CartTotals.js +89 -0
- package/esm/assets/merchi-monster-loader.gif +0 -0
- package/esm/assets/merchi-swipe-outline.png +0 -0
- package/esm/assets/product-not-found.png +0 -0
- package/esm/assets/stripe-payment-secure.png +0 -0
- package/esm/buttons/Button.js +23 -0
- package/esm/buttons/ButtonBack.js +35 -0
- package/esm/buttons/ButtonClearCart.js +17 -0
- package/esm/buttons/ButtonInvoiceDownload.js +88 -0
- package/esm/buttons/ButtonNext.js +39 -0
- package/esm/buttons/ButtonNextDynamic.js +19 -0
- package/esm/buttons/ButtonOpenCartMerchiCartModal.js +47 -0
- package/esm/buttons/ButtonPay.js +26 -0
- package/esm/buttons/ButtonShipmentTabNext.js +28 -0
- package/esm/buttons/index.js +7 -0
- package/esm/components/Alert.js +26 -0
- package/esm/components/CartBody.js +14 -0
- package/esm/components/CartClient.js +62 -0
- package/esm/components/CartFooter.js +12 -0
- package/esm/components/CartItemRow.js +230 -0
- package/esm/components/CartPaymentSettingsInvalid.js +13 -0
- package/esm/components/CartShipment.js +52 -0
- package/esm/components/CartTabContent.js +12 -0
- package/esm/components/CartTabPanel.js +25 -0
- package/esm/components/CartTableContainer.js +12 -0
- package/esm/components/CartTitle.js +26 -0
- package/esm/components/CartTotalsListGroup.js +71 -0
- package/esm/components/Collapse.js +32 -0
- package/esm/components/CustomCartProductForm.js +128 -0
- package/esm/components/CustomerCheckoutMethodTabs.js +94 -0
- package/esm/components/DiscountInputGroup.js +293 -0
- package/esm/components/LoadingTemplate.js +23 -0
- package/esm/components/NoCartItems.js +20 -0
- package/esm/components/ShipmentGroupCard.js +207 -0
- package/esm/components/Table.js +13 -0
- package/esm/components/containers.js +31 -0
- package/esm/components/index.js +18 -0
- package/esm/components/product-form-sdk-externals.js +36 -0
- package/esm/forms/FormNewCustomer.js +243 -0
- package/esm/forms/FormReturningCustomer.js +165 -0
- package/esm/forms/FormShipmentAddressAndNotes.js +195 -0
- package/esm/forms/FormSquarePayment.js +19 -0
- package/esm/forms/FormStripePayment.js +19 -0
- package/esm/forms/FormWhatsappCustomer.js +253 -0
- package/esm/forms/InputAcceptUserTermsAndConditions.js +35 -0
- package/esm/forms/InputError.js +16 -0
- package/esm/forms/InputSelect.js +48 -0
- package/esm/forms/InputText.js +56 -0
- package/esm/forms/InputsAddress.js +476 -0
- package/esm/forms/index.js +8 -0
- package/esm/index.js +13 -0
- package/esm/modals.js +51 -0
- package/esm/panels/PanelCartItems.js +49 -0
- package/esm/panels/PanelCartShipment.js +66 -0
- package/esm/panels/PanelClearCart.js +56 -0
- package/esm/panels/PanelClientCheckout.js +81 -0
- package/esm/panels/PanelEditCartItem.js +199 -0
- package/esm/panels/PanelPaymentSuccess.js +63 -0
- package/esm/panels/index.js +7 -0
- package/esm/square/SquareCard.js +106 -0
- package/esm/stripe/LegacyStripeCardForm.js +157 -0
- package/esm/stripe/StripeCardFields.js +126 -0
- package/esm/stripe/StripeCardForm.js +33 -0
- package/esm/stripe/StripePaymentButtons.js +98 -0
- package/esm/stripe/actions.js +192 -0
- package/esm/stripe/utils.js +20 -0
- package/esm/styles/globals.css +463 -0
- package/esm/styles/globals.css.map +1 -0
- package/esm/tabs/CartNav.js +28 -0
- package/esm/tabs/NavTab.js +31 -0
- package/esm/types/assets.d.js +0 -0
- package/esm/types/index.js +1 -0
- package/esm/types/merchi_product_form/index.d.js +0 -0
- package/esm/types/merchi_sdk_ts/index.d.js +0 -0
- package/esm/types/react-redux/index.d.js +0 -0
- package/esm/utilities/address.js +457 -0
- package/esm/utilities/area.js +297 -0
- package/esm/utilities/cart.js +95 -0
- package/esm/utilities/company.js +6 -0
- package/esm/utilities/cookie.js +156 -0
- package/esm/utilities/currency.js +219 -0
- package/esm/utilities/customForm.js +57 -0
- package/esm/utilities/helpers.js +229 -0
- package/esm/utilities/index.js +14 -0
- package/esm/utilities/invoice.js +112 -0
- package/esm/utilities/job.js +9 -0
- package/esm/utilities/local_storage.js +85 -0
- package/esm/utilities/product.js +13 -0
- package/esm/utilities/shipment.js +11 -0
- package/esm/utilities/tabs.js +51 -0
- package/esm/utilities/user.js +65 -0
- package/esm/utilities/variations.js +58 -0
- package/lib/Cart.d.ts +9 -0
- package/lib/Cart.js +69 -0
- package/lib/CartAlert.d.ts +3 -0
- package/lib/CartAlert.js +53 -0
- package/lib/CartHeader.d.ts +3 -0
- package/lib/CartHeader.js +37 -0
- package/lib/CartProvider.d.ts +236 -0
- package/lib/CartProvider.js +1107 -0
- package/lib/CartTotals.d.ts +7 -0
- package/lib/CartTotals.js +96 -0
- package/lib/assets/merchi-monster-loader.gif +0 -0
- package/lib/assets/merchi-swipe-outline.png +0 -0
- package/lib/assets/product-not-found.png +0 -0
- package/lib/assets/stripe-payment-secure.png +0 -0
- package/lib/buttons/Button.d.ts +11 -0
- package/lib/buttons/Button.js +31 -0
- package/lib/buttons/ButtonBack.d.ts +6 -0
- package/lib/buttons/ButtonBack.js +44 -0
- package/lib/buttons/ButtonClearCart.d.ts +3 -0
- package/lib/buttons/ButtonClearCart.js +24 -0
- package/lib/buttons/ButtonInvoiceDownload.d.ts +3 -0
- package/lib/buttons/ButtonInvoiceDownload.js +96 -0
- package/lib/buttons/ButtonNext.d.ts +3 -0
- package/lib/buttons/ButtonNext.js +48 -0
- package/lib/buttons/ButtonNextDynamic.d.ts +3 -0
- package/lib/buttons/ButtonNextDynamic.js +28 -0
- package/lib/buttons/ButtonOpenCartMerchiCartModal.d.ts +9 -0
- package/lib/buttons/ButtonOpenCartMerchiCartModal.js +57 -0
- package/lib/buttons/ButtonPay.d.ts +7 -0
- package/lib/buttons/ButtonPay.js +35 -0
- package/lib/buttons/ButtonShipmentTabNext.d.ts +2 -0
- package/lib/buttons/ButtonShipmentTabNext.js +37 -0
- package/lib/buttons/index.d.ts +7 -0
- package/lib/buttons/index.js +48 -0
- package/lib/components/Alert.d.ts +7 -0
- package/lib/components/Alert.js +34 -0
- package/lib/components/CartBody.d.ts +7 -0
- package/lib/components/CartBody.js +22 -0
- package/lib/components/CartClient.d.ts +4 -0
- package/lib/components/CartClient.js +71 -0
- package/lib/components/CartFooter.d.ts +6 -0
- package/lib/components/CartFooter.js +20 -0
- package/lib/components/CartItemRow.d.ts +7 -0
- package/lib/components/CartItemRow.js +236 -0
- package/lib/components/CartPaymentSettingsInvalid.d.ts +2 -0
- package/lib/components/CartPaymentSettingsInvalid.js +21 -0
- package/lib/components/CartShipment.d.ts +6 -0
- package/lib/components/CartShipment.js +59 -0
- package/lib/components/CartTabContent.d.ts +6 -0
- package/lib/components/CartTabContent.js +20 -0
- package/lib/components/CartTabPanel.d.ts +7 -0
- package/lib/components/CartTabPanel.js +31 -0
- package/lib/components/CartTableContainer.d.ts +6 -0
- package/lib/components/CartTableContainer.js +20 -0
- package/lib/components/CartTitle.d.ts +2 -0
- package/lib/components/CartTitle.js +34 -0
- package/lib/components/CartTotalsListGroup.d.ts +3 -0
- package/lib/components/CartTotalsListGroup.js +78 -0
- package/lib/components/Collapse.d.ts +3 -0
- package/lib/components/Collapse.js +40 -0
- package/lib/components/CustomCartProductForm.d.ts +18 -0
- package/lib/components/CustomCartProductForm.js +136 -0
- package/lib/components/CustomerCheckoutMethodTabs.d.ts +6 -0
- package/lib/components/CustomerCheckoutMethodTabs.js +103 -0
- package/lib/components/DiscountInputGroup.d.ts +2 -0
- package/lib/components/DiscountInputGroup.js +301 -0
- package/lib/components/LoadingTemplate.d.ts +7 -0
- package/lib/components/LoadingTemplate.js +30 -0
- package/lib/components/NoCartItems.d.ts +3 -0
- package/lib/components/NoCartItems.js +27 -0
- package/lib/components/ShipmentGroupCard.d.ts +7 -0
- package/lib/components/ShipmentGroupCard.js +215 -0
- package/lib/components/Table.d.ts +7 -0
- package/lib/components/Table.js +19 -0
- package/lib/components/containers.d.ts +14 -0
- package/lib/components/containers.js +40 -0
- package/lib/components/index.d.ts +18 -0
- package/lib/components/index.js +133 -0
- package/lib/components/product-form-sdk-externals.d.ts +46 -0
- package/lib/components/product-form-sdk-externals.js +43 -0
- package/lib/forms/FormNewCustomer.d.ts +4 -0
- package/lib/forms/FormNewCustomer.js +252 -0
- package/lib/forms/FormReturningCustomer.d.ts +3 -0
- package/lib/forms/FormReturningCustomer.js +173 -0
- package/lib/forms/FormShipmentAddressAndNotes.d.ts +15 -0
- package/lib/forms/FormShipmentAddressAndNotes.js +203 -0
- package/lib/forms/FormSquarePayment.d.ts +3 -0
- package/lib/forms/FormSquarePayment.js +27 -0
- package/lib/forms/FormStripePayment.d.ts +3 -0
- package/lib/forms/FormStripePayment.js +27 -0
- package/lib/forms/FormWhatsappCustomer.d.ts +3 -0
- package/lib/forms/FormWhatsappCustomer.js +261 -0
- package/lib/forms/InputAcceptUserTermsAndConditions.d.ts +7 -0
- package/lib/forms/InputAcceptUserTermsAndConditions.js +41 -0
- package/lib/forms/InputError.d.ts +8 -0
- package/lib/forms/InputError.js +24 -0
- package/lib/forms/InputSelect.d.ts +14 -0
- package/lib/forms/InputSelect.js +55 -0
- package/lib/forms/InputText.d.ts +12 -0
- package/lib/forms/InputText.js +63 -0
- package/lib/forms/InputsAddress.d.ts +11 -0
- package/lib/forms/InputsAddress.js +485 -0
- package/lib/forms/index.d.ts +8 -0
- package/lib/forms/index.js +63 -0
- package/lib/index.d.ts +13 -0
- package/lib/index.js +93 -0
- package/lib/modals.d.ts +17 -0
- package/lib/modals.js +59 -0
- package/lib/panels/PanelCartItems.d.ts +3 -0
- package/lib/panels/PanelCartItems.js +56 -0
- package/lib/panels/PanelCartShipment.d.ts +3 -0
- package/lib/panels/PanelCartShipment.js +72 -0
- package/lib/panels/PanelClearCart.d.ts +3 -0
- package/lib/panels/PanelClearCart.js +62 -0
- package/lib/panels/PanelClientCheckout.d.ts +3 -0
- package/lib/panels/PanelClientCheckout.js +88 -0
- package/lib/panels/PanelEditCartItem.d.ts +6 -0
- package/lib/panels/PanelEditCartItem.js +206 -0
- package/lib/panels/PanelPaymentSuccess.d.ts +3 -0
- package/lib/panels/PanelPaymentSuccess.js +69 -0
- package/lib/panels/index.d.ts +7 -0
- package/lib/panels/index.js +48 -0
- package/lib/square/SquareCard.d.ts +3 -0
- package/lib/square/SquareCard.js +114 -0
- package/lib/stripe/LegacyStripeCardForm.d.ts +3 -0
- package/lib/stripe/LegacyStripeCardForm.js +166 -0
- package/lib/stripe/StripeCardFields.d.ts +15 -0
- package/lib/stripe/StripeCardFields.js +135 -0
- package/lib/stripe/StripeCardForm.d.ts +2 -0
- package/lib/stripe/StripeCardForm.js +42 -0
- package/lib/stripe/StripePaymentButtons.d.ts +8 -0
- package/lib/stripe/StripePaymentButtons.js +106 -0
- package/lib/stripe/actions.d.ts +4 -0
- package/lib/stripe/actions.js +200 -0
- package/lib/stripe/utils.d.ts +18 -0
- package/lib/stripe/utils.js +27 -0
- package/lib/styles/globals.css +463 -0
- package/lib/styles/globals.css.map +1 -0
- package/lib/tabs/CartNav.d.ts +3 -0
- package/lib/tabs/CartNav.js +36 -0
- package/lib/tabs/NavTab.d.ts +9 -0
- package/lib/tabs/NavTab.js +39 -0
- package/lib/types/index.d.ts +13 -0
- package/lib/types/index.js +1 -0
- package/lib/utilities/address.d.ts +30 -0
- package/lib/utilities/address.js +468 -0
- package/lib/utilities/area.d.ts +77 -0
- package/lib/utilities/area.js +328 -0
- package/lib/utilities/cart.d.ts +9 -0
- package/lib/utilities/cart.js +108 -0
- package/lib/utilities/company.d.ts +2 -0
- package/lib/utilities/company.js +13 -0
- package/lib/utilities/cookie.d.ts +4 -0
- package/lib/utilities/cookie.js +165 -0
- package/lib/utilities/currency.d.ts +5 -0
- package/lib/utilities/currency.js +229 -0
- package/lib/utilities/customForm.d.ts +17 -0
- package/lib/utilities/customForm.js +64 -0
- package/lib/utilities/helpers.d.ts +24 -0
- package/lib/utilities/helpers.js +240 -0
- package/lib/utilities/index.d.ts +14 -0
- package/lib/utilities/index.js +159 -0
- package/lib/utilities/invoice.d.ts +3 -0
- package/lib/utilities/invoice.js +118 -0
- package/lib/utilities/job.d.ts +1 -0
- package/lib/utilities/job.js +15 -0
- package/lib/utilities/local_storage.d.ts +31 -0
- package/lib/utilities/local_storage.js +96 -0
- package/lib/utilities/product.d.ts +2 -0
- package/lib/utilities/product.js +21 -0
- package/lib/utilities/shipment.d.ts +2 -0
- package/lib/utilities/shipment.js +18 -0
- package/lib/utilities/tabs.d.ts +14 -0
- package/lib/utilities/tabs.js +60 -0
- package/lib/utilities/user.d.ts +5 -0
- package/lib/utilities/user.js +75 -0
- package/lib/utilities/variations.d.ts +18 -0
- package/lib/utilities/variations.js +66 -0
- package/package.json +109 -0
- package/src/Cart.tsx +96 -0
- package/src/CartAlert.tsx +35 -0
- package/src/CartHeader.tsx +28 -0
- package/src/CartProvider.tsx +992 -0
- package/src/CartTotals.tsx +102 -0
- package/src/assets/merchi-monster-loader.gif +0 -0
- package/src/assets/merchi-swipe-outline.png +0 -0
- package/src/assets/product-not-found.png +0 -0
- package/src/assets/stripe-payment-secure.png +0 -0
- package/src/buttons/Button.tsx +35 -0
- package/src/buttons/ButtonBack.tsx +42 -0
- package/src/buttons/ButtonClearCart.tsx +17 -0
- package/src/buttons/ButtonInvoiceDownload.tsx +60 -0
- package/src/buttons/ButtonNext.tsx +35 -0
- package/src/buttons/ButtonNextDynamic.tsx +31 -0
- package/src/buttons/ButtonOpenCartMerchiCartModal.tsx +61 -0
- package/src/buttons/ButtonPay.tsx +32 -0
- package/src/buttons/ButtonShipmentTabNext.tsx +24 -0
- package/src/buttons/index.ts +15 -0
- package/src/components/Alert.tsx +31 -0
- package/src/components/CartBody.tsx +16 -0
- package/src/components/CartClient.tsx +52 -0
- package/src/components/CartFooter.tsx +15 -0
- package/src/components/CartItemRow.tsx +212 -0
- package/src/components/CartPaymentSettingsInvalid.tsx +12 -0
- package/src/components/CartShipment.tsx +56 -0
- package/src/components/CartTabContent.tsx +15 -0
- package/src/components/CartTabPanel.tsx +25 -0
- package/src/components/CartTableContainer.tsx +15 -0
- package/src/components/CartTitle.tsx +22 -0
- package/src/components/CartTotalsListGroup.tsx +58 -0
- package/src/components/Collapse.tsx +23 -0
- package/src/components/CustomCartProductForm.tsx +123 -0
- package/src/components/CustomerCheckoutMethodTabs.tsx +106 -0
- package/src/components/DiscountInputGroup.tsx +160 -0
- package/src/components/LoadingTemplate.tsx +22 -0
- package/src/components/NoCartItems.tsx +20 -0
- package/src/components/ShipmentGroupCard.tsx +170 -0
- package/src/components/Table.tsx +15 -0
- package/src/components/containers.tsx +40 -0
- package/src/components/index.ts +38 -0
- package/src/components/product-form-sdk-externals.ts +67 -0
- package/src/forms/FormNewCustomer.tsx +170 -0
- package/src/forms/FormReturningCustomer.tsx +117 -0
- package/src/forms/FormShipmentAddressAndNotes.tsx +165 -0
- package/src/forms/FormSquarePayment.tsx +19 -0
- package/src/forms/FormStripePayment.tsx +19 -0
- package/src/forms/FormWhatsappCustomer.tsx +179 -0
- package/src/forms/InputAcceptUserTermsAndConditions.tsx +43 -0
- package/src/forms/InputError.tsx +23 -0
- package/src/forms/InputSelect.tsx +58 -0
- package/src/forms/InputText.tsx +56 -0
- package/src/forms/InputsAddress.tsx +438 -0
- package/src/forms/index.ts +18 -0
- package/src/index.ts +31 -0
- package/src/modals.tsx +65 -0
- package/src/panels/PanelCartItems.tsx +56 -0
- package/src/panels/PanelCartShipment.tsx +86 -0
- package/src/panels/PanelClearCart.tsx +50 -0
- package/src/panels/PanelClientCheckout.tsx +102 -0
- package/src/panels/PanelEditCartItem.tsx +172 -0
- package/src/panels/PanelPaymentSuccess.tsx +66 -0
- package/src/panels/index.ts +15 -0
- package/src/square/SquareCard.tsx +84 -0
- package/src/stripe/LegacyStripeCardForm.tsx +91 -0
- package/src/stripe/StripeCardFields.tsx +173 -0
- package/src/stripe/StripeCardForm.tsx +18 -0
- package/src/stripe/StripePaymentButtons.tsx +117 -0
- package/src/stripe/actions.ts +94 -0
- package/src/stripe/utils.ts +22 -0
- package/src/styles/globals.scss +475 -0
- package/src/tabs/CartNav.tsx +18 -0
- package/src/tabs/NavTab.tsx +36 -0
- package/src/types/assets.d.ts +4 -0
- package/src/types/index.ts +15 -0
- package/src/types/merchi_product_form/index.d.ts +1 -0
- package/src/types/merchi_sdk_ts/index.d.ts +1 -0
- package/src/types/react-redux/index.d.ts +0 -0
- package/src/utilities/address.ts +463 -0
- package/src/utilities/area.ts +359 -0
- package/src/utilities/cart.ts +80 -0
- package/src/utilities/company.ts +8 -0
- package/src/utilities/cookie.ts +58 -0
- package/src/utilities/currency.ts +216 -0
- package/src/utilities/customForm.ts +71 -0
- package/src/utilities/helpers.ts +213 -0
- package/src/utilities/index.ts +14 -0
- package/src/utilities/invoice.ts +60 -0
- package/src/utilities/job.ts +13 -0
- package/src/utilities/local_storage.ts +130 -0
- package/src/utilities/product.ts +14 -0
- package/src/utilities/shipment.ts +11 -0
- package/src/utilities/tabs.ts +38 -0
- package/src/utilities/user.ts +33 -0
- package/src/utilities/variations.ts +80 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useForm } from 'react-hook-form';
|
|
3
|
+
import InputAcceptUserTermsAndConditions from './InputAcceptUserTermsAndConditions';
|
|
4
|
+
import { Button } from '../buttons';
|
|
5
|
+
import InputSelect from './InputSelect';
|
|
6
|
+
import InputText from './InputText';
|
|
7
|
+
import { useCartContext } from '../CartProvider';
|
|
8
|
+
import { cartEmbed, phoneOptions } from '../utilities/helpers';
|
|
9
|
+
import InputError from './InputError';
|
|
10
|
+
import { createNewCustomer, makeUser } from '../utilities/user';
|
|
11
|
+
import { makeCart } from '../utilities/cart';
|
|
12
|
+
import { getCartCookieToken } from '../utilities/cookie';
|
|
13
|
+
import {
|
|
14
|
+
getSavedCheckoutCustomer,
|
|
15
|
+
saveCheckoutCustomer,
|
|
16
|
+
} from '../utilities/local_storage';
|
|
17
|
+
|
|
18
|
+
export const emailValidation = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]/i;
|
|
19
|
+
|
|
20
|
+
export function FormCustomerNew() {
|
|
21
|
+
const {
|
|
22
|
+
cart,
|
|
23
|
+
classNameBtnPrimary,
|
|
24
|
+
classNameCartFormGroup,
|
|
25
|
+
classNameCartFormGroupButton,
|
|
26
|
+
domainId,
|
|
27
|
+
setCart,
|
|
28
|
+
setCartClient,
|
|
29
|
+
showUserTermsAndConditions,
|
|
30
|
+
} = useCartContext();
|
|
31
|
+
const [loading, setLoading] = React.useState(false);
|
|
32
|
+
const [error, setError] = React.useState(({} as any));
|
|
33
|
+
const [acceptConditions, setAcceptConditions] = React.useState(true);
|
|
34
|
+
const savedCustomer = getSavedCheckoutCustomer(domainId);
|
|
35
|
+
|
|
36
|
+
async function actionCreateNewCustomer(customerJson: any) {
|
|
37
|
+
setError({});
|
|
38
|
+
setLoading(true);
|
|
39
|
+
try {
|
|
40
|
+
const r = await createNewCustomer(
|
|
41
|
+
{...customerJson, registeredUnderDomains: [{id: domainId}]}
|
|
42
|
+
);
|
|
43
|
+
const { user } = r;
|
|
44
|
+
if (!user?.id) {
|
|
45
|
+
throw new Error('Unable to create customer.');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// patch cart with new user
|
|
49
|
+
const cartToken = await getCartCookieToken((domainId as number));
|
|
50
|
+
const clientEnt = makeUser({id: user.id}, true);
|
|
51
|
+
const cartEnt = makeCart({ ...cart }, false, cartToken);
|
|
52
|
+
cartEnt.sendWhatsapp = false;
|
|
53
|
+
cartEnt.client = clientEnt;
|
|
54
|
+
const _cart = await cartEnt.save({embed: cartEmbed});
|
|
55
|
+
const cartJson = _cart.toJson();
|
|
56
|
+
if (!cartJson?.client?.id) {
|
|
57
|
+
throw new Error('Unable to attach client to cart.');
|
|
58
|
+
}
|
|
59
|
+
saveCheckoutCustomer(domainId, {
|
|
60
|
+
id: user.id,
|
|
61
|
+
name: customerJson.name,
|
|
62
|
+
emailAddress: customerJson.emailAddresses?.[0]?.emailAddress,
|
|
63
|
+
phoneNumbers: customerJson.phoneNumbers,
|
|
64
|
+
});
|
|
65
|
+
setCartClient(cartJson.client);
|
|
66
|
+
setCart(cartJson);
|
|
67
|
+
} catch (e: any) {
|
|
68
|
+
setError({message: e.errorMessage || e.message || 'Unable to attach client to cart.'});
|
|
69
|
+
} finally {
|
|
70
|
+
setLoading(false);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const { control, handleSubmit, watch } = useForm({
|
|
75
|
+
defaultValues: {
|
|
76
|
+
emailAddresses: [{
|
|
77
|
+
emailAddress: savedCustomer?.emailAddress || '',
|
|
78
|
+
}],
|
|
79
|
+
name: savedCustomer?.name || '',
|
|
80
|
+
phoneNumbers: [{
|
|
81
|
+
code: savedCustomer?.phoneNumbers?.[0]?.code || 'AU',
|
|
82
|
+
number: savedCustomer?.phoneNumbers?.[0]?.number || '',
|
|
83
|
+
}],
|
|
84
|
+
registeredAsGuest: false,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
async function onSubmit(values: any) {
|
|
89
|
+
await actionCreateNewCustomer({ ...values });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Basic validation for phone. Checking that phone is a number. Can make more complex if we want.
|
|
93
|
+
function validatePhone() {
|
|
94
|
+
const phone = watch('phoneNumbers.0.number');
|
|
95
|
+
if (isNaN(phone as any)) return 'Phone number must be a number';
|
|
96
|
+
else return true;
|
|
97
|
+
}
|
|
98
|
+
return (
|
|
99
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
100
|
+
<InputText
|
|
101
|
+
control={control}
|
|
102
|
+
label='Full Name'
|
|
103
|
+
name='name'
|
|
104
|
+
placeholder='John Smith'
|
|
105
|
+
rules={{ required: 'Full name is required.' }}
|
|
106
|
+
/>
|
|
107
|
+
<InputText
|
|
108
|
+
control={control}
|
|
109
|
+
label='Email'
|
|
110
|
+
name='emailAddresses[0].emailAddress'
|
|
111
|
+
placeholder='john@example.com'
|
|
112
|
+
rules={{
|
|
113
|
+
required: 'Email is required.',
|
|
114
|
+
validate: emailValidation,
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
<div style={{ display: 'flex', gap: '1rem' }}>
|
|
118
|
+
<div style={{ flexGrow: 1 }}>
|
|
119
|
+
<InputSelect
|
|
120
|
+
control={control}
|
|
121
|
+
label='Country Code'
|
|
122
|
+
name='phoneNumbers[0].code'
|
|
123
|
+
options={phoneOptions}
|
|
124
|
+
/>
|
|
125
|
+
</div>
|
|
126
|
+
<div style={{ flexGrow: 1 }}>
|
|
127
|
+
<InputText
|
|
128
|
+
control={control}
|
|
129
|
+
label='Phone Number'
|
|
130
|
+
name='phoneNumbers[0].number'
|
|
131
|
+
placeholder='0400 000 000'
|
|
132
|
+
rules={{
|
|
133
|
+
required: 'Phone number is required',
|
|
134
|
+
validate: validatePhone,
|
|
135
|
+
}}
|
|
136
|
+
type='phone'
|
|
137
|
+
/>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
{showUserTermsAndConditions && (
|
|
141
|
+
<div className={classNameCartFormGroup}>
|
|
142
|
+
<InputAcceptUserTermsAndConditions
|
|
143
|
+
isChecked={acceptConditions}
|
|
144
|
+
setIsChecked={setAcceptConditions}
|
|
145
|
+
/>
|
|
146
|
+
{!acceptConditions && (
|
|
147
|
+
<InputError
|
|
148
|
+
error={{
|
|
149
|
+
message:
|
|
150
|
+
'You must agree to the user profile terms and conditions to proceed.',
|
|
151
|
+
}}
|
|
152
|
+
/>
|
|
153
|
+
)}
|
|
154
|
+
</div>
|
|
155
|
+
)}
|
|
156
|
+
<InputError error={error || {}} />
|
|
157
|
+
<div className={classNameCartFormGroupButton}>
|
|
158
|
+
<Button
|
|
159
|
+
className={classNameBtnPrimary}
|
|
160
|
+
disabled={loading}
|
|
161
|
+
type='submit'
|
|
162
|
+
>
|
|
163
|
+
{loading ? 'Loading...' : 'Submit'}
|
|
164
|
+
</Button>
|
|
165
|
+
</div>
|
|
166
|
+
</form>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export default FormCustomerNew;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useForm } from 'react-hook-form';
|
|
3
|
+
import { Button } from '../buttons';
|
|
4
|
+
import InputError from './InputError';
|
|
5
|
+
import { useCartContext } from '../CartProvider';
|
|
6
|
+
import {
|
|
7
|
+
makeUser,
|
|
8
|
+
tryReturningCustomerEmail,
|
|
9
|
+
} from '../utilities/user';
|
|
10
|
+
import { makeCart } from '../utilities/cart';
|
|
11
|
+
import { getCartCookieToken } from '../utilities/cookie';
|
|
12
|
+
import { cartEmbed } from '../utilities/helpers';
|
|
13
|
+
import {
|
|
14
|
+
getSavedCheckoutCustomer,
|
|
15
|
+
saveCheckoutCustomer,
|
|
16
|
+
} from '../utilities/local_storage';
|
|
17
|
+
|
|
18
|
+
const emailValidation = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]/i;
|
|
19
|
+
|
|
20
|
+
function FormReturningCustomer() {
|
|
21
|
+
const {
|
|
22
|
+
alertError,
|
|
23
|
+
cart,
|
|
24
|
+
classNameBtnPrimary,
|
|
25
|
+
classNameCartFormGroup,
|
|
26
|
+
classNameCartFormInput,
|
|
27
|
+
classNameCartFormGroupButton,
|
|
28
|
+
domainId,
|
|
29
|
+
setCart,
|
|
30
|
+
setCartClient,
|
|
31
|
+
} = useCartContext();
|
|
32
|
+
const [loading, setLoading] = React.useState(false);
|
|
33
|
+
const [error, setError] = React.useState(({} as any));
|
|
34
|
+
const savedCustomer = getSavedCheckoutCustomer(domainId);
|
|
35
|
+
|
|
36
|
+
const hookForm = useForm({
|
|
37
|
+
defaultValues: { emailAddress: savedCustomer?.emailAddress || '' },
|
|
38
|
+
});
|
|
39
|
+
const {
|
|
40
|
+
handleSubmit,
|
|
41
|
+
formState: { errors },
|
|
42
|
+
getValues,
|
|
43
|
+
register,
|
|
44
|
+
} = hookForm;
|
|
45
|
+
async function submit() {
|
|
46
|
+
setError({});
|
|
47
|
+
const { emailAddress } = getValues();
|
|
48
|
+
setLoading(true);
|
|
49
|
+
try {
|
|
50
|
+
const user: any = await tryReturningCustomerEmail(emailAddress);
|
|
51
|
+
// /user-check-email/ returns user_id (not id)
|
|
52
|
+
const userId = user.user_id ?? user.id;
|
|
53
|
+
if (!userId) {
|
|
54
|
+
throw new Error('Unable to find returning customer.');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Attach by id only — extra user fields trigger a forbidden user PATCH.
|
|
58
|
+
const cartToken = await getCartCookieToken((domainId as number));
|
|
59
|
+
const clientEnt = makeUser({id: userId}, true);
|
|
60
|
+
const cartEnt = makeCart({ ...cart }, false, cartToken);
|
|
61
|
+
cartEnt.sendWhatsapp = false;
|
|
62
|
+
cartEnt.client = clientEnt;
|
|
63
|
+
const _cart = await cartEnt.save({embed: cartEmbed});
|
|
64
|
+
const cartJson = _cart.toJson();
|
|
65
|
+
if (!cartJson?.client?.id) {
|
|
66
|
+
throw new Error('Unable to attach client to cart.');
|
|
67
|
+
}
|
|
68
|
+
saveCheckoutCustomer(domainId, {
|
|
69
|
+
id: userId,
|
|
70
|
+
name: user.name || savedCustomer?.name,
|
|
71
|
+
emailAddress,
|
|
72
|
+
});
|
|
73
|
+
setCartClient(cartJson.client);
|
|
74
|
+
setCart(cartJson);
|
|
75
|
+
} catch(e: any) {
|
|
76
|
+
alertError(e.errorMessage || e.message);
|
|
77
|
+
setError({message: e.errorMessage || e.message || 'Server error.'});
|
|
78
|
+
} finally {
|
|
79
|
+
setLoading(false);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return (
|
|
83
|
+
<form onSubmit={handleSubmit(submit)}>
|
|
84
|
+
<div className={classNameCartFormGroup}>
|
|
85
|
+
<input
|
|
86
|
+
className={classNameCartFormInput}
|
|
87
|
+
placeholder='info@example.com'
|
|
88
|
+
type='email'
|
|
89
|
+
{...register('emailAddress', {
|
|
90
|
+
required: 'Email address required',
|
|
91
|
+
pattern: {
|
|
92
|
+
value: emailValidation,
|
|
93
|
+
message: 'Invalid email address'
|
|
94
|
+
}
|
|
95
|
+
})}
|
|
96
|
+
/>
|
|
97
|
+
<small>
|
|
98
|
+
If you are a returning customer please use the same email
|
|
99
|
+
which you used previously.
|
|
100
|
+
</small>
|
|
101
|
+
<InputError error={errors.emailAddress} />
|
|
102
|
+
{error && <InputError error={error} />}
|
|
103
|
+
</div>
|
|
104
|
+
<div className={classNameCartFormGroupButton}>
|
|
105
|
+
<Button
|
|
106
|
+
className={classNameBtnPrimary}
|
|
107
|
+
disabled={loading}
|
|
108
|
+
type='submit'
|
|
109
|
+
>
|
|
110
|
+
{loading ? 'Loading...' : 'Submit'}
|
|
111
|
+
</Button>
|
|
112
|
+
</div>
|
|
113
|
+
</form>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export default FormReturningCustomer;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { useForm } from "react-hook-form";
|
|
2
|
+
import InputsAddress from "./InputsAddress";
|
|
3
|
+
import { CheckoutContainer, InnerContainer } from "../components/containers";
|
|
4
|
+
import { Title } from "../components";
|
|
5
|
+
import { shipmentFormId } from "../utilities/shipment";
|
|
6
|
+
import { faMapMarkerAlt } from "@fortawesome/free-solid-svg-icons";
|
|
7
|
+
import { useCartContext } from "../CartProvider";
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { getCartCookieToken } from "../utilities/cookie";
|
|
10
|
+
import { makeAddress, sanitizeAddressFields } from "../utilities/address";
|
|
11
|
+
import { makeCart } from "../utilities/cart";
|
|
12
|
+
import { cartEmbed } from "../utilities/helpers";
|
|
13
|
+
import { tabIdCheckout } from "../utilities/tabs";
|
|
14
|
+
import {
|
|
15
|
+
addressHasContent,
|
|
16
|
+
getSavedCheckoutAddress,
|
|
17
|
+
saveCheckoutAddress,
|
|
18
|
+
} from "../utilities/local_storage";
|
|
19
|
+
|
|
20
|
+
interface PropsAddress {
|
|
21
|
+
defaultAddress?: any;
|
|
22
|
+
labelGeoSuggest?: string;
|
|
23
|
+
hookForm: any;
|
|
24
|
+
name?: string;
|
|
25
|
+
placeholder?: string;
|
|
26
|
+
updateAddress: (address: any) => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const AddressGeoSuggestInput = (props: PropsAddress) => (
|
|
30
|
+
<InputsAddress {...props} name="receiverAddress" />
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
interface Props {
|
|
34
|
+
address?: any;
|
|
35
|
+
addressFieldsOpen: boolean;
|
|
36
|
+
formId: string;
|
|
37
|
+
notes?: string;
|
|
38
|
+
showIcon?: boolean;
|
|
39
|
+
deliveryNomenclature?: boolean;
|
|
40
|
+
showHeadings?: boolean;
|
|
41
|
+
setCartShipmentAddress: (values: any) => void | Promise<void>;
|
|
42
|
+
toggleAddressFields: () => void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function FormShipmentAddressAndNotes({
|
|
46
|
+
address = {},
|
|
47
|
+
formId,
|
|
48
|
+
notes = "",
|
|
49
|
+
showIcon = true,
|
|
50
|
+
deliveryNomenclature = false,
|
|
51
|
+
showHeadings = true,
|
|
52
|
+
setCartShipmentAddress,
|
|
53
|
+
}: Props) {
|
|
54
|
+
const { classNameCartFormGroup, updateCartShipmentAddress } =
|
|
55
|
+
useCartContext();
|
|
56
|
+
const hookForm = useForm({
|
|
57
|
+
defaultValues: {
|
|
58
|
+
receiverAddress: address,
|
|
59
|
+
receiverNotes: notes,
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
const { getValues, handleSubmit, register, reset } = hookForm;
|
|
63
|
+
|
|
64
|
+
async function onSubmit() {
|
|
65
|
+
await setCartShipmentAddress(getValues());
|
|
66
|
+
}
|
|
67
|
+
function updateAddress(addr: any) {
|
|
68
|
+
const oldAddresses: any = getValues();
|
|
69
|
+
const newAddress = addr ? { ...addr } : {};
|
|
70
|
+
oldAddresses["receiverAddress"] = newAddress;
|
|
71
|
+
reset(oldAddresses);
|
|
72
|
+
updateCartShipmentAddress(newAddress);
|
|
73
|
+
}
|
|
74
|
+
return (
|
|
75
|
+
<form id={formId} onSubmit={handleSubmit(onSubmit)}>
|
|
76
|
+
{showHeadings && (
|
|
77
|
+
<CheckoutContainer>
|
|
78
|
+
<InnerContainer paddingBottom="0px">
|
|
79
|
+
<Title
|
|
80
|
+
icon={showIcon ? faMapMarkerAlt : null}
|
|
81
|
+
title="Delivery / billing address"
|
|
82
|
+
/>
|
|
83
|
+
</InnerContainer>
|
|
84
|
+
</CheckoutContainer>
|
|
85
|
+
)}
|
|
86
|
+
<AddressGeoSuggestInput
|
|
87
|
+
defaultAddress={address}
|
|
88
|
+
hookForm={hookForm}
|
|
89
|
+
labelGeoSuggest={`Enter your ${
|
|
90
|
+
deliveryNomenclature ? "delivery" : "shipping"
|
|
91
|
+
} address`}
|
|
92
|
+
name="receiverAddress"
|
|
93
|
+
updateAddress={updateAddress}
|
|
94
|
+
/>
|
|
95
|
+
<div className={classNameCartFormGroup}>
|
|
96
|
+
<label>{deliveryNomenclature ? "Delivery" : "Shipment"} notes</label>
|
|
97
|
+
<textarea
|
|
98
|
+
className="form-control input"
|
|
99
|
+
defaultValue={notes}
|
|
100
|
+
placeholder="Example - Leave at top of stairs"
|
|
101
|
+
rows={4}
|
|
102
|
+
{...register("receiverNotes")}
|
|
103
|
+
></textarea>
|
|
104
|
+
</div>
|
|
105
|
+
</form>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function ActiveFormShipmentAddressAndNotes() {
|
|
110
|
+
const {
|
|
111
|
+
alertError,
|
|
112
|
+
domainId,
|
|
113
|
+
cart,
|
|
114
|
+
setCart,
|
|
115
|
+
setLoadingTotals,
|
|
116
|
+
setActiveTabAndEditDisabled,
|
|
117
|
+
} = useCartContext();
|
|
118
|
+
const saved = getSavedCheckoutAddress(domainId);
|
|
119
|
+
const cartAddress = cart?.receiverAddress;
|
|
120
|
+
const receiverAddress = addressHasContent(cartAddress)
|
|
121
|
+
? cartAddress
|
|
122
|
+
: saved.address || {};
|
|
123
|
+
const receiverNotes = cart?.receiverNotes || saved.receiverNotes || "";
|
|
124
|
+
const [addressFieldsOpen, setAddressFieldsOpen] = useState(false);
|
|
125
|
+
|
|
126
|
+
async function saveCartShipmentAddressAndGoToNextTab(values: any) {
|
|
127
|
+
const { receiverAddress: address, receiverNotes } = values;
|
|
128
|
+
setLoadingTotals(true);
|
|
129
|
+
try {
|
|
130
|
+
const cartToken = await getCartCookieToken(domainId as number);
|
|
131
|
+
// Never PATCH an existing Address via cart token — create a fresh embed.
|
|
132
|
+
const addressFields = sanitizeAddressFields(address);
|
|
133
|
+
const receiverAddress = makeAddress(addressFields, true);
|
|
134
|
+
const cartEnt = makeCart(cart, false, cartToken);
|
|
135
|
+
cartEnt.receiverAddress = receiverAddress;
|
|
136
|
+
cartEnt.receiverNotes = receiverNotes;
|
|
137
|
+
await cartEnt.save({ embed: cartEmbed });
|
|
138
|
+
saveCheckoutAddress(domainId, addressFields, receiverNotes);
|
|
139
|
+
setCart(cartEnt.toJson());
|
|
140
|
+
setActiveTabAndEditDisabled({
|
|
141
|
+
tabId: tabIdCheckout,
|
|
142
|
+
tabIndexToSet: 2,
|
|
143
|
+
disabled: false,
|
|
144
|
+
});
|
|
145
|
+
} catch (e: any) {
|
|
146
|
+
alertError(
|
|
147
|
+
e.errorMessage || e.message || "Unable to set shipment address."
|
|
148
|
+
);
|
|
149
|
+
} finally {
|
|
150
|
+
setLoadingTotals(false);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return (
|
|
154
|
+
<FormShipmentAddressAndNotes
|
|
155
|
+
address={receiverAddress}
|
|
156
|
+
addressFieldsOpen={addressFieldsOpen}
|
|
157
|
+
formId={shipmentFormId}
|
|
158
|
+
notes={receiverNotes}
|
|
159
|
+
setCartShipmentAddress={saveCartShipmentAddressAndGoToNextTab}
|
|
160
|
+
toggleAddressFields={() => setAddressFieldsOpen(!addressFieldsOpen)}
|
|
161
|
+
/>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export default FormShipmentAddressAndNotes;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Suspense, lazy } from 'react';
|
|
3
|
+
import { useCartContext } from '../CartProvider';
|
|
4
|
+
import { LoadingTemplateSm } from '../components/LoadingTemplate';
|
|
5
|
+
|
|
6
|
+
const SquareCard = lazy(() => import('../square/SquareCard'));
|
|
7
|
+
|
|
8
|
+
function FormSquarePayment() {
|
|
9
|
+
const { cart } = useCartContext();
|
|
10
|
+
const company = cart && cart.domain && cart.domain.company;
|
|
11
|
+
if (!company?.acceptSquare) return null;
|
|
12
|
+
return (
|
|
13
|
+
<Suspense fallback={<LoadingTemplateSm />}>
|
|
14
|
+
<SquareCard />
|
|
15
|
+
</Suspense>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default FormSquarePayment;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Suspense, lazy } from 'react';
|
|
3
|
+
import { useCartContext } from '../CartProvider';
|
|
4
|
+
import { LoadingTemplateSm } from '../components/LoadingTemplate';
|
|
5
|
+
|
|
6
|
+
const StripeCardForm = lazy(() => import('../stripe/StripeCardForm'));
|
|
7
|
+
|
|
8
|
+
function FormStripePayment() {
|
|
9
|
+
const { cart } = useCartContext();
|
|
10
|
+
const company = cart && cart.domain && cart.domain.company;
|
|
11
|
+
if (!company) return null;
|
|
12
|
+
return (
|
|
13
|
+
<Suspense fallback={<LoadingTemplateSm />}>
|
|
14
|
+
<StripeCardForm />
|
|
15
|
+
</Suspense>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default FormStripePayment;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useForm } from 'react-hook-form';
|
|
3
|
+
import InputAcceptUserTermsAndConditions from './InputAcceptUserTermsAndConditions';
|
|
4
|
+
import { Button } from '../buttons';
|
|
5
|
+
import InputSelect from './InputSelect';
|
|
6
|
+
import InputText from './InputText';
|
|
7
|
+
import { useCartContext } from '../CartProvider';
|
|
8
|
+
import { cartEmbed, phoneOptions } from '../utilities/helpers';
|
|
9
|
+
import InputError from './InputError';
|
|
10
|
+
import { createNewCustomer, makeUser } from '../utilities/user';
|
|
11
|
+
import { makeCart } from '../utilities/cart';
|
|
12
|
+
import { getCartCookieToken } from '../utilities/cookie';
|
|
13
|
+
import {
|
|
14
|
+
getSavedCheckoutCustomer,
|
|
15
|
+
saveCheckoutCustomer,
|
|
16
|
+
} from '../utilities/local_storage';
|
|
17
|
+
import { emailValidation } from './FormNewCustomer';
|
|
18
|
+
|
|
19
|
+
function FormWhatsappCustomer() {
|
|
20
|
+
const {
|
|
21
|
+
cart,
|
|
22
|
+
classNameBtnPrimary,
|
|
23
|
+
classNameCartFormGroup,
|
|
24
|
+
classNameCartFormGroupButton,
|
|
25
|
+
domainId,
|
|
26
|
+
setCart,
|
|
27
|
+
setCartClient,
|
|
28
|
+
showUserTermsAndConditions,
|
|
29
|
+
} = useCartContext();
|
|
30
|
+
const [loading, setLoading] = React.useState(false);
|
|
31
|
+
const [error, setError] = React.useState(({} as any));
|
|
32
|
+
const [acceptConditions, setAcceptConditions] = React.useState(true);
|
|
33
|
+
const savedCustomer = getSavedCheckoutCustomer(domainId);
|
|
34
|
+
|
|
35
|
+
async function actionWhatsappCheckout(customerJson: any) {
|
|
36
|
+
setError({});
|
|
37
|
+
setLoading(true);
|
|
38
|
+
try {
|
|
39
|
+
const r = await createNewCustomer({
|
|
40
|
+
...customerJson,
|
|
41
|
+
registeredUnderDomains: [{ id: domainId }],
|
|
42
|
+
});
|
|
43
|
+
const { user } = r;
|
|
44
|
+
if (!user?.id) {
|
|
45
|
+
throw new Error('Unable to create customer.');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const cartToken = await getCartCookieToken((domainId as number));
|
|
49
|
+
const clientEnt = makeUser({ id: user.id }, true);
|
|
50
|
+
const cartEnt = makeCart({ ...cart }, false, cartToken);
|
|
51
|
+
cartEnt.sendWhatsapp = true;
|
|
52
|
+
cartEnt.client = clientEnt;
|
|
53
|
+
const _cart = await cartEnt.save({ embed: cartEmbed });
|
|
54
|
+
const cartJson = _cart.toJson();
|
|
55
|
+
if (!cartJson?.client?.id) {
|
|
56
|
+
throw new Error('Unable to attach client to cart.');
|
|
57
|
+
}
|
|
58
|
+
saveCheckoutCustomer(domainId, {
|
|
59
|
+
id: user.id,
|
|
60
|
+
name: customerJson.name,
|
|
61
|
+
emailAddress: customerJson.emailAddresses?.[0]?.emailAddress,
|
|
62
|
+
phoneNumbers: customerJson.phoneNumbers,
|
|
63
|
+
});
|
|
64
|
+
setCartClient(cartJson.client);
|
|
65
|
+
setCart(cartJson);
|
|
66
|
+
} catch (e: any) {
|
|
67
|
+
setError({
|
|
68
|
+
message:
|
|
69
|
+
e.errorMessage || e.message || 'Unable to attach client to cart.',
|
|
70
|
+
});
|
|
71
|
+
} finally {
|
|
72
|
+
setLoading(false);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const { control, handleSubmit, watch } = useForm({
|
|
77
|
+
defaultValues: {
|
|
78
|
+
emailAddresses: [{
|
|
79
|
+
emailAddress: savedCustomer?.emailAddress || '',
|
|
80
|
+
}],
|
|
81
|
+
name: savedCustomer?.name || '',
|
|
82
|
+
phoneNumbers: [{
|
|
83
|
+
code: savedCustomer?.phoneNumbers?.[0]?.code || 'AU',
|
|
84
|
+
number: savedCustomer?.phoneNumbers?.[0]?.number || '',
|
|
85
|
+
}],
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
async function onSubmit(values: any) {
|
|
90
|
+
if (showUserTermsAndConditions && !acceptConditions) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
await actionWhatsappCheckout({ ...values });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function validatePhone() {
|
|
97
|
+
const phone = watch('phoneNumbers.0.number');
|
|
98
|
+
if (!phone) return 'Phone number is required for WhatsApp checkout';
|
|
99
|
+
if (isNaN(phone as any)) return 'Phone number must be a number';
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
105
|
+
<InputText
|
|
106
|
+
control={control}
|
|
107
|
+
label='Full Name'
|
|
108
|
+
name='name'
|
|
109
|
+
placeholder='John Smith'
|
|
110
|
+
rules={{ required: 'Full name is required.' }}
|
|
111
|
+
/>
|
|
112
|
+
<InputText
|
|
113
|
+
control={control}
|
|
114
|
+
label='Email'
|
|
115
|
+
name='emailAddresses[0].emailAddress'
|
|
116
|
+
placeholder='john@example.com'
|
|
117
|
+
rules={{
|
|
118
|
+
required: 'Email is required.',
|
|
119
|
+
validate: emailValidation,
|
|
120
|
+
}}
|
|
121
|
+
/>
|
|
122
|
+
<div style={{ display: 'flex', gap: '1rem' }}>
|
|
123
|
+
<div style={{ flexGrow: 1 }}>
|
|
124
|
+
<InputSelect
|
|
125
|
+
control={control}
|
|
126
|
+
label='Country Code'
|
|
127
|
+
name='phoneNumbers[0].code'
|
|
128
|
+
options={phoneOptions}
|
|
129
|
+
/>
|
|
130
|
+
</div>
|
|
131
|
+
<div style={{ flexGrow: 1 }}>
|
|
132
|
+
<InputText
|
|
133
|
+
control={control}
|
|
134
|
+
label='WhatsApp Number'
|
|
135
|
+
name='phoneNumbers[0].number'
|
|
136
|
+
placeholder='0400 000 000'
|
|
137
|
+
rules={{
|
|
138
|
+
required: 'WhatsApp number is required',
|
|
139
|
+
validate: validatePhone,
|
|
140
|
+
}}
|
|
141
|
+
type='phone'
|
|
142
|
+
/>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
<small className={classNameCartFormGroup}>
|
|
146
|
+
By continuing, you agree to receive order updates via WhatsApp at this
|
|
147
|
+
number.
|
|
148
|
+
</small>
|
|
149
|
+
{showUserTermsAndConditions && (
|
|
150
|
+
<div className={classNameCartFormGroup}>
|
|
151
|
+
<InputAcceptUserTermsAndConditions
|
|
152
|
+
isChecked={acceptConditions}
|
|
153
|
+
setIsChecked={setAcceptConditions}
|
|
154
|
+
/>
|
|
155
|
+
{!acceptConditions && (
|
|
156
|
+
<InputError
|
|
157
|
+
error={{
|
|
158
|
+
message:
|
|
159
|
+
'You must agree to the user profile terms and conditions to proceed.',
|
|
160
|
+
}}
|
|
161
|
+
/>
|
|
162
|
+
)}
|
|
163
|
+
</div>
|
|
164
|
+
)}
|
|
165
|
+
<InputError error={error || {}} />
|
|
166
|
+
<div className={classNameCartFormGroupButton}>
|
|
167
|
+
<Button
|
|
168
|
+
className={classNameBtnPrimary}
|
|
169
|
+
disabled={loading}
|
|
170
|
+
type='submit'
|
|
171
|
+
>
|
|
172
|
+
{loading ? 'Loading...' : 'Continue with WhatsApp'}
|
|
173
|
+
</Button>
|
|
174
|
+
</div>
|
|
175
|
+
</form>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export default FormWhatsappCustomer;
|