diff --git a/gridcast-react/app/(protected)/admin/page.tsx b/gridcast-react/app/(protected)/admin/page.tsx index 4f7004c..d678427 100644 --- a/gridcast-react/app/(protected)/admin/page.tsx +++ b/gridcast-react/app/(protected)/admin/page.tsx @@ -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'; @@ -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: }, + { id: 'analysis', label: 'Analysis', icon: }, + { id: 'models', label: 'Models', icon: }, + { id: 'reports', label: 'Reports', icon: }, ]; if (error) { @@ -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" > - ← Sign Out + Sign Out @@ -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={🎯} + icon={} modelColor={config.color} /> p.load_mw) ?? [0])).toLocaleString()} MW`} subtext="24h Maximum" - icon={πŸ“ˆ} + icon={} modelColor={config.color} /> ⚑} + icon={} modelColor={config.color} /> 🧠} + icon={} modelColor={config.color} highlighted /> @@ -291,42 +304,19 @@ export default function AdminDashboard() {
{/* Model Comparison - CRITICAL: Shows both errors */} -
+
- - {/* Operational Alerts */} -
-

- πŸ”” Engine Alerts -

-
-
-
-
-

Forecast Synced

-

Successfully fetched {activeHorizon} matrix for {activeModel}.

-
-
-
-
-
-

Peak Load Warning

-

Approaching seasonal peak in next 4 hours. MAPE variance may increase.

-
-
-
-
{/* Heatmap Section */} -
+
@@ -383,7 +373,7 @@ export default function AdminDashboard() {
- {m === 'xgboost' ? '🌳' : '🧠'} + {m === 'xgboost' ? : }

{cfg.name}

@@ -405,7 +395,7 @@ export default function AdminDashboard() { ); })}
- βž• +

Add Ensemble Layer

Coming Q3 2026

