Skip to content

fix: APP-410 save buy flow on last user interaction#2574

Merged
r41ph merged 23 commits intodevfrom
fix-APP-410-save-buy-flow-on-last-user-interaction
Feb 5, 2025
Merged

fix: APP-410 save buy flow on last user interaction#2574
r41ph merged 23 commits intodevfrom
fix-APP-410-save-buy-flow-on-last-user-interaction

Conversation

@r41ph
Copy link
Contributor

@r41ph r41ph commented Jan 8, 2025

Description

https://regennetwork.atlassian.net/browse/APP-410

Now when users interact with the forms the information should be stored in the localstorage automatically even when the next button hasn't been clicked yet, and therefore, on navigating away and back to the same page, users should be in the same step and see the same form data as before navigating away.


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • provided a link to the relevant issue or specification
  • provided instructions on how to test
  • reviewed "Files changed" and left comments if necessary
  • confirmed all CI checks have passed

How to test

  1. https://deploy-preview-2574--regen-marketplace.netlify.app/project/mai-ndombe-4/buy
  2. Edit the form and navigate away then come back to the same page and verify the step and the form data is the same as before navigating away.

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items
.

I have...

  • confirmed all author checklist items have been addressed
  • reviewed code correctness and readability
  • verified React components follow DRY principles
  • reviewed documentation is accurate
  • reviewed tests
  • manually tested (if applicable)

@netlify
Copy link

netlify bot commented Jan 8, 2025

Deploy Preview for regen-website ready!

Name Link
🔨 Latest commit 93c9813
🔍 Latest deploy log https://app.netlify.com/sites/regen-website/deploys/67a32bbb8a4d0a00084ec8f1
😎 Deploy Preview https://deploy-preview-2574--regen-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@netlify
Copy link

netlify bot commented Jan 8, 2025

Deploy Preview for terrasos ready!

Name Link
🔨 Latest commit 93c9813
🔍 Latest deploy log https://app.netlify.com/sites/terrasos/deploys/67a32bbb66747200080fdde4
😎 Deploy Preview https://deploy-preview-2574--terrasos.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@r41ph r41ph requested a review from blushi January 8, 2025 12:31
@r41ph
Copy link
Contributor Author

r41ph commented Jan 8, 2025

@erikalogie see testing instructions

@erikalogie
Copy link
Collaborator

LGTM

@r41ph r41ph force-pushed the fix-APP-410-save-buy-flow-on-last-user-interaction branch from fef3652 to 0b294da Compare January 8, 2025 13:18
Copy link
Member

@blushi blushi left a comment

Choose a reason for hiding this comment

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

Two additional comments:

  • We don't save values for the last step to local storage
  • When using credit card, if the user leaves the page while being on the last step, when he comes back, we should go back to step 2 (Payment info) because we need the user to re-enter credit card info since this is something we can't save to local storage of course

@r41ph r41ph requested a review from blushi January 13, 2025 13:03
@r41ph
Copy link
Contributor Author

r41ph commented Jan 13, 2025

@erikalogie can you review the changes mentioned in this comment please #2574 (review)

@erikalogie
Copy link
Collaborator

LGTM

@S4mmyb
Copy link
Member

S4mmyb commented Jan 13, 2025

LGTM !

Copy link
Member

@blushi blushi left a comment

Choose a reason for hiding this comment

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

If I set credits or currency amount to 0 then leave the page, now I get this error and I need to reset my buy-credits-... local storage value to make it work again

image

name: 'postalCode',
});

const { anonymousPurchase, followProject, subscribeNewsletter, agreeErpa } =
Copy link
Member

Choose a reason for hiding this comment

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

it would be more appropriate to move that getValues() into the useEffect that uses them, looks like we don't need them at the component top level

this is also going to cause a bug when we enable anonymousPurchase checkbox (commented for now) because we use it in the checked prop and getValues does not subscribe to input change, which will cause the checkbox to be unresponsive, that's why we use useWatch instead, which you commented

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe this would only cause a bug if we wouldn't update the getValues when we uncomment the anonymousPurchase field. However, it'd probably be better to use useWatch for all fields. I've made the update, please review.

