Skip to content

Commit 4f32110

Browse files
authored
Merge pull request #221 from vernu/dev
show past-due billing alert in dashboard
2 parents b57a551 + f6556ea commit 4f32110

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
'use client'
2+
3+
import { Alert, AlertDescription } from '@/components/ui/alert'
4+
import { Button } from '@/components/ui/button'
5+
import { ApiEndpoints } from '@/config/api'
6+
import httpBrowserClient from '@/lib/httpBrowserClient'
7+
import { polarCustomerPortalRequestUrl } from '@/config/external-links'
8+
import { useQuery } from '@tanstack/react-query'
9+
import { CreditCard, AlertTriangle } from 'lucide-react'
10+
import Link from 'next/link'
11+
12+
export default function PastDueBillingAlert() {
13+
const { data: currentSubscription, isLoading: subLoading } = useQuery({
14+
queryKey: ['currentSubscription'],
15+
queryFn: () =>
16+
httpBrowserClient
17+
.get(ApiEndpoints.billing.currentSubscription())
18+
.then((res) => res.data),
19+
})
20+
21+
const { data: currentUser, isLoading: userLoading } = useQuery({
22+
queryKey: ['currentUser'],
23+
queryFn: () =>
24+
httpBrowserClient
25+
.get(ApiEndpoints.auth.whoAmI())
26+
.then((res) => res.data?.data),
27+
})
28+
29+
if (subLoading || userLoading || !currentSubscription || !currentUser) {
30+
return null
31+
}
32+
33+
const status = currentSubscription.status as string | undefined
34+
const planName = (currentSubscription.plan as { name?: string } | undefined)
35+
?.name
36+
const isPaid =
37+
planName &&
38+
planName.toLowerCase() !== 'free' &&
39+
(currentSubscription.amount ?? 0) > 0
40+
41+
if (status !== 'past_due' || !isPaid) {
42+
return null
43+
}
44+
45+
const portalUrl = polarCustomerPortalRequestUrl(currentUser.email)
46+
47+
return (
48+
<Alert className='border-amber-500/80 bg-amber-50 text-amber-950 dark:bg-amber-950/40 dark:text-amber-50 dark:border-amber-600'>
49+
<AlertDescription className='flex flex-col sm:flex-row flex-wrap items-center gap-2 md:gap-4'>
50+
<span className='w-full sm:flex-1 text-center sm:text-left text-sm md:text-base font-medium flex items-center justify-center sm:justify-start gap-2'>
51+
<AlertTriangle className='h-5 w-5 shrink-0' />
52+
Your subscription payment failed and your account is past due. Update
53+
your payment method to avoid losing access.
54+
</span>
55+
<div className='w-full sm:w-auto mt-2 sm:mt-0 flex justify-center sm:justify-end'>
56+
<Button
57+
variant='default'
58+
size='sm'
59+
asChild
60+
className='bg-amber-700 hover:bg-amber-800 text-white dark:bg-amber-600 dark:hover:bg-amber-500'
61+
>
62+
<Link href={portalUrl} target='_blank' rel='noopener noreferrer'>
63+
<CreditCard className='mr-2 h-4 w-4' />
64+
Update payment
65+
</Link>
66+
</Button>
67+
</div>
68+
</AlertDescription>
69+
</Alert>
70+
)
71+
}

web/app/(app)/dashboard/layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import UpgradeToProAlert from './(components)/upgrade-to-pro-alert'
88
import UpdateAppModal from './(components)/update-app-modal'
99
import UpdateAppNotificationBar from './(components)/update-app-notification-bar'
1010
import VerifyEmailAlert from './(components)/verify-email-alert'
11+
import PastDueBillingAlert from './(components)/past-due-billing-alert'
1112
import { SurveyModal } from '@/components/shared/survey-modal'
1213

1314
export default function DashboardLayout({
@@ -54,6 +55,7 @@ export default function DashboardLayout({
5455
<div className='space-y-2 p-4'>
5556
<UpdateAppNotificationBar />
5657
<VerifyEmailAlert />
58+
<PastDueBillingAlert />
5759
<AccountDeletionAlert />
5860
<UpgradeToProAlert />
5961
{/* <BlackFridayModal /> */}

0 commit comments

Comments
 (0)