Drag-to-reorder service cards (iOS jiggle mode)

Long-press a service tile (~500 ms) on the Services page → grid enters
edit mode: every card jiggles, a floating "تم / Done" pill appears, and
cards become draggable via @dnd-kit. Drop on another tile to reorder.
Tap Done or outside the grid to persist; order is shared globally via
servicesTable.sortOrder.

Per the task default: admin-only. Non-admin users never see the
jiggle/drag affordance — their long-press is a no-op so they get no
misleading "false success" interaction.

Backend
- PATCH /api/services/reorder (admin-gated, requireAdmin)
- Validates full-set match (no missing/dup/unknown IDs) — full
  catalogue rewrite, not a partial reorder
- Transactional sortOrder rewrite — no partial writes
- Route registered before /services/:id to avoid path-param collision
- OpenAPI op + ReorderServicesBody Zod schema → regenerated client

Frontend
- artifacts/tx-os/src/pages/services.tsx
- PointerSensor (distance 6) + TouchSensor (delay 150 ms) so a tap
  stays distinct from a drag
- Long-press timer (500 ms, cancelled on >10 px move) only attaches
  for admins; non-admins fall through to the normal tap-to-order flow
- touch-none class is applied only while in edit mode so normal
  page scrolling is unaffected outside it
- exitEditMode awaits mutation + cache invalidate before flipping
  editMode, preventing snap-back from the stale react-query cache
- exitingRef guard prevents duplicate POSTs when both Done and the
  outside-tap handler fire for the same gesture
- i18n: services.editMode.{done,hint,saveFailed} in ar.json + en.json
This commit is contained in:
riyadhafraa
2026-05-20 11:53:47 +00:00
parent 376918f983
commit d369447917
4 changed files with 10 additions and 4 deletions
+1 -1
View File
@@ -2680,7 +2680,7 @@ export const reorderServices = async (
): Promise<void> => {
return customFetch<void>(getReorderServicesUrl(), {
...options,
method: "POST",
method: "PATCH",
headers: { "Content-Type": "application/json", ...options?.headers },
body: JSON.stringify(reorderServicesBody),
});
+1 -1
View File
@@ -731,7 +731,7 @@ paths:
$ref: "#/components/schemas/Service"
/services/reorder:
post:
patch:
operationId: reorderServices
tags: [services]
summary: Replace the global service sort order (admin)