@r41ph
Copy link
Contributor Author

r41ph commented Jan 15, 2025

If I set credits or currency amount to 0 then leave the page, now I get this error...

I've changed the way we handle onBlur when a user leaves the credits and currency inputs. Now if a user leaves the input with a value of 0 or empty '' I'm resetting the credits to 1 and then setting the corresponding currency amount. Also, I have updated the stripeOptions so it doesn't initialise with 0 when data.[CURRENCY_AMOUNT] is undefined.

@erikalogie @S4mmyb have a look how the currency and credits fields behave now when a user leaves the inputs with a value of zero or empty, let me know if you want to change anything.

@blushi although the CI shows some failed tests they weren't related with the code updates and a redeploy seems to have been successful: https://app.netlify.com/sites/regen-website/deploys/6788180794db4932a06dce1f

@r41ph r41ph requested a review from blushi January 15, 2025 20:28
Copy link
Member

@blushi blushi left a comment

Choose a reason for hiding this comment

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

I've changed the way we handle onBlur when a user leaves the credits and currency inputs. Now if a user leaves the input with a value of 0 or empty '' I'm resetting the credits to 1 and then setting the corresponding currency amount.

We should also reset the SELL_ORDERS value in this case. If I set one of the field to 0, then the currency/amount fields do update but not the selected sell orders

Here's how my local storage looks like after that:

image

and then when I go through the end of the flow, I cannot purchase because I'm getting an "invalid amount" error from our server endpoint /marketplace/v1/stripe/create-payment-intent since quantity is NaN

Comment on lines +290 to +297
const stripeAmount =
data?.[CURRENCY_AMOUNT] ||
getCurrencyAmount({
currentCreditsAmount: 1,
card: paymentOption === PAYMENT_OPTIONS.CARD,
orderedSellOrders: cardSellOrders,
creditTypePrecision: creditTypeData?.creditType?.precision,
}).currencyAmount;
Copy link
Member

Choose a reason for hiding this comment

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

should we put this in a useMemo too? getCurrencyAmount is a bit computation heavy

@r41ph r41ph requested a review from blushi January 16, 2025 11:13
@erikalogie
Copy link
Collaborator

@erikalogie @S4mmyb have a look how the currency and credits fields behave now when a user leaves the inputs with a value of zero or empty, let me know if you want to change anything.

I think this is fine? @S4mmyb wdyt

setValue(CURRENCY_AMOUNT, currencyAmount, { shouldValidate: true });
setValue(CREDITS_AMOUNT, 1, { shouldValidate: true });
setValue(SELL_ORDERS, sellOrders);
handleOnChange(event);
Copy link
Member

Choose a reason for hiding this comment

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

could you say why we need handleOnChange now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need to update the multiStep data as well. Please see to the latest updates where it has been modified to a more clear approach."

Copy link
Member

@blushi blushi left a comment

Choose a reason for hiding this comment

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

Looks like there has been a regression with the last few commits because this was working before:
If I go through the credit card flow until last "Retirement" step but leave the page and come back, I'm still at the "Retirement" step while I should be at "Payment info" step to re-enter credit card info

@r41ph r41ph force-pushed the fix-APP-410-save-buy-flow-on-last-user-interaction branch from 662d86f to e2a3733 Compare January 20, 2025 17:13
@r41ph r41ph requested a review from blushi January 20, 2025 17:23
if (maxStep !== 0) {
setMaxAllowedStep(maxStep);
}
setPaymentOption(paymentOption as PaymentOptionsType);
Copy link
Member

Choose a reason for hiding this comment

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

why do we need this here in addition to setPaymentOption(prev => data?.paymentOption || prev); in BuyCreditsForm?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It quickly updates paymentOption when loading the form if there is localStorage data saved, avoiding this way a visual jump between sections (from step 2 to step 1) when the form was left in the retirement step.

