feat: complete comprehensive zero-state metrics across all dashboard pages for new accounts
This commit is contained in:
@@ -3,24 +3,33 @@
|
||||
import { TrendingUp, TrendingDown, Brain, Zap, Target, Clock } from "lucide-react"
|
||||
import { Card, CardContent } from "@/components/ui/card"
|
||||
import { useState } from "react"
|
||||
import { useActiveUser, isDemoUser } from "@/hooks/useActiveUser"
|
||||
|
||||
const DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
||||
const QUESTIONS = [42, 58, 35, 71, 65, 48, 60]
|
||||
const ACCURACY = [82, 78, 91, 88, 85, 79, 93]
|
||||
const HOURS = [2.5, 3.5, 2, 4.5, 4, 3, 3.8]
|
||||
const DEMO_QUESTIONS = [42, 58, 35, 71, 65, 48, 60]
|
||||
const DEMO_ACCURACY = [82, 78, 91, 88, 85, 79, 93]
|
||||
const DEMO_HOURS = [2.5, 3.5, 2, 4.5, 4, 3, 3.8]
|
||||
|
||||
const ZERO_DATA = [0, 0, 0, 0, 0, 0, 0]
|
||||
|
||||
export function WeeklyProgressReport() {
|
||||
const { userId } = useActiveUser()
|
||||
const isDemo = isDemoUser(userId)
|
||||
const [metric, setMetric] = useState<"questions" | "accuracy" | "hours">("accuracy")
|
||||
const [hovered, setHovered] = useState<number | null>(null)
|
||||
|
||||
const QUESTIONS = isDemo ? DEMO_QUESTIONS : ZERO_DATA
|
||||
const ACCURACY = isDemo ? DEMO_ACCURACY : ZERO_DATA
|
||||
const HOURS = isDemo ? DEMO_HOURS : ZERO_DATA
|
||||
|
||||
const DATA = metric === "questions" ? QUESTIONS : metric === "accuracy" ? ACCURACY : HOURS
|
||||
const maxVal = Math.max(...DATA)
|
||||
const maxVal = Math.max(1, ...DATA)
|
||||
const avgVal = Math.round((DATA.reduce((a, b) => a + b, 0) / DATA.length) * 10) / 10
|
||||
const trend = DATA[DATA.length - 1] - DATA[0]
|
||||
const trend = isDemo ? DATA[DATA.length - 1] - DATA[0] : 0
|
||||
const trendUp = trend >= 0
|
||||
|
||||
const UNIT = metric === "accuracy" ? "%" : metric === "hours" ? "h" : ""
|
||||
const avgAccuracy = Math.round(ACCURACY.reduce((a, b) => a + b, 0) / ACCURACY.length)
|
||||
const avgAccuracy = isDemo ? Math.round(ACCURACY.reduce((a, b) => a + b, 0) / ACCURACY.length) : 0
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
@@ -38,7 +47,7 @@ export function WeeklyProgressReport() {
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 text-xs font-bold px-2.5 py-1 rounded-full bg-yellow-500/10 text-yellow-500 border border-yellow-500/20">
|
||||
<Zap size={12} />
|
||||
7/7 days active
|
||||
{isDemo ? "7/7 days active" : "Day 1 Active"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -89,13 +98,15 @@ export function WeeklyProgressReport() {
|
||||
)}
|
||||
<div
|
||||
className={`w-full rounded-t-md transition-all duration-700 ${
|
||||
i === 6
|
||||
!isDemo
|
||||
? "bg-white/5 border border-white/10"
|
||||
: i === 6
|
||||
? "bg-gradient-to-t from-[#00F0FF]/60 to-[#00F0FF]"
|
||||
: hovered === i
|
||||
? "bg-gradient-to-t from-[#00F0FF]/40 to-[#00F0FF]/80"
|
||||
: "bg-gradient-to-t from-white/10 to-white/25"
|
||||
}`}
|
||||
style={{ height: `${(DATA[i] / maxVal) * 100}%` }}
|
||||
style={{ height: isDemo ? `${(DATA[i] / maxVal) * 100}%` : "4px" }}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
@@ -116,8 +127,8 @@ export function WeeklyProgressReport() {
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
{[
|
||||
{ label: "Avg Accuracy", value: `${avgAccuracy}%`, icon: <Target size={12} className="text-green-400" /> },
|
||||
{ label: "Questions / Day", value: `${Math.round(QUESTIONS.reduce((a, b) => a + b, 0) / 7)}`, icon: <Zap size={12} className="text-[#00F0FF]" /> },
|
||||
{ label: "Study Hrs / Day", value: `${(HOURS.reduce((a, b) => a + b, 0) / 7).toFixed(1)}h`, icon: <Clock size={12} className="text-amber-400" /> },
|
||||
{ label: "Questions / Day", value: isDemo ? `${Math.round(QUESTIONS.reduce((a, b) => a + b, 0) / 7)}` : "0", icon: <Zap size={12} className="text-[#00F0FF]" /> },
|
||||
{ label: "Study Hrs / Day", value: isDemo ? `${(HOURS.reduce((a, b) => a + b, 0) / 7).toFixed(1)}h` : "0.0h", icon: <Clock size={12} className="text-amber-400" /> },
|
||||
].map(stat => (
|
||||
<div key={stat.label} className="p-2.5 rounded-xl bg-white/5 border border-border/30 text-center">
|
||||
<div className="flex items-center justify-center gap-1 mb-0.5">{stat.icon}</div>
|
||||
@@ -131,8 +142,16 @@ export function WeeklyProgressReport() {
|
||||
<div className="px-3 py-2.5 bg-[#00F0FF]/10 border border-[#00F0FF]/20 rounded-xl text-xs text-[#00F0FF] font-medium flex items-start gap-2.5">
|
||||
<Brain size={15} className="shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<span className="font-black text-white">Sign errors in Thermodynamics</span> — detected in your last 3 attempts (W = −PΔV misapplied). We've queued 3 targeted practice questions for tomorrow.{" "}
|
||||
<span className="text-[#00F0FF]/80"><strong className="text-white">Tip:</strong> You peak at 7–9 PM. Schedule the hardest topics then.</span>
|
||||
{isDemo ? (
|
||||
<>
|
||||
<span className="font-black text-white">Sign errors in Thermodynamics</span> — detected in your last 3 attempts (W = −PΔV misapplied). We've queued 3 targeted practice questions for tomorrow.{" "}
|
||||
<span className="text-[#00F0FF]/80"><strong className="text-white">Tip:</strong> You peak at 7–9 PM. Schedule the hardest topics then.</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span className="font-black text-white">AI Progress Engine Calibrating</span> — Complete your first CBT mock test or DPP to begin mapping subject retention, speed trends, and error velocity.
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -140,3 +159,4 @@ export function WeeklyProgressReport() {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user