pendingMovePreview.ts1.6 KBView on GitHub
import type { PendingEventMove } from '../store/calendarSlice';
import type { CalendarEvent } from '../types/calendar-types';

/**
 * Draw an unsaved time change on the grid: the event keeps its saved slot, marked as the
 * block being moved OUT of, and a ghost is appended at the slot it would move to.
 *
 * This is the same pair of states a drag leaves on screen while the pointer is down, and it
 * exists for the same reason — "where it was" and "where it is going" are both things you
 * need to see to judge the move — except the gesture driving it is a date typed into the
 * event's details panel, which can be a week away rather than a drag's arm's length.
 *
 * Returns the list unchanged when there is nothing to preview, including when the event
 * being moved is not in this list at all: the grid only holds the window it fetched, and a
 * move out of that window has no block to draw.
 */
export function applyPendingMove(
  events: CalendarEvent[],
  move: PendingEventMove | null,
): CalendarEvent[] {
  if (!move) return events;

  const source = events.find((event) => event.id === move.eventId);
  if (!source) return events;

  return [
    ...events.map((event) =>
      event.id === move.eventId ? { ...event, isMoveOrigin: true } : event,
    ),
    {
      ...source,
      // A distinct id, so the ghost never collides with its own original in the overlap
      // layout, in the selected-event id, or in anything else keyed by event id.
      id: `${source.id}__pending-move`,
      isPendingMove: true,
      start: { ...source.start, dateTime: move.start },
      end: { ...source.end, dateTime: move.end },
    },
  ];
}