Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add ACH payment method #3616

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Next Next commit
feat: Add ACH payment method
  • Loading branch information
suejung-sentry committed Dec 31, 2024
commit 34bfe3e9bad64dddeb0f1728b6c5b4e982ffc40e
2 changes: 2 additions & 0 deletions .env.development
Original file line number Diff line number Diff line change
@@ -5,3 +5,5 @@ REACT_APP_MARKETING_BASE_URL=https://about.codecov.io
# REACT_APP_STRIPE_KEY=
# REACT_APP_LAUNCHDARKLY=
# REACT_APP_BAREMETRICS_TOKEN=
REACT_APP_STRIPE_KEY=pk_test_514SJTOGlVGuVgOrkRgh7zxp3tQ7bX4CY6pnxxw6zRZZSoDVtUUjArPKC7oXeeIbJNICTqS7H88FRfwZnWMskPKxo00bAnu2i9I
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_514SJTOGlVGuVgOrkRgh7zxp3tQ7bX4CY6pnxxw6zRZZSoDVtUUjArPKC7oXeeIbJNICTqS7H88FRfwZnWMskPKxo00bAnu2i9I
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react'

Check failure on line 1 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/Address/AddressCard.tsx

GitHub Actions / Run Lint

'useState' is defined but never used. Allowed unused vars must match /^_/u
import { z } from 'zod'

import {
@@ -6,54 +6,51 @@
SubscriptionDetailSchema,
} from 'services/account'
import A from 'ui/A'
import Button from 'ui/Button'

Check failure on line 9 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/Address/AddressCard.tsx

GitHub Actions / Run Lint

'A' is defined but never used. Allowed unused vars must match /^_/u
import Icon from 'ui/Icon'

Check failure on line 11 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/Address/AddressCard.tsx

GitHub Actions / Run Lint

'Icon' is defined but never used. Allowed unused vars must match /^_/u
import AddressForm from './AddressForm'
import { cn } from 'shared/utils/cn'

interface AddressCardProps {
isEditMode: boolean
setEditMode: (isEditMode: boolean) => void
subscriptionDetail: z.infer<typeof SubscriptionDetailSchema>
provider: string
owner: string
className?: string
}

