Files
calchat/apps/server/src/repositories/mongo/models/ChatModel.ts
Linus Waldowsky 6f0d172bf2 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
2026-01-31 18:46:31 +01:00

156 lines
3.1 KiB
TypeScript

import mongoose, { Schema, Document, Model } from "mongoose";
import {
ChatMessage,
Conversation,
CreateEventDTO,
UpdateEventDTO,
ProposedEventChange,
} from "@calchat/shared";
import { IdVirtual } from "./types";
export interface ChatMessageDocument extends Omit<ChatMessage, "id">, Document {
toJSON(): ChatMessage;
}
export interface ConversationDocument
extends Omit<Conversation, "id">, Document {
toJSON(): Conversation;
}
const EventSchema = new Schema<CreateEventDTO>(
{
title: { type: String, required: true },
description: { type: String },
startTime: { type: Date, required: true },
endTime: { type: Date, required: true },
note: { type: String },
recurrenceRule: { type: String },
exceptionDates: { type: [String] },
},
{ _id: false },
);
const UpdatesSchema = new Schema<UpdateEventDTO>(
{
title: { type: String },
description: { type: String },
startTime: { type: Date },
endTime: { type: Date },
note: { type: String },
recurrenceRule: { type: String },
},
{ _id: false },
);
const ProposedChangeSchema = new Schema<ProposedEventChange>(
{
id: { type: String, required: true },
action: {
type: String,
enum: ["create", "update", "delete"],
required: true,
},
eventId: { type: String },
event: { type: EventSchema },
updates: { type: UpdatesSchema },
respondedAction: {
type: String,
enum: ["confirm", "reject"],
},
deleteMode: {
type: String,
enum: ["single", "future", "all"],
},
occurrenceDate: { type: String },
},
{ _id: false },
);
const ChatMessageSchema = new Schema<
ChatMessageDocument,
Model<ChatMessageDocument, {}, {}, IdVirtual>,
{},
{},
IdVirtual
>(
{
conversationId: {
type: String,
required: true,
},
sender: {
type: String,
enum: ["user", "assistant"],
required: true,
},
content: {
type: String,
required: true,
},
proposedChanges: {
type: [ProposedChangeSchema],
default: undefined,
},
},
{
timestamps: true,
virtuals: {
id: {
get() {
return this._id.toString();
},
},
},
toJSON: {
virtuals: true,
transform: (_, ret: Record<string, unknown>) => {
delete ret._id;
delete ret.__v;
return ret;
},
},
},
);
const ConversationSchema = new Schema<
ConversationDocument,
Model<ConversationDocument, {}, {}, IdVirtual>,
{},
{},
IdVirtual
>(
{
userId: {
type: String,
required: true,
index: true,
},
},
{
timestamps: true,
virtuals: {
id: {
get() {
return this._id.toString();
},
},
},
toJSON: {
virtuals: true,
transform: (_, ret: Record<string, unknown>) => {
delete ret._id;
delete ret.__v;
return ret;
},
},
},
);
export const ChatMessageModel = mongoose.model<ChatMessageDocument>(
"ChatMessage",
ChatMessageSchema,
);
export const ConversationModel = mongoose.model<ConversationDocument>(
"Conversation",
ConversationSchema,
);