'use client'; import { useState } from 'react'; import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors, type DragEndEvent, } from '@dnd-kit/core'; import { SortableContext, arrayMove, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; import { GripVertical, LayoutGrid } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from '@/components/ui/dialog'; import { Switch } from '@/components/ui/switch'; import { cn } from '@/lib/utils'; import { useDashboardWidgets } from '@/hooks/use-dashboard-widgets'; import type { DashboardWidget } from './widget-registry'; /** * Combined visibility + reorder picker for the dashboard header. Two * sections in one modal: * * 1. "On dashboard" — visible widgets, each row with a drag handle * (reorder via dnd-kit single SortableContext, no buckets); flipping * a switch off moves the row to section 2. * 2. "Hidden" — widgets currently off; flipping a switch on appends to * the bottom of section 1. * * Both visibility toggles and order changes commit optimistically via * `useDashboardWidgets` so the dashboard reflows in the background and * the rep can keep editing. The "Rearrange" button on the header is * gone — order lives here too now, keeping all dashboard layout * controls in one place. */ export function CustomizeWidgetsMenu() { const [open, setOpen] = useState(false); const { allWidgets, visibleWidgets, visibility, setVisible, setAll, setOrder, resetToDefaults, isSaving, } = useDashboardWidgets(); const visibleCount = Object.values(visibility).filter(Boolean).length; const allVisible = visibleCount === allWidgets.length; const allHidden = visibleCount === 0; const matchesDefaults = allWidgets.every((w) => (visibility[w.id] ?? false) === w.defaultVisible); // Hidden = everything not currently rendered. Sorted by registry order // so it reads predictably (newly-added widgets appear at the bottom // until the rep explicitly enables them). const hidden = allWidgets.filter((w) => !visibility[w.id]); const sensors = useSensors( useSensor(PointerSensor, { activationConstraint: { distance: 5 } }), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }), ); function onDragEnd(event: DragEndEvent) { const { active, over } = event; if (!over || active.id === over.id) return; const ids = visibleWidgets.map((w) => w.id); const oldIndex = ids.indexOf(String(active.id)); const newIndex = ids.indexOf(String(over.id)); if (oldIndex === -1 || newIndex === -1) return; setOrder(arrayMove(ids, oldIndex, newIndex)); } return ( ); } function Section({ title, children }: { title: string; children: React.ReactNode }) { return (
{widget.description}
{widget.description}