'use client'; /* Queue preferences popover — gear button on the Queue posture card. * * Lists every active queue with a Switch per row. Toggling persists to * /api/me/queue-preferences (full-set PUT) and calls onSaved() so the * parent can refetch trends and the heatmap drops the hidden rows. * * State is owned by this component; it lazy-loads queue data on first * open to keep the dashboard's initial paint cheap. */ import { useEffect, useState } from 'react'; import { Settings2, Loader2, Search } from 'lucide-react'; import { toast } from 'sonner'; import { Button } from '@/components/ui/button'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { Switch } from '@/components/ui/switch'; import { Input } from '@/components/ui/input'; interface QueueRow { id: number; label: string; hidden: boolean; } interface Props { onSaved: () => void; } export function QueuePreferencesPopover({ onSaved }: Props) { const [open, setOpen] = useState(false); const [queues, setQueues] = useState(null); const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(null); const [filter, setFilter] = useState(''); useEffect(() => { if (!open || queues !== null) return; setLoading(true); fetch('/api/me/queue-preferences') .then((r) => r.json()) .then((data: { queues: QueueRow[] }) => setQueues(data.queues)) .catch(() => toast.error('Failed to load queues')) .finally(() => setLoading(false)); }, [open, queues]); async function toggle(queueId: number, nextHidden: boolean) { if (!queues) return; const previous = queues; const next = queues.map((q) => (q.id === queueId ? { ...q, hidden: nextHidden } : q)); setQueues(next); setSaving(queueId); try { const hiddenIds = next.filter((q) => q.hidden).map((q) => q.id); const res = await fetch('/api/me/queue-preferences', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ hiddenIds }), }); if (!res.ok) throw new Error(`HTTP ${res.status}`); onSaved(); } catch { setQueues(previous); toast.error('Failed to update queue preference'); } finally { setSaving(null); } } const visible = queues?.filter((q) => filter ? q.label.toLowerCase().includes(filter.toLowerCase()) : true, ); return (

Visible queues

Toggle off to hide a queue from your dashboard.

setFilter(e.target.value)} placeholder="Filter queues…" className="pl-7 h-8 text-sm" />
{loading || queues === null ? (
) : visible && visible.length === 0 ? (

No queues match.

) : (
    {visible!.map((q) => (
  • {q.label} toggle(q.id, !checked)} disabled={saving === q.id} aria-label={`${q.hidden ? 'Show' : 'Hide'} ${q.label}`} />
  • ))}
)}
); }