Files
Papo/frontend/src/pages/SupportLogin.tsx
Pepe44DEV 3c31832a0d
Some checks failed
Deploy Discord Bot / deploy (push) Failing after -1m3s
SonarQube / sonar (push) Successful in 1m17s
improve dashboard usability and fix backend TS build errors
Frontend: fix HeroUI Switch usage across the whole app (Content/Control/
Thumb composition was missing, so no toggle ever rendered visibly),
replace raw channel/role ID text fields with proper name-based dropdowns
(ChannelSelect/RoleSelect) backed by the existing /guild/resources
endpoint, redesign Automod's filters as inline toggle rows, turn the
Ticket Pipeline tab into a drag-and-drop Kanban board, narrow the
sidebar further and rework its collapse toggle and profile footer, and
add a Discord-style message preview for Welcome/Support Login.

Backend: fix the ~50 TypeScript build errors blocking `npm run build`
(SlashCommandBuilder typing, discord.js v14 channel-union guards,
Prisma JSON null handling, logger.warn signature, and related type
narrowing) so the project compiles cleanly again.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-02 13:55:17 +02:00

138 lines
5.8 KiB
TypeScript

import { Card, CardContent, CardDescription, CardHeader, CardTitle, Input, TextArea, Button, Chip, Separator, TextField, Label } from '@heroui/react';
import { UserRound, Save, Send } from 'lucide-react';
import { useApp } from '../context/AppContext';
import { SectionCard } from '../components/shared/SectionCard';
import { AppAvatar } from '../components/shared/AppAvatar';
import { DiscordPreview, DiscordButton } from '../components/shared/DiscordPreview';
import { ChannelSelect } from '../components/shared/ChannelSelect';
import { AppSwitch } from '../components/shared/AppSwitch';
import { useGuildResources } from '../hooks/useGuildResources';
export function SupportLogin() {
const { supportLogin, setSupportLogin, saveSupportLogin, currentGuildId } = useApp();
const { channels } = useGuildResources(currentGuildId);
return (
<SectionCard title="Support Login" subtitle="Login-Panel fuer Supporter konfigurieren">
<div className="grid gap-5 xl:grid-cols-[1fr_400px]">
<Card>
<CardHeader>
<div>
<CardTitle>Panel-Konfiguration</CardTitle>
<CardDescription>Texte und Zielkanal mit normalen HeroUI-Feldern pflegen.</CardDescription>
</div>
</CardHeader>
<CardContent className="flex flex-col gap-4">
<AppSwitch
isSelected={supportLogin?.config?.autoRefresh !== false}
onChange={(v) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, autoRefresh: v } } : s)}
label="Auto-Refresh aktiv"
/>
<TextField>
<Label>Panel Channel</Label>
<ChannelSelect
options={channels}
value={supportLogin?.config?.panelChannelId}
onChange={(id) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, panelChannelId: id } } : s)}
placeholder="Channel für das Panel wählen"
/>
</TextField>
<TextField>
<Label>Titel</Label>
<Input
value={supportLogin?.config?.title || 'Support Login'}
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, title: e.target.value } } : s)}
/>
</TextField>
<TextField>
<Label>Beschreibung</Label>
<TextArea
value={supportLogin?.config?.description || ''}
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, description: e.target.value } } : s)}
/>
</TextField>
<TextField>
<Label>Login Button Label</Label>
<Input
value={supportLogin?.config?.loginLabel || 'Ich bin jetzt im Support'}
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, loginLabel: e.target.value } } : s)}
/>
</TextField>
<TextField>
<Label>Logout Button Label</Label>
<Input
value={supportLogin?.config?.logoutLabel || 'Ich bin nicht mehr im Support'}
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, logoutLabel: e.target.value } } : s)}
/>
</TextField>
<Separator />
<div className="flex gap-2">
<Button variant="primary" onPress={saveSupportLogin}>
<Save size={16} /> Speichern & Panel senden
</Button>
<Button variant="ghost">
<Send size={16} /> Panel manuell senden
</Button>
</div>
</CardContent>
</Card>
<div className="space-y-4">
<Card>
<CardHeader>
<div>
<CardTitle>Live Vorschau</CardTitle>
<CardDescription>So sieht das Panel auf Discord aus.</CardDescription>
</div>
</CardHeader>
<CardContent>
<DiscordPreview
title={supportLogin?.config?.title || 'Support Login'}
description={supportLogin?.config?.description || 'Melde dich als Support an/ab.'}
>
<DiscordButton variant="primary">{supportLogin?.config?.loginLabel || 'Ich bin jetzt im Support'}</DiscordButton>
<DiscordButton variant="secondary">{supportLogin?.config?.logoutLabel || 'Ich bin nicht mehr im Support'}</DiscordButton>
</DiscordPreview>
</CardContent>
</Card>
<Card>
<CardHeader>
<div>
<CardTitle>Aktive Supporter</CardTitle>
<CardDescription>Aktueller Status aus der Guild.</CardDescription>
</div>
</CardHeader>
<CardContent className="flex flex-col gap-2">
{supportLogin?.status?.active?.length ? supportLogin.status.active.map((s, i) => (
<Card key={i} className="bg-surface-tertiary">
<CardContent className="flex items-center gap-3">
<AppAvatar name={s.username} size="sm" className="size-6" />
<span className="font-medium">{s.username || s.userId}</span>
<Chip size="sm" variant="soft" color="success" className="ml-auto">Online</Chip>
</CardContent>
</Card>
)) : (
<div className="flex flex-col items-center gap-2 py-4 text-center text-xs text-muted">
<UserRound size={20} />
Keine aktiven Supporter
</div>
)}
<p className="mt-2 text-xs text-muted">
Support Role ID: {supportLogin?.supportRoleId || 'Nicht gesetzt'}
</p>
</CardContent>
</Card>
</div>
</div>
</SectionCard>
);
}