Warn Before Date-Sensitive Actions Cross Week Boundaries

confirmation dialogs date-sensitive ui move and copy paths pre-mutation guards ux safety Jul 02, 2026

Users can preserve the selected dashboard week and still accidentally move or copy a card into a past or future week without realizing it. The data layer may be correct. The movement logic may work. The gap is UX safety: nothing warns before a date-sensitive action crosses a period boundary the user did not intend.

The problem

The surface symptom sounds like a date or storage bug: a card ends up in the wrong week. The instinct is to trace how dates are written or how week navigation works.

Often the selected week is already preserved correctly. The real gap is that destination clicks can trigger mutations into non-current weeks with no confirmation. Users do not get a chance to notice they are about to place work in a past or future period before the action commits.

What actually happened

The important seam was the UI dispatch path—not the server action, not the RPC, not a dashboard navigation redesign. The safe interception point sat before any state change, server call, optimistic update, or revalidation.

Hidden complexity came from sibling execution paths. What looked like a "move" problem also included copy behaviour. Normal moves used one mutation path; child placement into a weekly list used a separate copy path. A guard wired only to the move handler would have missed the copy route entirely.

The fix stayed structural at the dispatch seam: intercept before mutation, warn when the destination week differs from the current week, and preserve existing backend behaviour on confirm. Cancel had to block mutation entirely. Confirm had to delegate to the existing path exactly once.

Verification matched the risk surface: current-week actions proceed without warning, past and future destinations trigger confirmation, cancel prevents mutation, confirm executes once, and the copy path is covered alongside the move path.

Residual risk remains around full browser dialog interaction in a modal-heavy component—stacking, focus, and rapid double-confirm were not fully exercised end-to-end.

The lesson

For date-sensitive UI actions, define three things before building:

  1. Where "current" comes from — which function, which timezone assumption, which week-start convention, and which normalized date format drives the comparison.
  2. The narrowest pre-mutation seam — the last point before any state change or server call where a guard can intercept every relevant path.
  3. Every branch that can reach that seam — use "move/copy/mutate" language until the audit proves only one path exists.

Confirmation dialogs in components that already manage multiple pending flows need separate state. A new warning must not clobber an existing delete, edit, or navigation confirmation.

The broader principle

Small UX safety items can still hide real complexity when one UI action fans out into multiple mutation paths. The pattern that generalizes: audit the real dispatch seam, guard before mutation, preserve existing backend behaviour, and test both cancel and confirm.

Direct implementation is appropriate when the audit identifies a bounded seam, clear non-goals, and testable acceptance behaviour. No architectural redesign and no unresolved product ambiguity are required for a well-scoped guard.

For verification, prove the new behaviour and the old bad behaviour. Tests should fail against the previous model: accidental cross-week placement without warning should no longer be possible.

How to apply it

  1. Map the dispatch path. Trace from user click through handler to mutation. Name every branch—including copy paths that "move" language might hide.
  2. Place the guard before mutation. Do not add warning text after state has already changed. Intercept before server actions, optimistic updates, and revalidation.
  3. Specify the date contract. Document week-start convention, comparison method, and formatting. Make "current week" explicit, not implicit.
  4. Add acceptance criteria for both outcomes. Cancel must block mutation. Confirm must execute the existing path once.
  5. Test adjacent confirmation flows. When adding a dialog to a modal-heavy component, add at least one regression for collision with existing pending states.
  6. Keep scope narrow. Resist RPC changes, navigation redesign, and adjacent fixes unless the audit proves they are in scope.

The backend does not need to change when the problem is accidental user intent at the UI layer. The guard belongs where the user's choice becomes a mutation.