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
This commit is contained in:
41
CLAUDE.md
41
CLAUDE.md
@@ -76,6 +76,7 @@ src/
|
||||
│ │ ├── chat.tsx # Chat screen (AI conversation)
|
||||
│ │ ├── calendar.tsx # Calendar overview
|
||||
│ │ └── settings.tsx # Settings screen (theme switcher, logout)
|
||||
│ ├── editEvent.tsx # Event edit screen (dual-mode: calendar/chat)
|
||||
│ ├── event/
|
||||
│ │ └── [id].tsx # Event detail screen (dynamic route)
|
||||
│ └── note/
|
||||
@@ -93,8 +94,10 @@ src/
|
||||
│ ├── EventCardBase.tsx # Event card layout with icons (uses CardBase)
|
||||
│ ├── EventCard.tsx # Calendar event card (uses EventCardBase + edit/delete buttons)
|
||||
│ ├── EventConfirmDialog.tsx # AI-proposed event confirmation modal (skeleton)
|
||||
│ ├── ProposedEventCard.tsx # Chat event proposal (uses EventCardBase + confirm/reject buttons)
|
||||
│ └── DeleteEventModal.tsx # Delete confirmation modal (uses ModalBase)
|
||||
│ ├── ProposedEventCard.tsx # Chat event proposal (uses EventCardBase + confirm/reject/edit buttons)
|
||||
│ ├── DeleteEventModal.tsx # Delete confirmation modal (uses ModalBase)
|
||||
│ ├── DateTimePicker.tsx # Date and time picker components
|
||||
│ └── ScrollableDropdown.tsx # Scrollable dropdown component
|
||||
├── Themes.tsx # Theme definitions: THEMES object with defaultLight/defaultDark, Theme type
|
||||
├── logging/
|
||||
│ ├── index.ts # Re-exports
|
||||
@@ -104,14 +107,16 @@ src/
|
||||
│ ├── ApiClient.ts # HTTP client with X-User-Id header injection, request logging, handles empty responses (204)
|
||||
│ ├── AuthService.ts # login(), register(), logout() - calls API and updates AuthStore
|
||||
│ ├── EventService.ts # getAll(), getById(), getByDateRange(), create(), update(), delete(mode, occurrenceDate)
|
||||
│ └── ChatService.ts # sendMessage(), confirmEvent(deleteMode, occurrenceDate), rejectEvent(), getConversations(), getConversation()
|
||||
└── stores/ # Zustand state management
|
||||
├── index.ts # Re-exports all stores
|
||||
├── AuthStore.ts # user, isAuthenticated, isLoading, login(), logout(), loadStoredUser()
|
||||
│ # Uses expo-secure-store (native) / localStorage (web)
|
||||
├── ChatStore.ts # messages[], isWaitingForResponse, addMessage(), addMessages(), updateMessage(), clearMessages(), setWaitingForResponse(), chatMessageToMessageData()
|
||||
├── EventsStore.ts # events[], setEvents(), addEvent(), updateEvent(), deleteEvent()
|
||||
└── ThemeStore.ts # theme, setTheme() - reactive theme switching with Zustand
|
||||
│ └── ChatService.ts # sendMessage(), confirmEvent(deleteMode, occurrenceDate), rejectEvent(), getConversations(), getConversation(), updateProposalEvent()
|
||||
├── stores/ # Zustand state management
|
||||
│ ├── index.ts # Re-exports all stores
|
||||
│ ├── AuthStore.ts # user, isAuthenticated, isLoading, login(), logout(), loadStoredUser()
|
||||
│ │ # Uses expo-secure-store (native) / localStorage (web)
|
||||
│ ├── ChatStore.ts # messages[], isWaitingForResponse, addMessage(), addMessages(), updateMessage(), clearMessages(), setWaitingForResponse(), chatMessageToMessageData()
|
||||
│ ├── EventsStore.ts # events[], setEvents(), addEvent(), updateEvent(), deleteEvent()
|
||||
│ └── ThemeStore.ts # theme, setTheme() - reactive theme switching with Zustand
|
||||
└── hooks/
|
||||
└── useDropdownPosition.ts # Hook for positioning dropdowns relative to trigger element
|
||||
```
|
||||
|
||||
**Routing:** Tab-based navigation with Chat, Calendar, and Settings as main screens. Auth screens (login, register) outside tabs. Dynamic routes for event detail and note editing.
|
||||
@@ -223,7 +228,7 @@ src/
|
||||
├── app.ts # Entry point, DI setup, Express config
|
||||
├── controllers/ # Request handlers + middleware (per architecture diagram)
|
||||
│ ├── AuthController.ts # login(), register(), refresh(), logout()
|
||||
│ ├── ChatController.ts # sendMessage(), confirmEvent(), rejectEvent(), getConversations(), getConversation()
|
||||
│ ├── ChatController.ts # sendMessage(), confirmEvent(), rejectEvent(), getConversations(), getConversation(), updateProposalEvent()
|
||||
│ ├── EventController.ts # create(), getById(), getAll(), getByDateRange(), update(), delete()
|
||||
│ ├── AuthMiddleware.ts # authenticate() - X-User-Id header validation
|
||||
│ └── LoggingMiddleware.ts # httpLogger - pino-http request logging
|
||||
@@ -290,6 +295,7 @@ src/
|
||||
- `POST /api/chat/reject/:conversationId/:messageId` - Reject proposed event (protected)
|
||||
- `GET /api/chat/conversations` - Get all conversations (protected)
|
||||
- `GET /api/chat/conversations/:id` - Get messages of a conversation with cursor-based pagination (protected)
|
||||
- `PUT /api/chat/messages/:messageId/proposal` - Update proposal event data before confirming (protected)
|
||||
- `GET /health` - Health check
|
||||
- `POST /api/ai/test` - AI test endpoint (development only)
|
||||
|
||||
@@ -465,8 +471,8 @@ NODE_ENV=development # development = pretty logs, production = JSON
|
||||
- `utils/recurrenceExpander`: expandRecurringEvents() using rrule library for RRULE parsing
|
||||
- `ChatController`: getConversations(), getConversation() with cursor-based pagination support
|
||||
- `ChatService`: getConversations(), getConversation(), processMessage() uses real AI or test responses (via USE_TEST_RESPONSES), confirmEvent()/rejectEvent() update respondedAction and persist response messages
|
||||
- `MongoChatRepository`: Full CRUD implemented (getConversationsByUser, createConversation, getMessages with cursor pagination, createMessage, updateMessage, updateProposalResponse)
|
||||
- `ChatRepository` interface: updateMessage() and updateProposalResponse() for per-proposal respondedAction tracking
|
||||
- `MongoChatRepository`: Full CRUD implemented (getConversationsByUser, createConversation, getMessages with cursor pagination, createMessage, updateMessage, updateProposalResponse, updateProposalEvent)
|
||||
- `ChatRepository` interface: updateMessage(), updateProposalResponse(), updateProposalEvent() for per-proposal tracking
|
||||
- `GPTAdapter`: Full implementation with OpenAI GPT (gpt-4o-mini model), function calling for calendar operations, collects multiple proposals per response
|
||||
- `ai/utils/`: Provider-agnostic shared utilities (systemPrompt, toolDefinitions, toolExecutor, eventFormatter)
|
||||
- `ai/utils/systemPrompt`: Includes RRULE documentation - AI knows to create separate events when times differ by day, warns AI not to put RRULE in description field
|
||||
@@ -527,12 +533,12 @@ NODE_ENV=development # development = pretty logs, production = JSON
|
||||
- Auto-scroll to end on new messages and keyboard show
|
||||
- keyboardDismissMode="interactive" and keyboardShouldPersistTaps="handled"
|
||||
- `EventService`: getAll(), getById(), getByDateRange(), create(), update(), delete(mode, occurrenceDate) - fully implemented with recurring delete modes
|
||||
- `ChatService`: sendMessage(), confirmEvent(deleteMode, occurrenceDate), rejectEvent(), getConversations(), getConversation() - fully implemented with cursor pagination and recurring delete support
|
||||
- `ChatService`: sendMessage(), confirmEvent(deleteMode, occurrenceDate), rejectEvent(), getConversations(), getConversation(), updateProposalEvent() - fully implemented with cursor pagination, recurring delete support, and proposal editing
|
||||
- `CardBase`: Reusable card component with header (title/subtitle), content area, and optional footer button - configurable padding, border, text size via props, ScrollView uses `nestedScrollEnabled` for Android
|
||||
- `ModalBase`: Reusable modal wrapper with backdrop (absolute-positioned behind card), uses CardBase internally - provides click-outside-to-close, Android back button support, and proper scrolling on Android
|
||||
- `EventCardBase`: Event card with date/time/recurring icons - uses CardBase for structure
|
||||
- `EventCard`: Uses EventCardBase + edit/delete buttons (TouchableOpacity with delayPressIn for scroll-friendly touch handling)
|
||||
- `ProposedEventCard`: Uses EventCardBase + confirm/reject buttons for chat proposals, displays green highlighted text for new changes ("Neue Ausnahme: [date]" for single delete, "Neues Ende: [date]" for UNTIL updates)
|
||||
- `ProposedEventCard`: Uses EventCardBase + confirm/reject/edit buttons for chat proposals, displays green highlighted text for new changes ("Neue Ausnahme: [date]" for single delete, "Neues Ende: [date]" for UNTIL updates). Edit button allows modifying proposals before confirming.
|
||||
- `DeleteEventModal`: Delete confirmation modal using ModalBase - shows three options for recurring events (single/future/all), simple confirm for non-recurring
|
||||
- `EventOverlay` (in calendar.tsx): Day events overlay using ModalBase - shows EventCards for selected day
|
||||
- `Themes.tsx`: Theme definitions with THEMES object (defaultLight, defaultDark) including all color tokens (textPrimary, borderPrimary, eventIndicator, secondaryBg, shadowColor, etc.)
|
||||
@@ -542,6 +548,11 @@ NODE_ENV=development # development = pretty logs, production = JSON
|
||||
- `ChatBubble`: Reusable chat bubble component with Tailwind styling, used by ChatMessage and TypingIndicator
|
||||
- `TypingIndicator`: Animated typing indicator component showing `. → .. → ...` loop while waiting for AI response
|
||||
- Event Detail and Note screens exist as skeletons
|
||||
- `editEvent.tsx`: Dual-mode event editor screen
|
||||
- **Calendar mode**: Edit existing events, create new events - calls EventService API
|
||||
- **Chat mode**: Edit AI-proposed events before confirming - updates ChatStore locally and persists to server via ChatService.updateProposalEvent()
|
||||
- Route params: `mode` ('calendar' | 'chat'), `id?`, `date?`, `eventData?` (JSON), `proposalContext?` (JSON with messageId, proposalId, conversationId)
|
||||
- Supports recurring events with RRULE configuration (daily/weekly/monthly/yearly)
|
||||
|
||||
## Building
|
||||
|
||||
|
||||
Reference in New Issue
Block a user