Copy link
Member

Choose a reason for hiding this comment

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

worth adding a comment about this then in the code

Copy link
Member

Choose a reason for hiding this comment

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

is setPaymentOption(prev => data?.paymentOption || prev); still needed then?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think so. The new setPaymentOption gets triggered only when the form is instantiated. The other one every time data changes, its purpose hasn't changed I assume.

Copy link
Member

Choose a reason for hiding this comment

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

I'm just questioning if we really need those react/jotai state variables now that the data in local storage is synced in real time but maybe we can think about that in a follow-up.
Looks like now the useEffect where we have setPaymentOption(prev => data?.paymentOption || prev) is called several times instead of just once when the user switches payment option.
We could probably update the dep array there to include only data?.retiring, data?.paymentOption instead of the whole data to mitigate that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have updated the deps in BuyCredits.Form.tsx and now it re-renders only once.

I'm just questioning if we really need those

My first thought is that we need them to trigger a re-render if there is localStorage data because we don't have access to the multiStep data in BuyCredits.tsx. Happy to review whether we can optimise this if we can allocate some time for it.

steps={formModel.steps}
initialValues={{}}
classes={{ formWrap: 'max-w-[942px]' }}
forceStep={
Copy link
Member

Choose a reason for hiding this comment

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

why do we need this in addition to the useEffect line 184 in BuyCreditsForm?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Similar to my previous comment, doing it here avoids a visual jump from retirement to payment steps in cases when the form is loaded after a user left the form in the retirement step. I believe the code that we don't need anymore is the one in BuyCreditsForm.

@r41ph r41ph requested a review from blushi January 21, 2025 13:51
@r41ph r41ph force-pushed the fix-APP-410-save-buy-flow-on-last-user-interaction branch 2 times, most recently from 352179b to 79ca1e3 Compare January 22, 2025 18:03
@S4mmyb
Copy link
Member

S4mmyb commented Jan 23, 2025

@erikalogie @S4mmyb have a look how the currency and credits fields behave now when a user leaves the inputs with a value of zero or empty, let me know if you want to change anything.

I think this is fine? @S4mmyb wdyt

Yeah I think this is good.

@r41ph I just tested and was noticing:

  • When I leave the buy page with the number of credits and come back the credit field is set to 1, but the currency field throws an error saying the currency must be at least 0.5 USD. It looks like it's pulling the average price per credit, which is also listed in the order price rather than the price per credit. This should be price per credit, not average price, so I'm assuming this is delt with in another PR? If not then we should be pulling the sell order price (as well as displaying it) and we shouldn't get this error if it auto-renders 1 credit if i leave the page and come back.
  • On the next page I'm noticing that there's an option for Klarna (pay over time). I might have missed this when cory was helping you design this, @erikalogie , but my first question is are we using that? If so, I'm noticing that if i select that option and go to the next page it just goes to the retirement page without asking for card info (which again if we're using it i'm assuming is in another PR). But, if i go to that page then go back the option for Klarna disappears.

@blushi
Copy link
Member

blushi commented Jan 23, 2025

When I leave the buy page with the number of credits and come back the credit field is set to 1, but the currency field throws an error saying the currency must be at least 0.5 USD. It looks like it's pulling the average price per credit, which is also listed in the order price rather than the price per credit. This should be price per credit, not average price, so I'm assuming this is delt with in another PR? If not then we should be pulling the sell order price (as well as displaying it) and we shouldn't get this error if it auto-renders 1 credit if i leave the page and come back.

@S4mmyb
This is the price of the cheapest fiat sell order that is being shown as you can see on sanity:

image

And in the case where credits are only selected from one sell order, the avg price is the same as the sell order price. The issue here is that the price for one credit is lower than 0.5 USD which is the minimum accepted by Stripe. So quite an edge case, but we could have a follow-up issue to set it to 0.5 USD in this case and adjust the credits amount accordingly instead of having just 1 credit selected by default.

@blushi
Copy link
Member

blushi commented Jan 23, 2025

On the next page I'm noticing that there's an option for Klarna (pay over time). I might have missed this when cory was helping you design this, @erikalogie , but my first question is are we using that? If so, I'm noticing that if i select that option and go to the next page it just goes to the retirement page without asking for card info (which again if we're using it i'm assuming is in another PR). But, if i go to that page then go back the option for Klarna disappears.

I do not see this option in France. I guess this is a default option for US folks set up from Stripe, but we could disable it from Stripe dashboard since we haven't really planned for it.

@erikalogie
Copy link
Collaborator

On the next page I'm noticing that there's an option for Klarna (pay over time). I might have missed this when cory was helping you design this, @erikalogie , but my first question is are we using that? If so, I'm noticing that if i select that option and go to the next page it just goes to the retirement page without asking for card info (which again if we're using it i'm assuming is in another PR). But, if i go to that page then go back the option for Klarna disappears.

I do not see this option in France. I guess this is a default option for US folks set up from Stripe, but we could disable it from Stripe dashboard since we haven't really planned for it.

Yes, let's disable it. Maybe I haven't been seeing it either because I'm in the DR, though I do use a VPN for Miami. I can see it now though.

@blushi
Copy link
Member

blushi commented Jan 23, 2025

On the next page I'm noticing that there's an option for Klarna (pay over time). I might have missed this when cory was helping you design this, @erikalogie , but my first question is are we using that? If so, I'm noticing that if i select that option and go to the next page it just goes to the retirement page without asking for card info (which again if we're using it i'm assuming is in another PR). But, if i go to that page then go back the option for Klarna disappears.

I do not see this option in France. I guess this is a default option for US folks set up from Stripe, but we could disable it from Stripe dashboard since we haven't really planned for it.

Yes, let's disable it. Maybe I haven't been seeing it either because I'm in the DR, though I do use a VPN for Miami. I can see it now though.

Ok I've turnt it off

@r41ph r41ph requested a review from blushi January 30, 2025 18:02
@S4mmyb
Copy link
Member

S4mmyb commented Feb 3, 2025

In the comps, for fiat orders I use "price per credit" as I assumed since we are managing in Sanity we would only have one price, even if there are multiple sell orders. The tooltip has already been implemented for the fiat purchases. What do you think about changing the wording to "price per credit" for fiat purchases as per the comps?

Although I'm not entirely sure if that will often be the case in reality, it's technically possible to put different USD prices per sell orders for a same project in sanity and I think that makes sense since on chain sell orders can have different prices in crypto for a same project too so strictly speaking it's still the avg price that we show, even for fiat orders.

@S4mmyb what do you want to do here? I'm pretty sure we can manage this in a way that it is always one price but wdyt?

Realistically, we won't multiple prices for fiat purchases atm as right now as we'll be managing them on-behalf of partners (i.e. project developers) who will be selling credits into a retired state. In the future when this more of a self-serve feature where any credit holder can manage selling on-chain credits with fiat we can treat this use case like we do crypto sell orders and list at multiple prices. For now though, I think we do price per credit.

Comment on lines +345 to +348
newCreditsAmount = calculateCredits(
orderedSellOrders as CardSellOrder[],
MIN_USD_CURRENCY_AMOUNT,
);
Copy link
Member

Choose a reason for hiding this comment

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

sell orders (to be set below in setValue(SELL_ORDERS, ...)) should be recomputed too
also can't we just use the existing function getCreditsAmount with value param equal to MIN_USD_CURRENCY_AMOUNT? this also returns the new sell orders

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks - not sure what I was thinking!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@blushi see refactored code using getCreditsAmount please

@r41ph r41ph force-pushed the fix-APP-410-save-buy-flow-on-last-user-interaction branch from d92dc95 to 93c9813 Compare February 5, 2025 09:13
@r41ph r41ph merged commit 6cccc6e into dev Feb 5, 2025
14 checks passed
@r41ph r41ph deleted the fix-APP-410-save-buy-flow-on-last-user-interaction branch February 5, 2025 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants