refactor: add AuthGuard component and fix API client empty response handling
- Add reusable AuthGuard component for protected routes - Move auth logic from index.tsx to (tabs)/_layout.tsx via AuthGuard - Fix ApiClient to handle empty responses (204 No Content) - Use useFocusEffect in chat.tsx to load messages after auth is ready - Extract getDateKey() helper function in calendar.tsx
This commit is contained in:
18
CLAUDE.md
18
CLAUDE.md
@@ -81,6 +81,7 @@ src/
|
||||
│ └── note/
|
||||
│ └── [id].tsx # Note editor for event (dynamic route)
|
||||
├── components/
|
||||
│ ├── AuthGuard.tsx # Auth wrapper: loads user, shows loading, redirects if unauthenticated
|
||||
│ ├── BaseBackground.tsx # Common screen wrapper (themed)
|
||||
│ ├── BaseButton.tsx # Reusable button component (themed, supports children)
|
||||
│ ├── Header.tsx # Header component (themed)
|
||||
@@ -97,7 +98,7 @@ src/
|
||||
│ └── logger.ts # react-native-logs config (apiLogger, storeLogger)
|
||||
├── services/
|
||||
│ ├── index.ts # Re-exports all services
|
||||
│ ├── ApiClient.ts # HTTP client with X-User-Id header injection, request logging
|
||||
│ ├── 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()
|
||||
│ └── ChatService.ts # sendMessage(), confirmEvent(), rejectEvent(), getConversations(), getConversation()
|
||||
@@ -112,6 +113,13 @@ src/
|
||||
|
||||
**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.
|
||||
|
||||
**Authentication Flow:**
|
||||
- `AuthGuard` component wraps the tab layout in `(tabs)/_layout.tsx`
|
||||
- On app start, `AuthGuard` calls `loadStoredUser()` and shows loading indicator
|
||||
- If not authenticated, redirects to `/login`
|
||||
- `index.tsx` simply redirects to `/(tabs)/chat` - AuthGuard handles the rest
|
||||
- This pattern handles Expo Router's navigation state caching (avoids race conditions)
|
||||
|
||||
### Theme System
|
||||
|
||||
The app supports multiple themes (light/dark) via a reactive Zustand store.
|
||||
@@ -412,12 +420,14 @@ NODE_ENV=development # development = pretty logs, production = JSON
|
||||
- **Authentication fully implemented:**
|
||||
- `AuthStore`: Manages user state with expo-secure-store (native) / localStorage (web)
|
||||
- `AuthService`: login(), register(), logout() - calls backend API
|
||||
- `ApiClient`: Automatically injects X-User-Id header for authenticated requests
|
||||
- `ApiClient`: Automatically injects X-User-Id header for authenticated requests, handles empty responses (204)
|
||||
- `AuthGuard`: Reusable component that wraps protected routes - loads user, shows loading, redirects if unauthenticated
|
||||
- Login screen: Supports email OR userName login
|
||||
- Register screen: Email validation, checks for existing email/userName
|
||||
- `AuthButton`: Reusable button component with themed shadow
|
||||
- `Header`: Themed header component (logout moved to Settings)
|
||||
- `index.tsx`: Auth redirect - checks stored user on app start
|
||||
- `(tabs)/_layout.tsx`: Wraps tabs with AuthGuard for protected access
|
||||
- `index.tsx`: Simple redirect to chat (AuthGuard handles auth)
|
||||
- **Theme system fully implemented:**
|
||||
- `ThemeStore`: Zustand store with theme state and setTheme()
|
||||
- `Themes.tsx`: THEMES object with defaultLight/defaultDark variants
|
||||
@@ -438,7 +448,7 @@ NODE_ENV=development # development = pretty logs, production = JSON
|
||||
- Arrow navigation between proposals with "Event X von Y" counter
|
||||
- Each proposal individually confirmable/rejectable
|
||||
- **Typing indicator**: Animated dots (. .. ...) shown after 500ms delay while waiting for AI response
|
||||
- Messages persisted to database via ChatService and loaded on mount
|
||||
- Messages persisted to database via ChatService, loaded via `useFocusEffect` when screen gains focus
|
||||
- Tracks conversationId for message continuity across sessions
|
||||
- ChatStore with addMessages() for bulk loading, chatMessageToMessageData() helper
|
||||
- KeyboardAvoidingView for proper keyboard handling (iOS padding, Android height)
|
||||
|
||||
Reference in New Issue
Block a user