@@ -417,9 +407,7 @@ export default function AdminDashboard() {

System Reports

-
- πŸ“… -
+

Operational Digest

Automated summaries of grid stability and forecast accuracy for stakeholder review. diff --git a/gridcast-react/app/(protected)/company/page.tsx b/gridcast-react/app/(protected)/company/page.tsx index f4eec33..74e24be 100644 --- a/gridcast-react/app/(protected)/company/page.tsx +++ b/gridcast-react/app/(protected)/company/page.tsx @@ -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"), @@ -56,7 +71,7 @@ export default function CompanyDashboard() { value: (savings.co2Saved / 12).toFixed(1), unit: "tCOβ‚‚", color: "var(--gc-green)", - icon: "🌿", + icon: , trend: "+8.2% vs last month", }, { @@ -64,7 +79,7 @@ export default function CompanyDashboard() { value: (savings.savingsMWh / 12).toFixed(0), unit: "MWh", color: "var(--gc-cyan)", - icon: "⚑", + icon: , trend: "+12.1% vs last month", }, { @@ -72,7 +87,7 @@ export default function CompanyDashboard() { value: `β‚Ή${((savings.inrSaved / 12) / 100000).toFixed(1)}L`, unit: "", color: "var(--gc-amber)", - icon: "πŸ’°", + icon: , trend: "+9.5% vs last month", }, { @@ -80,7 +95,7 @@ export default function CompanyDashboard() { value: INDIA_GRID_EMISSION_FACTOR.toString(), unit: "tCOβ‚‚/MWh", color: "var(--gc-violet)", - icon: "πŸ“Š", + icon: , trend: "CEA FY2022-23 baseline", }, { @@ -88,7 +103,7 @@ export default function CompanyDashboard() { value: "22", unit: "%", color: "var(--gc-green)", - icon: "β˜€οΈ", + icon: , trend: "Target: 40% by 2027", }, { @@ -96,17 +111,17 @@ export default function CompanyDashboard() { value: "97.6", unit: "%", color: "var(--gc-cyan)", - icon: "🎯", + icon: , 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: , 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" }, ]; return ( @@ -216,7 +231,7 @@ export default function CompanyDashboard() { className="gc-btn gc-btn-dim" style={{ width: "100%", justifyContent: "center", fontSize: 12 }} > - ← Sign Out + Sign Out @@ -410,30 +425,30 @@ export default function CompanyDashboard() { [ `${savings.treesEquiv.toLocaleString("en-IN")}`, "Trees grown for 10 yrs", - "🌳", + , "var(--gc-green)", ], [ `${savings.homeEquiv.toLocaleString("en-IN")}`, "Indian homes powered for 1 yr", - "🏠", + , "var(--gc-cyan)", ], [ `${savings.carsEquiv.toFixed(0)}`, "Cars off road for 1 yr", - "πŸš—", + , "var(--gc-amber)", ], [ `${savings.coalEquiv.toFixed(1)} t`, "Coal not burned equivalent", - "🏭", + , "var(--gc-violet)", ], ].map(([val, label, icon, color]) => (

diff --git a/gridcast-react/app/(protected)/onboarding/page.tsx b/gridcast-react/app/(protected)/onboarding/page.tsx index 251f98e..e88a014 100644 --- a/gridcast-react/app/(protected)/onboarding/page.tsx +++ b/gridcast-react/app/(protected)/onboarding/page.tsx @@ -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; @@ -168,7 +174,7 @@ export default function OnboardingPage() { transition: "all 0.3s", }} > - {done ? "βœ“" : i + 1} + {done ? : i + 1}
- ⚑ Typical base load for{" "} + Typical base load for{" "} {industryDef.label}:{" "} - ← Back + Back
diff --git a/gridcast-react/app/(public)/landing/page.tsx b/gridcast-react/app/(public)/landing/page.tsx index c5a7f75..dc2e553 100644 --- a/gridcast-react/app/(public)/landing/page.tsx +++ b/gridcast-react/app/(public)/landing/page.tsx @@ -4,6 +4,35 @@ import { useEffect, useState } from "react"; import dynamic from "next/dynamic"; import LoadChart from "@/components/charts/LoadChart"; import { usePredictiveEngine } from "@/lib/predictiveEngine"; +import { + Zap, + Cloud, + BarChart3, + Database, + Construction, + CheckCircle2, + Check, + Hourglass, + Calendar, + ArrowRight, + TrendingUp, + TrendingDown, + Cpu, + Activity, + ArrowDown, + DownloadCloud, + FileSearch, + Filter, + Server, + Eye, + Settings, + Code2, + Box, + Layers, + LineChart, + HardDrive, + Target +} from "lucide-react"; const HeroCanvas = dynamic(() => import("@/components/three/HeroCanvas"), { ssr: false, @@ -219,12 +248,12 @@ export default function LandingPage() { - See Live Demo β†’ + See Live Demo - - How it works ↓ + + How it works
@@ -322,7 +351,7 @@ export default function LandingPage() { > {[ ["4.7B+", "People on global grids"], - ["β‚Ή2T+", "India grid investment"], + ["INR 2T+", "India grid investment"], ["30%", "Reserve waste reducible"], ["0.716", "tCOβ‚‚/MWh India grid"], ].map(([v, l]) => ( @@ -518,37 +547,37 @@ export default function LandingPage() { > {[ [ - "⚑", + , "Demand Volatility", "Load swings 15–40% within minutes during peak events, outpacing manual dispatch by 3–5Γ— the required speed.", false, ], [ - "☁️", + , "Renewable Intermittency", "Solar and wind generation can drop 80% in minutes. Without forecasting, grid operators over-provision expensive reserves.", false, ], [ - "πŸ“Š", + , "Dispatch Inefficiency", "Without accurate 15-min forecasts, operators carry 20–30% excess reserve capacity at β‚Ή8–12/unit hidden cost.", false, ], [ - "πŸ—„οΈ", + , "Data Quality Gaps", "SCADA telemetry drops, sensor drift, and holiday anomalies create gaps conventional models can't bridge.", false, ], [ - "πŸ—οΈ", + , "Infrastructure Stress", "Legacy transmission infrastructure carries 110–125% rated load during heatwaves, risking catastrophic failure.", false, ], [ - "βœ…", + , "GridCast Solves This", "96-step autoregressive XGBoost + LSTM pipeline with anomaly detection and sub-3% MAPE on NRLDC data.", true, @@ -567,7 +596,7 @@ export default function LandingPage() { : { padding: 24 } } > -
{icon}
+
{icon}
{[ - ["SC", "Scrape", "Selenium ETL from NLDC portal every 15 min"], - ["EX", "Extract", "Parquet feature store with lag & calendar features"], - ["CL", "Clean", "Z-score anomaly detection + gap interpolation"], - ["ML", "Train", "XGBoost + LSTM on 2-year NRLDC data"], - ["API", "Serve", "Flask REST endpoint β€” P95 latency <1ms"], - ["UI", "Visualize", "Operator dashboard for grid intelligence"], - ].map(([code, title, desc]) => ( + [, "Scrape", "Selenium ETL from NLDC portal every 15 min"], + [, "Extract", "Parquet feature store with lag & calendar features"], + [, "Clean", "Z-score anomaly detection + gap interpolation"], + [, "Train", "XGBoost + LSTM on 2-year NRLDC data"], + [, "Serve", "Flask REST endpoint β€” P95 latency <1ms"], + [, "Visualize", "Operator dashboard for grid intelligence"], + ].map(([icon, title, desc]) => (
- {code} + {icon}
{title}
(
+ {label === "API Status" && } {label}
- Β±5% CI + +/- 5% CI
@@ -863,16 +896,17 @@ export default function LandingPage() { }} > {[ - ["-30%", "Reserve capacity waste"], - ["<3%", "24hr MAPE target"], - ["96Γ—", "Decisions per day"], - ["<1ms", "API inference latency"], - ].map(([val, label]) => ( + ["-30%", "Reserve capacity waste", ], + ["<3%", "24hr MAPE target", ], + ["96Γ—", "Decisions per day", ], + ["<1ms", "API inference latency", ], + ].map(([val, label, icon]) => (
+
{icon}
{[ - ["βœ“", "Core ML Pipeline", "var(--gc-green)"], - ["βœ“", "Operator Dashboard", "var(--gc-green)"], - ["⏳", "Weather Features", "var(--gc-amber)"], - ["πŸ“…", "Multi-Region", "var(--gc-muted)"], - ["πŸ“…", "LSTM Fine-tune", "var(--gc-muted)"], + [, "Core ML Pipeline", "var(--gc-green)"], + [, "Operator Dashboard", "var(--gc-green)"], + [, "Weather Features", "var(--gc-amber)"], + [, "Multi-Region", "var(--gc-muted)"], + [, "LSTM Fine-tune", "var(--gc-muted)"], ].map(([icon, title, color]) => (
], [ "Pandas / Parquet", "Feature store with lag, rolling stats, and calendar features. Sub-100ms load time.", "var(--gc-cyan)", + ], [ "Flask REST API", "P95 latency <1ms. Joblib model serialization. Docker-ready deployment.", "var(--gc-green)", + ], [ "Selenium ETL", "Automated NLDC scraping every 15 minutes. Handles auth, retry logic and pagination.", "var(--gc-violet)", + ], [ "React / Next.js", "Pure SVG + Three.js visualizations. Operator dashboard with real-time data binding.", "var(--gc-cyan)", + ], [ "LSTM (Planned)", "PyTorch sequence model for long-range patterns. Captures weekly seasonality across 96+ steps.", "var(--gc-amber)", + ], - ].map(([title, desc, color]) => ( + ].map(([title, desc, color, icon]) => (
+ > + {icon} +
{title}
- Request a Demo β†’ + Request a Demo - View on GitHub β†— + View on GitHub
@@ -1117,7 +1156,7 @@ export default function LandingPage() { fontFamily: "var(--gc-font-mono)", }} > - {["GridCast v2.1", "MIT License", "Β© 2025 Team NavGati", "Built on NRLDC Open Data"].map( + {["GridCast v2.1", "MIT License", "(c) 2025 Team NavGati", "Built on NRLDC Open Data"].map( (t) => {t} )}
diff --git a/gridcast-react/app/globals.css b/gridcast-react/app/globals.css index 0a5256d..86868b0 100644 --- a/gridcast-react/app/globals.css +++ b/gridcast-react/app/globals.css @@ -42,6 +42,23 @@ --gc-ease-out: cubic-bezier(0, 0, 0.2, 1); } +/* ─── LIGHT THEME OVERRIDES ──────────────────────────────────────────────────── */ +.gc-theme-light { + --gc-bg: #f8fafc; + --gc-bg2: #ffffff; + --gc-bg3: #f1f5f9; + --gc-surface: #ffffff; + --gc-surface2: #f8fafc; + --gc-text: #0f172a; + --gc-text-2: #475569; + --gc-muted: #64748b; + --gc-subtle: #94a3b8; + --gc-ghost: #e2e8f0; + --gc-border: #e2e8f0; + --gc-border-2: rgba(6, 182, 212, 0.1); + --gc-border-3: rgba(6, 182, 212, 0.2); +} + /* ─── RESET & BASE ───────────────────────────────────────────────────────────── */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } @@ -175,17 +192,22 @@ body { .gc-select { appearance: none; + background-color: rgba(6, 182, 212, 0.05); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2364748b'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 12px center; background-size: 16px; padding-right: 36px !important; cursor: pointer; + color: var(--gc-text); + border: 1px solid var(--gc-border-2); + border-radius: 8px; } .gc-select option { - background-color: #0a1929; + background-color: #020f1a; color: #e2e8f0; + padding: 10px; } /* Autofill overrides for dark mode */ diff --git a/gridcast-react/app/login/page.tsx b/gridcast-react/app/login/page.tsx index 3745164..d69b649 100644 --- a/gridcast-react/app/login/page.tsx +++ b/gridcast-react/app/login/page.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { useRouter } from "next/navigation"; import Link from "next/link"; +import { Settings, Building2, ArrowLeft, ShieldCheck, ArrowRight, Terminal, Mail } from "lucide-react"; type LoginMode = null | "admin" | "company"; @@ -121,9 +122,9 @@ export default function LoginPage() {

{[ - { id: "admin", emoji: "πŸ”§", title: "Admin", sub: "Grid operators, NLDC engineers, system administrators" }, - { id: "company", emoji: "🏒", title: "Company", sub: "Industrial consumers, data centers, large enterprises" }, - ].map(({ id, emoji, title, sub }) => ( + { id: "admin", title: "Admin", sub: "Grid operators, NLDC engineers, system administrators" }, + { id: "company", title: "Company", sub: "Industrial consumers, data centers, large enterprises" }, + ].map(({ id, title, sub }) => ( @@ -173,11 +176,13 @@ export default function LoginPage() { display: "flex", alignItems: "center", gap: 6, }} > - ← Back + Back
- {mode === "admin" ? "πŸ”§" : "🏒"} + + {mode === "admin" ? : } +
{mode === "admin" ? "Admin Login" : "Company Login"} @@ -220,7 +225,11 @@ export default function LoginPage() { style={{ width: "100%", justifyContent: "center", fontSize: 14, padding: "13px", opacity: loading ? 0.75 : 1 }} disabled={loading} > - {loading ? "Authenticating…" : mode === "admin" ? "Sign In as Admin β†’" : "Sign In as Company β†’"} + {loading ? "Authenticating…" : ( + <> + {mode === "admin" ? "Sign In as Admin" : "Sign In as Company"} + + )}
@@ -230,7 +239,10 @@ export default function LoginPage() {
- {[{ icon: "G", label: "Google" }, { icon: "GH", label: "GitHub" }].map(({ icon, label }) => ( + {[ + { icon: , label: "Google" }, + { icon: , label: "GitHub" } + ].map(({ icon, label }) => ( ))}
diff --git a/gridcast-react/components/GridCastApp.tsx b/gridcast-react/components/GridCastApp.tsx index cdbf1f3..5a86885 100644 --- a/gridcast-react/components/GridCastApp.tsx +++ b/gridcast-react/components/GridCastApp.tsx @@ -11,6 +11,47 @@ import { ForecastChart } from '@/components/charts/ForecastChart'; import { ModelComparison } from '@/components/charts/ModelComparison'; import { ResidualHeatmap } from '@/components/charts/ResidualHeatmap'; import { KPICard } from '@/components/dashboard/KPICard'; +import { + Zap, + TrendingUp, + Target, + Activity, + RefreshCw, + Clock, + LogOut, + FileText, + LayoutDashboard, + Leaf, + DollarSign, + Sun, + BarChart, + Layers, + Home, + Car, + Factory, + CheckCircle, + AlertTriangle, + ArrowLeft, + ArrowRight, + ShieldCheck, + Building2, + Mail, + Terminal, + ChevronRight, + Info, + DownloadCloud, + FileSearch, + Filter, + Server, + Eye, + Settings, + Code2, + Box, + TrendingDown, + HardDrive, + Cloud, + Cpu +} from "lucide-react"; const ReactApexChart = dynamic(() => import("react-apexcharts"), { ssr: false }); @@ -25,6 +66,18 @@ declare global { const INDIA_GRID_EMISSION_FACTOR = 0.716; const INR_PER_KWH = 7.5; +const inputSt = { + background: "rgba(6,182,212,0.05)", + border: "1px solid rgba(6,182,212,0.2)", + borderRadius: 8, + padding: "11px 14px", + color: "#e2e8f0", + fontSize: 14, + width: "100%", + fontFamily: "inherit", + outline: "none" +}; + const REGIONS = [ { id: "north", label: "North (NRLDC)", nodes: ["DEL-N", "HR-01", "UP-02", "PB-01", "RJ-03"], color: "#06b6d4" }, { id: "west", label: "West (WRLDC)", nodes: ["MH-01", "GJ-02", "MP-03", "CG-01", "GJ-03"], color: "#f59e0b" }, @@ -755,15 +808,15 @@ function LandingPage({ onNavigate }: { onNavigate: (p: string) => void }) {
{[ - ["⚑", "Demand Volatility", "Load swings 15–40% within minutes during peak events, outpacing manual dispatch by 3–5Γ—."], - ["☁", "Renewable Intermittency", "Solar and wind generation can drop 80% in minutes. Without forecasting, operators over-provision expensive reserves."], - ["πŸ“Š", "Dispatch Inefficiency", "Without accurate 15-min forecasts, operators carry 20–30% excess reserve capacity at β‚Ή8–12/unit hidden cost."], - ["πŸ—„", "Data Quality Gaps", "SCADA telemetry drops, sensor drift, and holiday anomalies create gaps conventional models cannot bridge."], - ["πŸ—", "Infrastructure Stress", "Legacy transmission infrastructure carries 110–125% rated load during heatwaves, risking catastrophic failure."], - ["βœ…", "GridCast Solves This", "96-step autoregressive XGBoost + LSTM pipeline with automated anomaly detection and sub-3% MAPE on NRLDC data.", true], + [, "Demand Volatility", "Load swings 15–40% within minutes during peak events, outpacing manual dispatch by 3–5Γ—."], + [, "Renewable Intermittency", "Solar and wind generation can drop 80% in minutes. Without forecasting, operators over-provision expensive reserves."], + [, "Dispatch Inefficiency", "Without accurate 15-min forecasts, operators carry 20–30% excess reserve capacity at β‚Ή8–12/unit hidden cost."], + [, "Data Quality Gaps", "SCADA telemetry drops, sensor drift, and holiday anomalies create gaps conventional models can't bridge."], + [, "Infrastructure Stress", "Legacy transmission infrastructure carries 110–125% rated load during heatwaves, risking catastrophic failure."], + [, "GridCast Solves This", "96-step autoregressive XGBoost + LSTM pipeline with automated anomaly detection and sub-3% MAPE on NRLDC data.", true], ].map(([icon, title, desc, highlight]) => (
-
{icon}
+
{icon}
{title}
{desc}
@@ -779,9 +832,16 @@ function LandingPage({ onNavigate }: { onNavigate: (p: string) => void }) {
- {[["SC", "Scrape", "Selenium ETL from NLDC portal every 15 min"], ["EX", "Extract", "Parquet feature store with lag & calendar vars"], ["CL", "Clean", "Z-score anomaly detect + gap interpolation"], ["ML", "Train", "XGBoost + LSTM on 2-yr NRLDC data"], ["API", "Serve", "Flask REST Β· P95 latency <1ms"], ["UI", "Visualise", "Operator dashboard + company portal"]].map(([code, title, desc]) => ( -
-
{code}
+ {[ + [, "Scrape", "Selenium ETL from NLDC portal every 15 min"], + [, "Extract", "Parquet feature store with lag & calendar vars"], + [, "Clean", "Z-score anomaly detect + gap interpolation"], + [, "Train", "XGBoost + LSTM on 2-yr NRLDC data"], + [, "Serve", "Flask REST Β· P95 latency <1ms"], + [, "Visualise", "Operator dashboard + company portal"] + ].map(([icon, title, desc]) => ( +
+
{icon}
{title}
{desc}
@@ -823,8 +883,14 @@ function LandingPage({ onNavigate }: { onNavigate: (p: string) => void }) {

Results that matter

- {[["-30%", "Reserve capacity waste"], ["<3%", "24hr MAPE target"], ["96Γ—", "Decisions per day"], ["<1ms", "API inference latency"]].map(([val, label]) => ( + {[ + ["-30%", "Reserve capacity waste", ], + ["<3%", "24hr MAPE target", ], + ["96Γ—", "Decisions per day", ], + ["<1ms", "API inference latency", ] + ].map(([val, label, icon]) => (
+
{icon}
{val}
{label}
@@ -839,9 +905,16 @@ function LandingPage({ onNavigate }: { onNavigate: (p: string) => void }) {

Production-grade infrastructure

- {[["XGBoost", "Gradient-boosted forecasting with SHAP explainability. 96-step autoregressive rollout.", "#f59e0b"], ["Pandas / Parquet", "Feature store with lag, rolling stats, and calendar features. Sub-100ms load time.", "#06b6d4"], ["Flask REST API", "P95 latency <1ms. Joblib model serialization. Docker-ready deployment.", "#10b981"], ["Selenium ETL", "Automated NLDC data scraping every 15 minutes. Retry logic and gap filling.", "#a78bfa"], ["SVG Dashboard", "Pure SVG visualisations. Zero-dependency, works offline on operator terminals.", "#06b6d4"], ["LSTM (Planned)", "PyTorch sequence model for long-range patterns. Captures weekly seasonality across 96+ steps.", "#f59e0b"]].map(([title, desc, color]) => ( + {[ + ["XGBoost", "Gradient-boosted forecasting with SHAP explainability. 96-step autoregressive rollout.", "#f59e0b", ], + ["Pandas / Parquet", "Feature store with lag, rolling stats, and calendar features. Sub-100ms load time.", "#06b6d4", ], + ["Flask REST API", "P95 latency <1ms. Joblib model serialization. Docker-ready deployment.", "#10b981", ], + ["Selenium ETL", "Automated NLDC data scraping every 15 minutes. Retry logic and gap filling.", "#a78bfa", ], + ["SVG Dashboard", "Pure SVG visualisations. Zero-dependency, works offline on operator terminals.", "#06b6d4", ], + ["LSTM (Planned)", "PyTorch sequence model for long-range patterns. Captures weekly seasonality across 96+ steps.", "#f59e0b", ] + ].map(([title, desc, color, icon]) => (
-
+
{icon}
{title}
{desc}
@@ -894,13 +967,6 @@ function LoginPage({ onNavigate }: { onNavigate: (p: string) => void }) { } }; - const fillDemo = () => { - if (!mode) return; - const creds = DEMO_CREDS[mode]; - setForm({ email: creds.email, password: creds.password }); - setError(""); - }; - return (
@@ -924,13 +990,6 @@ function LoginPage({ onNavigate }: { onNavigate: (p: string) => void }) { {[200, 600, 1000].map(x => ( ))} - {[150, 500, 850].map(x => ( - - - - - - ))} {/* Glass card */} @@ -938,7 +997,7 @@ function LoginPage({ onNavigate }: { onNavigate: (p: string) => void }) {
- GridCast + GridCast

AI-powered grid forecasting platform

@@ -947,41 +1006,52 @@ function LoginPage({ onNavigate }: { onNavigate: (p: string) => void }) { <>

Select your access type to continue

- {[{ id: "admin" as const, icon: "πŸ”§", title: "Admin", sub: "Grid operators, NLDC engineers, system administrators" }, { id: "company" as const, icon: "🏒", title: "Company", sub: "Industrial consumers, data centers, large enterprises" }].map(({ id, icon, title, sub }) => ( - - ))} + +
) : ( <> - + -
- {mode === "admin" ? "πŸ”§" : "🏒"} +
+ {mode === "admin" ? : }
{mode === "admin" ? "Admin Login" : "Company Login"}
{mode === "admin" ? "Grid operator access Β· NRLDC" : "Industrial consumer access"}
-
- { setForm({ ...form, email: e.target.value }); setError(""); }} onKeyDown={e => e.key === "Enter" && handleLogin()} /> - { setForm({ ...form, password: e.target.value }); setError(""); }} onKeyDown={e => e.key === "Enter" && handleLogin()} /> -
- {error &&
{error}
} -
- - Forgot password? + +
+
+ + setForm({ ...form, email: e.target.value })} /> +
+
+ + setForm({ ...form, password: e.target.value })} /> +
+ + {error &&
+ {error} +
} + )} @@ -989,7 +1059,6 @@ function LoginPage({ onNavigate }: { onNavigate: (p: string) => void }) {
); } - // ───────────────────────────────────────────────────────────────────────────── // PAGE: ONBOARDING FORM // ───────────────────────────────────────────────────────────────────────────── @@ -1000,7 +1069,6 @@ function CompanyFormPage({ onNavigate }: { onNavigate: (p: string) => void }) { const industryDef = INDUSTRY_TYPES.find(i => i.value === formData.industry); const STEPS = ["Company Profile", "Electricity Setup", "Goals & Sustainability"]; - const inputSt = { background: "rgba(6,182,212,0.05)", border: "1px solid rgba(6,182,212,0.2)", borderRadius: 8, padding: "11px 14px", color: "#e2e8f0", fontSize: 14, width: "100%", fontFamily: "inherit", outline: "none" }; return (
@@ -1043,7 +1111,7 @@ function CompanyFormPage({ onNavigate }: { onNavigate: (p: string) => void }) { {INDUSTRY_TYPES.map(t => )} - {industryDef &&
⚑ Typical base load: {industryDef.baseLoad} MW · PUE: {industryDef.pue}
} + {industryDef &&
Typical base load: {industryDef.baseLoad} MW Β· PUE: {industryDef.pue}
}
@@ -1101,7 +1169,7 @@ function CompanyFormPage({ onNavigate }: { onNavigate: (p: string) => void }) {
@@ -1181,17 +1249,17 @@ function CompanyDashboard({ onNavigate }: { onNavigate: (p: string) => void }) { const modelLabel = model === "xgboost" ? "XGBoost" : "LSTM"; const kpiCards = [ - { label: "COβ‚‚ Avoided (MTD)", value: (co2Saved / 12).toFixed(1), unit: "tCOβ‚‚", color: "#10b981", icon: "🌿", trend: "+8.2% vs last month" }, - { label: "Energy Optimised (MTD)", value: (savingsMWh / 12).toFixed(0), unit: "MWh", color: "#06b6d4", icon: "⚑", trend: "+12.1% vs last month" }, - { label: "Cost Saved (MTD)", value: `β‚Ή${((inrSaved / 12) / 100000).toFixed(1)}L`, unit: "", color: "#f59e0b", icon: "πŸ’°", trend: "+9.5% vs last month" }, - { label: "Grid Carbon Intensity", value: "0.716", unit: "tCOβ‚‚/MWh", color: "#a78bfa", icon: "πŸ“Š", trend: "CEA FY2022-23 baseline" }, - { label: "Renewable Share", value: "22", unit: "%", color: "#10b981", icon: "β˜€οΈ", trend: "Target: 40% by 2027" }, + { label: "COβ‚‚ Avoided (MTD)", value: (co2Saved / 12).toFixed(1), unit: "tCOβ‚‚", color: "#10b981", icon: , trend: "+8.2% vs last month" }, + { label: "Energy Optimised (MTD)", value: (savingsMWh / 12).toFixed(0), unit: "MWh", color: "#06b6d4", icon: , trend: "+12.1% vs last month" }, + { label: "Cost Saved (MTD)", value: `β‚Ή${((inrSaved / 12) / 100000).toFixed(1)}L`, unit: "", color: "#f59e0b", icon: , trend: "+9.5% vs last month" }, + { label: "Grid Carbon Intensity", value: "0.716", unit: "tCOβ‚‚/MWh", color: "#a78bfa", icon: , trend: "CEA FY2022-23 baseline" }, + { label: "Renewable Share", value: "22", unit: "%", color: "#10b981", icon: , trend: "Target: 40% by 2027" }, { label: "Forecast Accuracy", value: metrics.mape !== null ? (100 - metrics.mape).toFixed(1) : "N/A", unit: metrics.mape !== null ? "%" : "", color: modelColor, - icon: "🎯", + icon: , trend: metrics.mape !== null ? `MAPE ${metrics.mape.toFixed(2)}% Β· ${horizon} Β· ${modelLabel}` @@ -1199,7 +1267,13 @@ function CompanyDashboard({ onNavigate }: { onNavigate: (p: string) => void }) { }, ]; - const NAV_ITEMS = [["πŸ“Š", "Overview", "overview"], ["⚑", "Load Forecast", "forecast"], ["🌿", "Carbon Tracker", "carbon"], ["πŸ“…", "Schedule Optimizer", "schedule"], ["πŸ“„", "Reports", "reports"]]; + const NAV_ITEMS = [ + { 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" } + ]; return (
@@ -1210,9 +1284,9 @@ function CompanyDashboard({ onNavigate }: { onNavigate: (p: string) => void }) { GridCast
Navigation
- {NAV_ITEMS.map(([icon, label, id]) => ( - ))}
@@ -1235,8 +1309,8 @@ function CompanyDashboard({ onNavigate }: { onNavigate: (p: string) => void }) { {/* Topbar */}
- {NAV_ITEMS.map(([icon, label, id]) => ( - + {NAV_ITEMS.map((item) => ( + ))}
@@ -1296,7 +1370,7 @@ function CompanyDashboard({ onNavigate }: { onNavigate: (p: string) => void }) {
{k.label} - {k.icon} +
{k.icon}
{k.value}{k.unit} @@ -1328,12 +1402,17 @@ function CompanyDashboard({ onNavigate }: { onNavigate: (p: string) => void }) {
COβ‚‚ Equivalents Avoided
- {[[`${treesEquiv.toLocaleString("en-IN")}`, "Trees grown for 10 yrs", "🌳", "#10b981"], [`${homeEquiv.toLocaleString("en-IN")}`, "Indian homes powered / yr", "🏠", "#06b6d4"], [`${(co2Saved / 2.31).toFixed(0)}`, "Cars off road for 1 yr", "πŸš—", "#f59e0b"], [`${(co2Saved * 0.1).toFixed(1)} t`, "Coal not burned", "🏭", "#a78bfa"]].map(([val, label, icon, color]) => ( -
- {icon} + {[ + [`${treesEquiv.toLocaleString("en-IN")}`, "Trees grown for 10 yrs", , "#10b981"], + [`${homeEquiv.toLocaleString("en-IN")}`, "Indian homes powered / yr", , "#06b6d4"], + [`${(co2Saved / 2.31).toFixed(0)}`, "Cars off road for 1 yr", , "#f59e0b"], + [`${(co2Saved * 0.1).toFixed(1)} t`, "Coal not burned", , "#a78bfa"] + ].map(([val, label, icon, color]) => ( +
+
{icon}
-
{val}
-
{label}
+
{val}
+
{label as string}
))} @@ -1478,9 +1557,9 @@ function CompanyDashboard({ onNavigate }: { onNavigate: (p: string) => void }) { })}
- β–  Low (01–05h) - β–  Medium - β–  Peak +
Low (01–05h) +
Medium +
Peak
@@ -1520,9 +1599,14 @@ function CompanyDashboard({ onNavigate }: { onNavigate: (p: string) => void }) { <>

Reports & Compliance

Download GHG inventory reports, BEE compliance summaries, and grid interaction logs.

- {[["πŸ“Š", "Monthly Energy Report", "April 2026 Β· PDF", "GHG inventory, load curve, savings summary"], ["🌿", "Scope 2 Carbon Report", "Q1 2026 Β· PDF", "CEA-compliant carbon accounting"], ["πŸ“‹", "BEE PAT Compliance", "FY2025-26 Β· XLSX", "Bureau of Energy Efficiency PAT data"], ["⚑", "Grid Interaction Log", "April 23 Β· CSV", "15-min demand & export data"]].map(([icon, title, meta, desc]) => ( -
- {icon} + {[ + [, "Monthly Energy Report", "April 2026 Β· PDF", "GHG inventory, load curve, savings summary"], + [, "Scope 2 Carbon Report", "Q1 2026 Β· PDF", "CEA-compliant carbon accounting"], + [, "BEE PAT Compliance", "FY2025-26 Β· XLSX", "Bureau of Energy Efficiency PAT data"], + [, "Grid Interaction Log", "April 23 Β· CSV", "15-min demand & export data"] + ].map(([icon, title, meta, desc]) => ( +
+ {icon}
{title}
{meta}
@@ -1600,12 +1684,12 @@ function AdminDashboard({ onNavigate }: { onNavigate: (p: string) => void }) { } return ( -
+
{/* Navbar */} -