From 4df9eebb34e9bba343d09f2008f3fb9051c1663f Mon Sep 17 00:00:00 2001 From: Kamran Ahmed <kamranahmed.se@gmail.com> Date: Fri, 11 Apr 2025 20:20:08 +0100 Subject: [PATCH] Add upgrade indicator in sidebar --- src/components/AITutor/AITutorSidebar.tsx | 41 ++++++++++++++++++- .../AITutor/AITutorSidebarProps.tsx | 13 ++++++ .../Billing/UpgradeAccountModal.tsx | 9 +++- 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/components/AITutor/AITutorSidebarProps.tsx diff --git a/src/components/AITutor/AITutorSidebar.tsx b/src/components/AITutor/AITutorSidebar.tsx index 5ee4fccc2..471d75849 100644 --- a/src/components/AITutor/AITutorSidebar.tsx +++ b/src/components/AITutor/AITutorSidebar.tsx @@ -1,5 +1,9 @@ -import { BookOpen, Compass, Plus, Star, X } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { BookOpen, Compass, Plus, Star, X, Zap } from 'lucide-react'; import { AITutorLogo } from '../ReactIcons/AITutorLogo'; +import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal'; +import { useIsPaidUser } from '../../queries/billing'; +import { isLoggedIn } from '../../lib/jwt'; type AITutorSidebarProps = { isFloating: boolean; @@ -39,8 +43,21 @@ export type AITutorTab = (typeof sidebarItems)[number]['key']; export function AITutorSidebar(props: AITutorSidebarProps) { const { activeTab, isFloating, onClose } = props; + const [isInitialLoad, setIsInitialLoad] = useState(true); + + const [isUpgradeModalOpen, setIsUpgradeModalOpen] = useState(false); + const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser(); + + useEffect(() => { + setIsInitialLoad(false); + }, []); + return ( <> + {isUpgradeModalOpen && ( + <UpgradeAccountModal onClose={() => setIsUpgradeModalOpen(false)} /> + )} + <aside className={`w-[255px] shrink-0 border-r border-slate-200 ${ isFloating @@ -94,6 +111,28 @@ export function AITutorSidebar(props: AITutorSidebarProps) { </a> </li> ))} + + {!isInitialLoad && + isLoggedIn() && + !isPaidUser && + !isPaidUserLoading && ( + <li> + <button + onClick={() => { + setIsUpgradeModalOpen(true); + }} + className="mx-4 mt-4 rounded-xl bg-amber-100 p-4 text-left transition-colors hover:bg-amber-200/80" + > + <span className="mb-2 flex items-center gap-2"> + <Zap className="size-4 text-amber-600" /> + <span className="font-medium text-amber-900">Upgrade</span> + </span> + <span className="mt-1 block text-left text-xs leading-4 text-amber-700"> + Get access to all features and benefits of the AI Tutor. + </span> + </button> + </li> + )} </ul> </aside> {isFloating && ( diff --git a/src/components/AITutor/AITutorSidebarProps.tsx b/src/components/AITutor/AITutorSidebarProps.tsx new file mode 100644 index 000000000..8ede3e1a4 --- /dev/null +++ b/src/components/AITutor/AITutorSidebarProps.tsx @@ -0,0 +1,13 @@ +import { Zap } from 'lucide-react'; + +<li> + <div className="mx-4 mt-4 rounded-lg bg-amber-50 p-3"> + <div className="flex items-center gap-2"> + <Zap className="size-4 text-amber-600" /> + <span className="font-medium text-amber-900">Free Tier</span> + </div> + <p className="mt-1 text-xs text-amber-700"> + Upgrade to Pro to unlock unlimited AI tutoring sessions + </p> + </div> +</li> \ No newline at end of file diff --git a/src/components/Billing/UpgradeAccountModal.tsx b/src/components/Billing/UpgradeAccountModal.tsx index 452fd2665..359c4acab 100644 --- a/src/components/Billing/UpgradeAccountModal.tsx +++ b/src/components/Billing/UpgradeAccountModal.tsx @@ -234,7 +234,14 @@ export function UpgradeAccountModal(props: UpgradeAccountModalProps) { )} </p> )} - <p className="text-2xl font-bold text-black sm:text-3xl"> + <p + className={cn( + 'text-2xl font-bold text-black sm:text-3xl', + { + 'mt-0 md:mt-6': !isYearly, + }, + )} + > ${plan.amount}{' '} <span className="text-xs font-normal text-gray-500 sm:text-sm"> / {isYearly ? 'year' : 'month'}