feat: vollständiges Dashboard-Redesign mit HeroUI - monolithische App.tsx aufgelöst, 16 Seiten, Context-API, collapsible Sidebar, neues Dashboard-Layout
Some checks failed
Deploy Discord Bot / deploy (push) Has been cancelled

This commit is contained in:
Pepe44DEV
2026-07-01 06:15:56 +02:00
parent ccaf7bd4d2
commit e2d8002bf2
29 changed files with 2776 additions and 1296 deletions

View File

@@ -0,0 +1,77 @@
import { Card, CardContent, CardHeader, Input, TextArea, Button, Chip, Separator } from '@heroui/react';
import { Tag, Save, Hash, List } from 'lucide-react';
import { useApp } from '../context/AppContext';
import { SectionCard } from '../components/shared/SectionCard';
export function ReactionRoles() {
const { reactionRoles, reactionDraft, setReactionDraft, saveReactionRole } = useApp();
return (
<SectionCard title="Reaction Roles" subtitle="Sets anzeigen und neue Zuordnungen anlegen">
<div className="grid gap-5 xl:grid-cols-[1fr_420px]">
<div>
<h3 className="mb-3 text-base font-semibold">Bestehende Sets ({reactionRoles.length})</h3>
<div className="space-y-3">
{reactionRoles.length ? reactionRoles.map((set, i) => (
<Card key={set.id || i} className="border border-default-100 bg-default-50/20">
<CardContent className="flex items-center gap-3 p-4">
<div className="flex size-10 items-center justify-center rounded-xl bg-primary-500/10 text-primary-400">
<Tag size={18} />
</div>
<div className="min-w-0 flex-1">
<div className="font-semibold text-small truncate">{set.title || 'Reaction Role'}</div>
<div className="text-tiny text-default-400 truncate">Channel: {set.channelId || '-'}</div>
</div>
<Chip size="sm" variant="flat">{(set.entries?.length || 0)} Eintr<EFBFBD>ge</Chip>
</CardContent>
</Card>
)) : (
<div className="flex flex-col items-center gap-2 py-8 text-center text-small text-default-400">
<Tag size={24} />
Keine Sets
</div>
)}
</div>
</div>
<Card className="border border-default-100 bg-default-50/20">
<CardHeader className="px-5 pt-5 pb-0">
<h3 className="text-base font-semibold">Neues Set</h3>
</CardHeader>
<CardContent className="flex flex-col gap-4 p-5">
<Input
label="Titel"
placeholder="Rollenauswahl"
value={reactionDraft.title}
onValueChange={(v) => setReactionDraft((s) => ({ ...s, title: v }))}
/>
<Input
label="Channel ID"
placeholder="Channel f<>r die Nachricht"
value={reactionDraft.channelId}
onValueChange={(v) => setReactionDraft((s) => ({ ...s, channelId: v }))}
/>
<div>
<label className="block text-small font-medium mb-1">Eintr<EFBFBD>ge</label>
<TextArea
placeholder="Emoji | Role ID | Label&#10;:emoji: | 123456789 | Rolle 1&#10;:wave: | 987654321 | Rolle 2"
minRows={6}
value={reactionDraft.entries}
onValueChange={(v) => setReactionDraft((s) => ({ ...s, entries: v }))}
/>
<p className="mt-1 text-tiny text-default-400">
Pro Zeile: Emoji | Role ID | Label (optional) | Beschreibung (optional)
</p>
</div>
<Button color="primary" startContent={<Save size={16} />} onPress={saveReactionRole}>
Reaction Role speichern
</Button>
</CardContent>
</Card>
</div>
</SectionCard>
);
}