diff --git a/src/components/features/favorite-tools-dnd.tsx b/src/components/features/favorite-tools-dnd.tsx new file mode 100644 index 0000000..4ef483f --- /dev/null +++ b/src/components/features/favorite-tools-dnd.tsx @@ -0,0 +1,148 @@ +"use client"; + +import { useState } from "react"; +import { DndContext, type DragEndEvent } from "@dnd-kit/core"; +import { + SortableContext, + arrayMove, + rectSortingStrategy, + useSortable, +} from "@dnd-kit/sortable"; +import { CSS } from "@dnd-kit/utilities"; +import { Star } from "lucide-react"; +import Link from "next/link"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent } from "@/components/ui/card"; +import { routeItems } from "@/lib/routes"; +import { cn } from "@/lib/utils"; + +type Tool = (typeof routeItems)[number]; + +export function FavoriteToolsDnd({ + favorites, + onToggleFavorite, +}: { + favorites: string[]; + onToggleFavorite: (path: string) => void; +}) { + const [order, setOrder] = useState([]); + const orderedFavorites = [ + ...order.filter((path) => favorites.includes(path)), + ...favorites.filter((path) => !order.includes(path)), + ]; + + function onDragEnd(event: DragEndEvent) { + const { active, over } = event; + if (!over || active.id === over.id) return; + setOrder( + arrayMove( + orderedFavorites, + orderedFavorites.indexOf(String(active.id)), + orderedFavorites.indexOf(String(over.id)), + ), + ); + } + + return ( + + +
+ {orderedFavorites + .map((path) => routeItems.find((item) => item.path === path)) + .filter((item): item is Tool => Boolean(item)) + .map((tool) => ( + onToggleFavorite(tool.path)} + /> + ))} +
+
+
+ ); +} + +function SortableTool({ + tool, + favorite, + onToggleFavorite, +}: { + tool: Tool; + favorite: boolean; + onToggleFavorite: () => void; +}) { + const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ + id: tool.path, + }); + + return ( +
+ +
+ ); +} + +function ToolCard({ + tool, + favorite, + compact, + onToggleFavorite, +}: { + tool: Tool; + favorite: boolean; + compact?: boolean; + onToggleFavorite: () => void; +}) { + const Icon = tool.icon; + return ( + + +
+ + + + + + {tool.label} + + {tool.description} + + + + +
+ {!compact ? ( +
+ {tool.category} + + {tool.danger ? "confirmation" : "allowed"} + +
+ ) : null} +
+
+ ); +}