feat: add CalDAV synchronization with automatic sync

- Add CaldavService with tsdav/ical.js for CalDAV server communication
- Add CaldavController, CaldavRepository, and caldav routes
- Add client-side CaldavConfigService with sync(), config CRUD
- Add CalDAV settings UI with config load/save in settings screen
- Sync on login, auto-login (AuthGuard), periodic timer (calendar), and sync button
- Push single events to CalDAV on server-side create/update/delete
- Push all events to CalDAV after chat event confirmation
- Refactor ChatService to use EventService instead of direct EventRepository
- Rename CalDav/calDav to Caldav/caldav for consistent naming
- Add Radicale Docker setup for local CalDAV testing
- Update PlantUML diagrams and CLAUDE.md with CalDAV architecture
This commit is contained in:
2026-02-08 19:24:59 +01:00
parent 81221d8b70
commit 325246826a
44 changed files with 7074 additions and 126 deletions

View File

@@ -30,6 +30,8 @@ package "Controller Layer" #ADD8E6 {
}
class EventController {
' -pushToCaldav()
' -deleteFromCaldav()
' +create()
' +getById()
' +getAll()
@@ -38,6 +40,15 @@ package "Controller Layer" #ADD8E6 {
' +delete()
}
class CaldavController {
' +saveConfig()
' +loadConfig()
' +deleteConfig()
' +pullEvents()
' +pushEvents()
' +pushEvent()
}
class AuthMiddleware {
' +authenticate()
}
@@ -59,9 +70,12 @@ package "Service Layer" #90EE90 {
' +findById()
' +findByUserId()
' +findByDateRange()
' +findByCaldavUUID()
' +searchByTitle()
' +create()
' +update()
' +delete()
' +addExceptionDate()
}
interface ChatRepository {
@@ -69,6 +83,14 @@ package "Service Layer" #90EE90 {
' +createConversation()
' +getMessages()
' +createMessage()
' +updateProposalResponse()
' +updateProposalEvent()
}
interface CaldavRepository {
' +findByUserId()
' +createOrUpdate()
' +deleteByUserId()
}
}
@@ -80,7 +102,7 @@ package "Service Layer" #90EE90 {
class ChatService {
' -chatRepo: ChatRepository
' -eventRepo: EventRepository
' -eventService: EventService
' -aiProvider: AIProvider
' +processMessage()
' +confirmEvent()
@@ -95,13 +117,29 @@ package "Service Layer" #90EE90 {
' +getById()
' +getAll()
' +getByDateRange()
' +searchByTitle()
' +findByCaldavUUID()
' +update()
' +delete()
' +deleteRecurring()
}
class CaldavService {
' -caldavRepo: CaldavRepository
' -eventService: EventService
' +connect()
' +pullEvents()
' +pushEvent()
' +pushAll()
' +deleteEvent()
' +getConfig()
' +saveConfig()
' +deleteConfig()
}
}
package "AI Implementations" #FFA07A {
class ClaudeAdapter implements AIProvider {
class GPTAdapter implements AIProvider {
' -apiKey: string
' +processMessage()
}
@@ -119,6 +157,10 @@ package "Data Access Implementations" #FFD700 {
class MongoChatRepository implements ChatRepository {
' -model: ChatModel
}
class MongoCaldavRepository implements CaldavRepository {
' -model: CaldavConfigModel
}
}
package "Models" #D3D3D3 {
@@ -169,15 +211,20 @@ package "Utils" #DDA0DD {
' Controller -> Service
AuthController --> AuthService
ChatController --> ChatService
ChatController --> CaldavService
EventController --> EventService
EventController --> CaldavService
CaldavController --> CaldavService
AuthMiddleware --> JWT
' Service -> Interfaces (intern)
AuthService --> UserRepository
ChatService --> ChatRepository
ChatService --> EventRepository
ChatService --> EventService
ChatService --> AIProvider
EventService --> EventRepository
CaldavService --> CaldavRepository
CaldavService --> EventService
' Auth uses Utils
AuthService --> JWT

View File

