Redesign college predictor, swap DPP contents, reorder sidebar, fix imports, add sql dump
This commit is contained in:
@@ -1,21 +1,20 @@
|
||||
"use client"
|
||||
"use client"
|
||||
|
||||
import { fetchWithAuth } from "@/lib/apiClient";
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent } from "@/components/ui/card"
|
||||
import { BrainCircuit, Play, CheckCircle2, Download, Filter, Lock, FileText, Eye, ShieldAlert, X, Sparkles, Share2, Maximize2, Minimize2, Zap } from "lucide-react"
|
||||
import { BrainCircuit, Play, CheckCircle2, Download, Filter, Lock, FileText, Eye, ShieldAlert, X, Sparkles, Share2, Maximize2, Minimize2 } from "lucide-react"
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import Link from "next/link"
|
||||
import { useActiveUser } from "@/hooks/useActiveUser"
|
||||
|
||||
export default function AIDailyPracticePage() {
|
||||
export default function DPPPage() {
|
||||
const { user, userId } = useActiveUser()
|
||||
const [dpps, setDpps] = useState<any[]>([])
|
||||
const [attempts, setAttempts] = useState<any[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [dateFilter, setDateFilter] = useState("")
|
||||
const [diffFilter, setDiffFilter] = useState("Mixed")
|
||||
const [selectedPdfDpp, setSelectedPdfDpp] = useState<any | null>(null)
|
||||
const [isFullScreen, setIsFullScreen] = useState(false)
|
||||
const [copiedShare, setCopiedShare] = useState(false)
|
||||
@@ -74,9 +73,10 @@ export default function AIDailyPracticePage() {
|
||||
const scheduledDate = new Date(dpp.scheduled_date).toISOString().split('T')[0];
|
||||
if (scheduledDate !== dateFilter) return false;
|
||||
}
|
||||
if (diffFilter !== "Mixed" && dpp.difficulty !== diffFilter) {
|
||||
return false;
|
||||
}
|
||||
const isNeet = user?.target_exam === "NEET";
|
||||
const title = dpp.title.toLowerCase();
|
||||
if (isNeet && (title.includes("math") || title.includes("mth"))) return false;
|
||||
if (!isNeet && title.includes("bio")) return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -97,26 +97,18 @@ export default function AIDailyPracticePage() {
|
||||
const cleanTitle = (title: string) => title.replace(/\s*\(ExamEnum\.[^)]+\)/, '');
|
||||
|
||||
return (
|
||||
<div className="p-6 md:p-8 space-y-6 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto">
|
||||
{/* Page Header */}
|
||||
<div className="border-b border-border/50 pb-6">
|
||||
<div className="flex items-start justify-between gap-4 flex-wrap">
|
||||
<div>
|
||||
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-1">
|
||||
<div className="p-8 space-y-8 animate-in fade-in zoom-in-95 origin-top duration-500 max-w-7xl mx-auto">
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between p-8 bg-gradient-to-r from-secondary/50 to-background border border-border rounded-2xl shadow-sm gap-6">
|
||||
<div>
|
||||
<h1 className="text-3xl md:text-4xl font-black tracking-tight flex items-center gap-3 mb-2">
|
||||
<span className="p-2.5 rounded-xl bg-cyan-50 dark:bg-[var(--cyan-ai-10)] border border-cyan-300/60 dark:border-[var(--cyan-ai-20)]">
|
||||
<Zap className="text-cyan-700 dark:text-[var(--cyan-ai)]" size={28} />
|
||||
</span>
|
||||
PrepPilot AI
|
||||
</h1>
|
||||
<p className="text-muted-foreground text-base font-medium max-w-2xl pl-1">
|
||||
Launch AI-generated Daily Practice Problems (DPPs) tailored to your exam pattern and weak areas.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
<span className="text-xs font-bold uppercase tracking-wider text-[var(--cyan-ai)] bg-cyan-50 dark:bg-[var(--cyan-ai-10)] border border-cyan-300/60 dark:border-[var(--cyan-ai-20)] px-3 py-1.5 rounded-full flex items-center gap-1.5">
|
||||
<BrainCircuit size={12} /> AI Powered
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-muted-foreground font-medium max-w-xl">
|
||||
Hyper-personalized problem sets generated daily by our AI Evaluator to target your specific weak areas based on past exam performance.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -134,9 +126,21 @@ export default function AIDailyPracticePage() {
|
||||
{diff}
|
||||
</button>
|
||||
))}
|
||||
<div className="flex items-center gap-1 ml-2 text-xs text-muted-foreground bg-secondary/50 px-2 py-1 rounded-md">
|
||||
<Lock size={12}/> Pro
|
||||
</div>
|
||||
</div>
|
||||
<Button variant="outline" className="gap-2 rounded-xl text-sm font-bold">
|
||||
<Download size={16} /> Export as PDF
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(window.location.origin + '/dashboard/dpp');
|
||||
setCopiedShare(true);
|
||||
setTimeout(() => setCopiedShare(false), 2000);
|
||||
}}
|
||||
className="gap-2 rounded-xl text-sm font-bold border-primary/30 hover:bg-primary/10 text-primary transition-all shadow-sm"
|
||||
>
|
||||
{copiedShare ? <CheckCircle2 size={16} className="text-green-500" /> : <Share2 size={16} />}
|
||||
{copiedShare ? "Share Link Copied!" : "Share DPPs Link"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -190,12 +194,10 @@ export default function AIDailyPracticePage() {
|
||||
</div>
|
||||
<h3 className="font-bold text-lg leading-tight group-hover:text-[var(--cyan-ai)] transition-colors">
|
||||
{cleanTitle(dpp.title)}
|
||||
</h3>
|
||||
<div className="mt-1">
|
||||
<span className={`text-[10px] uppercase px-2 py-0.5 rounded-md border font-bold tracking-wider ${getDifficultyColor(dpp.difficulty)}`}>
|
||||
<span className={`ml-2 text-[10px] uppercase px-2 py-0.5 rounded-md border font-bold tracking-wider ${getDifficultyColor(dpp.difficulty)}`}>
|
||||
{dpp.difficulty}
|
||||
</span>
|
||||
</div>
|
||||
</h3>
|
||||
<div className="text-sm text-muted-foreground mt-2 font-medium">
|
||||
{count} Questions • {dpp.total_time} mins
|
||||
{dpp.scheduled_date && (
|
||||
@@ -217,19 +219,15 @@ export default function AIDailyPracticePage() {
|
||||
<Button variant="outline" size="sm" className="font-bold border-border">Result</Button>
|
||||
</Link>
|
||||
{!isExpired && (
|
||||
<Link href={`/cbt/${dpp.id}`}>
|
||||
<Button variant="secondary" size="sm" className="font-bold bg-[var(--cyan-ai-10)] text-[var(--cyan-ai)] hover:bg-[var(--cyan-ai-20)] gap-2">
|
||||
<Play size={14} className="fill-current" /> Retake Test
|
||||
</Button>
|
||||
</Link>
|
||||
<Button onClick={() => setSelectedPdfDpp(dpp)} variant="secondary" size="sm" className="font-bold bg-[var(--cyan-ai-10)] text-[var(--cyan-ai)] hover:bg-[var(--cyan-ai-20)] gap-2">
|
||||
<Eye size={14} /> Read PDF
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<Link href={`/cbt/${dpp.id}`}>
|
||||
<Button variant="secondary" size="sm" className="rounded-xl bg-[var(--cyan-ai)] text-black hover:bg-[var(--cyan-ai-80)] font-extrabold gap-2 text-xs shadow-[0_0_12px_rgba(12,96,96,0.2)]">
|
||||
<Play size={14} className="fill-black" /> Launch Practice Test
|
||||
</Button>
|
||||
</Link>
|
||||
<Button onClick={() => setSelectedPdfDpp(dpp)} variant="secondary" className="rounded-xl bg-primary/10 text-primary hover:bg-primary/20 font-bold gap-2 text-xs">
|
||||
<Eye size={14} /> Open PDF
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -249,7 +247,7 @@ export default function AIDailyPracticePage() {
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-black text-base sm:text-lg flex items-center gap-2">
|
||||
{selectedPdfDpp.title}
|
||||
{cleanTitle(selectedPdfDpp.title)}
|
||||
<span className="text-[10px] bg-yellow-500/10 text-yellow-500 border border-yellow-500/20 px-2 py-0.5 rounded-full uppercase tracking-wider font-extrabold hidden md:inline-block">
|
||||
Protected In-App PDF View
|
||||
</span>
|
||||
@@ -264,7 +262,7 @@ export default function AIDailyPracticePage() {
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(window.location.origin + '/dashboard/ai-coach/cbt-dpp');
|
||||
navigator.clipboard.writeText(window.location.origin + '/dashboard/dpp');
|
||||
setCopiedShare(true);
|
||||
setTimeout(() => setCopiedShare(false), 2000);
|
||||
}}
|
||||
@@ -298,7 +296,7 @@ export default function AIDailyPracticePage() {
|
||||
</span>
|
||||
<Link href="/upgrade" className="hidden sm:block shrink-0 ml-2">
|
||||
<Button size="sm" className="bg-amber-500 text-black hover:bg-amber-400 font-extrabold h-7 text-[11px] rounded-lg">
|
||||
Upgrade for Interactive Practice Mode →
|
||||
Upgrade for Interactive CBT Mode →
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
@@ -332,7 +330,7 @@ export default function AIDailyPracticePage() {
|
||||
</Button>
|
||||
<Link href="/upgrade">
|
||||
<Button className="bg-[var(--cyan-ai)] text-black hover:bg-[var(--cyan-ai-80)] font-extrabold rounded-xl shadow-[0_0_15px_rgba(12,96,96,0.2)] text-xs h-9">
|
||||
<Sparkles size={14} className="mr-1.5" /> Upgrade to AI Coach
|
||||
<Sparkles size={14} className="mr-1.5" /> Upgrade to AI Coach for CBT
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user