Your Flashcards
-
+
diff --git a/src/app/page.tsx b/src/app/page.tsx
index a4cefec..417fd08 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -9,6 +9,8 @@ import FAQ from "@/components/FAQ";
import Noise from "@/components/noise";
import { ToastContainer } from "react-toastify";
import { motion } from "framer-motion";
+import { useUser } from "@clerk/nextjs";
+import { useSubscription } from "@/hooks/useSubscription";
const avatars = [
@@ -18,6 +20,9 @@ const avatars = [
];
export default function Home() {
+ const { isSignedIn } = useUser();
+ const { canAccessPro } = useSubscription();
+
return (
{/* Toast Notification Container */}
@@ -102,11 +107,11 @@ export default function Home() {
className={`group relative overflow-hidden bg-gradient-to-r from-purple-700 to-purple-600 hover:from-purple-600 hover:to-purple-500 text-white dark:from-purple-600 dark:to-purple-500 dark:hover:from-purple-500 dark:hover:to-purple-400 px-8 py-4 rounded-xl font-semibold text-lg shadow-xl hover:shadow-2xl transform hover:scale-105 transition-all duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-purple-500 focus-visible:ring-offset-2 ${buttonVariants({
size: "lg",
})}`}
- href="/generate"
+ href={isSignedIn ? (canAccessPro ? "/generate-pro" : "/generate") : "/sign-up"}
aria-label="Get started with FlashFathom AI"
>
- Get started
+ {isSignedIn ? (canAccessPro ? "Go to Pro Generator" : "Generate Flashcards") : "Get started"}
diff --git a/src/app/pricing/page.tsx b/src/app/pricing/page.tsx
index 0f9ab56..d686457 100644
--- a/src/app/pricing/page.tsx
+++ b/src/app/pricing/page.tsx
@@ -12,8 +12,8 @@ import { cn } from "@/lib/utils";
import { ArrowRight, Check, HelpCircle, Minus, Zap, Crown, Building, Sparkles } from "lucide-react";
import Link from "next/link";
import { useAuth } from "@clerk/nextjs";
-import { useRouter } from "next/navigation";
-import { useState } from "react";
+import { useRouter, useSearchParams } from "next/navigation";
+import { useState, useEffect, Suspense } from "react";
import { loadRazorpay } from "@/utils/get-razorpay";
import { useTheme } from "next-themes";
// â
ADDED: Import toast functionality
@@ -39,15 +39,30 @@ interface PricingItem {
};
}
-const Page = () => {
+const PricingContent = () => {
const { isSignedIn } = useAuth();
const router = useRouter();
+ const searchParams = useSearchParams();
const [billingCycle, setBillingCycle] = useState<"monthly" | "yearly">("monthly");
const [loading, setLoading] = useState
(null);
const { theme } = useTheme();
// â
ADDED: Toast hook
const { toast } = useToast();
+ // Check if user was redirected here for upgrade
+ const upgradeRequired = searchParams.get('upgrade') === 'required';
+ const redirectUrl = searchParams.get('redirect');
+
+ useEffect(() => {
+ if (upgradeRequired) {
+ toast({
+ title: "đ Pro Access Required",
+ description: "You need a Pro subscription to access this feature. Choose a plan below to continue.",
+ variant: "default",
+ });
+ }
+ }, [upgradeRequired, toast]);
+
const handleSignUp = async (plan: string) => {
if (!isSignedIn) {
router.push("/sign-in");
@@ -152,7 +167,12 @@ const Page = () => {
// Redirect after a short delay to show toast
setTimeout(() => {
- router.push('/result?payment=success');
+ // If user was redirected here for upgrade, go back to original page
+ if (redirectUrl) {
+ router.push(redirectUrl);
+ } else {
+ router.push('/result?payment=success');
+ }
}, 2000);
} else {
const error = await verifyResponse.json();
@@ -577,4 +597,12 @@ const Page = () => {
);
};
+const Page = () => {
+ return (
+ Loading...}>
+
+
+ );
+};
+
export default Page;
diff --git a/src/app/result/page.tsx b/src/app/result/page.tsx
index 7fc87c4..e85873b 100644
--- a/src/app/result/page.tsx
+++ b/src/app/result/page.tsx
@@ -1,7 +1,7 @@
'use client'
import { Suspense } from 'react';
-import { useRouter, useSearchParams } from 'next/navigation'
+import { useSearchParams } from 'next/navigation'
import { useEffect, useState } from 'react'
import { Card, CardContent } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
@@ -9,44 +9,26 @@ import { Loader2, CreditCard, CheckCircle, XCircle } from 'lucide-react'
import { Skeleton } from "@/components/ui/skeleton"
import Link from 'next/link'
-interface Session {
- payment_status: string;
- // Add other session properties as needed
-}
+// Stripe is removed; keep only simple status via query param
// â
FIXED: Separate component for search params logic
function ResultContent() {
- const router = useRouter()
const searchParams = useSearchParams()
- const session_id = searchParams.get('session_id')
+ const payment = searchParams.get('payment') // success | failed
const [loading, setLoading] = useState(true)
- const [session, setSession] = useState
(null)
const [error, setError] = useState(null)
useEffect(() => {
- const fetchCheckoutSession = async () => {
- if (!session_id) {
- setError('No session ID provided')
- setLoading(false)
- return
- }
-
- try {
- const res = await fetch(`/api/checkout-sessions?session_id=${session_id}`)
- const sessionData = await res.json()
- if (res.ok) {
- setSession(sessionData)
- } else {
- setError(sessionData.error)
- }
- } catch (err) {
- setError('An error occurred while retrieving the session.')
- } finally {
- setLoading(false)
- }
- }
- fetchCheckoutSession()
- }, [session_id])
+ const resolveResult = () => {
+ if (payment === 'success' || payment === 'failed') {
+ setLoading(false)
+ return
+ }
+ setError('Missing payment status')
+ setLoading(false)
+ }
+ resolveResult()
+ }, [payment])
if (loading) {
return (
@@ -86,7 +68,7 @@ function ResultContent() {
- ) : session?.payment_status === 'paid' ? (
+ ) : payment === 'success' ? (