From 38f3a79552f10e6712d2402475d44a70aba46e41 Mon Sep 17 00:00:00 2001 From: ArushKapoorJuspay <121166031+ArushKapoorJuspay@users.noreply.github.com> Date: Fri, 16 Feb 2024 13:55:49 +0530 Subject: [PATCH] fix: HS-132: Error handling for Address Fields (#171) Co-authored-by: Vrishab Srivatsa --- src/Components/BillingNamePaymentInput.res | 13 +++- src/Components/DynamicFields.res | 82 ++++++++++++++-------- src/Components/EmailPaymentInput.res | 13 +++- src/Components/FullNamePaymentInput.res | 15 +++- src/Utilities/DynamicFieldsUtils.res | 50 +++++++++++++ src/Utilities/Utils.res | 11 +++ 6 files changed, 146 insertions(+), 38 deletions(-) diff --git a/src/Components/BillingNamePaymentInput.res b/src/Components/BillingNamePaymentInput.res index 238fc0796..947583a45 100644 --- a/src/Components/BillingNamePaymentInput.res +++ b/src/Components/BillingNamePaymentInput.res @@ -19,9 +19,16 @@ let make = (~paymentType, ~customFieldName=None, ~optionalRequiredFields=None, ( let changeName = ev => { let val: string = ReactEvent.Form.target(ev)["value"] setBillingName(.prev => { - ...prev, value: val, - errorString: "", + isValid: Some(val !== ""), + errorString: val !== "" ? "" : prev.errorString, + }) + } + let onBlur = ev => { + let val: string = ReactEvent.Focus.target(ev)["value"] + setBillingName(.prev => { + ...prev, + isValid: Some(val !== ""), }) } let (placeholder, fieldName) = switch customFieldName { @@ -58,9 +65,11 @@ let make = (~paymentType, ~customFieldName=None, ~optionalRequiredFields=None, ( { - // let val = ReactEvent.Focus.target(ev)["value"] - // if !postalCode.isValid { - // setPostalCode(.prev => { - // ...prev, - // isValid: Some(false), - // errorString: "Invalid postal code", - // }) - // } - + let val: string = ReactEvent.Focus.target(ev)["value"] switch postalCode.isValid { - | Some(val) => - if !val { + | Some(bool) => + if !bool { setPostalCode(.prev => { ...prev, isValid: Some(false), - errorString: "Invalid postal code", }) } | None => setPostalCode(.prev => { ...prev, - isValid: Some(false), - errorString: "Invalid postal code", + isValid: Some(val !== ""), }) } // if regex !== "" && Js.Re.test_(regex->Js.Re.fromString, val) && val !== "" { @@ -283,6 +273,9 @@ let make = ( ~setRequiredFieldsBody, ) + let submitCallback = DynamicFieldsUtils.useSubmitCallback() + Utils.submitPaymentData(submitCallback) + let bottomElement = let getCustomFieldName = (item: PaymentMethodsRecord.paymentMethodsFields) => { @@ -540,15 +533,21 @@ let make = (
{ + let value = ReactEvent.Form.target(ev)["value"] + setCity(.prev => { + isValid: value !== "" ? Some(true) : Some(false), + value, + errorString: value !== "" ? "" : prev.errorString, + }) + }} + onBlur={ev => { + let value = ReactEvent.Focus.target(ev)["value"] setCity(.prev => { ...prev, - isValid: ReactEvent.Form.target(ev)["value"] !== "" - ? Some(true) - : Some(false), - value: ReactEvent.Form.target(ev)["value"], + isValid: Some(value !== ""), }) }} paymentType @@ -598,15 +597,21 @@ let make = ( | AddressLine1 => { + let value = ReactEvent.Form.target(ev)["value"] + setLine1(.prev => { + isValid: value !== "" ? Some(true) : Some(false), + value, + errorString: value !== "" ? "" : prev.errorString, + }) + }} + onBlur={ev => { + let value = ReactEvent.Focus.target(ev)["value"] setLine1(.prev => { ...prev, - isValid: ReactEvent.Form.target(ev)["value"] !== "" - ? Some(true) - : Some(false), - value: ReactEvent.Form.target(ev)["value"], + isValid: Some(value !== ""), }) }} paymentType @@ -618,15 +623,21 @@ let make = ( | AddressLine2 => { + let value = ReactEvent.Form.target(ev)["value"] + setLine2(.prev => { + isValid: value !== "" ? Some(true) : Some(false), + value, + errorString: value !== "" ? "" : prev.errorString, + }) + }} + onBlur={ev => { + let value = ReactEvent.Focus.target(ev)["value"] setLine2(.prev => { ...prev, - isValid: ReactEvent.Form.target(ev)["value"] !== "" - ? Some(true) - : Some(false), - value: ReactEvent.Form.target(ev)["value"], + isValid: Some(value !== ""), }) }} paymentType @@ -641,9 +652,18 @@ let make = ( setValue={setCity} value=city onChange={ev => { + let value = ReactEvent.Form.target(ev)["value"] + setCity(.prev => { + isValid: value !== "" ? Some(true) : Some(false), + value, + errorString: value !== "" ? "" : prev.errorString, + }) + }} + onBlur={ev => { + let value = ReactEvent.Focus.target(ev)["value"] setCity(.prev => { ...prev, - value: ReactEvent.Form.target(ev)["value"], + isValid: Some(value !== ""), }) }} paymentType @@ -670,7 +690,7 @@ let make = ( | AddressPincode => { let changeEmail = ev => { let val: string = ReactEvent.Form.target(ev)["value"] setEmail(.prev => { - ...prev, value: val, + isValid: val->Utils.isEmailValid, + errorString: val->Utils.isEmailValid->Belt.Option.getWithDefault(false) + ? "" + : prev.errorString, }) } - let onBlur = _ => { - Utils.checkEmailValid(email, setEmail) + let onBlur = ev => { + let val = ReactEvent.Focus.target(ev)["value"] + setEmail(.prev => { + ...prev, + isValid: val->Utils.isEmailValid, + }) } React.useEffect1(() => { diff --git a/src/Components/FullNamePaymentInput.res b/src/Components/FullNamePaymentInput.res index 34c221abc..2a277a617 100644 --- a/src/Components/FullNamePaymentInput.res +++ b/src/Components/FullNamePaymentInput.res @@ -15,11 +15,20 @@ let make = (~paymentType, ~customFieldName=None, ~optionalRequiredFields=None) = let changeName = ev => { let val: string = ReactEvent.Form.target(ev)["value"] setFullName(.prev => { - ...prev, value: val, - errorString: "", + isValid: Some(val !== ""), + errorString: val !== "" ? "" : prev.errorString, }) } + + let onBlur = ev => { + let val: string = ReactEvent.Focus.target(ev)["value"] + setFullName(.prev => { + ...prev, + isValid: Some(val !== ""), + }) + } + let (placeholder, fieldName) = switch customFieldName { | Some(val) => (val, val) | None => (localeString.fullNamePlaceholder, localeString.fullNameLabel) @@ -54,9 +63,11 @@ let make = (~paymentType, ~customFieldName=None, ~optionalRequiredFields=None) = combineCardExpiryMonthAndYear ->combineCardExpiryAndCvc } + +let useSubmitCallback = () => { + let logger = Recoil.useRecoilValueFromAtom(RecoilAtoms.loggerAtom) + let (line1, setLine1) = Recoil.useLoggedRecoilState(RecoilAtoms.userAddressline1, "line1", logger) + let (line2, setLine2) = Recoil.useLoggedRecoilState(RecoilAtoms.userAddressline2, "line2", logger) + let (state, setState) = Recoil.useLoggedRecoilState(RecoilAtoms.userAddressState, "state", logger) + let (postalCode, setPostalCode) = Recoil.useLoggedRecoilState( + RecoilAtoms.userAddressPincode, + "postal_code", + logger, + ) + let (city, setCity) = Recoil.useLoggedRecoilState(RecoilAtoms.userAddressCity, "city", logger) + + React.useCallback5((ev: Window.event) => { + let json = ev.data->Js.Json.parseExn + let confirm = json->Utils.getDictFromJson->ConfirmType.itemToObjMapper + if confirm.doSubmit { + if line1.value == "" { + setLine1(.prev => { + ...prev, + errorString: "Address line 1 cannot be empty", + }) + } + if line2.value == "" { + setLine2(.prev => { + ...prev, + errorString: "Address line 2 cannot be empty", + }) + } + if state.value == "" { + setState(.prev => { + ...prev, + errorString: "State cannot be empty", + }) + } + if postalCode.value == "" { + setPostalCode(.prev => { + ...prev, + errorString: "Postal code cannot be empty", + }) + } + if city.value == "" { + setCity(.prev => { + ...prev, + errorString: "City cannot be empty", + }) + } + } + }, (line1, line2, state, city, postalCode)) +} diff --git a/src/Utilities/Utils.res b/src/Utilities/Utils.res index b43f88a23..f80541cb5 100644 --- a/src/Utilities/Utils.res +++ b/src/Utilities/Utils.res @@ -353,6 +353,17 @@ let removeDuplicate = arr => { }) } +let isEmailValid = email => { + switch email->Js.String2.match_( + %re( + "/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/" + ), + ) { + | Some(_match) => Some(true) + | None => email->Js.String2.length > 0 ? Some(false) : None + } +} + let checkEmailValid = ( email: RecoilAtomTypes.field, fn: (. RecoilAtomTypes.field => RecoilAtomTypes.field) => unit,