feat: scaffold initial dashboard layout and base pages for all modules
This commit is contained in:
+154
-116
@@ -1,21 +1,15 @@
|
||||
"use client";
|
||||
|
||||
import { ArrowUpRight, Brain, TrendingUp, Zap, Target, ArrowDownRight, BarChart3, Filter } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
ArrowUpRight, Brain, TrendingUp, Zap, Target, ArrowDownRight,
|
||||
BarChart3, Filter, Download, Info, CheckCircle2, AlertCircle
|
||||
} from "lucide-react";
|
||||
import {
|
||||
Area,
|
||||
AreaChart,
|
||||
Bar,
|
||||
BarChart,
|
||||
CartesianGrid,
|
||||
ResponsiveContainer,
|
||||
Tooltip,
|
||||
XAxis,
|
||||
YAxis,
|
||||
Radar,
|
||||
RadarChart,
|
||||
PolarGrid,
|
||||
PolarAngleAxis,
|
||||
Area, AreaChart, Bar, BarChart, CartesianGrid, ResponsiveContainer,
|
||||
Tooltip, XAxis, YAxis, Radar, RadarChart, PolarGrid, PolarAngleAxis, Cell
|
||||
} from "recharts";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
|
||||
// Mock Data
|
||||
const productivityTrend = [
|
||||
@@ -29,10 +23,10 @@ const productivityTrend = [
|
||||
];
|
||||
|
||||
const habitCompletion = [
|
||||
{ name: "Reading", completed: 85, missed: 15 },
|
||||
{ name: "Workout", completed: 60, missed: 40 },
|
||||
{ name: "Meditation", completed: 90, missed: 10 },
|
||||
{ name: "Coding", completed: 75, missed: 25 },
|
||||
{ name: "Reading", completed: 85, missed: 15, color: "#6C5BB0" },
|
||||
{ name: "Workout", completed: 60, missed: 40, color: "#a798e8" },
|
||||
{ name: "Meditation", completed: 90, missed: 10, color: "#10b981" },
|
||||
{ name: "Coding", completed: 75, missed: 25, color: "#3b82f6" },
|
||||
];
|
||||
|
||||
const focusRadarData = [
|
||||
@@ -44,8 +38,16 @@ const focusRadarData = [
|
||||
];
|
||||
|
||||
export default function AnalyticsPage() {
|
||||
const [isExporting, setIsExporting] = useState(false);
|
||||
const [activeInsight, setActiveInsight] = useState<string | null>(null);
|
||||
|
||||
const handleExport = () => {
|
||||
setIsExporting(true);
|
||||
setTimeout(() => setIsExporting(false), 3000);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-7xl animate-in fade-in slide-in-from-bottom-4 duration-500 h-full flex flex-col text-foreground font-sans space-y-6">
|
||||
<div className="mx-auto max-w-7xl animate-in fade-in slide-in-from-bottom-4 duration-500 h-full flex flex-col text-foreground font-sans space-y-6 pb-12">
|
||||
|
||||
{/* Top Header */}
|
||||
<div className="flex items-center justify-between pb-4 border-b border-white/5 mt-4">
|
||||
@@ -61,95 +63,116 @@ export default function AnalyticsPage() {
|
||||
<option className="bg-[#0A0710]">This Year</option>
|
||||
</select>
|
||||
</div>
|
||||
<button className="bg-white/5 hover:bg-white/10 text-foreground border border-white/10 px-4 py-1.5 rounded-sm text-xs font-semibold flex items-center gap-2 transition-colors">
|
||||
<BarChart3 className="h-4 w-4" />
|
||||
EXPORT REPORT
|
||||
<button
|
||||
onClick={handleExport}
|
||||
disabled={isExporting}
|
||||
className={`min-w-[140px] px-4 py-1.5 rounded-sm text-xs font-semibold flex items-center justify-center gap-2 transition-all ${isExporting ? 'bg-emerald-500/20 text-emerald-400 border border-emerald-500/30' : 'bg-white/5 hover:bg-white/10 text-foreground border border-white/10'}`}
|
||||
>
|
||||
{isExporting ? (
|
||||
<>
|
||||
<motion.div animate={{ rotate: 360 }} transition={{ repeat: Infinity, duration: 1, ease: "linear" }}>
|
||||
<Download className="h-4 w-4" />
|
||||
</motion.div>
|
||||
GENERATING...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<BarChart3 className="h-4 w-4" />
|
||||
EXPORT REPORT
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* KPI Row */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-6">
|
||||
<KpiCard title="Total Focus Hours" value="124.5" change="+12%" icon={Zap} trend="up" />
|
||||
<KpiCard title="Goal Completion" value="82%" change="+4%" icon={Target} trend="up" color="emerald" />
|
||||
<KpiCard title="Productivity Score" value="9.2" change="-2%" icon={TrendingUp} trend="down" color="blue" />
|
||||
|
||||
<div className="rounded-sm border border-white/5 bg-[#0A0710] p-6 relative overflow-hidden group">
|
||||
<div className="absolute top-0 right-0 p-4 opacity-10 group-hover:opacity-20 transition-opacity">
|
||||
<Zap className="h-16 w-16 text-primary" />
|
||||
{/* Dynamic AI Score Ring */}
|
||||
<div className="rounded-sm border border-primary/20 bg-primary/5 p-6 relative overflow-hidden group flex items-center justify-between">
|
||||
<div>
|
||||
<h3 className="text-[10px] font-bold uppercase tracking-widest text-primary mb-2">Strategic Readiness</h3>
|
||||
<div className="text-3xl font-black text-foreground">94<span className="text-sm font-normal opacity-60 ml-1">%</span></div>
|
||||
<p className="text-[10px] text-muted-foreground mt-2 font-medium">Optimal alignment with goals.</p>
|
||||
</div>
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-4">Total Focus Hours</h3>
|
||||
<div className="flex items-end gap-3 mb-1">
|
||||
<span className="text-4xl font-bold text-foreground">124.5</span>
|
||||
<span className="text-xs text-emerald-500 flex items-center font-medium mb-1">
|
||||
<ArrowUpRight className="h-3 w-3 mr-0.5" /> 12%
|
||||
</span>
|
||||
<div className="relative w-16 h-16">
|
||||
<svg className="w-full h-full" viewBox="0 0 36 36">
|
||||
<path className="text-white/5" stroke="currentColor" strokeWidth="3" fill="none" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
|
||||
<motion.path
|
||||
initial={{ pathLength: 0 }}
|
||||
animate={{ pathLength: 0.94 }}
|
||||
transition={{ duration: 1.5, ease: "easeOut" }}
|
||||
className="text-primary"
|
||||
stroke="currentColor"
|
||||
strokeWidth="3"
|
||||
strokeDasharray="100, 100"
|
||||
fill="none"
|
||||
d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
|
||||
/>
|
||||
</svg>
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<Brain className="h-4 w-4 text-primary" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-[11px] text-muted-foreground">vs previous 30 days</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-sm border border-white/5 bg-[#0A0710] p-6 relative overflow-hidden group">
|
||||
<div className="absolute top-0 right-0 p-4 opacity-10 group-hover:opacity-20 transition-opacity">
|
||||
<Target className="h-16 w-16 text-emerald-500" />
|
||||
</div>
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-4">Goal Completion</h3>
|
||||
<div className="flex items-end gap-3 mb-1">
|
||||
<span className="text-4xl font-bold text-foreground">82%</span>
|
||||
<span className="text-xs text-emerald-500 flex items-center font-medium mb-1">
|
||||
<ArrowUpRight className="h-3 w-3 mr-0.5" /> 4%
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-[11px] text-muted-foreground">vs previous 30 days</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-sm border border-white/5 bg-[#0A0710] p-6 relative overflow-hidden group">
|
||||
<div className="absolute top-0 right-0 p-4 opacity-10 group-hover:opacity-20 transition-opacity">
|
||||
<TrendingUp className="h-16 w-16 text-blue-500" />
|
||||
</div>
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-4">Productivity Score</h3>
|
||||
<div className="flex items-end gap-3 mb-1">
|
||||
<span className="text-4xl font-bold text-foreground">9.2</span>
|
||||
<span className="text-xs text-rose-500 flex items-center font-medium mb-1">
|
||||
<ArrowDownRight className="h-3 w-3 mr-0.5" /> 2%
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-[11px] text-muted-foreground">Out of 10.0 max</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-sm border border-primary/20 bg-primary/5 p-6 relative overflow-hidden group flex flex-col justify-between">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Brain className="h-4 w-4 text-primary" />
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wider text-primary">AI Insight</h3>
|
||||
</div>
|
||||
<p className="text-xs text-foreground/80 leading-relaxed font-medium">
|
||||
Your energy peaks consistently around <span className="text-primary font-bold">10:00 AM</span>. Consider scheduling complex tasks during this block to maximize output.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Charts Grid */}
|
||||
{/* Main Analysis Area */}
|
||||
<div className="grid grid-cols-1 xl:grid-cols-3 gap-6 flex-1 min-h-[400px]">
|
||||
|
||||
{/* Main Area Chart */}
|
||||
<div className="xl:col-span-2 rounded-sm border border-white/5 bg-[#0A0710] p-6 flex flex-col">
|
||||
<div className="flex justify-between items-start mb-6">
|
||||
{/* Productivity Chart with Hotspots */}
|
||||
<div className="xl:col-span-2 rounded-sm border border-white/5 bg-[#0A0710] p-8 flex flex-col relative">
|
||||
<div className="flex justify-between items-start mb-8">
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold mb-1">Productivity vs Energy Correlation</h3>
|
||||
<p className="text-xs text-muted-foreground">How your physical energy levels impact deep work output.</p>
|
||||
<h3 className="text-lg font-bold mb-1">Correlation: Focus vs Energy</h3>
|
||||
<p className="text-sm text-muted-foreground">Detailed visual mapping of biological energy impact on focus output.</p>
|
||||
</div>
|
||||
<div className="flex gap-4 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
|
||||
<div className="flex items-center gap-2"><div className="w-2 h-2 rounded-sm bg-[#6C5BB0]"></div> Focus Score</div>
|
||||
<div className="flex items-center gap-2"><div className="w-2 h-2 rounded-sm bg-emerald-500"></div> Energy Level</div>
|
||||
<div className="flex gap-4 text-[10px] font-bold uppercase tracking-widest text-muted-foreground">
|
||||
<div className="flex items-center gap-2"><div className="w-2 h-2 rounded-full bg-[#6C5BB0]"></div> Focus</div>
|
||||
<div className="flex items-center gap-2"><div className="w-2 h-2 rounded-full bg-emerald-500"></div> Energy</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Chart Interaction Layer */}
|
||||
<div className="absolute top-24 left-1/2 -translate-x-1/2 z-10 flex gap-4">
|
||||
<button
|
||||
onMouseEnter={() => setActiveInsight("Your energy and focus peaked together on May 20. This suggests your evening rest was highly effective.")}
|
||||
onMouseLeave={() => setActiveInsight(null)}
|
||||
className="p-2 bg-primary/20 border border-primary/40 rounded-full text-primary hover:scale-110 transition-transform animate-pulse"
|
||||
>
|
||||
<Info className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<AnimatePresence>
|
||||
{activeInsight && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: 10 }}
|
||||
className="absolute top-36 left-1/2 -translate-x-1/2 z-20 w-64 p-3 bg-[#1F172B] border border-primary/30 rounded-sm shadow-2xl text-[11px] leading-relaxed text-foreground"
|
||||
>
|
||||
<div className="flex items-center gap-2 mb-1 text-primary font-bold uppercase tracking-widest">
|
||||
<Brain className="h-3 w-3" /> AI Observation
|
||||
</div>
|
||||
{activeInsight}
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
<div className="flex-1 w-full min-h-[300px]">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<AreaChart data={productivityTrend}>
|
||||
<defs>
|
||||
<linearGradient id="colorFocus" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="5%" stopColor="#6C5BB0" stopOpacity={0.3}/>
|
||||
<stop offset="5%" stopColor="#6C5BB0" stopOpacity={0.4}/>
|
||||
<stop offset="95%" stopColor="#6C5BB0" stopOpacity={0}/>
|
||||
</linearGradient>
|
||||
<linearGradient id="colorEnergy" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="5%" stopColor="#10b981" stopOpacity={0.3}/>
|
||||
<stop offset="5%" stopColor="#10b981" stopOpacity={0.4}/>
|
||||
<stop offset="95%" stopColor="#10b981" stopOpacity={0}/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
@@ -157,61 +180,76 @@ export default function AnalyticsPage() {
|
||||
<XAxis dataKey="date" axisLine={false} tickLine={false} tick={{ fontSize: 11, fill: '#8F89A5' }} dy={10} />
|
||||
<YAxis axisLine={false} tickLine={false} tick={{ fontSize: 11, fill: '#8F89A5' }} dx={-10} />
|
||||
<Tooltip
|
||||
contentStyle={{ backgroundColor: "#1F172B", border: "none", fontSize: "12px", color: "#FBF9FE", borderRadius: "4px" }}
|
||||
itemStyle={{ color: "#FBF9FE" }}
|
||||
cursor={{ stroke: '#6C5BB0', strokeWidth: 1 }}
|
||||
contentStyle={{ backgroundColor: "#150F1D", border: "1px solid rgba(255,255,255,0.05)", fontSize: "12px", color: "#FBF9FE", borderRadius: "4px" }}
|
||||
/>
|
||||
<Area type="monotone" dataKey="focus" stroke="#6C5BB0" strokeWidth={2} fillOpacity={1} fill="url(#colorFocus)" />
|
||||
<Area type="monotone" dataKey="energy" stroke="#10b981" strokeWidth={2} fillOpacity={1} fill="url(#colorEnergy)" />
|
||||
<Area type="monotone" dataKey="focus" stroke="#6C5BB0" strokeWidth={3} fillOpacity={1} fill="url(#colorFocus)" />
|
||||
<Area type="monotone" dataKey="energy" stroke="#10b981" strokeWidth={3} fillOpacity={1} fill="url(#colorEnergy)" />
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Side Charts Stack */}
|
||||
{/* Sidebar Insights */}
|
||||
<div className="flex flex-col gap-6">
|
||||
|
||||
{/* Radar Chart */}
|
||||
<div className="rounded-sm border border-white/5 bg-[#0A0710] p-6 flex-1 flex flex-col">
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-4">Effort Distribution</h3>
|
||||
<div className="flex-1 w-full min-h-[200px] flex items-center justify-center">
|
||||
<h3 className="text-[10px] font-bold uppercase tracking-widest text-muted-foreground mb-6">Effort Distribution</h3>
|
||||
<div className="flex-1 flex items-center justify-center">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<RadarChart cx="50%" cy="50%" outerRadius="70%" data={focusRadarData}>
|
||||
<PolarGrid stroke="#ffffff10" />
|
||||
<PolarAngleAxis dataKey="subject" tick={{ fill: '#8F89A5', fontSize: 10 }} />
|
||||
<Radar name="Effort" dataKey="A" stroke="#6C5BB0" fill="#6C5BB0" fillOpacity={0.3} />
|
||||
<Tooltip
|
||||
contentStyle={{ backgroundColor: "#1F172B", border: "none", fontSize: "12px", color: "#FBF9FE" }}
|
||||
itemStyle={{ color: "#FBF9FE" }}
|
||||
/>
|
||||
<RadarChart cx="50%" cy="50%" outerRadius="80%" data={focusRadarData}>
|
||||
<PolarGrid stroke="#ffffff05" />
|
||||
<PolarAngleAxis dataKey="subject" tick={{ fill: '#8F89A5', fontSize: 10, fontWeight: 600 }} />
|
||||
<Radar name="Effort" dataKey="A" stroke="#6C5BB0" strokeWidth={2} fill="#6C5BB0" fillOpacity={0.4} />
|
||||
<Tooltip contentStyle={{ backgroundColor: "#1F172B", border: "none", fontSize: "12px" }} />
|
||||
</RadarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bar Chart */}
|
||||
<div className="rounded-sm border border-white/5 bg-[#0A0710] p-6 flex-1 flex flex-col">
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground mb-4">Habit Consistency</h3>
|
||||
<div className="flex-1 w-full min-h-[150px]">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart data={habitCompletion} layout="vertical" margin={{ left: 0, right: 0, top: 0, bottom: 0 }}>
|
||||
<XAxis type="number" hide />
|
||||
<YAxis dataKey="name" type="category" axisLine={false} tickLine={false} tick={{ fontSize: 10, fill: '#8F89A5' }} width={70} />
|
||||
<Tooltip
|
||||
cursor={{ fill: '#ffffff05' }}
|
||||
contentStyle={{ backgroundColor: "#1F172B", border: "none", fontSize: "12px", color: "#FBF9FE" }}
|
||||
itemStyle={{ color: "#FBF9FE" }}
|
||||
/>
|
||||
<Bar dataKey="completed" stackId="a" fill="#6C5BB0" radius={[2, 0, 0, 2]} barSize={12} />
|
||||
<Bar dataKey="missed" stackId="a" fill="#2B2538" radius={[0, 2, 2, 0]} barSize={12} />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
<div className="rounded-sm border border-white/5 bg-[#0A0710] p-6 flex-1">
|
||||
<h3 className="text-[10px] font-bold uppercase tracking-widest text-muted-foreground mb-6">Strategic Alerts</h3>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-start gap-3 p-3 rounded-sm bg-emerald-500/5 border border-emerald-500/10">
|
||||
<CheckCircle2 className="h-4 w-4 text-emerald-500 mt-0.5" />
|
||||
<div>
|
||||
<div className="text-xs font-bold text-emerald-400">Habit Streak Maintained</div>
|
||||
<div className="text-[10px] text-muted-foreground mt-1">Reading streak is now at 12 days. Energy levels are correlating positively.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-3 p-3 rounded-sm bg-orange-500/5 border border-orange-500/10">
|
||||
<AlertCircle className="h-4 w-4 text-orange-500 mt-0.5" />
|
||||
<div>
|
||||
<div className="text-xs font-bold text-orange-400">Admin Overload</div>
|
||||
<div className="text-[10px] text-muted-foreground mt-1">Admin tasks have increased by 15%. Consider automating these via Cognis AI.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function KpiCard({ title, value, change, icon: Icon, trend, color = "primary" }: any) {
|
||||
const isUp = trend === "up";
|
||||
const trendColor = isUp ? "text-emerald-500" : "text-rose-500";
|
||||
|
||||
return (
|
||||
<div className="rounded-sm border border-white/5 bg-[#0A0710] p-6 relative overflow-hidden group">
|
||||
<div className={`absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity ${color === 'primary' ? 'text-primary' : color === 'emerald' ? 'text-emerald-500' : 'text-blue-500'}`}>
|
||||
<Icon className="h-16 w-16" />
|
||||
</div>
|
||||
<h3 className="text-[10px] font-bold uppercase tracking-widest text-muted-foreground mb-4">{title}</h3>
|
||||
<div className="flex items-end gap-3 mb-1">
|
||||
<span className="text-4xl font-black text-foreground tracking-tight">{value}</span>
|
||||
<span className={`text-[10px] flex items-center font-bold mb-1.5 px-1.5 py-0.5 rounded-sm bg-white/5 ${trendColor}`}>
|
||||
{isUp ? <ArrowUpRight className="h-3 w-3 mr-0.5" /> : <ArrowDownRight className="h-3 w-3 mr-0.5" />} {change}
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-[10px] font-medium text-muted-foreground uppercase tracking-wider">vs previous 30 days</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user