implement event persistence and improve Mongoose TypeScript patterns

- Add event persistence: confirmed events are now saved to MongoDB
- Refactor Mongoose models to use virtuals for id field with IdVirtual interface
- Update repositories to use toJSON() with consistent type casting
- Add more test responses for chat (doctor, birthday, gym, etc.)
- Show event description in ProposedEventCard
- Change mongo-express port to 8083
- Update CLAUDE.md with Mongoose model pattern documentation
This commit is contained in:
2026-01-04 11:52:05 +01:00
parent c33508a227
commit 9fecf94c7d
13 changed files with 240 additions and 48 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 } from "@caldav/shared";
import { ProposedEventChange, CreateEventDTO } from "@caldav/shared";
import { ProposedEventCard } from "../../components/ProposedEventCard";
// TODO: better shadows for everything
@@ -39,7 +39,8 @@ const Chat = () => {
const handleEventResponse = async (
action: "confirm" | "reject",
messageId: string,
conversationId: string
conversationId: string,
event?: CreateEventDTO
) => {
// Mark message as responded (optimistic update)
setMessages((prev) =>
@@ -50,8 +51,8 @@ const Chat = () => {
try {
const response =
action === "confirm"
? await ChatService.confirmEvent(conversationId, messageId)
action === "confirm" && event
? await ChatService.confirmEvent(conversationId, messageId, event)
: await ChatService.rejectEvent(conversationId, messageId);
const botMessage: MessageData = {
@@ -111,7 +112,7 @@ const Chat = () => {
proposedChange={item.proposedChange}
respondedAction={item.respondedAction}
onConfirm={() =>
handleEventResponse("confirm", item.id, item.conversationId!)
handleEventResponse("confirm", item.id, item.conversationId!, item.proposedChange?.event)
}
onReject={() =>
handleEventResponse("reject", item.id, item.conversationId!)

View File

@@ -40,6 +40,11 @@ export const ProposedEventCard = ({
<Text style={{ color: currentTheme.textSecondary }}>
{formatDateTime(event?.startTime)}
</Text>
{event?.description && (
<Text style={{ color: currentTheme.textSecondary }} className="text-sm mt-1">
{event.description}
</Text>
)}
{event?.isRecurring && (
<Text style={{ color: currentTheme.textMuted }} className="text-sm">
Wiederkehrend

View File

@@ -4,6 +4,7 @@ import {
ChatMessage,
ConversationSummary,
GetMessagesOptions,
CreateEventDTO,
} from "@caldav/shared";
import { ApiClient } from "./ApiClient";
@@ -14,9 +15,10 @@ export const ChatService = {
confirmEvent: async (
conversationId: string,
messageId: string
messageId: string,
event: CreateEventDTO
): Promise<ChatResponse> => {
return ApiClient.post<ChatResponse>(`/chat/confirm/${conversationId}/${messageId}`);
return ApiClient.post<ChatResponse>(`/chat/confirm/${conversationId}/${messageId}`, event);
},
rejectEvent: async (