Update share card with fb, whatsapp, download and export date; update CBT and Doubt Forum UI
This commit is contained in:
@@ -134,7 +134,7 @@ export default function CBTPage() {
|
||||
<span className="p-2.5 rounded-xl bg-yellow-50 dark:bg-[var(--cyan-ai-10)] border border-yellow-300/60 dark:border-[var(--cyan-ai-20)]">
|
||||
<CheckSquare className="text-yellow-600 dark:text-[var(--cyan-ai)]" size={28} />
|
||||
</span>
|
||||
Computer Based Tests (CBT)
|
||||
Mock Tests (CBT)
|
||||
</h1>
|
||||
<p className="text-muted-foreground text-base font-medium max-w-2xl pl-1">
|
||||
Real exam environment simulations to conquer {selectedPattern === "NEET" ? "NEET" : (targetExam || "JEE")}.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import { ReactNode, useState, useEffect, useRef } from "react"
|
||||
import { BookOpen, LayoutDashboard, Settings, FileText, Activity, LineChart, Trophy, User, ChevronUp, Lock, ShieldAlert, Flame, Target, Gauge, Zap, Calendar, Clock, BrainCircuit, BarChart3, School, CheckSquare } from "lucide-react"
|
||||
import { BookOpen, LayoutDashboard, Settings, FileText, Activity, LineChart, Trophy, User, ChevronUp, Lock, ShieldAlert, Flame, Target, Gauge, Zap, Calendar, Clock, BrainCircuit, BarChart3, School, CheckSquare, MessageSquare } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { LanguageToggle } from "@/components/LanguageToggle"
|
||||
@@ -145,7 +145,7 @@ export default function DashboardLayout({ children }: { children: ReactNode }) {
|
||||
<NavItem
|
||||
section="pro"
|
||||
href="/dashboard/community"
|
||||
icon={<School size={17} />}
|
||||
icon={<MessageSquare size={17} />}
|
||||
label="Doubt Forum"
|
||||
active={pathname.startsWith("/dashboard/community")}
|
||||
isLocked={!hasAccessTo("doubt-resolution-community")}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useRef, useState, useEffect } from "react"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { BrainCircuit, Play, ChevronRight, Activity, Target, CheckCircle2, AlertTriangle, TrendingUp, Calendar, Zap, LayoutDashboard, Share2, Trophy, Lock, ArrowRight, Clock } from "lucide-react"
|
||||
import { BrainCircuit, Play, ChevronRight, Activity, Target, CheckCircle2, AlertTriangle, TrendingUp, Calendar, Zap, LayoutDashboard, Share2, Trophy, Lock, ArrowRight, Clock, Facebook, Download, MessageCircle } from "lucide-react"
|
||||
import { MistakeHeatmap } from "@/components/AI/MistakeHeatmap"
|
||||
import { AdaptiveStudyPlan } from "@/components/AI/AdaptiveStudyPlan"
|
||||
import { useActiveUser } from "@/hooks/useActiveUser"
|
||||
@@ -14,6 +14,7 @@ export default function DashboardPage() {
|
||||
const [userStats, setUserStats] = useState<any>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [downloading, setDownloading] = useState(false)
|
||||
const [shareMenuOpen, setShareMenuOpen] = useState(false)
|
||||
const progressRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -39,20 +40,28 @@ export default function DashboardPage() {
|
||||
fetchStats()
|
||||
}, [userLoading, user?.id, userId])
|
||||
|
||||
const handleExport = async () => {
|
||||
const getShareUrl = () => {
|
||||
const score = isNew ? "0 / 0" : `${userStats?.today_score || 0} / ${userStats?.today_max_score || 60}`
|
||||
const accuracy = isNew ? "0%" : `${userStats?.overall_accuracy || 0}%`
|
||||
const qs = isNew ? "0" : (userStats?.total_questions_attempted || 0).toLocaleString()
|
||||
const rank = isNew ? "#--" : `#${userStats?.city_rank || 1} / ${userStats?.city_total || 50}`
|
||||
|
||||
const target = user?.target_exam === "NEET" ? "NEET" : "JEE"
|
||||
const plan = user?.tier === "Al_Coach" ? "AI Coach" : user?.tier || "Free"
|
||||
const name = user?.name || "Student"
|
||||
const date = new Intl.DateTimeFormat('en-IN', {
|
||||
dateStyle: 'medium',
|
||||
timeStyle: 'short',
|
||||
timeZone: 'Asia/Kolkata',
|
||||
}).format(new Date());
|
||||
|
||||
return `/api/og/dashboard?score=${encodeURIComponent(score)}&accuracy=${encodeURIComponent(accuracy)}&qs=${encodeURIComponent(qs)}&rank=${encodeURIComponent(rank)}&name=${encodeURIComponent(name)}&target=${target}&plan=${encodeURIComponent(plan)}&date=${encodeURIComponent(date)}`
|
||||
}
|
||||
|
||||
const handleDownload = async () => {
|
||||
try {
|
||||
setDownloading(true)
|
||||
const score = isNew ? "0 / 0" : `${userStats?.today_score || 0} / ${userStats?.today_max_score || 60}`
|
||||
const accuracy = isNew ? "0%" : `${userStats?.overall_accuracy || 0}%`
|
||||
const qs = isNew ? "0" : (userStats?.total_questions_attempted || 0).toLocaleString()
|
||||
const rank = isNew ? "#--" : `#${userStats?.city_rank || 1} / ${userStats?.city_total || 50}`
|
||||
|
||||
const target = user?.target_exam === "NEET" ? "NEET" : "JEE"
|
||||
const plan = user?.tier === "Al_Coach" ? "AI Coach" : user?.tier || "Free"
|
||||
const name = user?.name || "Student"
|
||||
|
||||
const url = `/api/og/dashboard?score=${encodeURIComponent(score)}&accuracy=${encodeURIComponent(accuracy)}&qs=${encodeURIComponent(qs)}&rank=${encodeURIComponent(rank)}&name=${encodeURIComponent(name)}&target=${target}&plan=${encodeURIComponent(plan)}`
|
||||
|
||||
const url = getShareUrl()
|
||||
const res = await fetch(url)
|
||||
const blob = await res.blob()
|
||||
const blobUrl = window.URL.createObjectURL(blob)
|
||||
@@ -68,9 +77,23 @@ export default function DashboardPage() {
|
||||
console.error("Failed to export image", err)
|
||||
} finally {
|
||||
setDownloading(false)
|
||||
setShareMenuOpen(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleShareFacebook = () => {
|
||||
const fullUrl = window.location.origin + getShareUrl()
|
||||
window.open(`https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(fullUrl)}`, '_blank')
|
||||
setShareMenuOpen(false)
|
||||
}
|
||||
|
||||
const handleShareWhatsApp = () => {
|
||||
const fullUrl = window.location.origin + getShareUrl()
|
||||
const text = `Check out my performance on PragatiVeer!\n\n${fullUrl}`
|
||||
window.open(`https://wa.me/?text=${encodeURIComponent(text)}`, '_blank')
|
||||
setShareMenuOpen(false)
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="h-[70vh] flex flex-col items-center justify-center p-8">
|
||||
@@ -100,10 +123,28 @@ export default function DashboardPage() {
|
||||
Your overall progress, scores, and active study plan at a glance.
|
||||
</p>
|
||||
</div>
|
||||
<Button onClick={handleExport} variant="outline" size="sm" className="gap-2 font-medium shrink-0" disabled={downloading}>
|
||||
{downloading ? <div className="h-4 w-4 border-2 border-current border-t-transparent rounded-full animate-spin"></div> : <Share2 size={16} />}
|
||||
{downloading ? 'Generating...' : 'Share Card'}
|
||||
</Button>
|
||||
<div className="relative">
|
||||
<Button onClick={() => setShareMenuOpen(!shareMenuOpen)} variant="outline" size="sm" className="gap-2 font-medium shrink-0" disabled={downloading}>
|
||||
{downloading ? <div className="h-4 w-4 border-2 border-current border-t-transparent rounded-full animate-spin"></div> : <Share2 size={16} />}
|
||||
{downloading ? 'Generating...' : 'Share Card'}
|
||||
</Button>
|
||||
{shareMenuOpen && (
|
||||
<div className="absolute right-0 top-full mt-2 w-48 bg-card border border-border rounded-xl shadow-xl z-50 overflow-hidden animate-in fade-in zoom-in-95 duration-200">
|
||||
<button onClick={handleShareFacebook} className="flex items-center w-full px-4 py-3 text-sm hover:bg-secondary text-left transition-colors">
|
||||
<Facebook size={16} className="mr-3 text-blue-600" />
|
||||
Share on Facebook
|
||||
</button>
|
||||
<button onClick={handleShareWhatsApp} className="flex items-center w-full px-4 py-3 text-sm hover:bg-secondary text-left transition-colors">
|
||||
<MessageCircle size={16} className="mr-3 text-green-500" />
|
||||
Share on WhatsApp
|
||||
</button>
|
||||
<button onClick={handleDownload} className="flex items-center w-full px-4 py-3 text-sm hover:bg-secondary text-left transition-colors border-t border-border">
|
||||
<Download size={16} className="mr-3 text-primary" />
|
||||
Download Image
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div ref={progressRef} className="grid grid-cols-2 md:grid-cols-4 gap-4 p-4 -mx-4 bg-background rounded-2xl">
|
||||
{/* Today's Score */}
|
||||
|
||||
Reference in New Issue
Block a user