Seed: developer-tools template (15 files)
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { CheckCircle2, AlertTriangle, Clock } from "lucide-react";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
|
||||
const services = [
|
||||
{ name: "API", status: "operational", uptime: "99.99" },
|
||||
{ name: "Dashboard", status: "operational", uptime: "99.98" },
|
||||
{ name: "CDN", status: "operational", uptime: "99.99" },
|
||||
{ name: "Database", status: "operational", uptime: "99.97" },
|
||||
{ name: "Auth", status: "degraded", uptime: "99.91" },
|
||||
{ name: "Webhooks", status: "operational", uptime: "99.95" },
|
||||
];
|
||||
|
||||
const incidents = [
|
||||
{
|
||||
date: "Mar 28, 2024",
|
||||
title: "Elevated API Latency in US-East",
|
||||
status: "resolved",
|
||||
duration: "23 minutes",
|
||||
desc: "API response times were elevated due to a database connection pool issue. The pool was resized and latency returned to normal.",
|
||||
},
|
||||
{
|
||||
date: "Mar 15, 2024",
|
||||
title: "Dashboard Login Timeout",
|
||||
status: "resolved",
|
||||
duration: "8 minutes",
|
||||
desc: "Some users experienced timeouts during login. The auth service was restarted and the issue was resolved.",
|
||||
},
|
||||
{
|
||||
date: "Feb 22, 2024",
|
||||
title: "CDN Cache Invalidation Delay",
|
||||
status: "resolved",
|
||||
duration: "45 minutes",
|
||||
desc: "Cache invalidation requests were delayed by up to 10 minutes due to a queue backlog. The queue was cleared and processing returned to normal.",
|
||||
},
|
||||
];
|
||||
|
||||
function StatusDot({ status }: { status: string }) {
|
||||
const colors: Record<string, string> = {
|
||||
operational: "bg-emerald-500",
|
||||
degraded: "bg-amber-500",
|
||||
down: "bg-red-500",
|
||||
};
|
||||
return <span className={`h-3 w-3 rounded-full \${colors[status] || colors.operational} inline-block`} />;
|
||||
}
|
||||
|
||||
export default function StatusPage() {
|
||||
const allOperational = services.every((s) => s.status === "operational");
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-slate-950 text-white antialiased">
|
||||
<Header />
|
||||
|
||||
<div className="pt-32 pb-24 mx-auto max-w-4xl px-6">
|
||||
{/* Overall Status */}
|
||||
<div className="text-center mb-16">
|
||||
<div className={`inline-flex items-center gap-3 px-6 py-3 rounded-full mb-6 \${
|
||||
allOperational
|
||||
? "bg-emerald-500/10 border border-emerald-500/20"
|
||||
: "bg-amber-500/10 border border-amber-500/20"
|
||||
}`}>
|
||||
{allOperational ? (
|
||||
<CheckCircle2 className="h-6 w-6 text-emerald-400" />
|
||||
) : (
|
||||
<AlertTriangle className="h-6 w-6 text-amber-400" />
|
||||
)}
|
||||
<span className={`text-lg font-semibold \${allOperational ? "text-emerald-400" : "text-amber-400"}`}>
|
||||
{allOperational ? "All Systems Operational" : "Partial Degradation"}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-slate-400">
|
||||
Last checked: {new Date().toLocaleString()}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Service Status Rows */}
|
||||
<Card className="bg-slate-900/60 border-slate-800 mb-12">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg text-white animate-fade-up">Service Status</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-0 stagger">
|
||||
{services.map((service, i) => (
|
||||
<div
|
||||
key={service.name}
|
||||
className={`flex items-center justify-between py-4 \${
|
||||
i < services.length - 1 ? "border-b border-slate-800" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<StatusDot status={service.status} />
|
||||
<span className="font-medium text-white">{service.name}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<Badge variant="outline" className={`text-xs \${
|
||||
service.status === "operational"
|
||||
? "text-emerald-400 border-emerald-500/30"
|
||||
: service.status === "degraded"
|
||||
? "text-amber-400 border-amber-500/30"
|
||||
: "text-red-400 border-red-500/30"
|
||||
}`}>
|
||||
{service.status}
|
||||
</Badge>
|
||||
<span className="text-sm text-slate-400 font-mono w-16 text-right">{service.uptime}%</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 90-Day Uptime Bar */}
|
||||
<Card className="bg-slate-900/60 border-slate-800 mb-12">
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="text-lg text-white">90-Day Uptime</CardTitle>
|
||||
<span className="text-sm text-emerald-400 font-mono">99.97%</span>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex gap-0.5 h-8">
|
||||
{Array.from({ length: 90 }).map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={`flex-1 rounded-sm \${
|
||||
i === 62 ? "bg-amber-500" : i === 71 ? "bg-amber-500" : "bg-emerald-500/60"
|
||||
}`}
|
||||
title={`Day \${90 - i}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex justify-between mt-2">
|
||||
<span className="text-xs text-slate-500">90 days ago</span>
|
||||
<span className="text-xs text-slate-500">Today</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Incident History */}
|
||||
<div className="mb-8">
|
||||
<h2 className="text-xl font-bold mb-6 animate-fade-up">Incident History</h2>
|
||||
<div className="space-y-6">
|
||||
{incidents.map((incident) => (
|
||||
<Card key={incident.date} className="bg-slate-900/60 border-slate-800">
|
||||
<CardContent className="p-6">
|
||||
<div className="flex flex-wrap items-center gap-3 mb-3">
|
||||
<Badge variant="outline" className="text-emerald-400 border-emerald-500/30 text-xs">
|
||||
{incident.status}
|
||||
</Badge>
|
||||
<span className="text-sm text-slate-500">{incident.date}</span>
|
||||
<div className="flex items-center gap-1 text-slate-500">
|
||||
<Clock className="h-3.5 w-3.5" />
|
||||
<span className="text-xs">{incident.duration}</span>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="font-semibold text-white mb-2">{incident.title}</h3>
|
||||
<p className="text-sm text-slate-400 leading-relaxed">{incident.desc}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user