Some checks failed
Build Frontend / build (push) Failing after 7s
Eliminated the ability to resize dashboard widgets by removing colSpan from WidgetConfig, related UI, and logic. Removed edit mode functionality and the EditDashboardButton, simplifying the dashboard layout and widget management. Updated drag-and-drop strategy to vertical list and incremented the storage key version.
129 lines
3.9 KiB
TypeScript
129 lines
3.9 KiB
TypeScript
"use client"
|
|
|
|
import React, { useState } from "react"
|
|
import {
|
|
DndContext,
|
|
closestCenter,
|
|
KeyboardSensor,
|
|
PointerSensor,
|
|
useSensor,
|
|
useSensors,
|
|
DragEndEvent,
|
|
DragOverlay,
|
|
DragStartEvent,
|
|
} from "@dnd-kit/core"
|
|
import {
|
|
SortableContext,
|
|
sortableKeyboardCoordinates,
|
|
verticalListSortingStrategy,
|
|
arrayMove,
|
|
} from "@dnd-kit/sortable"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Edit3, X, Check, RotateCcw } from "lucide-react"
|
|
import { WidgetConfig } from "@/hooks/useWidgetLayout"
|
|
import { motion, AnimatePresence } from "framer-motion"
|
|
|
|
interface DashboardEditorProps {
|
|
widgets: WidgetConfig[]
|
|
isEditMode: boolean
|
|
onToggleEditMode: () => void
|
|
onReorder: (activeId: string, overId: string) => void
|
|
onReset: () => void
|
|
children: React.ReactNode
|
|
}
|
|
|
|
export function DashboardEditor({
|
|
widgets,
|
|
isEditMode,
|
|
onToggleEditMode,
|
|
onReorder,
|
|
onReset,
|
|
children
|
|
}: DashboardEditorProps) {
|
|
const [activeId, setActiveId] = useState<string | null>(null)
|
|
|
|
const sensors = useSensors(
|
|
useSensor(PointerSensor, {
|
|
activationConstraint: {
|
|
distance: 8,
|
|
},
|
|
}),
|
|
useSensor(KeyboardSensor, {
|
|
coordinateGetter: sortableKeyboardCoordinates,
|
|
})
|
|
)
|
|
|
|
const handleDragStart = (event: DragStartEvent) => {
|
|
setActiveId(event.active.id as string)
|
|
}
|
|
|
|
const handleDragEnd = (event: DragEndEvent) => {
|
|
const { active, over } = event
|
|
|
|
if (over && active.id !== over.id) {
|
|
onReorder(active.id as string, over.id as string)
|
|
}
|
|
|
|
setActiveId(null)
|
|
}
|
|
|
|
const handleDragCancel = () => {
|
|
setActiveId(null)
|
|
}
|
|
|
|
return (
|
|
<DndContext
|
|
sensors={sensors}
|
|
collisionDetection={closestCenter}
|
|
onDragStart={handleDragStart}
|
|
onDragEnd={handleDragEnd}
|
|
onDragCancel={handleDragCancel}
|
|
>
|
|
<SortableContext
|
|
items={widgets.map(w => w.id)}
|
|
strategy={verticalListSortingStrategy}
|
|
>
|
|
{children}
|
|
</SortableContext>
|
|
|
|
{/* Edit Mode Banner */}
|
|
<AnimatePresence>
|
|
{isEditMode && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 50 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0, y: 50 }}
|
|
className="fixed bottom-6 left-1/2 -translate-x-1/2 z-50"
|
|
>
|
|
<div className="flex items-center gap-3 bg-primary text-primary-foreground px-4 py-2.5 rounded-full shadow-lg border border-primary-foreground/20">
|
|
<span className="text-sm font-medium">
|
|
Editing Dashboard • Drag widgets to reorder
|
|
</span>
|
|
<div className="h-4 w-px bg-primary-foreground/30" />
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
className="h-7 px-2 hover:bg-primary-foreground/20"
|
|
onClick={onReset}
|
|
>
|
|
<RotateCcw className="h-3.5 w-3.5 mr-1" />
|
|
Reset
|
|
</Button>
|
|
<Button
|
|
variant="secondary"
|
|
size="sm"
|
|
className="h-7 px-3"
|
|
onClick={onToggleEditMode}
|
|
>
|
|
<Check className="h-3.5 w-3.5 mr-1" />
|
|
Done
|
|
</Button>
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</DndContext>
|
|
)
|
|
}
|
|
|