Without a scope prompt, editing a single weekly-recurring slot rewrites every past and future occurrence, corrupting historical schedules and silently changing appointments customers have already booked. Hosts lose the ability to handle one-off changes (vacation, a shifted single week) without breaking the entire series. This erodes trust in the scheduling tool, forces manual database fixes, and can cause calendar-invite mismatches where the host's system shows one time and the attendee's another.
Info because this is a capability gap rather than an active defect, but absence blocks common scheduling workflows and causes data churn when workarounds are used.
Before applying any edit to a recurring event, open a dialog offering three choices: 'this only' (insert a row into availability_exceptions with the occurrence date), 'this and future' (set a new dtstart on a cloned rule), and 'all' (mutate the original rrule). Branch your persistence logic on the returned scope. See src/components/RecurringEditScopeDialog.tsx:
const scope = await showScopeDialog() // 'this' | 'thisFuture' | 'all'
if (scope === 'this') await db.availabilityExceptions.create({ recurringId, exceptionDate })
ID: booking-calendar-availability.recurring.recurring-edit-scope
Severity: info
What to look for: Search for recurring event edit UI components. Count all edit scope options presented to the user. Look for a dialog, modal, or prompt that offers at least 3 choices when editing a recurring event instance:
src/components/*RecurringEdit*, src/components/*ScopeDialog*, src/components/*Schedule*.Pass criteria: Enumerate all edit scope options in the recurring edit UI. At least 3 scope options must be presented ("this only", "this and future", "all"). Each option must trigger a distinct code path (exception creation, rule modification from date, or full rule update). Report: "Edit scope options: [list]. X of 3 required scopes implemented."
Fail criteria: No scope prompt appears when editing a recurring event, or only 1 scope option exists (e.g., always edits all occurrences).
Skip (N/A) when: Platform does not support editing recurring schedules, or does not have recurring schedule features.
Detail on fail: Example: "Editing a recurring Wednesday availability updates all occurrences, even past ones. No option to edit just future occurrences."
Cross-reference: Check rule-based-storage — edit scopes require rule-based storage to function properly.
Cross-reference: Check exception-handling — "edit this only" creates an exception that must be applied in real time.
Cross-reference: Check data-freshness — after editing scope, the calendar must refetch to reflect the change.
Remediation: Add a scope prompt when editing recurring schedules:
async function handleEditRecurring(eventId) {
const scope = await showScopeDialog()
// Options: 'this', 'thisFuture', 'all'
if (scope === 'this') {
// Create exception for this date only
await db.availabilityExceptions.create({
recurringId: eventId,
exceptionDate: selectedDate,
isAvailable: false,
})
} else if (scope === 'thisFuture') {
// Update rule with new dtstart
await db.recurringAvailability.update({
where: { id: eventId },
data: { rrule: updatedRRule },
})
} else if (scope === 'all') {
// Update entire recurring rule
await db.recurringAvailability.update({
where: { id: eventId },
data: { rrule: updatedRRule },
})
}
}