diff --git a/apps/webui/src/app/dashboard/[guildId]/commands/page.tsx b/apps/webui/src/app/dashboard/[guildId]/commands/page.tsx index 01ac972..68d7f21 100644 --- a/apps/webui/src/app/dashboard/[guildId]/commands/page.tsx +++ b/apps/webui/src/app/dashboard/[guildId]/commands/page.tsx @@ -1,6 +1,6 @@ import { Suspense } from 'react'; import { CommandsManager } from '@/components/modules/commands-manager'; -import { listGuildChannelsForDashboard, listGuildRolesForDashboard } from '@/lib/discord-guild-resources'; +import { listGuildChannelsForDashboard } from '@/lib/discord-guild-resources'; import { getLocale, t } from '@/lib/i18n'; import { getCommandGlobalRules } from '@/lib/module-configs/command-global-rules'; import { listCommandOverridesDashboard } from '@/lib/module-configs/commands'; @@ -11,12 +11,11 @@ interface CommandsPageProps { export default async function CommandsPage({ params }: CommandsPageProps) { const { guildId } = await params; - const [locale, commands, globalRules, channels, roles] = await Promise.all([ + const [locale, commands, globalRules, channels] = await Promise.all([ getLocale(), listCommandOverridesDashboard(guildId), getCommandGlobalRules(guildId), - listGuildChannelsForDashboard(guildId).catch(() => []), - listGuildRolesForDashboard(guildId).catch(() => []) + listGuildChannelsForDashboard(guildId).catch(() => []) ]); return ( @@ -31,7 +30,6 @@ export default async function CommandsPage({ params }: CommandsPageProps) { initialCommands={commands} initialGlobalRules={globalRules} channels={channels} - roles={roles} /> diff --git a/apps/webui/src/components/modules/birthdays-form.tsx b/apps/webui/src/components/modules/birthdays-form.tsx index c1f3dde..cccadb4 100644 --- a/apps/webui/src/components/modules/birthdays-form.tsx +++ b/apps/webui/src/components/modules/birthdays-form.tsx @@ -5,6 +5,8 @@ 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 { DiscordChannelSelect } from '@/components/ui/discord-channel-select'; +import { DiscordRoleSelect } from '@/components/ui/discord-role-select'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; @@ -36,8 +38,6 @@ interface BirthdaysFormProps { export function BirthdaysForm({ guildId, initialValue }: BirthdaysFormProps) { const t = useTranslations(); - const channelId = useId(); - const roleId = useId(); const timezoneId = useId(); return ( @@ -58,14 +58,22 @@ export function BirthdaysForm({ guildId, initialValue }: BirthdaysFormProps) {
- - setValue((prev) => ({ ...prev, channelId: event.target.value.trim() }))} placeholder="123456789012345678" /> + + setValue((prev) => ({ ...prev, channelId }))} + />
- - setValue((prev) => ({ ...prev, roleId: event.target.value.trim() }))} placeholder="123456789012345678" /> + + setValue((prev) => ({ ...prev, roleId }))} + />
diff --git a/apps/webui/src/components/modules/commands-manager.tsx b/apps/webui/src/components/modules/commands-manager.tsx index b9f4866..8d45084 100644 --- a/apps/webui/src/components/modules/commands-manager.tsx +++ b/apps/webui/src/components/modules/commands-manager.tsx @@ -3,8 +3,7 @@ import type { CommandGlobalRules, CommandOverrideDashboard, - DiscordChannelOption, - DiscordRoleOption + DiscordChannelOption } from '@nexumi/shared'; import { RotateCcw } from 'lucide-react'; import { useSearchParams } from 'next/navigation'; @@ -14,6 +13,7 @@ import { useTranslations } from '@/components/locale-provider'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { DiscordResourceMultiSelect } from '@/components/ui/discord-resource-multi-select'; +import { DiscordRoleMultiSelect } from '@/components/ui/discord-role-select'; import { Input } from '@/components/ui/input'; import { Switch } from '@/components/ui/switch'; @@ -26,15 +26,13 @@ interface CommandsManagerProps { initialCommands: CommandOverrideDashboard[]; initialGlobalRules: CommandGlobalRules; channels: DiscordChannelOption[]; - roles: DiscordRoleOption[]; } export function CommandsManager({ guildId, initialCommands, initialGlobalRules, - channels, - roles + channels }: CommandsManagerProps) { const t = useTranslations(); const searchParams = useSearchParams(); @@ -48,10 +46,6 @@ export function CommandsManager({ () => channels.map((channel) => ({ id: channel.id, name: channel.name, prefix: '#' })), [channels] ); - const roleOptions = useMemo( - () => roles.map((role) => ({ id: role.id, name: role.name, prefix: '@' })), - [roles] - ); useEffect(() => { const q = searchParams.get('q'); @@ -250,8 +244,8 @@ export function CommandsManager({

{t('modulePages.commands.allowedRoleIds')}

- patchLocal(entry.commandName, { allowedRoleIds })} placeholder={t('modulePages.commands.roleSearchPlaceholder')} @@ -260,8 +254,8 @@ export function CommandsManager({

{t('modulePages.commands.deniedRoleIds')}

- patchLocal(entry.commandName, { deniedRoleIds })} placeholder={t('modulePages.commands.roleSearchPlaceholder')} diff --git a/apps/webui/src/components/modules/feeds-manager.tsx b/apps/webui/src/components/modules/feeds-manager.tsx index b4a55bd..a8ba0d0 100644 --- a/apps/webui/src/components/modules/feeds-manager.tsx +++ b/apps/webui/src/components/modules/feeds-manager.tsx @@ -8,6 +8,8 @@ import { FieldAnchor } from '@/components/layout/field-anchor'; import { useTranslations } from '@/components/locale-provider'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { DiscordChannelSelect } from '@/components/ui/discord-channel-select'; +import { DiscordRoleSelect } 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'; @@ -182,17 +184,18 @@ export function FeedsManager({ guildId, initialFeeds }: FeedsManagerProps) {
- setDraft((prev) => ({ ...prev, channelId: event.target.value }))} - placeholder="123456789012345678" + onChange={(channelId) => setDraft((prev) => ({ ...prev, channelId }))} />
- setDraft((prev) => ({ ...prev, rolePingId: event.target.value }))} + onChange={(rolePingId) => setDraft((prev) => ({ ...prev, rolePingId }))} placeholder={t('common.optional')} />
diff --git a/apps/webui/src/components/modules/giveaways-manager.tsx b/apps/webui/src/components/modules/giveaways-manager.tsx index 788418b..2d285b5 100644 --- a/apps/webui/src/components/modules/giveaways-manager.tsx +++ b/apps/webui/src/components/modules/giveaways-manager.tsx @@ -9,6 +9,8 @@ import { useTranslations } from '@/components/locale-provider'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { DiscordChannelSelect } from '@/components/ui/discord-channel-select'; +import { DiscordRoleSelect } from '@/components/ui/discord-role-select'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; @@ -127,10 +129,10 @@ export function GiveawaysManager({ guildId, initialGiveaways }: GiveawaysManager
- setDraft((prev) => ({ ...prev, channelId: event.target.value }))} - placeholder="123456789012345678" + onChange={(channelId) => setDraft((prev) => ({ ...prev, channelId }))} />
@@ -156,9 +158,10 @@ export function GiveawaysManager({ guildId, initialGiveaways }: GiveawaysManager
- setDraft((prev) => ({ ...prev, requiredRoleId: event.target.value }))} + onChange={(requiredRoleId) => setDraft((prev) => ({ ...prev, requiredRoleId }))} placeholder={t('common.optional')} />
diff --git a/apps/webui/src/components/modules/leveling-form.tsx b/apps/webui/src/components/modules/leveling-form.tsx index e537e3c..3aab9a2 100644 --- a/apps/webui/src/components/modules/leveling-form.tsx +++ b/apps/webui/src/components/modules/leveling-form.tsx @@ -1,10 +1,11 @@ 'use client'; import type { LevelingConfigDashboard } 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 { 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'; @@ -14,24 +15,11 @@ import type { SettingsSaveResult } from '@/components/settings/settings-form'; import { SettingsForm } from '@/components/settings/settings-form'; interface LocalLevelingValue - extends Omit { - noXpChannelIdsText: string; - noXpRoleIdsText: string; + extends Omit { roleMultipliersText: string; channelMultipliersText: string; } -function toCsv(ids: string[]): string { - return ids.join(', '); -} - -function fromCsv(text: string): string[] { - return text - .split(',') - .map((entry) => entry.trim()) - .filter((entry) => entry.length > 0); -} - function toMultiplierText(map: Record): string { return Object.entries(map) .map(([id, multiplier]) => `${id}:${multiplier}`) @@ -58,11 +46,9 @@ function fromMultiplierText(text: string): { value: Record; erro } function toLocal(config: LevelingConfigDashboard): LocalLevelingValue { - const { noXpChannelIds, noXpRoleIds, roleMultipliers, channelMultipliers, ...rest } = config; + const { roleMultipliers, channelMultipliers, ...rest } = config; return { ...rest, - noXpChannelIdsText: toCsv(noXpChannelIds), - noXpRoleIdsText: toCsv(noXpRoleIds), roleMultipliersText: toMultiplierText(roleMultipliers), channelMultipliersText: toMultiplierText(channelMultipliers) }; @@ -78,12 +64,10 @@ async function saveLeveling(guildId: string, value: LocalLevelingValue): Promise return { ok: false, error: channelMultipliers.error }; } - const { noXpChannelIdsText, noXpRoleIdsText, roleMultipliersText: _roleMultipliersText, channelMultipliersText: _channelMultipliersText, ...rest } = value; + const { roleMultipliersText: _roleMultipliersText, channelMultipliersText: _channelMultipliersText, ...rest } = value; const payload: LevelingConfigDashboard = { ...rest, - noXpChannelIds: fromCsv(noXpChannelIdsText), - noXpRoleIds: fromCsv(noXpRoleIdsText), roleMultipliers: roleMultipliers.value, channelMultipliers: channelMultipliers.value }; @@ -111,8 +95,6 @@ interface LevelingFormProps { export function LevelingForm({ guildId, initialValue }: LevelingFormProps) { const t = useTranslations(); - const noXpChannelsId = useId(); - const noXpRolesId = useId(); return ( @@ -192,23 +174,21 @@ export function LevelingForm({ guildId, initialValue }: LevelingFormProps) {
- -