mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-09-08 16:20:40 +02:00
Improve empty billing page design
This commit is contained in:
@@ -3,6 +3,6 @@
|
||||
"enabled": false
|
||||
},
|
||||
"_variables": {
|
||||
"lastUpdateCheck": 1740595115510
|
||||
"lastUpdateCheck": 1741697790683
|
||||
}
|
||||
}
|
@@ -27,7 +27,7 @@ const sidebarLinks = [
|
||||
href: '/account/update-profile',
|
||||
title: 'Profile',
|
||||
id: 'profile',
|
||||
isNew: true,
|
||||
isNew: false,
|
||||
icon: {
|
||||
glyph: 'user',
|
||||
classes: 'h-4 w-4',
|
||||
@@ -56,7 +56,7 @@ const sidebarLinks = [
|
||||
},
|
||||
{
|
||||
href: '/account/road-card',
|
||||
title: 'Card',
|
||||
title: 'Road Card',
|
||||
id: 'road-card',
|
||||
isNew: false,
|
||||
icon: {
|
||||
@@ -70,7 +70,7 @@ const sidebarLinks = [
|
||||
id: 'billing',
|
||||
isNew: true,
|
||||
icon: {
|
||||
glyph: 'badge',
|
||||
glyph: 'credit-card',
|
||||
classes: 'h-4 w-4',
|
||||
},
|
||||
},
|
||||
|
@@ -11,6 +11,7 @@ import { httpPost } from '../../lib/query-http';
|
||||
import { UpgradeAccountModal } from './UpgradeAccountModal';
|
||||
import { getUrlParams } from '../../lib/browser';
|
||||
import { VerifyUpgrade } from './VerifyUpgrade';
|
||||
import { EmptyBillingScreen } from './EmptyBillingScreen';
|
||||
|
||||
export type CreateCustomerPortalBody = {};
|
||||
|
||||
@@ -96,19 +97,9 @@ export function BillingPage() {
|
||||
{showVerifyUpgradeModal && <VerifyUpgrade />}
|
||||
|
||||
{billingDetails?.status === 'none' && !isLoadingBillingDetails && (
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<p className="text-gray-800">
|
||||
You are not subscribed to any plan,
|
||||
<button
|
||||
className="text-black underline underline-offset-2 hover:text-gray-800"
|
||||
onClick={() => {
|
||||
setShowUpgradeModal(true);
|
||||
}}
|
||||
>
|
||||
upgrade account.
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
<EmptyBillingScreen
|
||||
onUpgrade={() => setShowUpgradeModal(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{billingDetails?.status !== 'none' &&
|
||||
|
63
src/components/Billing/EmptyBillingScreen.tsx
Normal file
63
src/components/Billing/EmptyBillingScreen.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
CreditCard,
|
||||
HeartHandshake,
|
||||
MessageCircleIcon,
|
||||
SparklesIcon,
|
||||
Zap,
|
||||
} from 'lucide-react';
|
||||
|
||||
type EmptyBillingScreenProps = {
|
||||
onUpgrade: () => void;
|
||||
};
|
||||
|
||||
const perks = [
|
||||
{
|
||||
icon: Zap,
|
||||
text: 'Unlimited AI course generations',
|
||||
},
|
||||
{
|
||||
icon: MessageCircleIcon,
|
||||
text: 'Unlimited AI Chat feature usage',
|
||||
},
|
||||
{
|
||||
icon: SparklesIcon,
|
||||
text: 'Early access to new features',
|
||||
},
|
||||
{
|
||||
icon: HeartHandshake,
|
||||
text: 'Support the development of platform',
|
||||
},
|
||||
];
|
||||
|
||||
export function EmptyBillingScreen(props: EmptyBillingScreenProps) {
|
||||
const { onUpgrade } = props;
|
||||
|
||||
return (
|
||||
<div className="mt-12 flex h-full w-full flex-col items-center">
|
||||
<CreditCard className="mb-3 h-12 w-12 text-gray-300" />
|
||||
<h3 className="mb-3 text-xl font-semibold text-black">
|
||||
No Active Subscription
|
||||
</h3>
|
||||
|
||||
<p className="text-balance text-gray-700">
|
||||
Unlock pro benefits by upgrading to a subscription
|
||||
</p>
|
||||
|
||||
<div className="my-8 flex flex-col gap-2">
|
||||
{perks.map((perk) => (
|
||||
<p className="textsm flex items-center text-gray-600" key={perk.text}>
|
||||
<perk.icon className="mr-2 h-4 w-4 text-gray-500" />
|
||||
{perk.text}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={onUpgrade}
|
||||
className="inline-flex items-center justify-center rounded-md bg-black px-6 py-2.5 text-sm font-medium text-white transition-colors hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2"
|
||||
>
|
||||
Upgrade Account
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
@@ -136,7 +136,7 @@ export function AICourseContent(props: AICourseContentProps) {
|
||||
const isLimitReached = error.includes('limit');
|
||||
|
||||
const icon = isLimitReached ? (
|
||||
<CircleAlert className="mb-4 size-16 text-red-500" />
|
||||
<CircleAlert className="mb-4 size-16 text-yellow-500" />
|
||||
) : (
|
||||
<ErrorIcon additionalClasses="mb-4 size-16" />
|
||||
);
|
||||
|
1
src/icons/credit-card.svg
Normal file
1
src/icons/credit-card.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-credit-card"><rect width="20" height="14" x="2" y="5" rx="2"/><line x1="2" x2="22" y1="10" y2="10"/></svg>
|
After Width: | Height: | Size: 308 B |
Reference in New Issue
Block a user