Files
Papo/frontend/src/pages/ServerStats.tsx
Pepe44DEV da72f49255
Some checks failed
Deploy Discord Bot / deploy (push) Has been cancelled
refactor frontend forms for updated HeroUI inputs
2026-07-01 15:21:59 +02:00

99 lines
4.5 KiB
TypeScript
Raw Blame History

import { Card, CardContent, CardHeader, Input, Button, Chip, Switch, Separator, TextField, Label } from '@heroui/react';
import { Activity, Save, Trash2, Plus, BarChart3 } from 'lucide-react';
import { useApp } from '../context/AppContext';
import { SectionCard } from '../components/shared/SectionCard';
export function ServerStats() {
const { statsDraft, setStatsDraft, saveServerStats, statsItemDraft, setStatsItemDraft, addStatsItem, deleteStatsItem } = useApp();
const items = (statsDraft?.items || []);
return (
<SectionCard title="Server Stats" subtitle="Counter und Refresh-Intervall steuern">
<div className="grid gap-5 xl:grid-cols-[420px_1fr]">
<Card className="border border-default-100 bg-default-50/20">
<CardHeader className="px-5 pt-5 pb-0">
<h3 className="text-base font-semibold">Konfiguration</h3>
</CardHeader>
<CardContent className="flex flex-col gap-4 p-5">
<Switch isSelected={statsDraft?.enabled === true} onChange={(v) => setStatsDraft((s) => ({ ...(s || {}), enabled: v }))}>
<div className="flex items-center gap-2"><BarChart3 size={16} /> Server Stats aktiv</div>
</Switch>
<TextField>
<Label>Kategorie-Name</Label>
<Input
placeholder="?? Server Stats"
value={statsDraft?.categoryName || ''}
onChange={(e) => setStatsDraft((s) => ({ ...(s || {}), categoryName: e.target.value }))}
/>
</TextField>
<TextField>
<Label>Refresh (Minuten)</Label>
<Input
type="number"
value={String(statsDraft?.refreshMinutes || 10)}
onChange={(e) => setStatsDraft((s) => ({ ...(s || {}), refreshMinutes: Number(e.target.value || 10) }))}
/>
</TextField>
<Button color="primary" startContent={<Save size={16} />} onPress={saveServerStats}>
Server Stats speichern
</Button>
</CardContent>
</Card>
<Card className="border border-default-100 bg-default-50/20">
<CardHeader className="px-5 pt-5 pb-0">
<h3 className="text-base font-semibold">Items ({items.length})</h3>
</CardHeader>
<CardContent className="flex flex-col gap-3 p-5">
{items.length ? items.map((item, i) => (
<div key={i} className="flex items-center justify-between rounded-xl border border-default-100 bg-default-50/30 px-4 py-3 text-small">
<div className="flex items-center gap-2">
<Activity size={14} className="text-primary-400" />
<span className="font-medium">{item.label || item.key}</span>
<Chip size="sm" variant="flat">{item.type || '-'}</Chip>
</div>
<Button isIconOnly size="sm" variant="light" color="danger" onPress={() => deleteStatsItem(i)}>
<Trash2 size={14} />
</Button>
</div>
)) : (
<div className="flex flex-col items-center gap-2 py-4 text-center text-tiny text-default-400">
<BarChart3 size={20} />
Keine Items
</div>
)}
<Separator />
<div>
<h4 className="text-small font-semibold mb-2">Item hinzuf<EFBFBD>gen</h4>
<div className="flex flex-col gap-2">
<Input placeholder="Label" value={statsItemDraft.label} onChange={(e) => setStatsItemDraft((s) => ({ ...s, label: e.target.value }))} />
<select
className="w-full rounded-xl border border-default-200 bg-default-50 px-3 py-2 text-sm outline-none"
value={statsItemDraft.type}
onChange={(e) => setStatsItemDraft((s) => ({ ...s, type: e.target.value }))}
>
<option value="members">Mitglieder</option>
<option value="channels">Channels</option>
<option value="roles">Rollen</option>
<option value="boosts">Boosts</option>
<option value="online">Online</option>
<option value="custom">Custom</option>
</select>
<Button size="sm" color="primary" startContent={<Plus size={14} />} onPress={addStatsItem}>
Hinzuf<EFBFBD>gen
</Button>
</div>
</div>
</CardContent>
</Card>
</div>
</SectionCard>
);
}