From c3ae2ac95db54113ebebe8abfeac415548c243b4 Mon Sep 17 00:00:00 2001 From: yatharthchopra2424 Date: Thu, 23 Apr 2026 22:18:13 +0530 Subject: [PATCH 01/11] style: replace emojis with professional Lucide iconography - Upgraded Landing Page 'Six Problems' section with professional vector icons. - Modernised Login Page with Shields, Buildings, and Social SVGs. - Standardised Company and Admin Dashboards by replacing emojis with industrial-grade icons. - Updated Onboarding flow with vector progress and navigation components. - Removed all text-based arrows and amateur symbols in favour of high-performance Lucide-React components. --- gridcast-react/app/(protected)/admin/page.tsx | 41 ++++++++++------ .../app/(protected)/company/page.tsx | 49 ++++++++++++------- .../app/(protected)/onboarding/page.tsx | 14 ++++-- gridcast-react/app/(public)/landing/page.tsx | 38 +++++++++----- gridcast-react/app/login/page.tsx | 24 ++++++--- 5 files changed, 112 insertions(+), 54 deletions(-) diff --git a/gridcast-react/app/(protected)/admin/page.tsx b/gridcast-react/app/(protected)/admin/page.tsx index 4f7004c..39fcaf0 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 /> @@ -303,7 +316,7 @@ export default function AdminDashboard() { {/* Operational Alerts */}

- πŸ”” Engine Alerts + Engine Alerts

@@ -383,7 +396,7 @@ export default function AdminDashboard() {
- {m === 'xgboost' ? '🌳' : '🧠'} + {m === 'xgboost' ? : }

{cfg.name}

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

Add Ensemble Layer

Coming Q3 2026

@@ -417,9 +430,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..9b0d863 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,25 +425,25 @@ 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..c072ed9 100644 --- a/gridcast-react/app/(public)/landing/page.tsx +++ b/gridcast-react/app/(public)/landing/page.tsx @@ -4,6 +4,20 @@ 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, + Cpu +} from "lucide-react"; const HeroCanvas = dynamic(() => import("@/components/three/HeroCanvas"), { ssr: false, @@ -518,37 +532,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 +581,7 @@ export default function LandingPage() { : { padding: 24 } } > -
{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]) => (
-
{emoji}
+
+ {id === "admin" ? : } +
{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 }) => ( ))}
From 575aee1850a887a291bf30133c44b53848d85f17 Mon Sep 17 00:00:00 2001 From: yatharthchopra2424 Date: Thu, 23 Apr 2026 22:21:17 +0530 Subject: [PATCH 02/11] style: enhance dashboard charts and optimize layout - Fixed data label clipping in Model Comparison chart by adding Y-axis headroom. - Standardized chart titles with professional vertical accent bars and uppercase typography. - Integrated Status Log into Model Comparison card to reduce vertical white space. - Tightened dashboard grid layout to improve data density and bring heatmap into view. --- gridcast-react/app/(protected)/admin/page.tsx | 34 ++------ .../components/charts/ForecastChart.tsx | 15 ++-- .../components/charts/ModelComparison.tsx | 86 +++++++++++++++---- .../components/charts/ResidualHeatmap.tsx | 17 ++-- 4 files changed, 97 insertions(+), 55 deletions(-) diff --git a/gridcast-react/app/(protected)/admin/page.tsx b/gridcast-react/app/(protected)/admin/page.tsx index 39fcaf0..b8cdb79 100644 --- a/gridcast-react/app/(protected)/admin/page.tsx +++ b/gridcast-react/app/(protected)/admin/page.tsx @@ -304,42 +304,24 @@ 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 */} -
+
diff --git a/gridcast-react/components/charts/ForecastChart.tsx b/gridcast-react/components/charts/ForecastChart.tsx index ac9559a..0d4cba5 100644 --- a/gridcast-react/components/charts/ForecastChart.tsx +++ b/gridcast-react/components/charts/ForecastChart.tsx @@ -167,12 +167,15 @@ export function ForecastChart({ data, model, loading }: ForecastChartProps) { } return ( -
-
-

- Forecast: {data.horizon} Ahead -

-

+

+
+
+
+

+ Forecast: {data.horizon} Ahead +

+
+

Engine Sync: {new Date(data.generated_at).toLocaleString('en-IN', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' })}

diff --git a/gridcast-react/components/charts/ModelComparison.tsx b/gridcast-react/components/charts/ModelComparison.tsx index 32109ac..ed6e8e8 100644 --- a/gridcast-react/components/charts/ModelComparison.tsx +++ b/gridcast-react/components/charts/ModelComparison.tsx @@ -3,12 +3,18 @@ import Chart from 'react-apexcharts'; import { useMemo } from 'react'; import { ForecastData, Horizon } from '@/types'; +import { Bell, CheckCircle2, AlertCircle } from 'lucide-react'; interface ModelComparisonProps { xgboostData: ForecastData | null; lstmData: ForecastData | null; horizon: Horizon; loading: boolean; + status?: { + type: 'stable' | 'warning' | 'error'; + message: string; + engine: string; + }; } export function ModelComparison({ @@ -16,6 +22,7 @@ export function ModelComparison({ lstmData, horizon, loading, + status, }: ModelComparisonProps) { const chartOptions = useMemo(() => { if (!xgboostData || !lstmData) { @@ -38,13 +45,17 @@ export function ModelComparison({ lstmData.horizon_metrics[horizon]?.mape || 0, ]; + // Find max value to set headroom + const allValues = [...xgbValues, ...lstmValues]; + const maxValue = Math.max(...allValues); + return { chart: { type: 'bar' as const, toolbar: { show: false }, fontFamily: 'DM Sans, sans-serif', background: 'transparent', - height: 280, + height: 250, }, series: [ { @@ -64,17 +75,20 @@ export function ModelComparison({ style: { fontSize: '12px', colors: '#94a3b8', + fontWeight: 600, }, }, axisBorder: { show: false }, axisTicks: { show: false }, }, yaxis: { + max: maxValue * 1.25, // Add 25% headroom for data labels title: { text: 'Error Value', style: { fontSize: '11px', color: '#94a3b8', + fontWeight: 600, }, }, labels: { @@ -84,6 +98,16 @@ export function ModelComparison({ }, }, }, + dataLabels: { + enabled: true, + offsetY: -20, + style: { + fontSize: '10px', + colors: ['#475569'], + fontWeight: 700, + }, + formatter: (val: number) => val.toFixed(1), + }, tooltip: { enabled: true, theme: 'dark', @@ -98,6 +122,10 @@ export function ModelComparison({ horizontalAlign: 'right' as const, fontSize: '12px', fontFamily: 'DM Sans, sans-serif', + fontWeight: 600, + labels: { + colors: '#64748b' + } }, grid: { show: true, @@ -108,8 +136,8 @@ export function ModelComparison({ plotOptions: { bar: { horizontal: false, - columnWidth: '60%', - borderRadius: 4, + columnWidth: '55%', + borderRadius: 6, dataLabels: { position: 'top' as const, }, @@ -135,21 +163,47 @@ export function ModelComparison({ } return ( -
-
-

- Model Comparison -

-

- Backtest Performance: XGBoost vs LSTM ({horizon}) +

+
+
+
+

+ Model Comparison +

+
+

+ Backtest Performance: {horizon} Horizon

- + +
+ +
+ + {status && ( +
+
+
+ {status.type === 'stable' ? : + status.type === 'warning' ? : + } +
+
+

{status.engine} {status.type}

+

{status.message}

+
+
+
+ )}
); } diff --git a/gridcast-react/components/charts/ResidualHeatmap.tsx b/gridcast-react/components/charts/ResidualHeatmap.tsx index 3b7ceeb..94d57f3 100644 --- a/gridcast-react/components/charts/ResidualHeatmap.tsx +++ b/gridcast-react/components/charts/ResidualHeatmap.tsx @@ -93,13 +93,16 @@ export function ResidualHeatmap({ data, loading }: ResidualHeatmapProps) { } return ( -
-
-

- Residual Errors (7 Days Γ— 24 Hours) -

-

- Error distribution heatmap - Green = Low, Red = High +

+
+
+
+

+ Residual Errors (7 Days Γ— 24 Hours) +

+
+

+ Error distribution heatmap Β· Green = Optimal

From 939abcbf621a8a3cdd14c4a3f7bfe989d73e4ffd Mon Sep 17 00:00:00 2001 From: yatharthchopra2424 Date: Thu, 23 Apr 2026 22:25:44 +0530 Subject: [PATCH 03/11] refactor: finalize dashboard layout and professional iconography - Removed Status Log from Admin Dashboard to streamline performance views. - Removed MAPE from Model Comparison bar chart (showing MAE and RMSE only). - Added left margin to all chart titles for improved visual alignment. - Replaced all remaining emojis and text-based arrows on Landing and Login pages with Lucide icons. - Cleaned up unused emoji properties in login configuration. --- gridcast-react/app/(protected)/admin/page.tsx | 5 --- gridcast-react/app/(public)/landing/page.tsx | 26 +++++++----- gridcast-react/app/login/page.tsx | 6 +-- .../components/charts/ForecastChart.tsx | 4 +- .../components/charts/ModelComparison.tsx | 40 +++---------------- .../components/charts/ResidualHeatmap.tsx | 4 +- 6 files changed, 29 insertions(+), 56 deletions(-) diff --git a/gridcast-react/app/(protected)/admin/page.tsx b/gridcast-react/app/(protected)/admin/page.tsx index b8cdb79..d678427 100644 --- a/gridcast-react/app/(protected)/admin/page.tsx +++ b/gridcast-react/app/(protected)/admin/page.tsx @@ -310,11 +310,6 @@ export default function AdminDashboard() { lstmData={lstmData} horizon={activeHorizon} loading={loading} - status={{ - type: 'stable', - message: 'Latest forecast successfully generated. MAPE variance within optimal bounds.', - engine: 'XGBOOST' - }} />
diff --git a/gridcast-react/app/(public)/landing/page.tsx b/gridcast-react/app/(public)/landing/page.tsx index c072ed9..5b2d116 100644 --- a/gridcast-react/app/(public)/landing/page.tsx +++ b/gridcast-react/app/(public)/landing/page.tsx @@ -16,7 +16,9 @@ import { Calendar, ArrowRight, TrendingUp, - Cpu + Cpu, + Activity, + ArrowDown } from "lucide-react"; const HeroCanvas = dynamic(() => import("@/components/three/HeroCanvas"), { @@ -233,12 +235,12 @@ export default function LandingPage() { - See Live Demo β†’ + See Live Demo - - How it works ↓ + + How it works
@@ -743,7 +745,7 @@ export default function LandingPage() { ["Peak Forecast", chartData ? `${Math.round(Math.max(...chartData.forecast)).toLocaleString()} MW` : "45,320 MW", "var(--gc-amber)"], ["Model MAPE", metrics?.mape ? `${metrics.mape.toFixed(2)}%` : "2.4%", "var(--gc-green)"], ["Last Updated", metrics?.dataEnd ? new Date(metrics.dataEnd).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : "14:30 IST", "var(--gc-text-2)"], - ["API Status", loading ? "● SYNCING" : chartData ? "● LIVE" : "β—‹ OFFLINE", loading ? "var(--gc-amber)" : chartData ? "var(--gc-green)" : "var(--gc-red)"], + ["API Status", loading ? "SYNCING" : chartData ? "LIVE" : "OFFLINE", loading ? "var(--gc-amber)" : chartData ? "var(--gc-green)" : "var(--gc-red)"], ].map(([label, val, color]) => (
+ {label === "API Status" && } {label}
- Request a Demo β†’ + Request a Demo - View on GitHub β†— + View on GitHub
diff --git a/gridcast-react/app/login/page.tsx b/gridcast-react/app/login/page.tsx index 12b8574..417e185 100644 --- a/gridcast-react/app/login/page.tsx +++ b/gridcast-react/app/login/page.tsx @@ -122,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 }) => ( -
@@ -924,13 +958,6 @@ function LoginPage({ onNavigate }: { onNavigate: (p: string) => void }) { {[200, 600, 1000].map(x => ( ))} - {[150, 500, 850].map(x => ( - - - - - - ))} {/* Glass card */} @@ -938,7 +965,7 @@ function LoginPage({ onNavigate }: { onNavigate: (p: string) => void }) {
- GridCast + GridCast

AI-powered grid forecasting platform

@@ -947,41 +974,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 +1027,6 @@ function LoginPage({ onNavigate }: { onNavigate: (p: string) => void }) {
); } - // ───────────────────────────────────────────────────────────────────────────── // PAGE: ONBOARDING FORM // ───────────────────────────────────────────────────────────────────────────── @@ -1000,7 +1037,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 +1079,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 +1137,7 @@ function CompanyFormPage({ onNavigate }: { onNavigate: (p: string) => void }) {
@@ -1181,17 +1217,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 +1235,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 +1252,9 @@ function CompanyDashboard({ onNavigate }: { onNavigate: (p: string) => void }) { GridCast
Navigation
- {NAV_ITEMS.map(([icon, label, id]) => ( - ))}
@@ -1235,8 +1277,8 @@ function CompanyDashboard({ onNavigate }: { onNavigate: (p: string) => void }) { {/* Topbar */}
- {NAV_ITEMS.map(([icon, label, id]) => ( - + {NAV_ITEMS.map((item) => ( + ))}
@@ -1296,7 +1338,7 @@ function CompanyDashboard({ onNavigate }: { onNavigate: (p: string) => void }) {
{k.label} - {k.icon} +
{k.icon}
{k.value}{k.unit} @@ -1328,12 +1370,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 +1525,9 @@ function CompanyDashboard({ onNavigate }: { onNavigate: (p: string) => void }) { })}
- β–  Low (01–05h) - β–  Medium - β–  Peak +
Low (01–05h) +
Medium +
Peak
@@ -1600,12 +1647,12 @@ function AdminDashboard({ onNavigate }: { onNavigate: (p: string) => void }) { } return ( -
+
{/* Navbar */} -