Files
GMW/services/frontend/src/components/shared/guild-picker.tsx
T
asepharyana 392db8eba1 feat(frontend): Ambient/WebGL console revamp + lint/type cleanup
Ground-up rebuild of the GMW frontend as an Ambient Field console:
- WebGL ambient background (Three.js shader, drifting motes, reduced-motion aware)
- Glassmorphism dark cyber theme across all 8 routes
- SSR page + client view split with SWR fallback; realtime via WebSocket
- Command palette (Cmd+K), chatbot FAB, guild/channel pickers
- Chart primitives: donut, radial-gauge, area-activity, sparkline, equalizer

Cleanup (review pass):
- Remove stray Puppeteer nav-test/nav-debug scripts
- Replace non-null assertions with guards (dashboard/moderation)
- Drop unused useGuilds fetches in messages/voice views
- Type implicit-any `let` declarations across pages
- Add a11y roles/labels to SVG charts and audio, tidy imports
2026-08-15 20:03:55 +07:00

71 lines
1.8 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { Select, type SelectOption } from "@/components/primitives";
import { useGuilds, useTextChannels, useVoiceChannels } from "@/hooks";
import type { Guild } from "@/lib/types";
export function GuildChannelPicker({
mode,
guildsInitial,
guildId,
channelId,
onChange,
}: {
mode: "voice" | "text";
guildsInitial?: Guild[];
guildId: string | null;
channelId: string | null;
onChange: (guildId: string, channelId: string | null) => void;
}) {
const { data: guilds } = useGuilds(guildsInitial);
// Call both hooks unconditionally (rules of hooks); select by mode.
const voiceChannels = useVoiceChannels(guildId ?? "");
const textChannels = useTextChannels(guildId ?? "");
const channels = mode === "voice" ? voiceChannels.data : textChannels.data;
const [g, setG] = useState(guildId);
const [c, setC] = useState(channelId);
useEffect(() => setG(guildId), [guildId]);
useEffect(() => setC(channelId), [channelId]);
const guildOpts: SelectOption[] = (guilds ?? []).map((x) => ({
value: x.id,
label: x.name,
}));
const channelOpts: SelectOption[] = (channels ?? []).map((x) => ({
value: x.id,
label: x.name,
hint: x.type,
}));
return (
<div className="flex flex-wrap items-center gap-2">
<Select
value={g}
onChange={(v) => {
setG(v);
setC(null);
onChange(v, null);
}}
options={guildOpts}
placeholder="Guild"
size="sm"
className="w-44"
/>
<Select
value={c}
onChange={(v) => {
setC(v);
if (g) onChange(g, v);
}}
options={channelOpts}
placeholder={mode === "voice" ? "Voice channel" : "Text channel"}
size="sm"
className="w-52"
/>
</div>
);
}