'use client'; import type { LevelingConfigDashboard } from '@nexumi/shared'; import { FieldAnchor } from '@/components/layout/field-anchor'; import { useTranslations } from '@/components/locale-provider'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { DiscordChannelMultiSelect, DiscordChannelSelect } from '@/components/ui/discord-channel-select'; import { DiscordMultiplierEditor, mapToMultiplierEntries, multiplierEntriesToMap, type MultiplierEntry } from '@/components/ui/discord-multiplier-editor'; import { DiscordRoleMultiSelect } from '@/components/ui/discord-role-select'; 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 { Textarea } from '@/components/ui/textarea'; import type { SettingsSaveResult } from '@/components/settings/settings-form'; import { SettingsForm } from '@/components/settings/settings-form'; interface LocalLevelingValue extends Omit { roleMultiplierEntries: MultiplierEntry[]; channelMultiplierEntries: MultiplierEntry[]; } function toLocal(config: LevelingConfigDashboard): LocalLevelingValue { const { roleMultipliers, channelMultipliers, ...rest } = config; return { ...rest, roleMultiplierEntries: mapToMultiplierEntries(roleMultipliers), channelMultiplierEntries: mapToMultiplierEntries(channelMultipliers) }; } async function saveLeveling(guildId: string, value: LocalLevelingValue, t: (key: string) => string): Promise { const roleMultipliers = multiplierEntriesToMap(value.roleMultiplierEntries); if (roleMultipliers.error) { return { ok: false, error: t(`modulePages.leveling.errors.${roleMultipliers.error}`) }; } const channelMultipliers = multiplierEntriesToMap(value.channelMultiplierEntries); if (channelMultipliers.error) { return { ok: false, error: t(`modulePages.leveling.errors.${channelMultipliers.error}`) }; } const { roleMultiplierEntries: _roleMultiplierEntries, channelMultiplierEntries: _channelMultiplierEntries, ...rest } = value; const payload: LevelingConfigDashboard = { ...rest, roleMultipliers: roleMultipliers.value, channelMultipliers: channelMultipliers.value }; try { const response = await fetch(`/api/guilds/${guildId}/leveling`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); 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' }; } } interface LevelingFormProps { guildId: string; initialValue: LevelingConfigDashboard; } export function LevelingForm({ guildId, initialValue }: LevelingFormProps) { const t = useTranslations(); return ( initialValue={toLocal(initialValue)} onSave={(value) => saveLeveling(guildId, value, t)} > {({ value, setValue }) => (
{t('modulePages.leveling.title')} {t('modulePages.leveling.description')}
setValue((prev) => ({ ...prev, enabled: checked }))} />
setValue((prev) => ({ ...prev, textXpMin: Number(event.target.value) || 1 }))} />
setValue((prev) => ({ ...prev, textXpMax: Number(event.target.value) || 1 }))} />
setValue((prev) => ({ ...prev, textCooldownSeconds: Number(event.target.value) || 1 })) } />
setValue((prev) => ({ ...prev, voiceXpPerMinute: Number(event.target.value) || 0 })) } />
setValue((prev) => ({ ...prev, noXpChannelIds }))} />
setValue((prev) => ({ ...prev, noXpRoleIds }))} />
setValue((prev) => ({ ...prev, roleMultiplierEntries }))} />

{t('modulePages.leveling.multiplierHint')}

setValue((prev) => ({ ...prev, channelMultiplierEntries })) } />

{t('modulePages.leveling.multiplierHint')}

{t('modulePages.leveling.levelUpTitle')}
setValue((prev) => ({ ...prev, levelUpChannelId }))} />