Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions src/components/common/CustomAccordionView.res
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,12 @@ let make = (
let (accountPaymentMethodData, customerPaymentMethodData, _) = React.useContext(
AllApiDataContextNew.allApiDataContext,
)
let {getRequiredFieldsForButton, setInitialValueCountry, setSheetType} = React.useContext(
DynamicFieldsContext.dynamicFieldsContext,
)
let layout = nativeProp.configuration.paymentMethodLayout

let defaultCollapsed = layout.defaultCollapsed
let defaultCollapsed = layout.layoutType === LayoutTypes.Catalog || layout.defaultCollapsed
let maxVisibleItems = layout.maxAccordionItems
let showRadios = layout.radios

Expand All @@ -151,7 +154,7 @@ let make = (
->Option.map(c => c.customer_payment_methods->Array.length > 0)
->Option.getOr(false)

if hasData && expandedSections->Array.length === 0 {
if layout.layoutType !== Catalog && hasData && expandedSections->Array.length === 0 {
let expandIndex = switch layout.savedMethodCustomization.defaultCollapsed
? None
: switch hocComponentArr->Array.findIndex(hoc => hoc.name === "Saved") {
Expand All @@ -177,7 +180,7 @@ let make = (

let emitter = PaymentEvents.usePaymentEventEmitter()

let handleSectionToggle = (sectionKey: int) => {
let toggleSection = (sectionKey: int) => {
setExpandedSections(prevExpanded => {
if allowMultipleExpanded {
if prevExpanded->Array.includes(sectionKey) {
Expand All @@ -193,6 +196,31 @@ let make = (
})
}

let handleSectionToggle = (sectionKey: int) => {
let catalogHoc =
layout.layoutType === LayoutTypes.Catalog ? hocComponentArr->Array.get(sectionKey) : None

switch catalogHoc {
| Some(hoc) if hoc.name === "Saved" => setSheetType(DynamicFieldsContext.SavedMethodsSheet)
| Some(hoc) =>
switch hoc.paymentMethodData {
| Some(paymentMethodData) =>
let (_, _, defaultCountry) = getRequiredFieldsForButton(
~forceSheet=true,
paymentMethodData,
Dict.make(),
None,
None,
true,
None,
)
setInitialValueCountry(defaultCountry)
| None => toggleSection(sectionKey)
}
| None => toggleSection(sectionKey)
}
}

React.useEffect1(() => {
onAllCollapsed(expandedSections->Array.length === 0)
None
Expand Down
2 changes: 1 addition & 1 deletion src/components/common/CustomView.res
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ module Wrapper = {
})

let contentStyle = s({
minHeight: 250.->dp,
minHeight: 100.->dp,
paddingHorizontal: sheetContentPadding->dp,
paddingTop: sheetContentPadding->dp,
// paddingBottom: viewPortContants.bottomInset->dp,
Expand Down
70 changes: 21 additions & 49 deletions src/components/dynamic/DynamicComponent.res
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ let make = (~setConfirmButtonData) => {
getRequiredFieldsForButton,
country,
setInitialValueCountry,
eligibilityStatus,
} = React.useContext(DynamicFieldsContext.dynamicFieldsContext)

let {
Expand All @@ -28,15 +29,14 @@ let make = (~setConfirmButtonData) => {
useIntentData,
} = walletData
let payment_method = paymentMethodData.payment_method
let payment_method_str = paymentMethodData.payment_method_str
let payment_method_type = paymentMethodData.payment_method_type
let payment_method_type_wallet = paymentMethodData.payment_method_type_wallet
let payment_experience = paymentMethodData.payment_experience

let {sheetContentPadding} = ThemebasedStyle.useThemeBasedStyle()
let redirectHook = AllPaymentHooks.useRedirectHook()
let handleSuccessFailure = AllPaymentHooks.useHandleSuccessFailure()
let notifyValidationFailure = UseWidgetActions.useNotifyValidationFailure()
let checkEligibility = EligibilityHook.useCheckEligibility(~paymentMethodData)

let (formData, setFormDataState) = React.useState(_ => Dict.make())

Expand Down Expand Up @@ -104,53 +104,20 @@ let make = (~setConfirmButtonData) => {
}
}

let paymentMethodDataDict = switch payment_method {
| CARD =>
switch nickname {
| Some(name) =>
[
(
"payment_method_data",
[
(
payment_method_str,
[("nick_name", name->Js.Json.string)]->Dict.fromArray->Js.Json.object_,
),
]
->Dict.fromArray
->Js.Json.object_,
),
]->Dict.fromArray
| None => Dict.make()
}
| pm =>
[
(
"payment_method_data",
[
(
payment_method_str,
[
(
payment_method_type ++ (
pm === PAY_LATER || payment_method_type_wallet === PAYPAL ? "_redirect" : ""
),
walletDict->Option.getOr(Dict.make())->Js.Json.object_,
),
]
->Dict.fromArray
->Js.Json.object_,
),
]
->Dict.fromArray
->Js.Json.object_,
),
]->Dict.fromArray
}
let (
paymentMethodDataDict,
tabDict,
paymentMethodStr,
) = PaymentUtils.getPaymentMethodDataForConfirm(
~paymentMethodData,
~nickname,
~walletDict,
~tabDict,
)

let body = PaymentUtils.generateCardConfirmBody(
~nativeProp,
~payment_method_str,
~payment_method_str=paymentMethodStr,
~payment_method_type,
~payment_method_data=?CommonUtils.mergeDict(paymentMethodDataDict, tabDict)->Dict.get(
"payment_method_data",
Expand Down Expand Up @@ -193,7 +160,11 @@ let make = (~setConfirmButtonData) => {
}

let handlePress = _ => {
if isFormValid || missingRequiredFields->Array.length === 0 {
// Only gate on eligibility for card payments; non-card methods skip the check
let isEligibilityBlocked = isCardPayment && eligibilityStatus !== DynamicFieldsContext.Allowed
if isEligibilityBlocked {
()
} else if isFormValid || missingRequiredFields->Array.length === 0 {
processRequest(
CommonUtils.mergeDict(initialValues, formData),
Some(walletDict),
Expand All @@ -215,7 +186,7 @@ let make = (~setConfirmButtonData) => {
~isPristine,
)

React.useEffect3(() => {
React.useEffect4(() => {
let confirmButton = {
GlobalConfirmButton.loading: false,
handlePress,
Expand All @@ -226,7 +197,7 @@ let make = (~setConfirmButtonData) => {
setConfirmButtonData(confirmButton)

None
}, (walletData, isFormValid, formData))
}, (walletData, isFormValid, formData, eligibilityStatus))

<ReactNative.View
style={ReactNative.Style.s({paddingVertical: sheetContentPadding->ReactNative.Style.dp})}>
Expand All @@ -241,6 +212,7 @@ let make = (~setConfirmButtonData) => {
isCardPayment
enabledCardSchemes
accessible=true
checkEligibility
/>
</ReactNative.View>
}
5 changes: 4 additions & 1 deletion src/components/dynamic/DynamicFields.res
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ let make = (
setNickname,
setIsNicknameValid,
sheetType,
walletData,
} = React.useContext(DynamicFieldsContext.dynamicFieldsContext)
let localeObject = GetLocale.useGetLocalObj()

Expand Down Expand Up @@ -95,7 +96,9 @@ let make = (
<Space height=10. />
</UIUtils.RenderIf>
<UIUtils.RenderIf
condition={!isCardPayment && !isGiftCardPayment && sheetType !== DynamicFieldsSheet}>
condition={!isCardPayment &&
!isGiftCardPayment &&
(sheetType !== DynamicFieldsSheet || walletData.paymentMethodData.payment_method !== WALLET)}>
<UIUtils.RenderIf
condition={fields->Array.length == 0 &&
nativeProp.configuration.paymentMethodLayout.layoutType === Tabs}>
Expand Down
1 change: 0 additions & 1 deletion src/components/elements/ModalHeader.res
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ let make = (~onModalClose, ~isLoading=false, ~isSavedPaymentScreen) => {
<View
style={s({
display: #flex,
flexGrow: ?(ReactNative.Platform.os !== #web ? Some(1.) : None),
flexDirection: #row,
alignItems: #center,
justifyContent: #"space-between",
Expand Down
13 changes: 10 additions & 3 deletions src/contexts/DynamicFieldsContext.res
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type walletDataRecord = {
useIntentData: bool,
}

type sheetType = ButtonSheet | DynamicFieldsSheet
type sheetType = ButtonSheet | DynamicFieldsSheet | SavedMethodsSheet

type eligibilityStatus = Denied | Allowed | Pending

Expand All @@ -31,6 +31,7 @@ type dynamicFieldsData = {
string,
),
getRequiredFieldsForButton: (
~forceSheet: bool=?,
AccountPaymentMethodType.payment_method_type,
RescriptCore.Dict.t<Core__JSON.t>,
option<SdkTypes.addressDetails>,
Expand All @@ -57,7 +58,7 @@ let dynamicFieldsContext = React.createContext({
sheetType: ButtonSheet,
setSheetType: _ => (),
getRequiredFieldsForTabs: (_, _, _) => ([], Dict.make(), false, [], false, ""),
getRequiredFieldsForButton: (_, _, _, _, _, _) => (true, Dict.make(), ""),
getRequiredFieldsForButton: (~forceSheet as _=?, _, _, _, _, _, _) => (true, Dict.make(), ""),
country: SdkTypes.defaultCountry,
setCountry: _ => (),
setInitialValueCountry: _ => (),
Expand Down Expand Up @@ -107,6 +108,11 @@ let make = (~children) => {
setSheetType(_ => val)
}, [setSheetType])

React.useEffect0(() => {
let cleanup = NativeEventListener.setupOnBackListener(~onBack=() => setSheetType(ButtonSheet))
Some(cleanup)
})

let (country, setCountry) = React.useState(_ => None)
let (initialValueCountry, setInitialValueCountry) = React.useState(_ =>
nativeProp.sdkParams.country
Expand Down Expand Up @@ -258,6 +264,7 @@ let make = (~children) => {
)

let getRequiredFieldsForButton = (
~forceSheet=false,
paymentMethodData: AccountPaymentMethodType.payment_method_type,
walletDict,
billingAddress,
Expand Down Expand Up @@ -342,7 +349,7 @@ let make = (~children) => {

let isFieldsMissing = missingRequiredFields->Array.length > 0

if isFieldsMissing {
if isFieldsMissing || forceSheet {
setWalletData(
~missingRequiredFields,
~initialValues=switch formData {
Expand Down
6 changes: 6 additions & 0 deletions src/hooks/AllApiDataModifier.res
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type hoc = {
name: string,
paymentMethodType: string,
componentHoc: componentHoc,
paymentMethodData: option<AccountPaymentMethodType.payment_method_type>,
}

type walletProp = {
Expand Down Expand Up @@ -42,6 +43,7 @@ let useAccountPaymentMethodModifier = () => {
paymentMethodType: "saved_payment_method",
componentHoc: (~isScreenFocus as _, ~setConfirmButtonData as _) =>
<InitialLoader />,
paymentMethodData: None,
},
],
[],
Expand Down Expand Up @@ -73,6 +75,7 @@ let useAccountPaymentMethodModifier = () => {
animated=true
style={ReactNative.Style.s({marginBottom: 10.->ReactNative.Style.dp})}
/>,
paymentMethodData: None,
},
]
: [],
Expand Down Expand Up @@ -196,6 +199,7 @@ let useAccountPaymentMethodModifier = () => {
/>
: (~isScreenFocus, ~setConfirmButtonData) =>
<PaymentMethod isScreenFocus paymentMethodData setConfirmButtonData />,
paymentMethodData: isGroupByPMCard ? None : Some(paymentMethodData),
})

| TabSheet | WidgetTabSheet =>
Expand All @@ -209,6 +213,7 @@ let useAccountPaymentMethodModifier = () => {
/>
: (~isScreenFocus, ~setConfirmButtonData) =>
<PaymentMethod isScreenFocus paymentMethodData setConfirmButtonData />,
paymentMethodData: isGroupByPMCard ? None : Some(paymentMethodData),
})
| ButtonSheet | WidgetButtonSheet =>
elementArr->Array.push(
Expand Down Expand Up @@ -236,6 +241,7 @@ let useAccountPaymentMethodModifier = () => {
<CustomLoader />
<Space height=20. />
</>,
paymentMethodData: None,
}

switch nativeProp.sdkState {
Expand Down
60 changes: 60 additions & 0 deletions src/hooks/EligibilityHook.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
let useCheckEligibility = (~paymentMethodData: AccountPaymentMethodType.payment_method_type) => {
let (accountPaymentMethodData, _, _) = React.useContext(AllApiDataContextNew.allApiDataContext)
let {setEligibilityStatus} = React.useContext(DynamicFieldsContext.dynamicFieldsContext)
let callEligibilityCheck = AllPaymentHooks.useEligibilityCheckHook()

(cardNumberOpt: option<string>) => {
switch cardNumberOpt {
| None => setEligibilityStatus(_ => Allowed)
| Some(cardNumber) =>
let shouldCheck =
accountPaymentMethodData
->Option.flatMap(d => d.sdk_next_action)
->Option.mapOr(false, action => action == "eligibility_check")

if shouldCheck {
setEligibilityStatus(_ => Pending)
let pmData =
[
(
paymentMethodData.payment_method_str,
[("card_number", cardNumber->JSON.Encode.string)]
->Dict.fromArray
->JSON.Encode.object,
),
]
->Dict.fromArray
->JSON.Encode.object
callEligibilityCheck(
~paymentMethodType=paymentMethodData.payment_method_str,
~paymentMethodData=pmData,
)
->Promise.then(json => {
let nextActionJson =
json
->Utils.getDictFromJson
->Utils.getOptionalObj("sdk_next_action")
->Option.flatMap(d => d->Dict.get("next_action"))
let isDenied = switch nextActionJson {
| Some(json) =>
switch JSON.Decode.string(json) {
| Some("deny") => true
| Some(_) => false
| None => json->Utils.getDictFromJson->Dict.get("deny")->Option.isSome
}
| None => false
}
setEligibilityStatus(_ => isDenied ? Denied : Allowed)
Promise.resolve()
})
->Promise.catch(_ => {
setEligibilityStatus(_ => Allowed)
Promise.resolve()
})
->ignore
} else {
setEligibilityStatus(_ => Allowed)
}
}
}
}
Loading
Loading