feat(fase-5.11): selection mode + bulk actions (delete / move / mark-checked)

Long-press on mobile or the new header toggle on desktop puts
/lists/[id] into multi-select mode. Rows render a checkbox on the left,
the stepper + drag handle go away, and swipes + double-tap are disabled.

Chrome during selection mode
  Mobile: header turns into a dark slate-900 action bar with "N selected"
    + Cancel on the left, and a bottom action bar (Delete / Move / Check)
    appears above the BottomTabBar. The sticky add-item form is hidden.
  Desktop: same dark header with Cancel + inline action icons on the right.

Bulk actions
  Delete — one scheduleUndoable with a batch restore (re-inserts all
    snapshots) / batch commit (bulkDeleteItems). Single undo toast.
  Move — opens a bottom sheet / dialog with the collective's other active
    lists + a "Create new list" row that creates an empty list and moves
    into it in a single gesture.
  Mark checked — flips only the selected unchecked items
    (bulkCheckItems with is_checked=false filter), no toggle.

Store helpers (apps/web/src/lib/stores/lists.ts)
  bulkDeleteItems(ids)           → DELETE .in('id', ids)
  bulkMoveItems(ids, newListId)  → UPDATE list_id .in('id', ids)
  bulkCheckItems(ids, userId)    → UPDATE is_checked=true where !is_checked

Entry / exit
  Long-press 500 ms on a row enters with that row pre-selected. Movement
    cancels the long-press intent so it never fights the swipe.
  Single-tap toggles selection while active (instead of invoking the
    no-op short-tap / dbltap-overlay path).
  Cancel button exits + clears selection.

Tests
  apps/web/tests/e2e/selection.test.ts (3 desktop tests)
    SEL-01 toggle enters, row click toggles, Cancel exits
    SEL-02 bulk delete → row gone + undo toast visible
    SEL-03 mark checked → row gains strikethrough
  Mobile long-press tests deferred until WebKit install lands (same
  reason as the swipe-toggle M-series).

i18n additions
  list_select, list_cancel_selection, list_selection_count({n}),
  list_bulk_delete/move/mark_checked, list_undo_bulk_delete({n}),
  list_move_title, list_move_create_new (en/es).

Verification
  just test-e2e → 43 passed + 2 skipped (was 40 + 2).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-13 19:33:46 +02:00
parent 1cb408acc2
commit f3e8234b70
5 changed files with 559 additions and 97 deletions

View File

@@ -170,5 +170,14 @@
"list_reorder_handle": "Reorder",
"list_edit_item": "Edit item",
"list_confirm": "Confirm",
"list_close": "Close"
"list_close": "Close",
"list_select": "Select",
"list_selection_count": "{n} selected",
"list_cancel_selection": "Cancel",
"list_bulk_delete": "Delete",
"list_bulk_move": "Move",
"list_bulk_mark_checked": "Mark checked",
"list_undo_bulk_delete": "Deleted {n} items",
"list_move_title": "Move to list",
"list_move_create_new": "Create new list"
}

View File

@@ -170,5 +170,14 @@
"list_reorder_handle": "Reordenar",
"list_edit_item": "Editar producto",
"list_confirm": "Confirmar",
"list_close": "Cerrar"
"list_close": "Cerrar",
"list_select": "Seleccionar",
"list_selection_count": "{n} seleccionados",
"list_cancel_selection": "Cancelar",
"list_bulk_delete": "Eliminar",
"list_bulk_move": "Mover",
"list_bulk_mark_checked": "Marcar",
"list_undo_bulk_delete": "{n} eliminados",
"list_move_title": "Mover a lista",
"list_move_create_new": "Crear lista nueva"
}