feat: add recurring event deletion with three modes

Implement three deletion modes for recurring events:
- single: exclude specific occurrence via EXDATE mechanism
- future: set RRULE UNTIL to stop future occurrences
- all: delete entire event series

Changes include:
- Add exceptionDates field to CalendarEvent model
- Add RecurringDeleteMode type and DeleteRecurringEventDTO
- EventService.deleteRecurring() with mode-based logic using rrule library
- EventController DELETE endpoint accepts mode/occurrenceDate query params
- recurrenceExpander filters out exception dates during expansion
- AI tools support deleteMode and occurrenceDate for proposed deletions
- ChatService.confirmEvent() handles recurring delete modes
- New DeleteEventModal component for unified delete confirmation UI
- Calendar screen integrates modal for both recurring and non-recurring events
This commit is contained in:
2026-01-25 15:19:31 +01:00
parent a42e2a7c1c
commit 2b999d9b0f
35 changed files with 787 additions and 200 deletions

View File

@@ -8,10 +8,18 @@ export interface CalendarEvent {
note?: string;
isRecurring?: boolean;
recurrenceRule?: string;
exceptionDates?: string[]; // ISO date strings (YYYY-MM-DD) for excluded occurrences
createdAt?: Date;
updatedAt?: Date;
}
export type RecurringDeleteMode = "single" | "future" | "all";
export interface DeleteRecurringEventDTO {
mode: RecurringDeleteMode;
occurrenceDate?: string; // ISO date string of the occurrence to delete
}
export interface CreateEventDTO {
title: string;
description?: string;
@@ -30,6 +38,7 @@ export interface UpdateEventDTO {
note?: string;
isRecurring?: boolean;
recurrenceRule?: string;
exceptionDates?: string[];
}
export interface ExpandedEvent extends CalendarEvent {

View File

@@ -1,4 +1,8 @@
import { CreateEventDTO, UpdateEventDTO } from "./CalendarEvent";
import {
CreateEventDTO,
UpdateEventDTO,
RecurringDeleteMode,
} from "./CalendarEvent";
export type MessageSender = "user" | "assistant";
@@ -13,6 +17,8 @@ export interface ProposedEventChange {
event?: CreateEventDTO; // Required for create
updates?: UpdateEventDTO; // Required for update
respondedAction?: RespondedAction; // User's response to this specific proposal
deleteMode?: RecurringDeleteMode; // For recurring event deletion
occurrenceDate?: string; // ISO date string of specific occurrence for single/future delete
}
export interface ChatMessage {