This commit is contained in:
1 parent
8efd032cc6
commit
df38dccbf1
735 files changed
+128321
-120870
No files matched your search
@@ -4,107 +4,126 @@ import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
|
||||
interface ChatMessage {
|
||||
id: number;
|
||||
roomId: number;
|
||||
timestamp: number;
|
||||
message: string;
|
||||
id: number;
|
||||
roomId: number;
|
||||
timestamp: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
interface CommandEntry {
|
||||
id: number;
|
||||
timestamp: number;
|
||||
command: string;
|
||||
params: string;
|
||||
succes: string;
|
||||
id: number;
|
||||
timestamp: number;
|
||||
command: string;
|
||||
params: string;
|
||||
succes: string;
|
||||
}
|
||||
|
||||
interface UserActivityLogProps {
|
||||
chatLogs: ChatMessage[];
|
||||
commandLogs: CommandEntry[];
|
||||
chatLogs: ChatMessage[];
|
||||
commandLogs: CommandEntry[];
|
||||
}
|
||||
|
||||
function formatTime(ts: number) {
|
||||
if (!ts) return "-";
|
||||
const d = new Date(ts * 1000);
|
||||
return d.toLocaleString(undefined, {
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
if (!ts) return "-";
|
||||
const d = new Date(ts * 1000);
|
||||
return d.toLocaleString(undefined, {
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
}
|
||||
|
||||
export function UserActivityLog({ chatLogs, commandLogs }: UserActivityLogProps) {
|
||||
return (
|
||||
<div className="grid gap-6 lg:grid-cols-2">
|
||||
{/* Chat Messages */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<MessageSquare className="h-4 w-4" />
|
||||
Recent Messages ({chatLogs.length})
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{chatLogs.length === 0 ? (
|
||||
<p className="text-sm text-muted-foreground">No recent messages.</p>
|
||||
) : (
|
||||
<div className="space-y-2 max-h-[400px] overflow-y-auto">
|
||||
{chatLogs.map((log) => (
|
||||
<div key={log.id} className="rounded-md border px-3 py-2 text-sm">
|
||||
<div className="flex items-center justify-between gap-2 mb-1">
|
||||
<Link
|
||||
href={`/admin/rooms/${log.roomId}`}
|
||||
className="text-xs text-primary hover:underline"
|
||||
>
|
||||
Room #{log.roomId}
|
||||
</Link>
|
||||
<span className="text-xs text-muted-foreground">{formatTime(log.timestamp)}</span>
|
||||
</div>
|
||||
<p className="break-words">{log.message}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
export function UserActivityLog({
|
||||
chatLogs,
|
||||
commandLogs,
|
||||
}: UserActivityLogProps) {
|
||||
return (
|
||||
<div className="grid gap-6 lg:grid-cols-2">
|
||||
{/* Chat Messages */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<MessageSquare className="h-4 w-4" />
|
||||
Recent Messages ({chatLogs.length})
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{chatLogs.length === 0 ? (
|
||||
<p className="text-sm text-muted-foreground">No recent messages.</p>
|
||||
) : (
|
||||
<div className="space-y-2 max-h-[400px] overflow-y-auto">
|
||||
{chatLogs.map((log) => (
|
||||
<div
|
||||
key={log.id}
|
||||
className="rounded-md border px-3 py-2 text-sm"
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2 mb-1">
|
||||
<Link
|
||||
href={`/admin/rooms/${log.roomId}`}
|
||||
className="text-xs text-primary hover:underline"
|
||||
>
|
||||
Room #{log.roomId}
|
||||
</Link>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{formatTime(log.timestamp)}
|
||||
</span>
|
||||
</div>
|
||||
<p className="break-words">{log.message}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Commands */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Terminal className="h-4 w-4" />
|
||||
Recent Commands ({commandLogs.length})
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{commandLogs.length === 0 ? (
|
||||
<p className="text-sm text-muted-foreground">No recent commands.</p>
|
||||
) : (
|
||||
<div className="space-y-2 max-h-[400px] overflow-y-auto">
|
||||
{commandLogs.map((log) => (
|
||||
<div key={log.id} className="rounded-md border px-3 py-2 text-sm">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<code className="font-mono text-xs font-bold">:{log.command}</code>
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge
|
||||
variant={log.succes === "yes" ? "default" : "destructive"}
|
||||
className="text-[10px]"
|
||||
>
|
||||
{log.succes === "yes" ? "OK" : "FAIL"}
|
||||
</Badge>
|
||||
<span className="text-xs text-muted-foreground">{formatTime(log.timestamp)}</span>
|
||||
</div>
|
||||
</div>
|
||||
{log.params && (
|
||||
<p className="text-xs text-muted-foreground mt-1 break-words">{log.params}</p>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
{/* Commands */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Terminal className="h-4 w-4" />
|
||||
Recent Commands ({commandLogs.length})
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{commandLogs.length === 0 ? (
|
||||
<p className="text-sm text-muted-foreground">No recent commands.</p>
|
||||
) : (
|
||||
<div className="space-y-2 max-h-[400px] overflow-y-auto">
|
||||
{commandLogs.map((log) => (
|
||||
<div
|
||||
key={log.id}
|
||||
className="rounded-md border px-3 py-2 text-sm"
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<code className="font-mono text-xs font-bold">
|
||||
:{log.command}
|
||||
</code>
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge
|
||||
variant={
|
||||
log.succes === "yes" ? "default" : "destructive"
|
||||
}
|
||||
className="text-[10px]"
|
||||
>
|
||||
{log.succes === "yes" ? "OK" : "FAIL"}
|
||||
</Badge>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{formatTime(log.timestamp)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{log.params && (
|
||||
<p className="text-xs text-muted-foreground mt-1 break-words">
|
||||
{log.params}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user