refactor: improve AI event handling and conflict display in chat
- AI fetches events on-demand via callbacks for better efficiency - Add conflict detection with warning display when proposing overlapping events - Improve event search and display in chat interface - Load full chat history for display while limiting AI context
This commit is contained in:
@@ -22,9 +22,6 @@ import { EventService, ChatService } from "../services";
|
||||
import { buildRRule, CreateEventDTO } from "@calchat/shared";
|
||||
import { useChatStore } from "../stores";
|
||||
|
||||
// Direct store access for getting current state in callbacks
|
||||
const getChatStoreState = () => useChatStore.getState();
|
||||
|
||||
type EditEventTextFieldProps = {
|
||||
titel: string;
|
||||
text?: string;
|
||||
@@ -443,31 +440,25 @@ const EditEventScreen = () => {
|
||||
: undefined,
|
||||
};
|
||||
|
||||
// Chat mode: update proposal locally and on server
|
||||
// Chat mode: update proposal on server and sync response to local store
|
||||
if (mode === "chat" && proposalContext) {
|
||||
try {
|
||||
const context = JSON.parse(proposalContext) as ProposalContext;
|
||||
|
||||
// Update locally in ChatStore
|
||||
const currentMessages = getChatStoreState().messages;
|
||||
const message = currentMessages.find((m) => m.id === context.messageId);
|
||||
|
||||
if (message?.proposedChanges) {
|
||||
const updatedProposals = message.proposedChanges.map((p) =>
|
||||
p.id === context.proposalId ? { ...p, event: eventObject } : p,
|
||||
);
|
||||
updateMessage(context.messageId, {
|
||||
proposedChanges: updatedProposals,
|
||||
});
|
||||
}
|
||||
|
||||
// Persist to server
|
||||
await ChatService.updateProposalEvent(
|
||||
// Persist to server - returns updated message with recalculated conflictingEvents
|
||||
const updatedMessage = await ChatService.updateProposalEvent(
|
||||
context.messageId,
|
||||
context.proposalId,
|
||||
eventObject,
|
||||
);
|
||||
|
||||
// Update local ChatStore with server response (includes updated conflicts)
|
||||
if (updatedMessage?.proposedChanges) {
|
||||
updateMessage(context.messageId, {
|
||||
proposedChanges: updatedMessage.proposedChanges,
|
||||
});
|
||||
}
|
||||
|
||||
router.back();
|
||||
} catch (error) {
|
||||
console.error("Failed to update proposal:", error);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { View, Text, Pressable } from "react-native";
|
||||
import { Feather } from "@expo/vector-icons";
|
||||
import { ProposedEventChange, formatDate } from "@calchat/shared";
|
||||
import { Feather, Ionicons } from "@expo/vector-icons";
|
||||
import { ProposedEventChange, formatDate, formatTime } from "@calchat/shared";
|
||||
import { rrulestr } from "rrule";
|
||||
import { useThemeStore } from "../stores/ThemeStore";
|
||||
import { EventCardBase } from "./EventCardBase";
|
||||
@@ -143,6 +143,29 @@ export const ProposedEventCard = ({
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
{/* Show conflicting events warning */}
|
||||
{proposedChange.conflictingEvents &&
|
||||
proposedChange.conflictingEvents.length > 0 && (
|
||||
<View className="mb-2">
|
||||
{proposedChange.conflictingEvents.map((conflict, index) => (
|
||||
<View key={index} className="flex-row items-center mt-1">
|
||||
<Ionicons
|
||||
name="alert-circle"
|
||||
size={16}
|
||||
color={theme.rejectButton}
|
||||
style={{ marginRight: 8 }}
|
||||
/>
|
||||
<Text
|
||||
style={{ color: theme.rejectButton }}
|
||||
className="text-sm flex-1"
|
||||
>
|
||||
Konflikt: {conflict.title} ({formatTime(conflict.startTime)}{" "}
|
||||
- {formatTime(conflict.endTime)})
|
||||
</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
)}
|
||||
<ActionButtons
|
||||
isDisabled={isDisabled}
|
||||
respondedAction={proposedChange.respondedAction}
|
||||
|
||||
Reference in New Issue
Block a user