"use client";
import { useId } from "react";
import { ArrowDown, ArrowUp, GripVertical } from "lucide-react";
import {
DndContext,
KeyboardSensor,
PointerSensor,
closestCenter,
useSensor,
useSensors,
type DragEndEvent,
} from "@dnd-kit/core";
import {
SortableContext,
sortableKeyboardCoordinates,
useSortable,
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { Button } from "@/components/ui/button";
import { reorderById } from "@/lib/insights-layout-reorder";
import { prefersReducedMotion } from "@/lib/charts/reduced-motion";
import { useTranslations } from "@/lib/i18n/context";
import { EmptyState } from "@/components/ui/empty-state";
/**
* v1.18.6 — generic, controlled reorder list shared by the
* Vorsorge / Illness / Labs settings pages.
*
* A single section (no active/inactive split — the secondary modules have a
* flat list) with the same vocabulary as the medication order editor: an
* `@dnd-kit` drag handle (pointer + keyboard sensors) plus per-row up/down
* arrow buttons as the primary keyboard surface. Unlike the medication
* editor it is fully controlled — there is no Save/Cancel draft state
* because the host persists each move immediately to the localStorage order
* (the choice is presentational, not a server write). The swap-and-renumber
* logic is the shared `reorderById` helper so the order semantics match the
* dashboard / insights / medications surfaces exactly.
*/
export interface ReorderItem {
id: string;
/** Primary label (bold). */
name: string;
/** Optional secondary line (muted). */
secondary?: string;
}
interface ModuleOrderEditorProps {
/** The list in its current effective order. */
items: ReorderItem[];
/** Persist the full id order after every move. */
onChange: (order: string[]) => void;
}
export function ModuleOrderEditor({ items, onChange }: ModuleOrderEditorProps) {
const { t } = useTranslations();
const dragHintId = useId();
const ids = items.map((i) => i.id);
const sensors = useSensors(
useSensor(PointerSensor, { activationConstraint: { distance: 6 } }),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
}),
);
const labels = {
moveUp: t("dashboard.moveUp"),
moveDown: t("dashboard.moveDown"),
dragHandle: t("dashboard.dragHandle"),
};
function applyReorder(fromId: string, toId: string) {
onChange(
reorderById(
ids.map((id, order) => ({ id, order })),
fromId,
toId,
).map((r) => r.id),
);
}
function move(id: string, delta: -1 | 1) {
const idx = ids.indexOf(id);
const targetIdx = idx + delta;
if (idx < 0 || targetIdx < 0 || targetIdx >= ids.length) return;
applyReorder(id, ids[targetIdx]);
}
function handleDragEnd(event: DragEndEvent) {
const { active, over } = event;
if (!over || active.id === over.id) return;
applyReorder(String(active.id), String(over.id));
}
if (items.length === 0) {
return (
{t("dashboard.dragHandleHint")}