refactor: add CardBase and ModalBase components
- Add CardBase: reusable card with header, content, footer - Configurable via props: padding, border, text size, background - Add ModalBase: modal wrapper using CardBase internally - Provides backdrop, click-outside-to-close, Android back button - Refactor EventCardBase to use CardBase - Refactor DeleteEventModal to use ModalBase - Refactor EventOverlay (calendar.tsx) to use ModalBase - Update CLAUDE.md with component documentation
This commit is contained in:
65
CLAUDE.md
65
CLAUDE.md
@@ -86,13 +86,15 @@ src/
|
||||
│ ├── BaseButton.tsx # Reusable button component (themed, supports children)
|
||||
│ ├── Header.tsx # Header component (themed)
|
||||
│ ├── AuthButton.tsx # Reusable button for auth screens (themed, with shadow)
|
||||
│ ├── CardBase.tsx # Reusable card component (header + content + optional footer)
|
||||
│ ├── ModalBase.tsx # Reusable modal with backdrop (uses CardBase, click-outside-to-close)
|
||||
│ ├── ChatBubble.tsx # Reusable chat bubble component (used by ChatMessage & TypingIndicator)
|
||||
│ ├── TypingIndicator.tsx # Animated typing indicator (. .. ...) shown while waiting for AI response
|
||||
│ ├── EventCardBase.tsx # Shared event card layout with icons (used by EventCard & ProposedEventCard)
|
||||
│ ├── 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 # Unified delete confirmation modal (recurring: 3 options, non-recurring: simple confirm)
|
||||
│ └── DeleteEventModal.tsx # Delete confirmation modal (uses ModalBase)
|
||||
├── Themes.tsx # Theme definitions: THEMES object with defaultLight/defaultDark, Theme type
|
||||
├── logging/
|
||||
│ ├── index.ts # Re-exports
|
||||
@@ -157,6 +159,58 @@ setTheme("defaultDark"); // or "defaultLight"
|
||||
|
||||
**Note:** `shadowColor` only works on iOS. Android uses `elevation` with system-defined shadow colors.
|
||||
|
||||
### Base Components (CardBase & ModalBase)
|
||||
|
||||
Reusable base components for cards and modals with consistent styling.
|
||||
|
||||
**CardBase** - Card structure with header, content, and optional footer:
|
||||
```typescript
|
||||
<CardBase
|
||||
title="Title"
|
||||
subtitle="Optional subtitle"
|
||||
footer={{ label: "Button", onPress: () => {} }}
|
||||
// Styling props (all optional):
|
||||
headerPadding={4} // p-{n}, default: px-3 py-2
|
||||
contentPadding={4} // p-{n}, default: px-3 py-2
|
||||
headerTextSize="text-lg" // "text-sm" | "text-base" | "text-lg" | "text-xl"
|
||||
borderWidth={2} // outer border, default: 2
|
||||
headerBorderWidth={3} // header bottom border, default: borderWidth
|
||||
contentBg={theme.primeBg} // content background color, default: theme.secondaryBg
|
||||
scrollable={true} // wrap content in ScrollView
|
||||
maxContentHeight={400} // for scrollable content
|
||||
>
|
||||
{children}
|
||||
</CardBase>
|
||||
```
|
||||
|
||||
**ModalBase** - Modal with backdrop using CardBase internally:
|
||||
```typescript
|
||||
<ModalBase
|
||||
visible={isVisible}
|
||||
onClose={() => setVisible(false)}
|
||||
title="Modal Title"
|
||||
subtitle="Optional"
|
||||
footer={{ label: "Close", onPress: onClose }}
|
||||
scrollable={true}
|
||||
maxContentHeight={400}
|
||||
>
|
||||
{children}
|
||||
</ModalBase>
|
||||
```
|
||||
|
||||
ModalBase provides: transparent Modal + backdrop (click-outside-to-close) + Android back button support.
|
||||
|
||||
**Component Hierarchy:**
|
||||
```
|
||||
CardBase
|
||||
├── ModalBase (uses CardBase)
|
||||
│ ├── DeleteEventModal
|
||||
│ └── EventOverlay (in calendar.tsx)
|
||||
└── EventCardBase (uses CardBase)
|
||||
├── EventCard
|
||||
└── ProposedEventCard
|
||||
```
|
||||
|
||||
### Backend Architecture (apps/server)
|
||||
|
||||
```
|
||||
@@ -461,10 +515,13 @@ NODE_ENV=development # development = pretty logs, production = JSON
|
||||
- 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
|
||||
- `EventCardBase`: Shared base component with event layout (header, date/time/recurring icons, description) - used by both EventCard and ProposedEventCard
|
||||
- `CardBase`: Reusable card component with header (title/subtitle), content area, and optional footer button - configurable padding, border, text size via props
|
||||
- `ModalBase`: Reusable modal wrapper with backdrop, uses CardBase internally - provides click-outside-to-close and Android back button support
|
||||
- `EventCardBase`: Event card with date/time/recurring icons - uses CardBase for structure
|
||||
- `EventCard`: Uses EventCardBase + edit/delete buttons for calendar display
|
||||
- `ProposedEventCard`: Uses EventCardBase + confirm/reject buttons for chat proposals (supports create/update/delete actions with deleteMode display)
|
||||
- `DeleteEventModal`: Unified delete confirmation modal - shows three options for recurring events (single/future/all), simple confirm for non-recurring
|
||||
- `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.)
|
||||
- `EventsStore`: Zustand store with setEvents(), addEvent(), updateEvent(), deleteEvent() - stores ExpandedEvent[]
|
||||
- `ChatStore`: Zustand store with addMessage(), addMessages(), updateMessage(), clearMessages(), isWaitingForResponse/setWaitingForResponse() for typing indicator - loads from server on mount and persists across tab switches
|
||||
|
||||
Reference in New Issue
Block a user