Compare commits
2 Commits
c8aba94879
...
8e58ab4249
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e58ab4249 | |||
| 24ab6f0420 |
10
CLAUDE.md
10
CLAUDE.md
@@ -77,9 +77,10 @@ src/
|
||||
├── components/
|
||||
│ ├── BaseBackground.tsx # Common screen wrapper
|
||||
│ ├── Header.tsx # Header component
|
||||
│ ├── EventCard.tsx # Event card for calendar display
|
||||
│ ├── EventCardBase.tsx # Shared event card layout with icons (used by EventCard & ProposedEventCard)
|
||||
│ ├── EventCard.tsx # Calendar event card (uses EventCardBase + edit/delete buttons)
|
||||
│ ├── EventConfirmDialog.tsx # AI-proposed event confirmation modal
|
||||
│ └── ProposedEventCard.tsx # Inline event proposal with confirm/reject buttons
|
||||
│ └── ProposedEventCard.tsx # Chat event proposal (uses EventCardBase + confirm/reject buttons)
|
||||
├── Themes.tsx # Centralized color/theme definitions
|
||||
├── services/
|
||||
│ ├── index.ts # Re-exports all services
|
||||
@@ -305,8 +306,9 @@ MONGODB_URI=mongodb://root:mongoose@localhost:27017/calchat?authSource=admin
|
||||
- `ApiClient`: get(), post(), put(), delete() implemented
|
||||
- `EventService`: getAll(), getById(), getByDateRange(), create(), update(), delete() - fully implemented
|
||||
- `ChatService`: sendMessage(), confirmEvent(convId, msgId, action, event?, eventId?, updates?), rejectEvent() - supports create/update/delete actions
|
||||
- `EventCard`: Displays event details (title, date, time, duration, recurring indicator) with Feather icons and edit/delete buttons
|
||||
- `ProposedEventCard`: Displays proposed events (title, date, description, recurring indicator) with confirm/reject buttons
|
||||
- `EventCardBase`: Shared base component with event layout (header, date/time/recurring icons, description) - used by both EventCard and ProposedEventCard
|
||||
- `EventCard`: Uses EventCardBase + edit/delete buttons for calendar display
|
||||
- `ProposedEventCard`: Uses EventCardBase + confirm/reject buttons for chat proposals (supports create/update/delete actions)
|
||||
- `Themes.tsx`: Centralized color definitions including textPrimary, borderPrimary, eventIndicator
|
||||
- `EventsStore`: Zustand store with setEvents(), addEvent(), updateEvent(), deleteEvent() - stores ExpandedEvent[]
|
||||
- `ChatStore`: Zustand store with addMessage(), updateMessage(), clearMessages() - persists messages across tab switches
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { View, Text, Pressable } from "react-native";
|
||||
import { View, Pressable } from "react-native";
|
||||
import { ExpandedEvent } from "@caldav/shared";
|
||||
import { Feather } from "@expo/vector-icons";
|
||||
import currentTheme from "../Themes";
|
||||
import { EventCardBase } from "./EventCardBase";
|
||||
|
||||
type EventCardProps = {
|
||||
event: ExpandedEvent;
|
||||
@@ -9,117 +10,16 @@ type EventCardProps = {
|
||||
onDelete: () => void;
|
||||
};
|
||||
|
||||
function formatDate(date: Date): string {
|
||||
const d = new Date(date);
|
||||
return d.toLocaleDateString("de-DE", {
|
||||
weekday: "short",
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
}
|
||||
|
||||
function formatTime(date: Date): string {
|
||||
const d = new Date(date);
|
||||
return d.toLocaleTimeString("de-DE", {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
}
|
||||
|
||||
function formatDuration(start: Date, end: Date): string {
|
||||
const startDate = new Date(start);
|
||||
const endDate = new Date(end);
|
||||
const diffMs = endDate.getTime() - startDate.getTime();
|
||||
const diffMins = Math.round(diffMs / 60000);
|
||||
|
||||
if (diffMins < 60) {
|
||||
return `${diffMins} min`;
|
||||
}
|
||||
|
||||
const hours = Math.floor(diffMins / 60);
|
||||
const mins = diffMins % 60;
|
||||
|
||||
if (mins === 0) {
|
||||
return hours === 1 ? "1 Std" : `${hours} Std`;
|
||||
}
|
||||
|
||||
return `${hours} Std ${mins} min`;
|
||||
}
|
||||
|
||||
export const EventCard = ({ event, onEdit, onDelete }: EventCardProps) => {
|
||||
return (
|
||||
<View
|
||||
className="rounded-xl overflow-hidden mb-3"
|
||||
style={{ borderWidth: 2, borderColor: currentTheme.borderPrimary }}
|
||||
>
|
||||
{/* Header with title */}
|
||||
<View
|
||||
className="px-3 py-2"
|
||||
style={{
|
||||
backgroundColor: currentTheme.chatBot,
|
||||
borderBottomWidth: 2,
|
||||
borderBottomColor: currentTheme.borderPrimary,
|
||||
}}
|
||||
<View className="mb-3">
|
||||
<EventCardBase
|
||||
title={event.title}
|
||||
startTime={event.occurrenceStart}
|
||||
endTime={event.occurrenceEnd}
|
||||
description={event.description}
|
||||
isRecurring={event.isRecurring}
|
||||
>
|
||||
<Text className="font-bold text-base">{event.title}</Text>
|
||||
</View>
|
||||
|
||||
{/* Content */}
|
||||
<View className="px-3 py-2 bg-white">
|
||||
{/* Date */}
|
||||
<View className="flex-row items-center mb-1">
|
||||
<Feather
|
||||
name="calendar"
|
||||
size={16}
|
||||
color={currentTheme.textPrimary}
|
||||
style={{ marginRight: 8 }}
|
||||
/>
|
||||
<Text style={{ color: currentTheme.textPrimary }}>
|
||||
{formatDate(event.occurrenceStart)}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Time with duration */}
|
||||
<View className="flex-row items-center mb-1">
|
||||
<Feather
|
||||
name="clock"
|
||||
size={16}
|
||||
color={currentTheme.textPrimary}
|
||||
style={{ marginRight: 8 }}
|
||||
/>
|
||||
<Text style={{ color: currentTheme.textPrimary }}>
|
||||
{formatTime(event.occurrenceStart)} -{" "}
|
||||
{formatTime(event.occurrenceEnd)} (
|
||||
{formatDuration(event.occurrenceStart, event.occurrenceEnd)})
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Recurring indicator */}
|
||||
{event.isRecurring && (
|
||||
<View className="flex-row items-center mb-1">
|
||||
<Feather
|
||||
name="repeat"
|
||||
size={16}
|
||||
color={currentTheme.textPrimary}
|
||||
style={{ marginRight: 8 }}
|
||||
/>
|
||||
<Text style={{ color: currentTheme.textPrimary }}>
|
||||
Wiederkehrend
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Description */}
|
||||
{event.description && (
|
||||
<Text
|
||||
style={{ color: currentTheme.textPrimary }}
|
||||
className="text-sm mt-1"
|
||||
>
|
||||
{event.description}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{/* Action buttons */}
|
||||
<View className="flex-row justify-end mt-3 gap-3">
|
||||
<Pressable
|
||||
@@ -147,7 +47,7 @@ export const EventCard = ({ event, onEdit, onDelete }: EventCardProps) => {
|
||||
/>
|
||||
</Pressable>
|
||||
</View>
|
||||
</View>
|
||||
</EventCardBase>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
141
apps/client/src/components/EventCardBase.tsx
Normal file
141
apps/client/src/components/EventCardBase.tsx
Normal file
@@ -0,0 +1,141 @@
|
||||
import { View, Text } from "react-native";
|
||||
import { Feather } from "@expo/vector-icons";
|
||||
import { ReactNode } from "react";
|
||||
import currentTheme from "../Themes";
|
||||
|
||||
type EventCardBaseProps = {
|
||||
className?: string;
|
||||
title: string;
|
||||
startTime: Date;
|
||||
endTime: Date;
|
||||
description?: string;
|
||||
isRecurring?: boolean;
|
||||
children?: ReactNode;
|
||||
};
|
||||
|
||||
function formatDate(date: Date): string {
|
||||
const d = new Date(date);
|
||||
return d.toLocaleDateString("de-DE", {
|
||||
weekday: "short",
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
}
|
||||
|
||||
function formatTime(date: Date): string {
|
||||
const d = new Date(date);
|
||||
return d.toLocaleTimeString("de-DE", {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
}
|
||||
|
||||
function formatDuration(start: Date, end: Date): string {
|
||||
const startDate = new Date(start);
|
||||
const endDate = new Date(end);
|
||||
const diffMs = endDate.getTime() - startDate.getTime();
|
||||
const diffMins = Math.round(diffMs / 60000);
|
||||
|
||||
if (diffMins < 60) {
|
||||
return `${diffMins} min`;
|
||||
}
|
||||
|
||||
const hours = Math.floor(diffMins / 60);
|
||||
const mins = diffMins % 60;
|
||||
|
||||
if (mins === 0) {
|
||||
return hours === 1 ? "1 Std" : `${hours} Std`;
|
||||
}
|
||||
|
||||
return `${hours} Std ${mins} min`;
|
||||
}
|
||||
|
||||
export const EventCardBase = ({
|
||||
className,
|
||||
title,
|
||||
startTime,
|
||||
endTime,
|
||||
description,
|
||||
isRecurring,
|
||||
children,
|
||||
}: EventCardBaseProps) => {
|
||||
return (
|
||||
<View
|
||||
className={`rounded-xl overflow-hidden ${className}`}
|
||||
style={{ borderWidth: 2, borderColor: currentTheme.borderPrimary }}
|
||||
>
|
||||
{/* Header with title */}
|
||||
<View
|
||||
className="px-3 py-2"
|
||||
style={{
|
||||
backgroundColor: currentTheme.chatBot,
|
||||
borderBottomWidth: 2,
|
||||
borderBottomColor: currentTheme.borderPrimary,
|
||||
}}
|
||||
>
|
||||
<Text className="font-bold text-base">{title}</Text>
|
||||
</View>
|
||||
|
||||
{/* Content */}
|
||||
<View className="px-3 py-2 bg-white">
|
||||
{/* Date */}
|
||||
<View className="flex-row items-center mb-1">
|
||||
<Feather
|
||||
name="calendar"
|
||||
size={16}
|
||||
color={currentTheme.textPrimary}
|
||||
style={{ marginRight: 8 }}
|
||||
/>
|
||||
<Text style={{ color: currentTheme.textPrimary }}>
|
||||
{formatDate(startTime)}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Time with duration */}
|
||||
<View className="flex-row items-center mb-1">
|
||||
<Feather
|
||||
name="clock"
|
||||
size={16}
|
||||
color={currentTheme.textPrimary}
|
||||
style={{ marginRight: 8 }}
|
||||
/>
|
||||
<Text style={{ color: currentTheme.textPrimary }}>
|
||||
{formatTime(startTime)} - {formatTime(endTime)} (
|
||||
{formatDuration(startTime, endTime)})
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Recurring indicator */}
|
||||
{isRecurring && (
|
||||
<View className="flex-row items-center mb-1">
|
||||
<Feather
|
||||
name="repeat"
|
||||
size={16}
|
||||
color={currentTheme.textPrimary}
|
||||
style={{ marginRight: 8 }}
|
||||
/>
|
||||
<Text style={{ color: currentTheme.textPrimary }}>
|
||||
Wiederkehrend
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Description */}
|
||||
{description && (
|
||||
<Text
|
||||
style={{ color: currentTheme.textPrimary }}
|
||||
className="text-sm mt-1"
|
||||
>
|
||||
{description}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{/* Action buttons slot */}
|
||||
{children}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default EventCardBase;
|
||||
@@ -1,6 +1,7 @@
|
||||
import { View, Text, Pressable } from "react-native";
|
||||
import { ProposedEventChange } from "@caldav/shared";
|
||||
import currentTheme from "../Themes";
|
||||
import { EventCardBase } from "./EventCardBase";
|
||||
|
||||
type ProposedEventCardProps = {
|
||||
proposedChange: ProposedEventChange;
|
||||
@@ -9,17 +10,52 @@ type ProposedEventCardProps = {
|
||||
onReject: () => void;
|
||||
};
|
||||
|
||||
function formatDateTime(date?: Date): string {
|
||||
if (!date) return "";
|
||||
const d = new Date(date);
|
||||
return d.toLocaleDateString("de-DE", {
|
||||
weekday: "long",
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
}
|
||||
const ConfirmRejectButtons = ({
|
||||
isDisabled,
|
||||
respondedAction,
|
||||
onConfirm,
|
||||
onReject,
|
||||
}: {
|
||||
isDisabled: boolean;
|
||||
respondedAction?: "confirm" | "reject";
|
||||
onConfirm: () => void;
|
||||
onReject: () => void;
|
||||
}) => (
|
||||
<View className="flex-row mt-3 gap-2">
|
||||
<Pressable
|
||||
onPress={onConfirm}
|
||||
disabled={isDisabled}
|
||||
className="flex-1 py-2 rounded-lg items-center"
|
||||
style={{
|
||||
backgroundColor: isDisabled
|
||||
? currentTheme.disabledButton
|
||||
: currentTheme.confirmButton,
|
||||
borderWidth: respondedAction === "confirm" ? 2 : 0,
|
||||
borderColor: currentTheme.confirmButton,
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: currentTheme.buttonText }} className="font-medium">
|
||||
Annehmen
|
||||
</Text>
|
||||
</Pressable>
|
||||
<Pressable
|
||||
onPress={onReject}
|
||||
disabled={isDisabled}
|
||||
className="flex-1 py-2 rounded-lg items-center"
|
||||
style={{
|
||||
backgroundColor: isDisabled
|
||||
? currentTheme.disabledButton
|
||||
: currentTheme.rejectButton,
|
||||
borderWidth: respondedAction === "reject" ? 2 : 0,
|
||||
borderColor: currentTheme.rejectButton,
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: currentTheme.buttonText }} className="font-medium">
|
||||
Ablehnen
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
|
||||
export const ProposedEventCard = ({
|
||||
proposedChange,
|
||||
@@ -30,71 +66,27 @@ export const ProposedEventCard = ({
|
||||
const event = proposedChange.event;
|
||||
const isDisabled = !!respondedAction;
|
||||
|
||||
return (
|
||||
<View
|
||||
className="border-t p-2 mt-2"
|
||||
style={{ borderTopColor: currentTheme.placeholderBg }}
|
||||
>
|
||||
{/* Event Details */}
|
||||
<Text className="font-bold text-base">{event?.title}</Text>
|
||||
<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
|
||||
</Text>
|
||||
)}
|
||||
if (!event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
{/* Buttons */}
|
||||
<View className="flex-row mt-3 gap-2">
|
||||
<Pressable
|
||||
onPress={onConfirm}
|
||||
disabled={isDisabled}
|
||||
className="flex-1 py-2 rounded-lg items-center"
|
||||
style={{
|
||||
backgroundColor: isDisabled
|
||||
? currentTheme.disabledButton
|
||||
: currentTheme.confirmButton,
|
||||
borderWidth: respondedAction === "confirm" ? 2 : 0,
|
||||
borderColor: currentTheme.confirmButton,
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{ color: currentTheme.buttonText }}
|
||||
className="font-medium"
|
||||
>
|
||||
Annehmen
|
||||
</Text>
|
||||
</Pressable>
|
||||
<Pressable
|
||||
onPress={onReject}
|
||||
disabled={isDisabled}
|
||||
className="flex-1 py-2 rounded-lg items-center"
|
||||
style={{
|
||||
backgroundColor: isDisabled
|
||||
? currentTheme.disabledButton
|
||||
: currentTheme.rejectButton,
|
||||
borderWidth: respondedAction === "reject" ? 2 : 0,
|
||||
borderColor: currentTheme.rejectButton,
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{ color: currentTheme.buttonText }}
|
||||
className="font-medium"
|
||||
>
|
||||
Ablehnen
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
return (
|
||||
<View className="mt-2">
|
||||
<EventCardBase
|
||||
className="m-2"
|
||||
title={event.title}
|
||||
startTime={event.startTime}
|
||||
endTime={event.endTime}
|
||||
description={event.description}
|
||||
isRecurring={event.isRecurring}
|
||||
>
|
||||
<ConfirmRejectButtons
|
||||
isDisabled={isDisabled}
|
||||
respondedAction={respondedAction}
|
||||
onConfirm={onConfirm}
|
||||
onReject={onReject}
|
||||
/>
|
||||
</EventCardBase>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -21,7 +21,16 @@ let responseIndex = 0;
|
||||
// Static test responses (event proposals)
|
||||
const staticResponses: TestResponse[] = [
|
||||
// {{{
|
||||
// Response 0: Meeting mit Jens - next Friday 14:00
|
||||
// Response 0: Help response (text only)
|
||||
{
|
||||
content:
|
||||
"Ich bin dein Kalender-Assistent! Du kannst mir einfach sagen, welche Termine du erstellen, ändern oder löschen möchtest. Zum Beispiel:\n\n" +
|
||||
'• "Erstelle einen Termin für morgen um 15 Uhr"\n' +
|
||||
'• "Was habe ich nächste Woche vor?"\n' +
|
||||
'• "Verschiebe das Meeting auf Donnerstag"\n\n' +
|
||||
"Wie kann ich dir helfen?",
|
||||
},
|
||||
// Response 1: Meeting mit Jens - next Friday 14:00
|
||||
{
|
||||
content:
|
||||
"Alles klar! Ich erstelle dir einen Termin für das Meeting mit Jens am nächsten Freitag um 14:00 Uhr:",
|
||||
@@ -35,7 +44,7 @@ const staticResponses: TestResponse[] = [
|
||||
},
|
||||
},
|
||||
},
|
||||
// Response 1: Recurring event - every Saturday 10:00
|
||||
// Response 2: Recurring event - every Saturday 10:00
|
||||
{
|
||||
content:
|
||||
"Verstanden! Ich erstelle einen wiederkehrenden Termin: Jeden Samstag um 10:00 Uhr Badezimmer putzen:",
|
||||
@@ -50,11 +59,11 @@ const staticResponses: TestResponse[] = [
|
||||
},
|
||||
},
|
||||
},
|
||||
// Response 2: 2-week overview (DYNAMIC - placeholder)
|
||||
// Response 3: 2-week overview (DYNAMIC - placeholder)
|
||||
{ content: "" },
|
||||
// Response 3: Delete "Meeting mit Jens" (DYNAMIC - placeholder)
|
||||
// Response 4: Delete "Meeting mit Jens" (DYNAMIC - placeholder)
|
||||
{ content: "" },
|
||||
// Response 4: Doctor appointment with description
|
||||
// Response 5: Doctor appointment with description
|
||||
{
|
||||
content:
|
||||
"Ich habe dir einen Arzttermin eingetragen. Denk daran, deine Versichertenkarte mitzunehmen!",
|
||||
@@ -68,7 +77,7 @@ const staticResponses: TestResponse[] = [
|
||||
},
|
||||
},
|
||||
},
|
||||
// Response 5: Birthday - yearly recurring
|
||||
// Response 6: Birthday - yearly recurring
|
||||
{
|
||||
content:
|
||||
"Geburtstage vergisst man leicht - aber nicht mit mir! Ich habe Mamas Geburtstag eingetragen:",
|
||||
@@ -83,7 +92,7 @@ const staticResponses: TestResponse[] = [
|
||||
},
|
||||
},
|
||||
},
|
||||
// Response 6: Gym - recurring for 2 months (8 weeks)
|
||||
// Response 7: Gym - recurring for 2 months (8 weeks)
|
||||
{
|
||||
content:
|
||||
"Perfekt! Ich habe dein Probetraining eingetragen - jeden Dienstag für die nächsten 2 Monate:",
|
||||
@@ -98,17 +107,8 @@ const staticResponses: TestResponse[] = [
|
||||
},
|
||||
},
|
||||
},
|
||||
// Response 7: 1-week overview (DYNAMIC - placeholder)
|
||||
// Response 8: 1-week overview (DYNAMIC - placeholder)
|
||||
{ content: "" },
|
||||
// Response 8: Help response (text only)
|
||||
{
|
||||
content:
|
||||
"Ich bin dein Kalender-Assistent! Du kannst mir einfach sagen, welche Termine du erstellen, ändern oder löschen möchtest. Zum Beispiel:\n\n" +
|
||||
'• "Erstelle einen Termin für morgen um 15 Uhr"\n' +
|
||||
'• "Was habe ich nächste Woche vor?"\n' +
|
||||
'• "Verschiebe das Meeting auf Donnerstag"\n\n' +
|
||||
"Wie kann ich dir helfen?",
|
||||
},
|
||||
// Response 9: Phone call - short appointment (Wednesday, so +2 days = Friday)
|
||||
{
|
||||
content:
|
||||
@@ -165,28 +165,34 @@ async function getTestResponse(
|
||||
const responseIdx = index % staticResponses.length;
|
||||
|
||||
// Dynamic responses: fetch events from DB and format
|
||||
if (responseIdx === 2) {
|
||||
if (responseIdx === 3) {
|
||||
return { content: await getWeeksOverview(eventRepo, userId, 2) };
|
||||
}
|
||||
|
||||
if (responseIdx === 3) {
|
||||
if (responseIdx === 4) {
|
||||
// Delete "Meeting mit Jens"
|
||||
const events = await eventRepo.findByUserId(userId);
|
||||
const jensEvent = events.find((e) => e.title === "Meeting mit Jens");
|
||||
if (jensEvent) {
|
||||
return {
|
||||
content:
|
||||
"Alles klar, ich lösche den Termin 'Meeting mit Jens' für dich:",
|
||||
content: "Soll ich diesen Termin wirklich löschen?",
|
||||
proposedChange: {
|
||||
action: "delete",
|
||||
eventId: jensEvent.id,
|
||||
event: {
|
||||
title: jensEvent.title,
|
||||
startTime: jensEvent.startTime,
|
||||
endTime: jensEvent.endTime,
|
||||
description: jensEvent.description,
|
||||
isRecurring: jensEvent.isRecurring,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
return { content: "Ich konnte keinen Termin 'Meeting mit Jens' finden." };
|
||||
}
|
||||
|
||||
if (responseIdx === 7) {
|
||||
if (responseIdx === 8) {
|
||||
return { content: await getWeeksOverview(eventRepo, userId, 1) };
|
||||
}
|
||||
|
||||
@@ -285,7 +291,9 @@ export class ChatService {
|
||||
: "Termin nicht gefunden.";
|
||||
} else if (action === "delete" && eventId) {
|
||||
await this.eventRepo.delete(eventId);
|
||||
content = "Der Termin wurde gelöscht.";
|
||||
content = event?.title
|
||||
? `Der Termin "${event.title}" wurde gelöscht.`
|
||||
: "Der Termin wurde gelöscht.";
|
||||
} else {
|
||||
content = "Ungültige Aktion.";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user