Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 28 additions & 40 deletions gridcast-react/app/(protected)/admin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ import { useEffect, useState } from 'react';
import dynamic from 'next/dynamic';
import { useRouter } from 'next/navigation';
import Link from 'next/link';
import {
BarChart3,
TrendingUp,
Cpu,
FileText,
Target,
Zap,
Brain,
Plus,
Calendar,
Bell,
ArrowLeft
} from 'lucide-react';

// Types
import { ForecastData, ResidualData, ModelType, Horizon, MODEL_CONFIGS } from '@/types';
Expand Down Expand Up @@ -82,10 +95,10 @@ export default function AdminDashboard() {

// Sidebar Items
const navItems = [
{ id: 'forecast', label: 'Forecast', icon: '📊' },
{ id: 'analysis', label: 'Analysis', icon: '📈' },
{ id: 'models', label: 'Models', icon: '🧠' },
{ id: 'reports', label: 'Reports', icon: '📄' },
{ id: 'forecast', label: 'Forecast', icon: <BarChart3 size={18} /> },
{ id: 'analysis', label: 'Analysis', icon: <TrendingUp size={18} /> },
{ id: 'models', label: 'Models', icon: <Brain size={18} /> },
{ id: 'reports', label: 'Reports', icon: <FileText size={18} /> },
];

if (error) {
Expand Down Expand Up @@ -159,7 +172,7 @@ export default function AdminDashboard() {
onClick={() => router.push('/login')}
className="w-full flex items-center justify-center gap-2 py-3 px-4 rounded-xl bg-white/5 border border-white/10 text-white/60 text-sm font-medium hover:bg-white/10 hover:text-white transition-all"
>
<span>←</span> Sign Out
<ArrowLeft size={16} /> Sign Out
</button>
</div>
</aside>
Expand Down Expand Up @@ -236,28 +249,28 @@ export default function AdminDashboard() {
value={loading ? '...' : `${currentData?.horizon_metrics[activeHorizon]?.mape?.toFixed(2) ?? '--'}%`}
status={loading ? 'neutral' : (currentData?.horizon_metrics[activeHorizon]?.mape ?? 10) < 3 ? 'good' : 'warn'}
subtext="Backtest Avg Error"
icon={<span className="text-2xl">🎯</span>}
icon={<Target className="text-cyan-400" size={24} />}
modelColor={config.color}
/>
<KPICard
label="Predicted Peak"
value={loading ? '...' : `${Math.max(...(currentData?.forecast.map(p => p.load_mw) ?? [0])).toLocaleString()} MW`}
subtext="24h Maximum"
icon={<span className="text-2xl">📈</span>}
icon={<TrendingUp className="text-amber-400" size={24} />}
modelColor={config.color}
/>
<KPICard
label="Model Latency"
value="1.2s"
subtext="Inference Roundtrip"
icon={<span className="text-2xl">⚡</span>}
icon={<Zap className="text-cyan-400" size={24} />}
modelColor={config.color}
/>
<KPICard
label="Last Trained"
value={loading ? '...' : currentData?.trained_at.split(' ')[0] ?? '--'}
subtext="Season-aware refresh"
icon={<span className="text-2xl">🧠</span>}
icon={<Brain className="text-cyan-400" size={24} />}
modelColor={config.color}
highlighted
/>
Expand Down Expand Up @@ -291,42 +304,19 @@ export default function AdminDashboard() {

<div className="space-y-6">
{/* Model Comparison - CRITICAL: Shows both errors */}
<div className="bg-black/30 backdrop-blur-xl rounded-3xl p-8 border border-white/5 shadow-2xl">
<div className="bg-black/30 backdrop-blur-xl rounded-3xl border border-white/5 shadow-2xl">
<ModelComparison
xgboostData={xgboostData}
lstmData={lstmData}
horizon={activeHorizon}
loading={loading}
loading={loading}
/>
</div>

{/* Operational Alerts */}
<div className="bg-black/30 backdrop-blur-xl rounded-3xl p-8 border border-white/5 shadow-2xl">
<h3 className="text-lg font-bold mb-4 flex items-center gap-2">
<span>🔔</span> Engine Alerts
</h3>
<div className="space-y-4">
<div className="flex gap-3 p-3 rounded-xl bg-cyan-500/10 border border-cyan-500/20">
<div className="w-1.5 h-1.5 rounded-full bg-cyan-400 mt-1.5" />
<div>
<p className="text-sm font-bold text-cyan-400">Forecast Synced</p>
<p className="text-[11px] text-white/50">Successfully fetched {activeHorizon} matrix for {activeModel}.</p>
</div>
</div>
<div className="flex gap-3 p-3 rounded-xl bg-amber-500/10 border border-amber-500/20">
<div className="w-1.5 h-1.5 rounded-full bg-amber-400 mt-1.5" />
<div>
<p className="text-sm font-bold text-amber-400">Peak Load Warning</p>
<p className="text-[11px] text-white/50">Approaching seasonal peak in next 4 hours. MAPE variance may increase.</p>
</div>
</div>
</div>
</div>
</div>
</div>

{/* Heatmap Section */}
<div className="mt-8">
<div className="mt-4">
<div className="bg-black/30 backdrop-blur-xl rounded-3xl p-8 border border-white/5 shadow-2xl">
<ResidualHeatmap data={residualData} loading={loading} />
</div>
Expand Down Expand Up @@ -383,7 +373,7 @@ export default function AdminDashboard() {
<div key={m} className="p-6 bg-white/5 rounded-3xl border border-white/10 hover:border-white/20 transition-all group">
<div className="flex items-center gap-4 mb-4">
<div className="p-3 rounded-2xl bg-white/5 group-hover:scale-110 transition-transform">
<span className="text-2xl">{m === 'xgboost' ? '🌳' : '🧠'}</span>
{m === 'xgboost' ? <BarChart3 size={24} /> : <Brain size={24} />}
</div>
<div>
<h4 className="text-xl font-bold">{cfg.name}</h4>
Expand All @@ -405,7 +395,7 @@ export default function AdminDashboard() {
);
})}
<div className="p-6 bg-white/5 rounded-3xl border border-white/5 border-dashed flex flex-col items-center justify-center text-center opacity-50">
<span className="text-2xl mb-2">➕</span>
<Plus size={24} className="text-white/20 mb-2" />
<h4 className="text-sm font-bold">Add Ensemble Layer</h4>
<p className="text-[10px] text-white/40 mt-1">Coming Q3 2026</p>
</div>
Expand All @@ -417,9 +407,7 @@ export default function AdminDashboard() {
<div className="animate-in fade-in duration-500">
<h1 className="text-4xl font-bold tracking-tight mb-8">System Reports</h1>
<div className="bg-white/5 rounded-3xl border border-white/10 p-8 text-center">
<div className="w-16 h-16 bg-white/5 rounded-full flex items-center justify-center mx-auto mb-4 text-2xl">
📅
</div>
<Calendar size={32} className="text-cyan-400/50 mx-auto mb-4" />
<h3 className="text-xl font-bold mb-2">Operational Digest</h3>
<p className="text-white/50 text-sm max-w-md mx-auto mb-6">
Automated summaries of grid stability and forecast accuracy for stakeholder review.
Expand Down
53 changes: 34 additions & 19 deletions gridcast-react/app/(protected)/company/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@ import {
INDIA_GRID_EMISSION_FACTOR,
INR_PER_KWH,
} from "@/lib/constants";
import {
Leaf,
Zap,
IndianRupee,
BarChart3,
Sun,
Target,
Calendar,
FileText,
TreePine,
Home,
Car,
Factory,
ArrowLeft
} from "lucide-react";

const DashGridCanvas = dynamic(
() => import("@/components/three/DashGridCanvas"),
Expand Down Expand Up @@ -56,57 +71,57 @@ export default function CompanyDashboard() {
value: (savings.co2Saved / 12).toFixed(1),
unit: "tCO₂",
color: "var(--gc-green)",
icon: "🌿",
icon: <Leaf size={18} />,
trend: "+8.2% vs last month",
},
{
label: "Energy Optimised (MTD)",
value: (savings.savingsMWh / 12).toFixed(0),
unit: "MWh",
color: "var(--gc-cyan)",
icon: "⚡",
icon: <Zap size={18} />,
trend: "+12.1% vs last month",
},
{
label: "Cost Saved (MTD)",
value: `₹${((savings.inrSaved / 12) / 100000).toFixed(1)}L`,
unit: "",
color: "var(--gc-amber)",
icon: "💰",
icon: <IndianRupee size={18} />,
trend: "+9.5% vs last month",
},
{
label: "Grid Carbon Intensity",
value: INDIA_GRID_EMISSION_FACTOR.toString(),
unit: "tCO₂/MWh",
color: "var(--gc-violet)",
icon: "📊",
icon: <BarChart3 size={18} />,
trend: "CEA FY2022-23 baseline",
},
{
label: "Renewable Share",
value: "22",
unit: "%",
color: "var(--gc-green)",
icon: "☀️",
icon: <Sun size={18} />,
trend: "Target: 40% by 2027",
},
{
label: "Forecast Accuracy",
value: "97.6",
unit: "%",
color: "var(--gc-cyan)",
icon: "🎯",
icon: <Target size={18} />,
trend: "MAPE 2.4% · 24hr horizon",
},
];

const navItems: { icon: string; label: string; id: Tab }[] = [
{ icon: "📊", label: "Overview", id: "overview" },
{ icon: "⚡", label: "Load Forecast", id: "forecast" },
{ icon: "🌿", label: "Carbon Tracker", id: "carbon" },
{ icon: "📅", label: "Schedule Optimizer", id: "schedule" },
{ icon: "📄", label: "Reports", id: "reports" },
const navItems: { icon: any; label: string; id: Tab }[] = [
{ icon: <BarChart3 size={14} />, label: "Overview", id: "overview" },
{ icon: <Zap size={14} />, label: "Load Forecast", id: "forecast" },
{ icon: <Leaf size={14} />, label: "Carbon Tracker", id: "carbon" },
{ icon: <Calendar size={14} />, label: "Schedule Optimizer", id: "schedule" },
{ icon: <FileText size={14} />, label: "Reports", id: "reports" },
];

return (
Expand Down Expand Up @@ -216,7 +231,7 @@ export default function CompanyDashboard() {
className="gc-btn gc-btn-dim"
style={{ width: "100%", justifyContent: "center", fontSize: 12 }}
>
Sign Out
<ArrowLeft size={14} /> Sign Out
</button>
</aside>

Expand Down Expand Up @@ -410,30 +425,30 @@ export default function CompanyDashboard() {
[
`${savings.treesEquiv.toLocaleString("en-IN")}`,
"Trees grown for 10 yrs",
"🌳",
<TreePine key="tree" size={20} />,
"var(--gc-green)",
],
[
`${savings.homeEquiv.toLocaleString("en-IN")}`,
"Indian homes powered for 1 yr",
"🏠",
<Home key="home" size={20} />,
"var(--gc-cyan)",
],
[
`${savings.carsEquiv.toFixed(0)}`,
"Cars off road for 1 yr",
"🚗",
<Car key="car" size={20} />,
"var(--gc-amber)",
],
[
`${savings.coalEquiv.toFixed(1)} t`,
"Coal not burned equivalent",
"🏭",
<Factory key="factory" size={20} />,
"var(--gc-violet)",
],
].map(([val, label, icon, color]) => (
<div
key={label}
key={label as string}
style={{
display: "flex",
alignItems: "center",
Expand All @@ -448,7 +463,7 @@ export default function CompanyDashboard() {
style={{
fontSize: 15,
fontWeight: 700,
color,
color: color as string,
fontFamily: "var(--gc-font-mono)",
}}
>
Expand Down
14 changes: 10 additions & 4 deletions gridcast-react/app/(protected)/onboarding/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import {
INDIA_GRID_EMISSION_FACTOR,
INR_PER_KWH,
} from "@/lib/constants";
import {
ArrowLeft,
ArrowRight,
Check,
Zap
} from "lucide-react";

type FormData = {
companyName: string;
Expand Down Expand Up @@ -168,7 +174,7 @@ export default function OnboardingPage() {
transition: "all 0.3s",
}}
>
{done ? "✓" : i + 1}
{done ? <Check size={16} /> : i + 1}
</div>
<div
style={{
Expand Down Expand Up @@ -272,7 +278,7 @@ export default function OnboardingPage() {
color: "var(--gc-text-2)",
}}
>
Typical base load for{" "}
<Zap size={14} className="text-cyan-400" /> Typical base load for{" "}
<strong style={{ color: "var(--gc-text)" }}>{industryDef.label}</strong>:{" "}
<span
style={{
Expand Down Expand Up @@ -667,7 +673,7 @@ export default function OnboardingPage() {
}
className="gc-btn gc-btn-dim"
>
Back
<ArrowLeft size={16} /> Back
</button>
<button
onClick={() =>
Expand All @@ -676,7 +682,7 @@ export default function OnboardingPage() {
className="gc-btn gc-btn-primary"
style={step === 3 ? { background: "var(--gc-green)" } : {}}
>
{step === 3 ? "Launch My Dashboard" : "Continue →"}
{step === 3 ? "Launch My Dashboard" : "Continue"} <ArrowRight size={16} />
</button>
</div>
</div>
Expand Down
Loading
Loading