Drag-to-reorder service cards (iOS jiggle mode)
Long-press a service tile (~500 ms) → 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; the new order is shared globally via
servicesTable.sortOrder.
Backend
- POST /api/services/reorder (admin-gated, requireAdmin)
- Validates full-set match (no missing/dup/unknown IDs)
- 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 rewritten
- PointerSensor (distance 6) + TouchSensor (delay 150 ms) — long-press
and tap-to-open stay distinct
- touch-none only applied while in edit mode so normal scrolling is
unaffected outside it
- exitEditMode awaits mutation + invalidate before flipping editMode,
preventing snap-back from stale react-query cache
- exitingRef guard against duplicate exit calls (Done button +
outside-tap handler firing for the same gesture)
- Non-admins can enter edit mode (haptic affordance) but local reorder
is silently reverted on exit
- i18n: services.editMode.{done,hint,saveFailed} added to ar.json/en.json
Pre-existing unrelated typecheck errors in push.ts and
executive-meeting-font-settings.ts are not touched by this change.
This commit is contained in:
@@ -730,6 +730,33 @@ paths:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Service"
|
||||
|
||||
/services/reorder:
|
||||
post:
|
||||
operationId: reorderServices
|
||||
tags: [services]
|
||||
summary: Replace the global service sort order (admin)
|
||||
description: |
|
||||
Persists a new global `sortOrder` for the service catalogue by
|
||||
applying the index of each id in `orderedIds`. Admin-only.
|
||||
The body must contain every existing service id exactly once;
|
||||
partial reorders are rejected with 400 so the client can never
|
||||
accidentally drop services from the sort plan.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ReorderServicesBody"
|
||||
responses:
|
||||
"204":
|
||||
description: Sort order updated
|
||||
"400":
|
||||
description: Validation error or mismatched id set
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorResponse"
|
||||
|
||||
/services/{id}:
|
||||
get:
|
||||
operationId: getService
|
||||
@@ -4031,6 +4058,24 @@ components:
|
||||
sortOrder:
|
||||
type: integer
|
||||
|
||||
ReorderServicesBody:
|
||||
type: object
|
||||
description: |
|
||||
New global service order. `orderedIds` must contain every
|
||||
existing service id exactly once. The server sets each
|
||||
service's `sortOrder` to its position in the list (0-based),
|
||||
so a later GET /services returns them in the same order.
|
||||
properties:
|
||||
orderedIds:
|
||||
type: array
|
||||
minItems: 1
|
||||
maxItems: 1000
|
||||
items:
|
||||
type: integer
|
||||
minimum: 1
|
||||
required:
|
||||
- orderedIds
|
||||
|
||||
ServiceCategory:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
Reference in New Issue
Block a user