-
Notifications
You must be signed in to change notification settings - Fork 24
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 microdeposits handling #3693
Changes from 4 commits
36dbab4
c9f5c17
3210ed6
0df4e54
c5c4d95
45c68aa
c12204b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,11 @@ import config from 'config' | |
|
||
import { SentryRoute } from 'sentry' | ||
|
||
import { useUnverifiedPaymentMethods } from 'services/account/useUnverifiedPaymentMethods' | ||
import { Provider } from 'shared/api/helpers' | ||
import { Theme, useThemeContext } from 'shared/ThemeContext' | ||
import A from 'ui/A' | ||
import { Alert } from 'ui/Alert' | ||
import LoadingLogo from 'ui/LoadingLogo' | ||
|
||
import { PlanProvider } from './context' | ||
|
@@ -35,11 +39,21 @@ const Loader = () => ( | |
</div> | ||
) | ||
|
||
interface URLParams { | ||
owner: string | ||
provider: Provider | ||
} | ||
|
||
function PlanPage() { | ||
const { owner, provider } = useParams() | ||
const { owner, provider } = useParams<URLParams>() | ||
const { data: ownerData } = useSuspenseQueryV5( | ||
PlanPageDataQueryOpts({ owner, provider }) | ||
) | ||
const { data: unverifiedPaymentMethods } = useUnverifiedPaymentMethods({ | ||
provider, | ||
owner, | ||
}) | ||
|
||
const { theme } = useThemeContext() | ||
const isDarkMode = theme !== Theme.LIGHT | ||
|
||
|
@@ -61,6 +75,11 @@ function PlanPage() { | |
> | ||
<PlanProvider> | ||
<PlanBreadcrumb /> | ||
{unverifiedPaymentMethods?.length ? ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe .length > 0 rather than the property existing, but this is also falsey for the 0 case I believe.... maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think as is works, but I'll make it more explicit with the length check so it we don't have to double think |
||
<UnverifiedPaymentMethodAlert | ||
url={unverifiedPaymentMethods?.[0]?.hostedVerificationUrl} | ||
/> | ||
) : null} | ||
<Suspense fallback={<Loader />}> | ||
<Switch> | ||
<SentryRoute path={path} exact> | ||
|
@@ -90,4 +109,28 @@ function PlanPage() { | |
) | ||
} | ||
|
||
const UnverifiedPaymentMethodAlert = ({ url }: { url?: string | null }) => { | ||
return ( | ||
<> | ||
<Alert variant="warning"> | ||
<Alert.Title>Verify Your New Payment Method</Alert.Title> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: should double check caps on this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's the title and what @Adal3n3 suggested. I could go either way on that 🤷♀️ |
||
<Alert.Description> | ||
Your new payment method needs to be verified.{' '} | ||
<A | ||
href={url} | ||
isExternal | ||
hook="stripe-payment-method-verification" | ||
to={undefined} | ||
> | ||
Click here | ||
</A>{' '} | ||
to complete the process. The verification code may take around 2 days | ||
to appear on your bank statement. | ||
</Alert.Description> | ||
</Alert> | ||
<br /> | ||
</> | ||
) | ||
} | ||
|
||
export default PlanPage |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ import { useSuspenseQuery as useSuspenseQueryV5 } from '@tanstack/react-queryV5' | |
import { useParams } from 'react-router-dom' | ||
|
||
import { usePlanUpdatedNotification } from 'pages/PlanPage/context' | ||
import { useAccountDetails, usePlanData } from 'services/account' | ||
import { useAccountDetails, useCurrentOrgPlanPageData } from 'services/account' | ||
import { Provider } from 'shared/api/helpers' | ||
import { getScheduleStart } from 'shared/plan/ScheduledPlanDetails/ScheduledPlanDetails' | ||
import A from 'ui/A' | ||
|
@@ -28,7 +28,7 @@ function CurrentOrgPlan() { | |
owner, | ||
}) | ||
|
||
const { data: planData } = usePlanData({ | ||
const { data: pageData } = useCurrentOrgPlanPageData({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: can maybe just use data vs. pageData. Meaning is around the same but can avoid the cast |
||
provider, | ||
owner, | ||
}) | ||
|
@@ -40,16 +40,25 @@ function CurrentOrgPlan() { | |
}) | ||
) | ||
|
||
// awaitingInitialPaymentMethodVerification is true if the | ||
// customer needs to verify a delayed notification payment method | ||
// like ACH for their first subscription | ||
const awaitingInitialPaymentMethodVerification = | ||
!accountDetails?.subscriptionDetail?.defaultPaymentMethod && | ||
pageData?.billing?.unverifiedPaymentMethods?.length | ||
|
||
const scheduledPhase = accountDetails?.scheduleDetail?.scheduledPhase | ||
const isDelinquent = accountDetails?.delinquent | ||
const isDelinquent = | ||
accountDetails?.delinquent && !awaitingInitialPaymentMethodVerification | ||
const scheduleStart = scheduledPhase | ||
? getScheduleStart(scheduledPhase) | ||
: undefined | ||
|
||
const shouldRenderBillingDetails = | ||
(accountDetails?.planProvider !== 'github' && | ||
!awaitingInitialPaymentMethodVerification && | ||
((accountDetails?.planProvider !== 'github' && | ||
!accountDetails?.rootOrganization) || | ||
accountDetails?.usesInvoice | ||
accountDetails?.usesInvoice) | ||
|
||
const planUpdatedNotification = usePlanUpdatedNotification() | ||
|
||
|
@@ -62,9 +71,13 @@ function CurrentOrgPlan() { | |
subscriptionDetail={accountDetails?.subscriptionDetail} | ||
/> | ||
) : null} | ||
<InfoMessageStripeCallback /> | ||
<InfoMessageStripeCallback | ||
hasUnverifiedPaymentMethods={ | ||
!!pageData?.billing?.unverifiedPaymentMethods?.length | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: can maybe set this to a const at the top as hasUnverifiedPaymentMethods and use that for the awaitingInitialPaymentMethodVerification const |
||
} | ||
/> | ||
{isDelinquent ? <DelinquentAlert /> : null} | ||
{planData?.plan ? ( | ||
{pageData?.plan ? ( | ||
<div className="flex flex-col gap-4 sm:mr-4 sm:flex-initial md:w-2/3 lg:w-3/4"> | ||
{planUpdatedNotification.alertOption && | ||
!planUpdatedNotification.isCancellation ? ( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: This should be React.FC