Skip to content

Commit

Permalink
feat: add initialValues to PaymentInfoForm
Browse files Browse the repository at this point in the history
  • Loading branch information
blushi committed Sep 23, 2024
1 parent 63ea185 commit 681d9f7
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Suspense, useCallback, useEffect, useMemo, useState } from 'react';
import { useFormState, useWatch } from 'react-hook-form';
import { Suspense, useCallback, useMemo, useState } from 'react';
import { DefaultValues, useFormState, useWatch } from 'react-hook-form';
import { useLingui } from '@lingui/react';
import { CreditsAmount } from 'web-marketplace/src/components/molecules/CreditsAmount/CreditsAmount';
import {
Expand Down Expand Up @@ -44,7 +44,7 @@ export type Props = {
cardDisabled: boolean;
allowedDenoms?: AllowedDenoms;
creditTypePrecision?: number | null;
initialValues?: ChooseCreditsFormSchemaType;
initialValues?: DefaultValues<ChooseCreditsFormSchemaType>;
onPrev: () => void;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@ import { PaymentElement } from '@stripe/react-stripe-js';

import CheckboxLabel from 'web-components/src/components/inputs/new/CheckboxLabel/CheckboxLabel';
import { Body } from 'web-components/src/components/typography';
import { UseStateSetter } from 'web-components/src/types/react/useState';

import { paymentElementOptions } from './PaymentInfoForm.constants';
import { PaymentInfoFormSchemaType } from './PaymentInfoForm.schema';

type CardInfoProps = {
accountId?: string;
className?: string;
setPaymentInfoValid: UseStateSetter<boolean>;
};
export const CardInfo = ({ accountId, className }: CardInfoProps) => {
export const CardInfo = ({
accountId,
className,
setPaymentInfoValid,
}: CardInfoProps) => {
const ctx = useFormContext<PaymentInfoFormSchemaType>();
const { register, control, setValue } = ctx;

Expand All @@ -32,7 +38,11 @@ export const CardInfo = ({ accountId, className }: CardInfoProps) => {

return (
<div className={className}>
<PaymentElement id="payment-element" options={paymentElementOptions} />
<PaymentElement
id="payment-element"
options={paymentElementOptions}
onChange={event => setPaymentInfoValid(event.complete)}
/>
<CheckboxLabel
className="pt-30"
checked={savePaymentMethod}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const CustomerInfo = ({
className={!accountId && !wallet?.address ? 'mb-30' : ''}
label={_(msg`Your email`)}
description={
!!wallet && !accountEmail ? (
!!wallet?.address && !accountEmail ? (
<Trans>
Input an email address to receive a receipt of your purchase.
<i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@ import { PaymentMethod } from '@stripe/stripe-js';
import Card from 'web-components/src/components/cards/Card';
import { Radio } from 'web-components/src/components/inputs/new/Radio/Radio';
import { Title } from 'web-components/src/components/typography';
import { UseStateSetter } from 'web-components/src/types/react/useState';

import { CardInfo } from './PaymentInfoForm.CardInfo';
import { PaymentInfoFormSchemaType } from './PaymentInfoForm.schema';

export type PaymentInfoProps = {
paymentMethods?: Array<PaymentMethod> | null;
setPaymentInfoValid: UseStateSetter<boolean>;
accountId?: string;
};
export const PaymentInfo = ({
paymentMethods,
accountId,
setPaymentInfoValid,
}: PaymentInfoProps) => {
const { _ } = useLingui();
const ctx = useFormContext<PaymentInfoFormSchemaType>();
Expand Down Expand Up @@ -62,12 +65,19 @@ export const PaymentInfo = ({
{...register(`paymentMethodId`)}
>
{paymentMethodId === '' && (
<CardInfo className="mt-20" accountId={accountId} />
<CardInfo
className="mt-20"
accountId={accountId}
setPaymentInfoValid={setPaymentInfoValid}
/>
)}
</Radio>
</>
) : (
<CardInfo accountId={accountId} />
<CardInfo
accountId={accountId}
setPaymentInfoValid={setPaymentInfoValid}
/>
)}
</Card>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { z } from 'zod';

import { Wallet } from 'lib/wallet/wallet';

import { PAYMENT_OPTIONS } from 'pages/BuyCredits/BuyCredits.constants';
import { PaymentOptionsType } from 'pages/BuyCredits/BuyCredits.types';

export const paymentInfoFormSchema = (paymentOption: PaymentOptionsType) =>
export const paymentInfoFormSchema = (
paymentOption: PaymentOptionsType,
wallet?: Wallet,
) =>
z.object({
name:
paymentOption === PAYMENT_OPTIONS.CARD ? z.string().min(1) : z.string(),
email:
paymentOption === PAYMENT_OPTIONS.CARD
paymentOption === PAYMENT_OPTIONS.CARD && !wallet?.address
? z.string().email().min(1)
: z.union([z.literal(''), z.string().email().nullable()]),
createAccount: z.boolean(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect } from 'react';
import { useFormState } from 'react-hook-form';
import { useEffect, useMemo, useState } from 'react';
import { DefaultValues, useFormState, useWatch } from 'react-hook-form';
import { useLingui } from '@lingui/react';
import { Stripe, StripeElements } from '@stripe/stripe-js';

Expand Down Expand Up @@ -29,6 +29,7 @@ export type PaymentInfoFormProps = {
setConfirmationTokenId: UseStateSetter<string | undefined>;
stripe?: Stripe | null;
elements?: StripeElements | null;
initialValues?: DefaultValues<PaymentInfoFormSchemaType>;
} & CustomerInfoProps &
PaymentInfoProps;

Expand All @@ -46,17 +47,19 @@ export const PaymentInfoForm = ({
setConfirmationTokenId,
stripe,
elements,
initialValues,
}: PaymentInfoFormProps) => {
const { _ } = useLingui();
const { handleBack } = useMultiStep();
const [paymentInfoValid, setPaymentInfoValid] = useState(false);

const form = useZodForm({
schema: paymentInfoFormSchema(paymentOption),
schema: paymentInfoFormSchema(paymentOption, wallet),
defaultValues: {
email: accountEmail,
name: accountName,
createAccount: true,
savePaymentMethod: true,
email: initialValues?.email || accountEmail,
name: initialValues?.name || accountName,
createAccount: initialValues?.createAccount || true,
savePaymentMethod: initialValues?.savePaymentMethod || true,
paymentMethodId: paymentMethods?.[0]?.id,
},
mode: 'onBlur',
Expand All @@ -73,6 +76,14 @@ export const PaymentInfoForm = ({
form.setValue('paymentMethodId', paymentMethods?.[0]?.id);
}, [accountEmail, accountName, form, paymentMethods]);

const paymentMethodId = useWatch({
control: form.control,
name: 'paymentMethodId',
});
const card = useMemo(
() => paymentOption === PAYMENT_OPTIONS.CARD,
[paymentOption],
);
return (
<Form
form={form}
Expand Down Expand Up @@ -119,16 +130,21 @@ export const PaymentInfoForm = ({
accountName={accountName}
retiring={retiring}
/>
{paymentOption === PAYMENT_OPTIONS.CARD && (
<PaymentInfo paymentMethods={paymentMethods} accountId={accountId} />
{card && (
<PaymentInfo
paymentMethods={paymentMethods}
accountId={accountId}
setPaymentInfoValid={setPaymentInfoValid}
/>
)}
</div>
<div className="float-right pt-40">
<PrevNextButtons
saveDisabled={
!isValid ||
isSubmitting ||
(!stripe && paymentOption === PAYMENT_OPTIONS.CARD)
(!stripe && card) ||
(card && !paymentMethodId && !paymentInfoValid)
}
saveText={_(NEXT)}
onPrev={handleBack}
Expand Down
33 changes: 24 additions & 9 deletions web-marketplace/src/pages/BuyCredits/BuyCredits.Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type Props = {
retiring: boolean;
setRetiring: UseStateSetter<boolean>;
setConfirmationTokenId: UseStateSetter<string | undefined>;
setPaymentMethodId: UseStateSetter<string | undefined>;
cardSellOrders: Array<CardSellOrder>;
cryptoSellOrders: Array<UISellOrderInfo>;
creditTypeAbbrev?: string;
Expand All @@ -59,6 +60,7 @@ export const BuyCreditsForm = ({
retiring,
setRetiring,
setConfirmationTokenId,
setPaymentMethodId,
cardSellOrders,
cryptoSellOrders,
creditTypeAbbrev,
Expand Down Expand Up @@ -153,14 +155,11 @@ export const BuyCreditsForm = ({
creditTypePrecision={creditTypeData?.creditType?.precision}
onPrev={() => navigate(projectHref)}
initialValues={{
[CURRENCY_AMOUNT]: data?.[CURRENCY_AMOUNT] || 0,
[CREDITS_AMOUNT]: data?.[CREDITS_AMOUNT] || 0,
[SELL_ORDERS]: data?.[SELL_ORDERS] || [],
[CREDIT_VINTAGE_OPTIONS]: data?.[CREDIT_VINTAGE_OPTIONS] || [],
[CURRENCY]: data?.[CURRENCY] || {
askBaseDenom: '',
askDenom: '',
},
[CURRENCY_AMOUNT]: data?.[CURRENCY_AMOUNT],
[CREDITS_AMOUNT]: data?.[CREDITS_AMOUNT],
[SELL_ORDERS]: data?.[SELL_ORDERS],
[CREDIT_VINTAGE_OPTIONS]: data?.[CREDIT_VINTAGE_OPTIONS],
[CURRENCY]: data?.[CURRENCY],
}}
/>
)}
Expand All @@ -171,7 +170,11 @@ export const BuyCreditsForm = ({
<PaymentInfoFormFiat
paymentOption={paymentOption}
onSubmit={async (values: PaymentInfoFormSchemaType) => {
handleSaveNext({ ...data, ...values });
const { paymentMethodId, ...others } = values;
// we don't store paymentMethodId in local storage for security reasons,
// only in current state
handleSaveNext({ ...others, ...values });
setPaymentMethodId(paymentMethodId);
}}
login={onButtonClick}
retiring={retiring}
Expand All @@ -182,6 +185,12 @@ export const BuyCreditsForm = ({
paymentMethods={paymentMethodData?.paymentMethods}
setError={setErrorBannerTextAtom}
setConfirmationTokenId={setConfirmationTokenId}
initialValues={{
email: data?.email,
name: data?.name,
createAccount: data?.createAccount,
savePaymentMethod: data?.savePaymentMethod,
}}
/>
</Elements>
) : (
Expand All @@ -199,6 +208,12 @@ export const BuyCreditsForm = ({
paymentMethods={paymentMethodData?.paymentMethods}
setError={setErrorBannerTextAtom}
setConfirmationTokenId={setConfirmationTokenId}
initialValues={{
email: data?.email,
name: data?.name,
createAccount: data?.createAccount,
savePaymentMethod: data?.savePaymentMethod,
}}
/>
)}
</>
Expand Down
2 changes: 2 additions & 0 deletions web-marketplace/src/pages/BuyCredits/BuyCredits.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const BuyCredits = () => {
const [confirmationTokenId, setConfirmationTokenId] = useState<
string | undefined
>();
const [paymentMethodId, setPaymentMethodId] = useState<string | undefined>();

const formModel = getFormModel({ _, paymentOption, retiring });
const sellOrders = useMemo(
Expand Down Expand Up @@ -76,6 +77,7 @@ export const BuyCredits = () => {
onChainProjectId
}`}
setConfirmationTokenId={setConfirmationTokenId}
setPaymentMethodId={setPaymentMethodId}
/>
</MultiStepTemplate>
)}
Expand Down

0 comments on commit 681d9f7

Please sign in to comment.