diff --git a/apps/web-dashboard/src/app/chaos/page.tsx b/apps/web-dashboard/src/app/chaos/page.tsx
new file mode 100644
index 0000000..f1675a3
--- /dev/null
+++ b/apps/web-dashboard/src/app/chaos/page.tsx
@@ -0,0 +1,146 @@
+"use client";
+
+import { useState } from "react";
+import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
+import { Badge } from "@/components/ui/badge";
+import { Button } from "@/components/ui/button";
+import { Shield, Zap, Clock, AlertTriangle, Server, Database, Wifi } from "lucide-react";
+
+interface Experiment {
+ id: string;
+ name: string;
+ target: string;
+ type: string;
+ icon: typeof Server;
+ description: string;
+ status: "idle" | "running" | "completed" | "failed";
+ lastRun?: string;
+ duration?: string;
+}
+
+const initialExperiments: Experiment[] = [
+ {
+ id: "exp_001", name: "API Latency Injection", target: "API Server", type: "latency",
+ icon: Server, description: "Inject 500ms latency on all API endpoints to test client timeout handling.",
+ status: "idle", lastRun: "2026-04-13 15:00", duration: "5m",
+ },
+ {
+ id: "exp_002", name: "Database Connection Kill", target: "PostgreSQL", type: "kill",
+ icon: Database, description: "Terminate database connections to verify reconnection and circuit breaker logic.",
+ status: "idle", lastRun: "2026-04-12 10:30", duration: "2m",
+ },
+ {
+ id: "exp_003", name: "Charging Engine Crash", target: "Charging Engine", type: "crash",
+ icon: Zap, description: "Simulate Rust charging engine crash to validate Go fallback and graceful degradation.",
+ status: "idle", lastRun: "2026-04-11 09:00", duration: "3m",
+ },
+ {
+ id: "exp_004", name: "Network Partition", target: "AMF Gateway", type: "partition",
+ icon: Wifi, description: "Simulate network partition between API server and AMF to test session continuity.",
+ status: "idle", duration: "10m",
+ },
+ {
+ id: "exp_005", name: "Redis Cache Flush", target: "Redis", type: "flush",
+ icon: Database, description: "Flush all Redis keys to test cache miss handling and cold-start performance.",
+ status: "idle", lastRun: "2026-04-10 14:00", duration: "1m",
+ },
+ {
+ id: "exp_006", name: "High Load Simulation", target: "API Server", type: "load",
+ icon: AlertTriangle, description: "Send 10,000 concurrent requests to test rate limiting and autoscaling.",
+ status: "idle", duration: "15m",
+ },
+];
+
+const statusVariant = (s: string) =>
+ s === "running" ? "warning" : s === "completed" ? "success" : s === "failed" ? "destructive" : "secondary";
+
+export default function ChaosPage() {
+ const [experiments, setExperiments] = useState(initialExperiments);
+
+ const runExperiment = (id: string) => {
+ setExperiments((prev) =>
+ prev.map((e) =>
+ e.id === id ? { ...e, status: "running" as const } : e
+ )
+ );
+ // Simulate completion after a delay
+ setTimeout(() => {
+ setExperiments((prev) =>
+ prev.map((e) =>
+ e.id === id
+ ? { ...e, status: (Math.random() > 0.2 ? "completed" : "failed") as Experiment["status"], lastRun: new Date().toISOString().slice(0, 16).replace("T", " ") }
+ : e
+ )
+ );
+ }, 3000);
+ };
+
+ return (
+
+
+
+
+
Chaos Engineering
+
Run controlled failure experiments to validate system resilience.
+
+
+
+
+
+
+ {experiments.filter((e) => e.status === "completed").length}
+ Experiments Passed
+
+
+
+
+ {experiments.filter((e) => e.status === "failed").length}
+ Experiments Failed
+
+
+
+
+ {experiments.filter((e) => e.status === "running").length}
+ Currently Running
+
+
+
+
+
+ {experiments.map((exp) => (
+
+
+
+
+
+
+
+ {exp.name}
+ Target: {exp.target}
+
+
+ {exp.status}
+
+
+ {exp.description}
+
+
+ {exp.duration}
+ {exp.lastRun && Last: {exp.lastRun}}
+
+
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/apps/web-dashboard/src/app/esim/page.tsx b/apps/web-dashboard/src/app/esim/page.tsx
new file mode 100644
index 0000000..dbc7275
--- /dev/null
+++ b/apps/web-dashboard/src/app/esim/page.tsx
@@ -0,0 +1,70 @@
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import { Badge } from "@/components/ui/badge";
+import { Button } from "@/components/ui/button";
+import { Radio, Download, RefreshCw } from "lucide-react";
+
+const profiles = [
+ { id: "prof_001", imsi: "208930000000001", euiccId: "89049032004008882600001", status: "active", subscriber: "Alice Martin", activatedAt: "2026-03-15" },
+ { id: "prof_002", imsi: "208930000000002", euiccId: "89049032004008882600002", status: "active", subscriber: "Bob Dupont", activatedAt: "2026-03-20" },
+ { id: "prof_003", imsi: "208930000000003", euiccId: "89049032004008882600003", status: "downloading", subscriber: "Claire Moreau", activatedAt: "-" },
+ { id: "prof_004", imsi: "208930000000005", euiccId: "89049032004008882600005", status: "active", subscriber: "Emma Petit", activatedAt: "2026-02-10" },
+ { id: "prof_005", imsi: "208930000000008", euiccId: "89049032004008882600008", status: "inactive", subscriber: "Henri Faure", activatedAt: "-" },
+];
+
+const statusVariant = (s: string) =>
+ s === "active" ? "success" : s === "downloading" ? "secondary" : s === "failed" ? "destructive" : "warning";
+
+export default function ESIMPage() {
+ return (
+
+
+
+
+
+
eSIM Profiles
+
Manage eSIM profile provisioning via SM-DP+ (ES2+).
+
+
+
+
+
+
+
+ All Profiles
+
+
+
+
+
+
+ | Profile ID |
+ Subscriber |
+ IMSI |
+ eUICC ID |
+ Status |
+ Activated |
+ Actions |
+
+
+
+ {profiles.map((p) => (
+
+ | {p.id} |
+ {p.subscriber} |
+ {p.imsi} |
+ {p.euiccId} |
+ {p.status} |
+ {p.activatedAt} |
+
+
+ |
+
+ ))}
+
+
+
+
+
+
+ );
+}
diff --git a/apps/web-dashboard/src/app/health/page.tsx b/apps/web-dashboard/src/app/health/page.tsx
new file mode 100644
index 0000000..10acf43
--- /dev/null
+++ b/apps/web-dashboard/src/app/health/page.tsx
@@ -0,0 +1,62 @@
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import { Badge } from "@/components/ui/badge";
+import { HeartPulse, Server, Database, Cpu, HardDrive, Wifi } from "lucide-react";
+
+const services = [
+ { name: "API Server", icon: Server, status: "healthy", latency: "12ms", uptime: "99.99%", cpu: "23%", memory: "512 MB" },
+ { name: "PostgreSQL", icon: Database, status: "healthy", latency: "3ms", uptime: "99.97%", cpu: "15%", memory: "2.1 GB" },
+ { name: "Redis Cache", icon: Database, status: "healthy", latency: "1ms", uptime: "99.99%", cpu: "5%", memory: "256 MB" },
+ { name: "Charging Engine (Rust)", icon: Cpu, status: "healthy", latency: "2ms", uptime: "99.98%", cpu: "8%", memory: "64 MB" },
+ { name: "AMF Gateway", icon: Wifi, status: "healthy", latency: "45ms", uptime: "99.95%", cpu: "12%", memory: "128 MB" },
+ { name: "ES2+ SM-DP+", icon: HardDrive, status: "degraded", latency: "230ms", uptime: "98.50%", cpu: "N/A", memory: "N/A" },
+];
+
+export default function HealthPage() {
+ return (
+
+
+
+
+
System Health
+
Monitor service health, latency, and resource usage.
+
+
+
+
+ {services.map((svc) => (
+
+
+
+
+ {svc.name}
+
+
+ {svc.status}
+
+
+
+
+
+
Latency
+
{svc.latency}
+
+
+
Uptime
+
{svc.uptime}
+
+
+
+
Memory
+
{svc.memory}
+
+
+
+
+ ))}
+
+
+ );
+}
diff --git a/apps/web-dashboard/src/app/layout.tsx b/apps/web-dashboard/src/app/layout.tsx
index e159121..24fb2f7 100644
--- a/apps/web-dashboard/src/app/layout.tsx
+++ b/apps/web-dashboard/src/app/layout.tsx
@@ -2,8 +2,9 @@ import type { Metadata } from "next";
import { Geist, Geist_Mono, Inter } from "next/font/google";
import "./globals.css";
import { cn } from "@/lib/utils";
+import { Sidebar } from "@/components/sidebar";
-const inter = Inter({subsets:['latin'],variable:'--font-sans'});
+const inter = Inter({ subsets: ["latin"], variable: "--font-sans" });
const geistSans = Geist({
variable: "--font-geist-sans",
@@ -16,8 +17,8 @@ const geistMono = Geist_Mono({
});
export const metadata: Metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
+ title: "Telecom Admin Dashboard",
+ description: "Sovereign Telecom-as-a-Service Platform Admin Dashboard",
};
export default function RootLayout({
@@ -30,7 +31,10 @@ export default function RootLayout({
lang="en"
className={cn("h-full", "antialiased", geistSans.variable, geistMono.variable, "font-sans", inter.variable)}
>
- {children}
+
+
+ {children}
+