fix(bots): channel picker dropdown instead of ID text input

Server selector + channel dropdown for built-in bot config.
No more asking users to paste UUIDs.
This commit is contained in:
2026-07-15 15:02:39 -04:00
parent 97c5d81d70
commit 3fd0b0e9e2
+35 -8
View File
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { useBotStore, type Bot } from '../stores/bot.ts';
import { useServerStore } from '../stores/server.ts';
import { useChannelStore } from '../stores/channel.ts';
// ponytail: config fields per bot type, add new types here
const BOT_TYPE_CONFIGS: Record<string, { label: string; fields: { key: string; label: string; type: 'text' | 'number' | 'channel'; placeholder: string }[] }> = {
@@ -27,12 +28,15 @@ export function BotManager() {
const servers = useServerStore((s) => s.servers);
const fetchServers = useServerStore((s) => s.fetchServers);
const channelsByServer = useChannelStore((s) => s.channelsByServer);
const fetchChannels = useChannelStore((s) => s.fetchChannels);
const [showCreate, setShowCreate] = useState(false);
const [createName, setCreateName] = useState('');
const [createDesc, setCreateDesc] = useState('');
const [createType, setCreateType] = useState('');
const [createConfig, setCreateConfig] = useState<Record<string, string>>({});
const [channelServerId, setChannelServerId] = useState('');
const [editingId, setEditingId] = useState<string | null>(null);
const [editName, setEditName] = useState('');
const [editDesc, setEditDesc] = useState('');
@@ -63,6 +67,7 @@ export function BotManager() {
setCreateDesc('');
setCreateType('');
setCreateConfig({});
setChannelServerId('');
setShowCreate(false);
} catch {
// error handled in store
@@ -221,13 +226,35 @@ export function BotManager() {
<div key={field.key}>
<label className="block text-gb-fg-f mb-1 font-mono text-xs">{field.label}:</label>
{field.type === 'channel' ? (
<input
type="text"
value={createConfig[field.key] || ''}
onChange={(e) => setCreateConfig((prev) => ({ ...prev, [field.key]: e.target.value }))}
placeholder="channel ID (from URL)"
className="terminal-input w-full"
/>
<div className="space-y-1">
<select
value={channelServerId}
onChange={(e) => {
setChannelServerId(e.target.value);
setCreateConfig((prev) => ({ ...prev, [field.key]: '' }));
if (e.target.value) fetchChannels(e.target.value);
}}
className="terminal-input w-full"
>
<option value="">-- select server first --</option>
{servers.map((s) => (
<option key={s.id} value={s.id}>{s.name}</option>
))}
</select>
<select
value={createConfig[field.key] || ''}
onChange={(e) => setCreateConfig((prev) => ({ ...prev, [field.key]: e.target.value }))}
className="terminal-input w-full"
disabled={!channelServerId}
>
<option value="">-- select channel --</option>
{(channelsByServer[channelServerId] || [])
.filter((c) => c.type === 'text')
.map((c) => (
<option key={c.id} value={c.id}>#{c.name}</option>
))}
</select>
</div>
) : (
<input
type={field.type}
@@ -245,7 +272,7 @@ export function BotManager() {
</button>
<button
type="button"
onClick={() => { setShowCreate(false); setCreateName(''); setCreateDesc(''); setCreateType(''); setCreateConfig({}); }}
onClick={() => { setShowCreate(false); setCreateName(''); setCreateDesc(''); setCreateType(''); setCreateConfig({}); setChannelServerId(''); }}
className="text-gb-fg-f hover:text-gb-aqua font-mono text-sm"
>
[CANCEL]