'use client'; import type { EscalationAction, EscalationRuleDashboard, ModerationDashboard } from '@nexumi/shared'; import { Plus, Trash2 } from 'lucide-react'; import { useId } from 'react'; import { useTranslations } from '@/components/locale-provider'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Switch } from '@/components/ui/switch'; import type { SettingsSaveResult } from '@/components/settings/settings-form'; import { SettingsForm } from '@/components/settings/settings-form'; const ESCALATION_ACTIONS: EscalationAction[] = ['TIMEOUT', 'KICK', 'BAN']; interface LocalEscalation extends EscalationRuleDashboard { clientKey: string; } function toLocal(rules: EscalationRuleDashboard[]): LocalEscalation[] { return rules.map((rule, index) => ({ ...rule, clientKey: rule.id ?? `existing-${index}` })); } function toRemote(rules: LocalEscalation[]): EscalationRuleDashboard[] { return rules.map(({ clientKey, ...rest }) => rest); } async function saveModeration(guildId: string, value: ModerationDashboard): Promise { try { const response = await fetch(`/api/guilds/${guildId}/moderation`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(value) }); if (!response.ok) { const body = (await response.json().catch(() => null)) as { error?: string } | null; return { ok: false, error: body?.error ?? `Request failed with status ${response.status}` }; } return { ok: true }; } catch { return { ok: false, error: 'Network error' }; } } function EscalationRow({ rule, onChange, onRemove }: { rule: LocalEscalation; onChange: (rule: LocalEscalation) => void; onRemove: () => void; }) { const t = useTranslations(); const warnCountId = useId(); const durationId = useId(); const reasonId = useId(); return (
onChange({ ...rule, warnCount: Number(event.target.value) || 1 })} />
{rule.action === 'TIMEOUT' && (
onChange({ ...rule, durationMs: Number(event.target.value) || null })} />
)}
onChange({ ...rule, enabled })} /> {t('common.enabled')}
onChange({ ...rule, reason: event.target.value || null })} placeholder={t('modulePages.moderation.reasonPlaceholder')} />
); } interface ModerationFormProps { guildId: string; initialValue: ModerationDashboard; } export function ModerationForm({ guildId, initialValue }: ModerationFormProps) { const t = useTranslations(); return ( initialValue={{ moderationEnabled: initialValue.moderationEnabled, escalations: toLocal(initialValue.escalations) }} onSave={(value) => saveModeration(guildId, { moderationEnabled: value.moderationEnabled, escalations: toRemote(value.escalations) }) } > {({ value, setValue }) => (
{t('modulePages.moderation.title')} {t('modulePages.moderation.description')}

{t('modulePages.moderation.enabledHint')}

setValue((prev) => ({ ...prev, moderationEnabled: checked }))} />
{t('modulePages.moderation.escalationsTitle')} {t('modulePages.moderation.escalationsDescription')} {value.escalations.length === 0 && (

{t('modulePages.moderation.noEscalations')}

)} {value.escalations.map((rule) => ( setValue((prev) => ({ ...prev, escalations: prev.escalations.map((entry) => (entry.clientKey === rule.clientKey ? updated : entry)) })) } onRemove={() => setValue((prev) => ({ ...prev, escalations: prev.escalations.filter((entry) => entry.clientKey !== rule.clientKey) })) } /> ))}
)} ); }