function AddressCard({
isEditMode,
setEditMode,
subscriptionDetail,
provider,
owner,
className,
}: AddressCardProps) {
const [isFormOpen, setIsFormOpen] = useState(false)
const billingDetails =
subscriptionDetail?.defaultPaymentMethod?.billingDetails

const isAddressSameAsPrimary = true // TODO

return (
<div className="flex flex-col gap-2 border-t p-4">
{isFormOpen && (
<div className={cn('flex gap-2', className)}>
{isEditMode && (
<AddressForm
name={billingDetails?.name || ''}
address={billingDetails?.address}
provider={provider}
owner={owner}
closeForm={() => setIsFormOpen(false)}
closeForm={() => setEditMode(false)}
/>
)}
{!isFormOpen && (
{!isEditMode && (
<>
<div className="flex justify-between">
<h4 className="font-semibold">Cardholder name</h4>
<A
variant="semibold"
onClick={() => setIsFormOpen(true)}
hook="edit-address"
isExternal={false}
to={undefined}
>
Edit <Icon name="chevronRight" size="sm" variant="solid" />
</A>
</div>
<BillingInner
billingDetails={billingDetails}
setIsFormOpen={setIsFormOpen}
setEditMode={setEditMode}
isAddressSameAsPrimary={isAddressSameAsPrimary}
/>
</>
)}
@@ -63,27 +60,36 @@

interface BillingInnerProps {
billingDetails?: z.infer<typeof BillingDetailsSchema>
setIsFormOpen: (val: boolean) => void
setEditMode: (val: boolean) => void
isAddressSameAsPrimary: boolean
}

function BillingInner({ billingDetails, setIsFormOpen }: BillingInnerProps) {
function BillingInner({
billingDetails,
setEditMode,
isAddressSameAsPrimary,
}: BillingInnerProps) {
if (billingDetails) {
return (
<div>
<p>{`${billingDetails.name ?? 'N/A'}`}</p>
<br />
<h4 className="mb-2 font-semibold">Billing address</h4>
<p>{`${billingDetails.address?.line1 ?? ''} ${
billingDetails.address?.line2 ?? ''
}`}</p>
<p>
{billingDetails.address?.city
? `${billingDetails.address?.city}, `
: ''}
{`${billingDetails.address?.state ?? ''} ${
billingDetails.address?.postalCode ?? ''
}`}
</p>
{isAddressSameAsPrimary ? (
<p>Same as primary address</p>
) : (
<>
<p>{`${billingDetails.address?.line1 ?? ''} ${
billingDetails.address?.line2 ?? ''
}`}</p>
<p>
{billingDetails.address?.city
? `${billingDetails.address?.city}, `
: ''}
{`${billingDetails.address?.state ?? ''} ${
billingDetails.address?.postalCode ?? ''
}`}
</p>
</>
)}
</div>
)
}
@@ -94,11 +100,11 @@
No address has been set. Please contact support if you think it’s an
error or set it yourself.
</p>
<div className="flex self-start">

Check failure on line 103 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/Address/AddressCard.tsx

GitHub Actions / Test Runner #2 - Vitest

Unhandled error

TypeError: setEditMode is not a function ❯ onClick src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/Address/AddressCard.tsx:103:7 ❯ HTMLUnknownElement.callCallback node_modules/react-dom/cjs/react-dom.development.js:4164:14 ❯ HTMLUnknownElement.callTheUserObjectsOperation node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30 ❯ innerInvokeEventListeners node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:350:25 ❯ invokeEventListeners node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:286:3 ❯ HTMLUnknownElementImpl._dispatch node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:233:9 ❯ HTMLUnknownElementImpl.dispatchEvent node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:104:17 ❯ HTMLUnknownElement.dispatchEvent node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34 ❯ Object.invokeGuardedCallbackDev node_modules/react-dom/cjs/react-dom.development.js:4213:16 ❯ invokeGuardedCallback node_modules/react-dom/cjs/react-dom.development.js:4277:31 This error originated in "src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/Address/AddressCard.test.tsx" test file. It doesn't mean the error was thrown inside the file itself, but while it was running. The latest test that might've caused the error is "doesn't render address info stuff anymore". It might mean one of the following: - The error was thrown, while Vitest was running this test. - If the error occurred after the test had been completed, this was the last documented test before it was thrown.

Check failure on line 103 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/Address/AddressCard.tsx

GitHub Actions / Test Runner #2 - Vitest

Unhandled error

TypeError: setEditMode is not a function ❯ onClick src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/Address/AddressCard.tsx:103:7 ❯ HTMLUnknownElement.callCallback node_modules/react-dom/cjs/react-dom.development.js:4164:14 ❯ HTMLUnknownElement.callTheUserObjectsOperation node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30 ❯ innerInvokeEventListeners node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:350:25 ❯ invokeEventListeners node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:286:3 ❯ HTMLUnknownElementImpl._dispatch node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:233:9 ❯ HTMLUnknownElementImpl.dispatchEvent node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:104:17 ❯ HTMLUnknownElement.dispatchEvent node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34 ❯ Object.invokeGuardedCallbackDev node_modules/react-dom/cjs/react-dom.development.js:4213:16 ❯ invokeGuardedCallback node_modules/react-dom/cjs/react-dom.development.js:4277:31 This error originated in "src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/Address/AddressCard.test.tsx" test file. It doesn't mean the error was thrown inside the file itself, but while it was running. The latest test that might've caused the error is "renders the address form component". It might mean one of the following: - The error was thrown, while Vitest was running this test. - If the error occurred after the test had been completed, this was the last documented test before it was thrown.
<Button
hook="open-modal"
variant="primary"
onClick={() => setIsFormOpen(true)}
onClick={() => setEditMode(true)}
to={undefined}
disabled={false}
>
Original file line number Diff line number Diff line change
@@ -105,7 +105,7 @@ function AddressForm({
disabled={isLoading}
to={undefined}
>
Update
Save
</Button>
<Button
type="button"
Original file line number Diff line number Diff line change
@@ -2,9 +2,12 @@

import { useAccountDetails } from 'services/account'

import AddressCard from './Address/AddressCard'
import EmailAddress from './EmailAddress'
import PaymentCard from './PaymentCard'
import PaymentMethod from './PaymentMethod'
import Button from 'ui/Button'
import { useState } from 'react'
import A from 'ui/A'
import EditablePaymentMethod from './EditablePaymentMethod'

interface URLParams {
provider: string
@@ -18,34 +21,82 @@
owner,
})
const subscriptionDetail = accountDetails?.subscriptionDetail
const [isEditMode, setEditMode] = useState(false)

const isAdmin = true // TODO

if (!subscriptionDetail) {
return null
}

console.log('iseditmode', isEditMode)

return (
<div className="flex flex-col border">
<h3 className="p-4 font-semibold">Billing details</h3>
<EmailAddress />
<PaymentCard
// @ts-expect-error - TODO fix this once we update PaymentCard to TS
subscriptionDetail={subscriptionDetail}
provider={provider}
owner={owner}
/>
<AddressCard
subscriptionDetail={subscriptionDetail}
provider={provider}
owner={owner}
/>
{subscriptionDetail.taxIds.length > 0 ? (
<div className="flex flex-col gap-2 p-4">
<h4 className="font-semibold">Tax ID</h4>
{subscriptionDetail.taxIds.map((val, index) => (
<p key={index}>{val?.value}</p>
))}
<div className="grid grid-cols-[1fr_auto] items-center gap-4 p-4">
<div>
<h3 className="font-semibold">Billing details</h3>
<p className="pt-1 text-xs text-ds-gray-octonary">
You can modify your billing details. To update your tax IDs, please{' '}
{/* @ts-expect-error ignore until we can convert A component to ts */}
<A to={{ pageName: 'support' }} variant="link">
contact support
</A>
</p>
</div>
) : null}
{!isEditMode ? (
<Button
hook="button"
onClick={() => setEditMode(true)}
variant="default"
disabled={!isAdmin}
>
Edit payment
</Button>
) : (
<Button
hook="button"
onClick={() => setEditMode(false)}
variant="danger"
disabled={!isAdmin}
>
Cancel edit
</Button>
)}
</div>
{isEditMode ? (
<EditablePaymentMethod />

Check failure on line 68 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/BillingDetails.tsx

GitHub Actions / Run Type Checker

Property 'clientSecret' is missing in type '{}' but required in type 'EditablePaymentMethodProps'.

Check failure on line 68 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/BillingDetails.tsx

GitHub Actions / Upload Bundle Stats - Staging

Property 'clientSecret' is missing in type '{}' but required in type 'EditablePaymentMethodProps'.

Check failure on line 68 in src/pages/PlanPage/subRoutes/CurrentOrgPlan/BillingDetails/BillingDetails.tsx

GitHub Actions / Upload Bundle Stats - Production

Property 'clientSecret' is missing in type '{}' but required in type 'EditablePaymentMethodProps'.
) : (
<>
<EmailAddress />
<PaymentMethod
heading="Primary Payment Method"
isPrimary={true}
isEditMode={isEditMode}
setEditMode={setEditMode}
subscriptionDetail={subscriptionDetail}
provider={provider}
owner={owner}
/>
<PaymentMethod
heading="Secondary Payment Method"
isPrimary={false}
isEditMode={isEditMode}
setEditMode={setEditMode}
subscriptionDetail={subscriptionDetail}
provider={provider}
owner={owner}
/>
{subscriptionDetail?.taxIds?.length ? (
<div className="flex flex-col gap-2 p-4">
<h4 className="font-semibold">Tax ID</h4>
{subscriptionDetail?.taxIds?.map((val, index) => (
<p key={index}>{val?.value}</p>
))}
</div>
) : null}
</>
)}
</div>
)
}
Loading
Oops, something went wrong.
Loading
Oops, something went wrong.