UI: Fix streak modal, light mode contrast, state datalist, and plan mapping
This commit is contained in:
@@ -32,15 +32,15 @@ export default function DashboardLayout({ children }: { children: ReactNode }) {
|
||||
return () => document.removeEventListener("mousedown", handleClickOutside)
|
||||
}, [])
|
||||
|
||||
const userInitials = user ? user.name.split(" ").map(n => n[0]).join("").toUpperCase() : "DS"
|
||||
const userInitials = user ? user.name.split(" ").filter(n => /^[a-zA-Z]/.test(n)).slice(0, 2).map(n => n[0]).join("").toUpperCase() : "DS"
|
||||
const targetExamLabel = user?.target_exam === "JEE_Main" ? "JEE Main" : user?.target_exam === "JEE_Advanced" ? "JEE Advanced" : user?.target_exam === "NEET" ? "NEET" : "NEET/JEE"
|
||||
|
||||
return (
|
||||
<div className="flex h-screen bg-background overflow-hidden text-foreground selection:bg-primary/20">
|
||||
{/* Sidebar */}
|
||||
<aside className="w-64 border-r border-border bg-background flex flex-col hidden md:flex">
|
||||
<div className="p-6">
|
||||
<Link href="/dashboard" className="block relative h-16 w-full hover:opacity-90 transition-opacity">
|
||||
<div className="px-5 py-4">
|
||||
<Link href="/dashboard" className="block relative h-10 w-full hover:opacity-90 transition-opacity">
|
||||
<div className="absolute inset-0 dark:hidden">
|
||||
<Image
|
||||
src="/PragatiVeer_Logo/SVG_Logos/Rectangular_light_background.svg"
|
||||
@@ -88,21 +88,21 @@ export default function DashboardLayout({ children }: { children: ReactNode }) {
|
||||
icon={<LineChart size={18} />}
|
||||
label="Performance Analytics"
|
||||
active={pathname.startsWith("/dashboard/analytics")}
|
||||
isLocked={!hasAccessTo("ai-mistake-tracking")}
|
||||
isLocked={!hasAccessTo("detailed-performance-analytics")}
|
||||
/>
|
||||
<NavItem
|
||||
href="/dashboard/rank-predictor"
|
||||
icon={<Trophy size={18} />}
|
||||
label="Rank Predictor"
|
||||
active={pathname.startsWith("/dashboard/rank-predictor")}
|
||||
isLocked={!hasAccessTo("ai-mistake-tracking")}
|
||||
isLocked={!hasAccessTo("college-predictor")}
|
||||
/>
|
||||
<NavItem
|
||||
href="/dashboard/ai-coach"
|
||||
icon={<BrainCircuitIcon />}
|
||||
label="AI Coach"
|
||||
active={pathname.startsWith("/dashboard/ai-coach")}
|
||||
isLocked={!hasAccessTo("ai-mistake-tracking")}
|
||||
isLocked={!hasAccessTo("ai-tutor-chat")}
|
||||
/>
|
||||
</nav>
|
||||
|
||||
|
||||
@@ -8,8 +8,10 @@ import { Activity, BrainCircuit, ArrowRight, Clock, Target, CheckCircle2, Trendi
|
||||
import * as htmlToImage from 'html-to-image'
|
||||
import { MistakeHeatmap } from "@/components/AI/MistakeHeatmap"
|
||||
import { AdaptiveStudyPlan } from "@/components/AI/AdaptiveStudyPlan"
|
||||
import { useActiveUser } from "@/hooks/useActiveUser"
|
||||
|
||||
export default function DashboardPage() {
|
||||
const { user, hasAccessTo } = useActiveUser()
|
||||
const progressRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const handleExport = async () => {
|
||||
@@ -29,7 +31,7 @@ export default function DashboardPage() {
|
||||
return (
|
||||
<div className="p-8 max-w-6xl mx-auto space-y-10 animate-in fade-in duration-500 slide-in-from-bottom-4">
|
||||
<header className="flex justify-end mb-2">
|
||||
<Button size="lg" className="gap-2 shadow-sm bg-[#00F0FF] text-background hover:bg-[#00F0FF]/90 font-bold">
|
||||
<Button size="lg" className="gap-2 shadow-sm bg-[#00F0FF] text-black hover:bg-[#00F0FF]/90 font-bold">
|
||||
<BrainCircuit size={18} />
|
||||
Generate AI Plan
|
||||
</Button>
|
||||
@@ -133,22 +135,41 @@ export default function DashboardPage() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="relative opacity-60 cursor-not-allowed border-dashed">
|
||||
<CardContent className="p-5 flex items-center justify-between">
|
||||
<div className="flex gap-4 items-center">
|
||||
<div className="p-3 bg-secondary rounded-xl text-muted-foreground">
|
||||
<Lock size={20} />
|
||||
{hasAccessTo("topic-wise-microtests-unlimited") ? (
|
||||
<Card className="hover:border-primary/30 hover:shadow-md cursor-pointer transition-all duration-300 group">
|
||||
<CardContent className="p-5 flex items-center justify-between">
|
||||
<div className="flex gap-4 items-center">
|
||||
<div className="p-3 bg-secondary rounded-xl text-foreground">
|
||||
<BrainCircuit size={20} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-medium text-base group-hover:text-primary transition-colors">Biology: Human Physiology</h3>
|
||||
<p className="text-sm text-muted-foreground mt-0.5">30 Questions • Medium Priority</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-medium text-base text-muted-foreground">Biology: Human Physiology</h3>
|
||||
<p className="text-sm text-muted-foreground mt-0.5 flex items-center gap-1"><Lock size={12}/> Pro Feature</p>
|
||||
<Button variant="outline" size="sm" className="gap-2 rounded-xl group-hover:bg-primary group-hover:text-primary-foreground group-hover:border-primary transition-all">
|
||||
Start <ArrowRight size={14} />
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : (
|
||||
<Card className="relative opacity-60 cursor-not-allowed border-dashed">
|
||||
<CardContent className="p-5 flex items-center justify-between">
|
||||
<div className="flex gap-4 items-center">
|
||||
<div className="p-3 bg-secondary rounded-xl text-muted-foreground">
|
||||
<Lock size={20} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-medium text-base text-muted-foreground">Biology: Human Physiology</h3>
|
||||
<p className="text-sm text-muted-foreground mt-0.5 flex items-center gap-1"><Lock size={12}/> Pro Feature</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Button variant="outline" size="sm" disabled className="gap-2 rounded-xl">
|
||||
Locked
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Button variant="outline" size="sm" disabled className="gap-2 rounded-xl">
|
||||
Locked
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -171,13 +192,23 @@ export default function DashboardPage() {
|
||||
</div>
|
||||
<Button variant="secondary" className="rounded-xl font-medium">Remind Me</Button>
|
||||
</div>
|
||||
<div className="p-5 bg-secondary/50 flex items-center justify-between transition-colors hover:bg-secondary/70">
|
||||
<div>
|
||||
<h3 className="font-medium text-sm text-foreground flex items-center gap-2"><Lock size={14} className="text-muted-foreground"/> Part Test 3: Mechanics</h3>
|
||||
<p className="text-xs text-muted-foreground mt-0.5 font-medium ml-6">Oct 24, 2026</p>
|
||||
{hasAccessTo("weekly-test-series") ? (
|
||||
<div className="p-5 bg-secondary/50 flex items-center justify-between transition-colors hover:bg-secondary/70 cursor-pointer group">
|
||||
<div>
|
||||
<h3 className="font-medium text-sm text-foreground flex items-center gap-2"><Activity size={14} className="text-primary group-hover:animate-pulse"/> Part Test 3: Mechanics</h3>
|
||||
<p className="text-xs text-muted-foreground mt-0.5 font-medium ml-6">Oct 24, 2026</p>
|
||||
</div>
|
||||
<Button variant="outline" size="sm" className="h-7 text-xs rounded-lg group-hover:bg-primary group-hover:text-primary-foreground group-hover:border-primary">Start <ArrowRight size={12} className="ml-1" /></Button>
|
||||
</div>
|
||||
<Badge variant="secondary" className="text-xs">Pro Only</Badge>
|
||||
</div>
|
||||
) : (
|
||||
<div className="p-5 bg-secondary/50 flex items-center justify-between transition-colors hover:bg-secondary/70 opacity-75">
|
||||
<div>
|
||||
<h3 className="font-medium text-sm text-foreground flex items-center gap-2"><Lock size={14} className="text-muted-foreground"/> Part Test 3: Mechanics</h3>
|
||||
<p className="text-xs text-muted-foreground mt-0.5 font-medium ml-6">Oct 24, 2026</p>
|
||||
</div>
|
||||
<Badge variant="secondary" className="text-xs">Pro Only</Badge>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -134,7 +134,7 @@ export default function SettingsPage() {
|
||||
className="hidden"
|
||||
disabled={uploading}
|
||||
/>
|
||||
<Button type="button" variant="outline" className="w-full gap-2 rounded-xl border-dashed" asChild>
|
||||
<Button type="button" variant="outline" className="w-full gap-2 rounded-xl border-dashed">
|
||||
<span>
|
||||
<Upload size={16} /> {avatarUrl ? "Change Photo" : "Upload Photo"}
|
||||
</span>
|
||||
@@ -182,14 +182,53 @@ export default function SettingsPage() {
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-bold">State</label>
|
||||
<label className="text-sm font-bold">State / Union Territory</label>
|
||||
<input
|
||||
type="text"
|
||||
value={state}
|
||||
placeholder="Enter your state (e.g. Rajasthan, Delhi)"
|
||||
list="indian-states"
|
||||
placeholder="Enter or select your state"
|
||||
onChange={(e) => setState(e.target.value)}
|
||||
className="w-full bg-secondary/50 border border-border rounded-lg px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-[#00F0FF]"
|
||||
/>
|
||||
<datalist id="indian-states">
|
||||
<option value="Andhra Pradesh" />
|
||||
<option value="Arunachal Pradesh" />
|
||||
<option value="Assam" />
|
||||
<option value="Bihar" />
|
||||
<option value="Chhattisgarh" />
|
||||
<option value="Goa" />
|
||||
<option value="Gujarat" />
|
||||
<option value="Haryana" />
|
||||
<option value="Himachal Pradesh" />
|
||||
<option value="Jharkhand" />
|
||||
<option value="Karnataka" />
|
||||
<option value="Kerala" />
|
||||
<option value="Madhya Pradesh" />
|
||||
<option value="Maharashtra" />
|
||||
<option value="Manipur" />
|
||||
<option value="Meghalaya" />
|
||||
<option value="Mizoram" />
|
||||
<option value="Nagaland" />
|
||||
<option value="Odisha" />
|
||||
<option value="Punjab" />
|
||||
<option value="Rajasthan" />
|
||||
<option value="Sikkim" />
|
||||
<option value="Tamil Nadu" />
|
||||
<option value="Telangana" />
|
||||
<option value="Tripura" />
|
||||
<option value="Uttar Pradesh" />
|
||||
<option value="Uttarakhand" />
|
||||
<option value="West Bengal" />
|
||||
<option value="Andaman and Nicobar Islands" />
|
||||
<option value="Chandigarh" />
|
||||
<option value="Dadra and Nagar Haveli and Daman and Diu" />
|
||||
<option value="Delhi" />
|
||||
<option value="Jammu and Kashmir" />
|
||||
<option value="Ladakh" />
|
||||
<option value="Lakshadweep" />
|
||||
<option value="Puducherry" />
|
||||
</datalist>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-bold">Email Address</label>
|
||||
|
||||
@@ -81,7 +81,7 @@ export function StreakOnboardingModal() {
|
||||
<div className="pt-4">
|
||||
<Button
|
||||
onClick={handleEnter}
|
||||
className="w-full size-12 rounded-xl text-base font-black bg-[#00F0FF] text-background hover:bg-[#00F0FF]/90 shadow-[0_0_20px_-3px_#00F0FF] hover:shadow-[0_0_30px_#00F0FF] transition-all duration-300"
|
||||
className="w-full h-14 rounded-xl text-lg font-black bg-[#00F0FF] text-black hover:bg-[#00F0FF]/90 shadow-[0_0_20px_-3px_#00F0FF] hover:shadow-[0_0_30px_#00F0FF] hover:-translate-y-1 transition-all duration-300"
|
||||
>
|
||||
Enter Workspace
|
||||
</Button>
|
||||
|
||||
@@ -8,7 +8,7 @@ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElemen
|
||||
}
|
||||
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant = "default", size = "default", ...props }, ref) => {
|
||||
({ className, variant = "default", size = "default", asChild, ...props }, ref) => {
|
||||
return (
|
||||
<button
|
||||
ref={ref}
|
||||
|
||||
Reference in New Issue
Block a user