feat: add EditEventScreen with calendar and chat mode support

Add a unified event editor that works in two modes:
- Calendar mode: Create/edit events directly via EventService API
- Chat mode: Edit AI-proposed events before confirming them

The chat mode allows users to modify proposed events (title, time,
recurrence) and persists changes both locally and to the server.

New components: DateTimePicker, ScrollableDropdown, useDropdownPosition
New API: PUT /api/chat/messages/:messageId/proposal
This commit is contained in:
2026-01-31 18:46:31 +01:00
parent 617543a603
commit 6f0d172bf2
33 changed files with 1394 additions and 289 deletions

View File

@@ -41,7 +41,6 @@ const staticResponses: TestResponse[] = [
startTime: getDay("Wednesday", 1, 18, 0),
endTime: getDay("Wednesday", 1, 19, 30),
description: "Wöchentliches Training",
isRecurring: true,
recurrenceRule: "FREQ=WEEKLY;BYDAY=WE",
},
},
@@ -158,7 +157,6 @@ const staticResponses: TestResponse[] = [
startTime: getDay("Monday", 1, 7, 0),
endTime: getDay("Monday", 1, 8, 0),
description: "Morgen-Yoga",
isRecurring: true,
recurrenceRule: "FREQ=WEEKLY;BYDAY=MO,WE,FR",
},
},
@@ -170,7 +168,6 @@ const staticResponses: TestResponse[] = [
startTime: getDay("Tuesday", 1, 18, 0),
endTime: getDay("Tuesday", 1, 19, 0),
description: "Abendlauf im Park",
isRecurring: true,
recurrenceRule: "FREQ=WEEKLY;BYDAY=TU,TH",
},
},
@@ -215,7 +212,6 @@ const staticResponses: TestResponse[] = [
title: "Badezimmer putzen",
startTime: getDay("Saturday", 1, 10, 0),
endTime: getDay("Saturday", 1, 11, 0),
isRecurring: true,
recurrenceRule: "FREQ=WEEKLY;BYDAY=SA",
},
},
@@ -255,7 +251,6 @@ const staticResponses: TestResponse[] = [
title: "Mamas Geburtstag",
startTime: getDay("Thursday", 2, 0, 0),
endTime: getDay("Thursday", 2, 23, 59),
isRecurring: true,
recurrenceRule: "FREQ=YEARLY",
},
},
@@ -273,7 +268,6 @@ const staticResponses: TestResponse[] = [
title: "Fitnessstudio Probetraining",
startTime: getDay("Tuesday", 1, 18, 0),
endTime: getDay("Tuesday", 1, 19, 30),
isRecurring: true,
recurrenceRule: "FREQ=WEEKLY;BYDAY=TU;COUNT=8",
},
},
@@ -327,7 +321,6 @@ const staticResponses: TestResponse[] = [
title: "Spanischkurs VHS",
startTime: getDay("Thursday", 1, 19, 0),
endTime: getDay("Thursday", 1, 20, 30),
isRecurring: true,
recurrenceRule: "FREQ=WEEKLY;BYDAY=TH,SA;COUNT=8",
},
},
@@ -373,7 +366,6 @@ async function getTestResponse(
exceptionDate.getTime() + 90 * 60 * 1000,
), // +90 min
description: sportEvent.description,
isRecurring: sportEvent.isRecurring,
recurrenceRule: sportEvent.recurrenceRule,
exceptionDates: sportEvent.exceptionDates,
},
@@ -412,7 +404,6 @@ async function getTestResponse(
startTime: sportEvent.startTime,
endTime: sportEvent.endTime,
description: sportEvent.description,
isRecurring: sportEvent.isRecurring,
recurrenceRule: newRule,
exceptionDates: sportEvent.exceptionDates,
},
@@ -452,7 +443,6 @@ async function getTestResponse(
exceptionDate.getTime() + 90 * 60 * 1000,
), // +90 min
description: sportEvent.description,
isRecurring: sportEvent.isRecurring,
recurrenceRule: sportEvent.recurrenceRule,
exceptionDates: sportEvent.exceptionDates,
},
@@ -488,7 +478,6 @@ async function getTestResponse(
startTime: jensEvent.startTime,
endTime: jensEvent.endTime,
description: jensEvent.description,
isRecurring: jensEvent.isRecurring,
},
},
],
@@ -718,4 +707,12 @@ export class ChatService {
return this.chatRepo.getMessages(conversationId, options);
}
async updateProposalEvent(
messageId: string,
proposalId: string,
event: CreateEventDTO,
): Promise<ChatMessage | null> {
return this.chatRepo.updateProposalEvent(messageId, proposalId, event);
}
}

View File

@@ -2,6 +2,7 @@ import {
ChatMessage,
Conversation,
CreateMessageDTO,
CreateEventDTO,
GetMessagesOptions,
UpdateMessageDTO,
} from "@calchat/shared";
@@ -32,4 +33,10 @@ export interface ChatRepository {
proposalId: string,
respondedAction: "confirm" | "reject",
): Promise<ChatMessage | null>;
updateProposalEvent(
messageId: string,
proposalId: string,
event: CreateEventDTO,
): Promise<ChatMessage | null>;
}