Skip to content

Conversation

@sakksham7
Copy link
Contributor

@sakksham7 sakksham7 commented Aug 17, 2025

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

Added a parameter inside layout object, named as savedMethodsLayout, it is an object having structure as

savedMethodsLayout : {
      displayMergedSavedMethods: bool,
      maxSavedItems: int,
    },

based upon which if there are saved payment methods and displayMergedSavedMethods is passed as true then instead of coming on a separate saved payment methods screen, it will come in either tabs flow or accordion flow depending upon the layout.
maxSavedItems is used to configure how many saved methods we want to show initially and then the rest can be shown after clicking on show more.

Screen.Recording.2025-08-26.at.4.47.04.PM.mov

How did you test it?

Tested the following cases for both Accordion view and Tabs View :-

  • When saved payment methods are present

  • displaySavedPaymentMethods is false, displayMergedSavedMethods is false or true No saved payment methods tab

  • displaySavedPaymentMethods is true, displayMergedSavedMethods is false Normal flow Saved payment methods screen

  • displaySavedPaymentMethods is true, displayMergedSavedMethods is true Saved payment methods in tabs or accordion

  • When No saved payment methods are present

  • each case will have no saved payment methods

Checklist

  • I ran npm run re:build
  • I reviewed submitted code
  • I added unit tests for my changes where possible

@sakksham7 sakksham7 self-assigned this Aug 17, 2025
@sakksham7 sakksham7 added the Ready for Review PR with label Ready for Review should only be reviewed. label Aug 17, 2025
@semanticdiff-com
Copy link

Review changes with  SemanticDiff

@sakksham7 sakksham7 changed the title feat: unified view for saved payment methods screen and payment metho… feat: unified view for saved and more payment methods screen Aug 17, 2025
aritro2002
aritro2002 previously approved these changes Aug 20, 2025
@vsrivatsa-edinburgh
Copy link
Contributor

Hmm. Quite confusing experience. If “Saved” implies all (saved) payment methods, why should it have a card icon. Right next it to is “Cards” with a card icon again. Worth revisiting

@sakksham7
Copy link
Contributor Author

Hmm. Quite confusing experience. If “Saved” implies all (saved) payment methods, why should it have a card icon. Right next it to is “Cards” with a card icon again. Worth revisiting

Thanks for pointing this out, we’ll revisit the icons.

aritro2002
aritro2002 previously approved these changes Aug 28, 2025
@github-actions
Copy link
Contributor

🚫 Missing Linked Issue

Hi 👋 This pull request does not appear to be linked to any open issue yet.

Linking your PR to an issue helps keep the project tidy and ensures the issue is closed automatically.

✔️ How to fix this

  • Add a keyword like Fixes #123 or Closes #456 to your PR description or a commit message.
  • Or link it manually using the "Linked issues" panel in the PR sidebar.

Tip: You can link multiple issues.
🚫 Note: If only one issue is linked, it must be open for this check to pass.

Once linked, this check will pass automatically on your next push or when you re-run the workflow.

Thanks for helping maintainers! 🙌

@github-actions
Copy link
Contributor

🚫 Missing Linked Issue

Hi 👋 This pull request does not appear to be linked to any open issue yet.

Linking your PR to an issue helps keep the project tidy and ensures the issue is closed automatically.

✔️ How to fix this

  • Add a keyword like Fixes #123 or Closes #456 to your PR description or a commit message.
  • Or link it manually using the "Linked issues" panel in the PR sidebar.

Tip: You can link multiple issues.
🚫 Note: If only one issue is linked, it must be open for this check to pass.

Once linked, this check will pass automatically on your next push or when you re-run the workflow.

Thanks for helping maintainers! 🙌

Comment on lines 79 to 112
let renderSavedCards = (cardsArr: array<PaymentType.customerMethods>) => {
cardsArr
->Array.mapWithIndex((obj, i) =>
<SavedCardItem
key={i->Int.toString}
setPaymentToken
isActive={paymentTokenVal == obj.paymentToken}
paymentItem=obj
brandIcon={obj->getPaymentMethodBrand}
index=i
savedCardlength
cvcProps
setRequiredFieldsBody
/>
)
->React.array
}

