From 18a75edf2a4438a6166e7f226b74651cf2447642 Mon Sep 17 00:00:00 2001 From: bonamin Date: Sun, 31 May 2026 23:54:02 +0300 Subject: [PATCH] feat: drag-to-reorder table groups in zone tabs Backend: - tables.py: PUT /api/tables/groups/reorder accepts an ordered list of group IDs and updates sort_order accordingly Frontend (TablesConfigTab): - Zone tabs are now draggable for group tabs (not All/Ungrouped) - HTML5 drag-and-drop with visual drop-target highlight and a grab cursor; fires reorderGroups mutation on drop Co-Authored-By: Claude Sonnet 4.6 --- local_backend/routers/tables.py | 9 ++- .../src/pages/TablesConfigTab.jsx | 68 ++++++++++++++----- 2 files changed, 58 insertions(+), 19 deletions(-) diff --git a/local_backend/routers/tables.py b/local_backend/routers/tables.py index 1fde1a8..6f51e80 100644 --- a/local_backend/routers/tables.py +++ b/local_backend/routers/tables.py @@ -1,4 +1,4 @@ -from fastapi import APIRouter, Depends, HTTPException, status +from fastapi import APIRouter, Depends, HTTPException, status, Body from sqlalchemy.orm import Session from typing import List @@ -36,6 +36,13 @@ def create_group(body: TableGroupCreate, db: Session = Depends(get_db), user: Us return group +@router.put("/groups/reorder", status_code=status.HTTP_204_NO_CONTENT) +def reorder_groups(body: List[int] = Body(...), db: Session = Depends(get_db), user: User = Depends(require_manager)): + for idx, group_id in enumerate(body): + db.query(TableGroup).filter(TableGroup.id == group_id).update({"sort_order": idx}) + db.commit() + + @router.put("/groups/{group_id}", response_model=TableGroupOut) def update_group(group_id: int, body: TableGroupUpdate, db: Session = Depends(get_db), user: User = Depends(require_manager)): group = db.query(TableGroup).filter(TableGroup.id == group_id).first() diff --git a/manager_dashboard/src/pages/TablesConfigTab.jsx b/manager_dashboard/src/pages/TablesConfigTab.jsx index 3e10663..2467c8a 100644 --- a/manager_dashboard/src/pages/TablesConfigTab.jsx +++ b/manager_dashboard/src/pages/TablesConfigTab.jsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { useState, useRef } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import toast from 'react-hot-toast' import client from '../api/client' @@ -43,6 +43,8 @@ export default function TablesPage() { const [activeTab, setActiveTab] = useState('all') // 'all' | group.id const [selected, setSelected] = useState(new Set()) const [anyHovered, setAnyHovered] = useState(false) + const dragGroupId = useRef(null) + const [dragOverId, setDragOverId] = useState(null) const { data: tables = [], isLoading } = useQuery({ queryKey: ['tables-all', showInactive], @@ -102,6 +104,12 @@ export default function TablesPage() { onError: () => toast.error('Σφάλμα'), }) + const reorderGroups = useMutation({ + mutationFn: (ids) => client.put('/api/tables/groups/reorder', ids), + onSuccess: invalidateGroups, + onError: () => toast.error('Σφάλμα αναδιάταξης'), + }) + // Filter tables for the active tab const visibleTables = activeTab === 'all' ? tables @@ -156,23 +164,47 @@ export default function TablesPage() { {/* Zone tabs */}
- {zoneTabs.map(tab => ( - - ))} + {zoneTabs.map(tab => { + const isGroup = tab.id !== 'all' && tab.id !== 'ungrouped' + const isDragOver = dragOverId === tab.id + return ( + + ) + })}
{/* Zone action bar (when viewing a specific zone) */}