add event CRUD actions and recurring event expansion

- Implement full CRUD in MongoEventRepository (findById, findByUserId, findByDateRange, update, delete)
- Extend ChatService to handle create/update/delete actions with dynamic test responses
- Add recurrenceExpander utility using rrule library for RRULE parsing
- Add eventFormatters utility for German-localized week/month overviews
- Add German translations for days and months in shared Constants
- Update client ChatService to support all event actions (action, eventId, updates params)
This commit is contained in:
2026-01-04 16:15:30 +01:00
parent 9fecf94c7d
commit 77f15b6dd1
11 changed files with 577 additions and 174 deletions

View File

@@ -5,7 +5,7 @@ import Header from "../../components/Header";
import BaseBackground from "../../components/BaseBackground";
import { FlashList } from "@shopify/flash-list";
import { ChatService } from "../../services";
import { ProposedEventChange, CreateEventDTO } from "@caldav/shared";
import { ProposedEventChange } from "@caldav/shared";
import { ProposedEventCard } from "../../components/ProposedEventCard";
// TODO: better shadows for everything
@@ -40,7 +40,7 @@ const Chat = () => {
action: "confirm" | "reject",
messageId: string,
conversationId: string,
event?: CreateEventDTO
proposedChange?: ProposedEventChange
) => {
// Mark message as responded (optimistic update)
setMessages((prev) =>
@@ -51,8 +51,15 @@ const Chat = () => {
try {
const response =
action === "confirm" && event
? await ChatService.confirmEvent(conversationId, messageId, event)
action === "confirm" && proposedChange
? await ChatService.confirmEvent(
conversationId,
messageId,
proposedChange.action,
proposedChange.event,
proposedChange.eventId,
proposedChange.updates
)
: await ChatService.rejectEvent(conversationId, messageId);
const botMessage: MessageData = {
@@ -112,7 +119,7 @@ const Chat = () => {
proposedChange={item.proposedChange}
respondedAction={item.respondedAction}
onConfirm={() =>
handleEventResponse("confirm", item.id, item.conversationId!, item.proposedChange?.event)
handleEventResponse("confirm", item.id, item.conversationId!, item.proposedChange)
}
onReject={() =>
handleEventResponse("reject", item.id, item.conversationId!)

View File

@@ -5,9 +5,18 @@ import {
ConversationSummary,
GetMessagesOptions,
CreateEventDTO,
UpdateEventDTO,
EventAction,
} from "@caldav/shared";
import { ApiClient } from "./ApiClient";
interface ConfirmEventRequest {
action: EventAction;
event?: CreateEventDTO;
eventId?: string;
updates?: UpdateEventDTO;
}
export const ChatService = {
sendMessage: async (data: SendMessageDTO): Promise<ChatResponse> => {
return ApiClient.post<ChatResponse>("/chat/message", data);
@@ -16,9 +25,13 @@ export const ChatService = {
confirmEvent: async (
conversationId: string,
messageId: string,
event: CreateEventDTO
action: EventAction,
event?: CreateEventDTO,
eventId?: string,
updates?: UpdateEventDTO
): Promise<ChatResponse> => {
return ApiClient.post<ChatResponse>(`/chat/confirm/${conversationId}/${messageId}`, event);
const body: ConfirmEventRequest = { action, event, eventId, updates };
return ApiClient.post<ChatResponse>(`/chat/confirm/${conversationId}/${messageId}`, body);
},
rejectEvent: async (