Add deep pages: fleet, repos, status, docs, activity + fix auth
Some checks failed
Autonomous Repo Agent / autonomous-build (push) Has been cancelled
BlackRoad AI Agents / agent-response (push) Has been cancelled
🔍 BlackRoad CodeQL Security Analysis / CodeQL Analysis (javascript) (push) Has been cancelled
🔍 BlackRoad CodeQL Security Analysis / CodeQL Analysis (python) (push) Has been cancelled
CI / Test (push) Has been cancelled
Deploy to Cloudflare Pages / Deploy to Cloudflare Pages (push) Has been cancelled
Trinity Compliance Check / check-compliance (push) Has been cancelled
Some checks failed
Autonomous Repo Agent / autonomous-build (push) Has been cancelled
BlackRoad AI Agents / agent-response (push) Has been cancelled
🔍 BlackRoad CodeQL Security Analysis / CodeQL Analysis (javascript) (push) Has been cancelled
🔍 BlackRoad CodeQL Security Analysis / CodeQL Analysis (python) (push) Has been cancelled
CI / Test (push) Has been cancelled
Deploy to Cloudflare Pages / Deploy to Cloudflare Pages (push) Has been cancelled
Trinity Compliance Check / check-compliance (push) Has been cancelled
- Fix signup/login to work in demo mode (no API dependency) - Add fleet page with clickable node cards → node detail pages - Add repos page with search/filter → repo detail with README - Add status page with real-time service health checks - Add docs page with 12 documentation articles (architecture, tunnels, daemon, models, etc.) - Add activity feed with live Gitea data - Add sidebar navigation for all new pages - Fix conversations/new Suspense boundary for Next.js 16 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> RoadChain-SHA2048: 8666c4a21fb4761b RoadChain-Identity: alexa@sovereign RoadChain-Full: 8666c4a21fb4761bca6ef278c572bdbc99c11ea232d10f1c2ffefa71b95026ca5720ee432b3b30d64e08940e6cb8af6ba0f9049cf2c51144f9a69939da48a393159dd3776526ff313831a2213740bfeb67a9aac4c6e26152b1e9e9f0fb49f7c99e5ae90bf603c81a86eb8cb6cec841357222802e95db38d9e53e5dc681f2a4ed8c8027a96a980dc9f9a9c45b5d971d767fddd5fd3fdd93abb4da595567f8bbe09019a5559abf3a7a09520da7a562dc5fea730528960afc013f8f67bbb6d0f645e6273c917190f2d97611314fc9da5ec4a7eabcc06b736790bee07d7ff3a282f61c96e68d9c4edb869648114dc64de9571de451d84335f08625ecb0f72e9a7fd4
This commit is contained in:
126
app/(app)/status/page.tsx
Normal file
126
app/(app)/status/page.tsx
Normal file
@@ -0,0 +1,126 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { CheckCircle, AlertTriangle, XCircle, Clock, Activity, Radio } from 'lucide-react';
|
||||
|
||||
interface ServiceStatus {
|
||||
name: string;
|
||||
status: 'operational' | 'degraded' | 'down';
|
||||
latency?: number;
|
||||
}
|
||||
|
||||
interface StatusData {
|
||||
status: string;
|
||||
services: ServiceStatus[];
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
const STATUS_ICON = {
|
||||
operational: CheckCircle,
|
||||
degraded: AlertTriangle,
|
||||
down: XCircle,
|
||||
};
|
||||
|
||||
const STATUS_COLOR = {
|
||||
operational: 'text-green-400',
|
||||
degraded: 'text-amber-400',
|
||||
down: 'text-red-400',
|
||||
};
|
||||
|
||||
const STATUS_BG = {
|
||||
operational: 'bg-green-400/10 border-green-400/20',
|
||||
degraded: 'bg-amber-400/10 border-amber-400/20',
|
||||
down: 'bg-red-400/10 border-red-400/20',
|
||||
};
|
||||
|
||||
export default function StatusPage() {
|
||||
const [data, setData] = useState<StatusData | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
async function load() {
|
||||
try {
|
||||
const res = await fetch('/api/status');
|
||||
const d = await res.json();
|
||||
setData(d);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
load();
|
||||
const interval = setInterval(load, 60000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
if (loading) return (
|
||||
<div className="p-6 flex items-center gap-3 text-gray-400">
|
||||
<Radio className="h-4 w-4 animate-pulse text-[#FF1D6C]" />
|
||||
Checking services...
|
||||
</div>
|
||||
);
|
||||
|
||||
const services = data?.services ?? [];
|
||||
const overall = data?.status ?? 'unknown';
|
||||
const overallLabel = overall === 'operational' ? 'All Systems Operational' :
|
||||
overall === 'partial_outage' ? 'Partial Outage' : 'Major Outage';
|
||||
|
||||
return (
|
||||
<div className="p-6 space-y-6 max-w-3xl">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-white">System Status</h1>
|
||||
<p className="text-gray-400 text-sm mt-1">Real-time health of BlackRoad infrastructure</p>
|
||||
</div>
|
||||
|
||||
{/* Overall status banner */}
|
||||
<div className={`rounded-xl border p-5 ${
|
||||
overall === 'operational' ? STATUS_BG.operational :
|
||||
overall === 'partial_outage' ? STATUS_BG.degraded : STATUS_BG.down
|
||||
}`}>
|
||||
<div className="flex items-center gap-3">
|
||||
{overall === 'operational' ? (
|
||||
<CheckCircle className="h-6 w-6 text-green-400" />
|
||||
) : overall === 'partial_outage' ? (
|
||||
<AlertTriangle className="h-6 w-6 text-amber-400" />
|
||||
) : (
|
||||
<XCircle className="h-6 w-6 text-red-400" />
|
||||
)}
|
||||
<span className="text-lg font-semibold text-white">{overallLabel}</span>
|
||||
</div>
|
||||
<p className="text-sm text-gray-400 mt-2">
|
||||
Last checked: {data?.timestamp ? new Date(data.timestamp).toLocaleString() : 'now'}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Individual services */}
|
||||
<div className="bg-white/5 border border-white/10 rounded-xl divide-y divide-white/5">
|
||||
{services.map(svc => {
|
||||
const Icon = STATUS_ICON[svc.status] ?? Activity;
|
||||
const color = STATUS_COLOR[svc.status] ?? 'text-gray-400';
|
||||
|
||||
return (
|
||||
<div key={svc.name} className="flex items-center justify-between p-4 hover:bg-white/[0.03] transition-colors">
|
||||
<div className="flex items-center gap-3">
|
||||
<Icon className={`h-5 w-5 ${color}`} />
|
||||
<span className="text-sm text-white">{svc.name}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
{svc.latency !== undefined && (
|
||||
<span className="text-xs text-gray-500 flex items-center gap-1">
|
||||
<Clock className="h-3 w-3" />
|
||||
{svc.latency}ms
|
||||
</span>
|
||||
)}
|
||||
<span className={`text-xs capitalize ${color}`}>{svc.status}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="text-xs text-gray-600 text-center pt-2">
|
||||
Auto-refreshes every 60s · Powered by edge health checks
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user