Files
Nexumi/apps/webui/src/components/modules/starboard-form.tsx
TheOnlyMace ed2ea23e87 Refactor channel and role selection in various forms to use Discord components
- Replaced standard input fields with DiscordChannelSelect and DiscordRoleSelect components in the BirthdaysForm, FeedsManager, GiveawaysManager, LevelingForm, LoggingForm, SchedulerManager, SelfRolesManager, StatsForm, SuggestionsConfigForm, TagsManager, TempVoiceForm, TicketConfigForm, and StarboardForm for improved user experience and consistency.
- Updated state management to accommodate new component structures, enhancing data handling for channel and role selections across the application.
2026-07-22 21:23:57 +02:00

106 lines
4.6 KiB
TypeScript

'use client';
import type { StarboardConfigDashboard } from '@nexumi/shared';
import { useId } from 'react';
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 { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Switch } from '@/components/ui/switch';
import type { SettingsSaveResult } from '@/components/settings/settings-form';
import { SettingsForm } from '@/components/settings/settings-form';
async function saveStarboard(guildId: string, value: StarboardConfigDashboard): Promise<SettingsSaveResult> {
try {
const response = await fetch(`/api/guilds/${guildId}/starboard`, {
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' };
}
}
interface StarboardFormProps {
guildId: string;
initialValue: StarboardConfigDashboard;
}
export function StarboardForm({ guildId, initialValue }: StarboardFormProps) {
const t = useTranslations();
const emojiId = useId();
const thresholdId = useId();
return (
<SettingsForm<StarboardConfigDashboard>
initialValue={initialValue}
onSave={(value) => saveStarboard(guildId, value)}
>
{({ value, setValue }) => (
<Card>
<CardHeader>
<CardTitle>{t('modulePages.starboard.title')}</CardTitle>
<CardDescription>{t('modulePages.starboard.description')}</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<FieldAnchor id="field-starboard-enabled">
<div className="flex items-center justify-between rounded-md border border-border p-4">
<Label>{t('modulePages.starboard.enabledLabel')}</Label>
<Switch checked={value.enabled} onCheckedChange={(enabled) => setValue((prev) => ({ ...prev, enabled }))} />
</div>
</FieldAnchor>
<div className="grid gap-4 sm:grid-cols-3">
<FieldAnchor id="field-starboard-channel">
<div className="space-y-2">
<Label>{t('modulePages.starboard.channelId')}</Label>
<DiscordChannelSelect
guildId={guildId}
value={value.channelId}
onChange={(channelId) => setValue((prev) => ({ ...prev, channelId }))}
/>
</div>
</FieldAnchor>
<FieldAnchor id="field-starboard-emoji">
<div className="space-y-2">
<Label htmlFor={emojiId}>{t('modulePages.starboard.emoji')}</Label>
<Input id={emojiId} value={value.emoji} onChange={(event) => setValue((prev) => ({ ...prev, emoji: event.target.value }))} />
</div>
</FieldAnchor>
<FieldAnchor id="field-starboard-threshold">
<div className="space-y-2">
<Label htmlFor={thresholdId}>{t('modulePages.starboard.threshold')}</Label>
<Input id={thresholdId} type="number" min={1} value={value.threshold} onChange={(event) => setValue((prev) => ({ ...prev, threshold: Number(event.target.value) || 1 }))} />
</div>
</FieldAnchor>
</div>
<FieldAnchor id="field-starboard-self">
<div className="flex items-center justify-between rounded-md border border-border p-4">
<Label>{t('modulePages.starboard.allowSelfStar')}</Label>
<Switch checked={value.allowSelfStar} onCheckedChange={(allowSelfStar) => setValue((prev) => ({ ...prev, allowSelfStar }))} />
</div>
</FieldAnchor>
<FieldAnchor id="field-starboard-ignored">
<div className="space-y-2">
<Label>{t('modulePages.starboard.ignoredChannelIds')}</Label>
<DiscordChannelMultiSelect
guildId={guildId}
value={value.ignoredChannelIds}
onChange={(ignoredChannelIds) => setValue((prev) => ({ ...prev, ignoredChannelIds }))}
/>
</div>
</FieldAnchor>
</CardContent>
</Card>
)}
</SettingsForm>
);
}