let clickToPayElement = {
<RenderIf condition={clickToPayConfig.isReady == Some(true)}>
<ClickToPayAuthenticate
loggerState
savedMethods
isClickToPayAuthenticateError
setIsClickToPayAuthenticateError
setPaymentToken
paymentTokenVal
cvcProps
getVisaCards
setIsClickToPayRememberMe
closeComponentIfSavedMethodsAreEmpty
/>
</RenderIf>
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a react component

Comment on lines 382 to 388
{if enableSavedPaymentShimmer {
<PaymentElementShimmer.SavedPaymentCardShimmer />
} else {
<RenderIf condition={!showPaymentMethodsScreen}> {bottomElement} </RenderIf>
<RenderIf condition={!showPaymentMethodsScreen}>
{displayMergedSavedMethods ? mergedViewBottomElement : bottomElement}
</RenderIf>
}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try this

<RenderIf condition={enableSavedPaymentShimmer}>
  <PaymentElementShimmer.SavedPaymentCardShimmer />
</RenderIf>

<RenderIf condition={!enableSavedPaymentShimmer && !showPaymentMethodsScreen}>
  {displayMergedSavedMethods ? mergedViewBottomElement : bottomElement}
</RenderIf>

Comment on lines 114 to 132
let mergedViewBottomElement = {
<div
className="PickerItemContainer" tabIndex={0} role="region" ariaLabel="Saved payment methods">
{renderSavedCards(cardOptionDetails)}
<div
className={`transition-all duration-300 ease-in-out overflow-hidden
${showMore ? "max-h-0 opacity-0" : "max-h-screen opacity-100"}
`}>
{renderSavedCards(dropDownOptionsDetails)}
</div>
clickToPayElement
</div>
}

let bottomElement = {
<div
className="PickerItemContainer" tabIndex={0} role="region" ariaLabel="Saved payment methods">
{savedMethods
->Array.mapWithIndex((obj, i) =>
<SavedCardItem
key={i->Int.toString}
setPaymentToken
isActive={paymentTokenVal == obj.paymentToken}
paymentItem=obj
brandIcon={obj->getPaymentMethodBrand}
index=i
savedCardlength
cvcProps
setRequiredFieldsBody
/>
)
->React.array}
<RenderIf condition={clickToPayConfig.isReady == Some(true)}>
<ClickToPayAuthenticate
loggerState
savedMethods
isClickToPayAuthenticateError
setIsClickToPayAuthenticateError
setPaymentToken
paymentTokenVal
cvcProps
getVisaCards
setIsClickToPayRememberMe
closeComponentIfSavedMethodsAreEmpty
/>
</RenderIf>
<RenderIf condition={!displayMergedSavedMethods}> {renderSavedCards(savedMethods)} </RenderIf>
clickToPayElement
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why these are not functional components?

Comment on lines 282 to 286
if displayMergedSavedMethods && selectedOption == "saved_methods" {
setShowPaymentMethodsScreen(_ => false)
} else if displayMergedSavedMethods {
setShowPaymentMethodsScreen(_ => true)
}
Copy link
Contributor

@Sanskar2001 Sanskar2001 Sep 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if displayMergedSavedMethods && selectedOption == "saved_methods" {
setShowPaymentMethodsScreen(_ => false)
} else if displayMergedSavedMethods {
setShowPaymentMethodsScreen(_ => true)
}
let showScreen =
displayMergedSavedMethods && selectedOption !== "saved_methods";
setShowPaymentMethodsScreen(showScreen);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would not be equivalent to the previous case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this

if displayMergedSavedMethods {
  setShowPaymentMethodsScreen(_ => selectedOption != "saved_methods")
}

Copy link
Contributor

@Sanskar2001 Sanskar2001 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please check the comments

Comment on lines 8 to 14
style={
fontSize: "14px",
float: "left",
fontWeight: "500",
width: "fit-content",
color: themeObj.colorPrimary,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why inlining styling is required here?

Comment on lines 436 to +447
let enableSavedPaymentShimmer = React.useMemo(() => {
savedCardlength === 0 &&
!showPaymentMethodsScreen &&
(loadSavedCards === PaymentType.LoadingSavedCards || clickToPayConfig.isReady->Option.isNone)
}, (savedCardlength, loadSavedCards, showPaymentMethodsScreen, clickToPayConfig.isReady))
(loadSavedCards === PaymentType.LoadingSavedCards || clickToPayConfig.isReady->Option.isNone) &&
!displayMergedSavedMethods
}, (
savedCardlength,
loadSavedCards,
showPaymentMethodsScreen,
clickToPayConfig.isReady,
displayMergedSavedMethods,
))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to simplify this condition for better readability.

| _ =>
<RenderIf
condition={!displaySavedPaymentMethods &&
condition={(!displaySavedPaymentMethods ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we simplify this? It's too many conditions inside a prop - not readable

<RenderIf
condition={((displaySavedPaymentMethods && savedMethods->Array.length > 0) ||
isShowPaymentMethodsDependingOnClickToPay) && showPaymentMethodsScreen}>
isShowPaymentMethodsDependingOnClickToPay) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we simplify this? It's too many conditions inside a prop - not readable

Comment on lines 11 to 13
onClick={_ => {
setShowMore(_ => !showMore)
}}>
Copy link
Contributor

@PritishBudhiraja PritishBudhiraja Sep 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
onClick={_ => {
setShowMore(_ => !showMore)
}}>
onClick={_ => setShowMore(prev => !prev) }>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready for Review PR with label Ready for Review should only be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Combined view for Saved Payment methods screen and payment methods screen

7 participants