"use client"; import type { ReactNode } from "react"; export interface OnlineUser { id: number; username: string; look: string; roomId: number | null; roomName: string | null; lastActivity: Date; } type State = "ok" | "warn" | "danger" | "neutral"; /** A single live-status tile (online users, emulator, DB, …). */ export function StatusCard({ label, value, hint, state = "neutral", icon, }: { label: string; value: ReactNode; hint?: string; state?: State; icon?: string; }) { return (
{label} {icon ? ( {icon} ) : null}
{value}
{hint ?
{hint}
: null}
); } /** A row in the system-diagnostics list with an ok/warn/error pill. */ export function DiagnosticRow({ label, detail, state, }: { label: string; detail: string; state: Exclude; }) { const text = state === "ok" ? "OK" : state === "warn" ? "WARN" : "ERROR"; return (
{label} {detail} {text}
); } /** Small labelled key/value used in the server-info card. */ export function InfoItem({ label, value }: { label: string; value: ReactNode }) { return (
{label} {value}
); } /** Live list of online users with room and activity tracking */ export function OnlineUsersWidget({ users, isLoading = false, }: { users: OnlineUser[]; isLoading?: boolean; }) { const formatLastSeen = (date: Date) => { const now = new Date(); const diff = Math.floor((now.getTime() - date.getTime()) / 1000); if (diff < 60) return "Just now"; if (diff < 3600) return `${Math.floor(diff / 60)}m ago`; if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`; return `${Math.floor(diff / 86400)}d ago`; }; return (

Online Now

{isLoading ? "..." : users.length} users
{users.length === 0 ? (
No users online
) : ( users.map((user) => (
{user.username} {user.roomId && user.roomName && (
)}
{user.roomId && user.roomName ? ( 🏠 {user.roomName} ) : ( ⏱️ {formatLastSeen(user.lastActivity)} )}
)) )}
); }