Files
office_translator/office-translator-landing-page/components/admin-system-health.tsx
Sepehr Ramezani 26bd096a06 feat: production deployment - full update with providers, admin, glossaries, pricing, tests
Major changes across backend, frontend, infrastructure:
- Provider system with model selection (Google, DeepL, OpenAI, Ollama, Google Cloud)
- Admin panel: user management, pricing, settings
- Glossary system with CSV import/export
- Subscription and tier quota management
- Security hardening (rate limiting, API key auth, path traversal fixes)
- Docker compose for dev, prod, and IONOS deployment
- Alembic migrations for new tables
- Frontend: dashboard, pricing page, landing page, i18n (en/fr)
- Test suite and verification scripts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-25 15:01:47 +02:00

110 lines
4.1 KiB
TypeScript

"use client"
import { useState, useCallback } from "react"
import {
Card,
CardContent,
} from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Progress } from "@/components/ui/progress"
import {
HeartPulse,
HardDrive,
FileWarning,
Trash2,
Loader2,
} from "lucide-react"
export function SystemHealthCards() {
const [purging, setPurging] = useState(false)
const [orphanedCount, setOrphanedCount] = useState(12)
const diskUsed = 42
const handlePurge = useCallback(() => {
setPurging(true)
setTimeout(() => {
setPurging(false)
setOrphanedCount(0)
}, 1800)
}, [])
return (
<div className="grid grid-cols-1 gap-3 md:grid-cols-3">
{/* Server Health */}
<Card className="py-0">
<CardContent className="flex items-center gap-3 px-4 py-3">
<div className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-[oklch(0.59_0.16_145/0.1)]">
<HeartPulse className="size-4 text-[oklch(0.59_0.16_145)]" />
</div>
<div className="flex flex-1 flex-col gap-0.5">
<span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground">
Server Health
</span>
<div className="flex items-center gap-1.5">
<span className="relative flex size-2">
<span className="absolute inline-flex size-full animate-ping rounded-full bg-[oklch(0.59_0.16_145)] opacity-75" />
<span className="relative inline-flex size-2 rounded-full bg-[oklch(0.59_0.16_145)]" />
</span>
<span className="text-sm font-semibold text-foreground">All Systems Operational</span>
</div>
<span className="text-[10px] text-muted-foreground">Uptime: 99.97% (30d)</span>
</div>
</CardContent>
</Card>
{/* Disk Space */}
<Card className="py-0">
<CardContent className="flex items-center gap-3 px-4 py-3">
<div className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-accent/10">
<HardDrive className="size-4 text-accent" />
</div>
<div className="flex flex-1 flex-col gap-1">
<span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground">
Disk Space
</span>
<div className="flex items-center justify-between">
<span className="text-sm font-semibold tabular-nums text-foreground">{diskUsed}% used</span>
<span className="text-[10px] tabular-nums text-muted-foreground">84 / 200 GB</span>
</div>
<Progress
value={diskUsed}
className="h-1.5 bg-muted [&>[data-slot=progress-indicator]]:bg-accent"
/>
</div>
</CardContent>
</Card>
{/* Temporary Files */}
<Card className="py-0">
<CardContent className="flex items-center gap-3 px-4 py-3">
<div className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-destructive/10">
<FileWarning className="size-4 text-destructive" />
</div>
<div className="flex flex-1 flex-col gap-0.5">
<span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground">
Temporary Files
</span>
<span className="text-sm font-semibold tabular-nums text-foreground">
{orphanedCount} orphaned files
</span>
</div>
<Button
variant="outline"
size="sm"
className="h-7 shrink-0 gap-1.5 border-destructive/30 text-destructive hover:bg-destructive/10 hover:text-destructive text-xs"
onClick={handlePurge}
disabled={purging || orphanedCount === 0}
>
{purging ? (
<Loader2 className="size-3 animate-spin" />
) : (
<Trash2 className="size-3" />
)}
{purging ? "Purging..." : orphanedCount === 0 ? "Clean" : "Purge"}
</Button>
</CardContent>
</Card>
</div>
)
}