diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx
index f048f2e..1dfff58 100644
--- a/frontend/src/pages/Dashboard.tsx
+++ b/frontend/src/pages/Dashboard.tsx
@@ -3,8 +3,7 @@ import {
Container,
Box,
Fade,
- IconButton,
- Tooltip,
+ Button,
} from '@mui/material';
import { Edit as EditIcon, Check as CheckIcon } from '@mui/icons-material';
import { useQuery, useQueryClient } from '@tanstack/react-query';
@@ -272,19 +271,6 @@ function Dashboard() {
- {/* Edit mode toggle */}
-
-
- setEditMode((prev) => !prev)}
- color={editMode ? 'primary' : 'default'}
- >
- {editMode ? : }
-
-
-
-
+
+ {/* Edit mode toggle — bottom */}
+
+ : }
+ onClick={() => setEditMode((prev) => !prev)}
+ color={editMode ? 'primary' : 'inherit'}
+ sx={{ borderRadius: 4, px: 3 }}
+ >
+ {editMode ? 'Bearbeitung beenden' : 'Widgets anordnen'}
+
+
);
}
diff --git a/frontend/src/pages/Settings.tsx b/frontend/src/pages/Settings.tsx
index 846fe60..bf3bd04 100644
--- a/frontend/src/pages/Settings.tsx
+++ b/frontend/src/pages/Settings.tsx
@@ -20,9 +20,25 @@ import {
ListItem,
ListItemText,
} from '@mui/material';
-import { Settings as SettingsIcon, Notifications, Palette, Language, SettingsBrightness, LightMode, DarkMode, Widgets, Cloud, LinkOff, Forum, Person, OpenInNew, ArrowUpward, ArrowDownward, Sort, Restore } from '@mui/icons-material';
+import { Settings as SettingsIcon, Notifications, Palette, Language, SettingsBrightness, LightMode, DarkMode, Widgets, Cloud, LinkOff, Forum, Person, OpenInNew, Sort, Restore, DragIndicator } from '@mui/icons-material';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
+import {
+ DndContext,
+ PointerSensor,
+ useSensor,
+ useSensors,
+ closestCenter,
+} from '@dnd-kit/core';
+import type { DragEndEvent } from '@dnd-kit/core';
+import {
+ SortableContext,
+ verticalListSortingStrategy,
+ arrayMove,
+ useSortable,
+} from '@dnd-kit/sortable';
+import { CSS } from '@dnd-kit/utilities';
+import { useNavigate } from 'react-router-dom';
import DashboardLayout from '../components/dashboard/DashboardLayout';
import { useThemeMode } from '../contexts/ThemeContext';
import { preferencesApi } from '../services/settings';
@@ -48,9 +64,37 @@ const ORDERABLE_NAV_ITEMS = [
{ text: 'Wissen', path: '/wissen', permission: 'wissen:view' },
{ text: 'Bestellungen', path: '/bestellungen', permission: 'bestellungen:view' },
{ text: 'Interne Bestellungen', path: '/ausruestungsanfrage', permission: 'ausruestungsanfrage:view' },
+ { text: 'Checklisten', path: '/checklisten', permission: 'checklisten:view' },
{ text: 'Issues', path: '/issues', permission: 'issues:view_own' },
];
+function SortableNavItem({ id, text }: { id: string; text: string }) {
+ const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id });
+ return (
+
+
+
+
+
+
+ );
+}
+
function Settings() {
const { themeMode, setThemeMode } = useThemeMode();
const queryClient = useQueryClient();
@@ -96,13 +140,23 @@ function Settings() {
return 0;
});
- const moveNavItem = (fromIdx: number, toIdx: number) => {
- if (toIdx < 0 || toIdx >= orderedNavItems.length) return;
- const newOrder = [...orderedNavItems];
- const [moved] = newOrder.splice(fromIdx, 1);
- newOrder.splice(toIdx, 0, moved);
+ const [localNavItems, setLocalNavItems] = useState(orderedNavItems);
+ useEffect(() => { setLocalNavItems(orderedNavItems); }, [menuOrder.join(',')]);
+
+ const navSensors = useSensors(
+ useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
+ );
+
+ const handleNavDragEnd = (event: DragEndEvent) => {
+ const { active, over } = event;
+ if (!over || active.id === over.id) return;
+ const oldIdx = localNavItems.findIndex((i) => i.path === active.id);
+ const newIdx = localNavItems.findIndex((i) => i.path === over.id);
+ if (oldIdx === -1 || newIdx === -1) return;
+ const newItems = arrayMove(localNavItems, oldIdx, newIdx);
+ setLocalNavItems(newItems);
const current = preferences ?? {};
- mutation.mutate({ ...current, menuOrder: newOrder.map((i) => i.path) });
+ mutation.mutate({ ...current, menuOrder: newItems.map((i) => i.path) });
};
const resetMenuOrder = () => {
@@ -270,41 +324,22 @@ function Settings() {
) : (
-
- {orderedNavItems.map((item, idx) => (
-
- moveNavItem(idx, idx - 1)}
- disabled={idx === 0 || mutation.isPending}
- aria-label="Nach oben"
- >
-
-
- moveNavItem(idx, idx + 1)}
- disabled={idx === orderedNavItems.length - 1 || mutation.isPending}
- aria-label="Nach unten"
- >
-
-
-
- }
- >
-
-
- ))}
-
+
+ i.path)}
+ strategy={verticalListSortingStrategy}
+ >
+
+ {localNavItems.map((item) => (
+
+ ))}
+
+
+
)}