@@ -16,6 +16,8 @@ package "apps/client (Expo React Native)" as ClientPkg #87CEEB {
[Login/Register] as AuthScreens
[Calendar View] as CalendarScreen
[Chat View] as ChatScreen
[Settings] as SettingsScreen
[Edit Event] as EditEventScreen
[Event Detail] as EventDetail
[Note Editor] as NoteScreen
}
@@ -25,17 +27,20 @@ package "apps/client (Expo React Native)" as ClientPkg #87CEEB {
[Auth Service] as ClientAuth
[Event Service] as ClientEvent
[Chat Service] as ClientChat
[Caldav Config Service] as ClientCaldav
}
package "Components" {
[UI Components] as UIComponents
[Event Cards] as EventCards
[Auth Guard] as AuthGuard
}
package "Stores" {
[Auth Store] as AuthStore
[Events Store] as EventsStore
[Chat Store] as ChatStore
[Theme Store] as ThemeStore
}
}
@@ -59,10 +64,11 @@ package "apps/server (Express.js)" as ServerPkg #98FB98 {
[AuthService] as AuthSvc
[ChatService] as ChatSvc
[EventService] as EventSvc
[CaldavService] as CaldavSvc
}
package "AI Implementations" {
[ClaudeAdapter] as Claude
[GPTAdapter] as GPT
}
package "Data Access Implementations" {
@@ -80,25 +86,35 @@ package "apps/server (Express.js)" as ServerPkg #98FB98 {
' ===== ROW 4: EXTERNAL =====
database "MongoDB" as MongoDB
cloud "Claude API" as ClaudeAPI
cloud "OpenAI API" as OpenAIAPI
cloud "CalDAV Server" as CaldavServer
' ===== CONNECTIONS =====
' Frontend: Screens -> Services
AuthScreens --> ClientAuth
CalendarScreen --> ClientEvent
CalendarScreen --> ClientCaldav
ChatScreen --> ClientChat
SettingsScreen --> ClientCaldav
EditEventScreen --> ClientEvent
EventDetail --> ClientEvent
NoteScreen --> ClientEvent
ClientAuth --> ApiClient
ClientEvent --> ApiClient
ClientChat --> ApiClient
ClientCaldav --> ApiClient
ApiClient --> AuthStore
ClientEvent --> EventsStore
ClientChat --> ChatStore
' Frontend: Auth
AuthGuard --> AuthStore
AuthGuard --> ClientCaldav
AuthScreens --> ClientCaldav
' Frontend: Screens -> Components
CalendarScreen --> EventCards
ChatScreen --> EventCards
@@ -121,14 +137,20 @@ Routes --> Controllers
Controllers --> AuthSvc
Controllers --> ChatSvc
Controllers --> EventSvc
Controllers --> CaldavSvc
' Backend: Service -> Interfaces
AuthSvc --> Interfaces
ChatSvc --> Interfaces
EventSvc --> Interfaces
CaldavSvc --> Interfaces
' Backend: Service dependencies
ChatSvc --> EventSvc
CaldavSvc --> EventSvc
' Backend: AI & Data Access implement Interfaces
Claude ..|> Interfaces
GPT ..|> Interfaces
Repos ..|> Interfaces
' Backend: Service -> Utils
@@ -143,6 +165,7 @@ Repos --> Schemas
' Backend -> External
Schemas --> MongoDB
Claude --> ClaudeAPI
GPT --> OpenAIAPI
CaldavSvc --> CaldavServer
@enduml

View File

@@ -22,18 +22,26 @@ package "Screens" #87CEEB {
class RegisterScreen
class CalendarScreen
class ChatScreen
class SettingsScreen
class EditEventScreen
class EventDetailScreen
class NoteScreen
}
' ===== COMPONENTS =====
package "Components" #FFA07A {
class AuthGuard
class BaseBackground
class Header
class BaseButton
class CardBase
class ModalBase
class EventCardBase
class EventCard
class ProposedEventCard
class EventConfirmDialog
class DeleteEventModal
class ChatBubble
class TypingIndicator
}
' ===== SERVICES =====
@@ -64,6 +72,13 @@ package "Services" #90EE90 {
+rejectEvent()
+getConversations()
+getConversation()
+updateProposalEvent()
}
class CaldavConfigService {
+getConfig()
+saveConfig()
+deleteConfig()
+sync()
}
}
@@ -71,11 +86,10 @@ package "Services" #90EE90 {
package "Stores" #FFD700 {
class AuthStore {
' +user
' +token
' +isAuthenticated
' +login()
' +logout()
' +setToken()
' +loadStoredUser()
}
class EventsStore {
' +events
@@ -86,10 +100,16 @@ package "Stores" #FFD700 {
}
class ChatStore {
' +messages
' +isWaitingForResponse
' +addMessage()
' +addMessages()
' +updateMessage()
' +clearMessages()
}
class ThemeStore {
' +theme
' +setTheme()
}
}
' ===== MODELS =====
@@ -97,6 +117,7 @@ package "Models (shared)" #D3D3D3 {
class User
class CalendarEvent
class ChatMessage
class CaldavConfig
}
' ===== RELATIONSHIPS =====
@@ -104,24 +125,39 @@ package "Models (shared)" #D3D3D3 {
' Screens -> Services
LoginScreen --> AuthService
CalendarScreen --> EventService
CalendarScreen --> CaldavConfigService
ChatScreen --> ChatService
NoteScreen --> EventService
EditEventScreen --> EventService
EditEventScreen --> ChatService
SettingsScreen --> CaldavConfigService
' Screens -> Components
CalendarScreen --> EventCard
ChatScreen --> ProposedEventCard
ChatScreen --> EventConfirmDialog
ChatScreen --> ChatBubble
ChatScreen --> TypingIndicator
EventCard --> EventCardBase
ProposedEventCard --> EventCardBase
EventCardBase --> CardBase
ModalBase --> CardBase
DeleteEventModal --> ModalBase
' Auth
AuthGuard --> AuthStore
AuthGuard --> CaldavConfigService
LoginScreen --> CaldavConfigService
' Services -> ApiClient
AuthService --> ApiClient
EventService --> ApiClient
ChatService --> ApiClient
CaldavConfigService --> ApiClient
' Services/Screens -> Stores
AuthService --> AuthStore
EventService --> EventsStore
CalendarScreen --> EventsStore
ChatScreen --> ChatStore
SettingsScreen --> ThemeStore
@enduml