# Technical Documentation

## Architecture Overview

```
┌─────────────────────────────────────────────────────────────────┐
│                        Expo App Layer                           │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐             │
│  │   Tasks     │  │  Calendar   │  │  Settings   │             │
│  │   Screen    │  │   Screen    │  │   Screen    │             │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘             │
│         │                │                │                      │
│         └────────────────┼────────────────┘                      │
│                          ▼                                       │
│  ┌─────────────────────────────────────────────┐               │
│  │         React Hook Form + Zod               │               │
│  │         (Form Validation)                   │               │
│  └─────────────────────────────────────────────┘               │
└────────────────────────────────┬────────────────────────────────┘
                                 │
                                 ▼
┌─────────────────────────────────────────────────────────────────┐
│                      Database Layer                             │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │              WatermelonDB Database                        │   │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐               │   │
│  │  │Categories│  │  Tasks   │  │ Subtasks │               │   │
│  │  └──────────┘  └──────────┘  └──────────┘               │   │
│  └─────────────────────────────────────────────────────────┘   │
│                          │                                       │
│                          ▼                                       │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │              SQLite Adapter (expo-sqlite)                 │   │
│  └─────────────────────────────────────────────────────────┘   │
└────────────────────────────────┬────────────────────────────────┘
                                 │
                                 ▼
┌─────────────────────────────────────────────────────────────────┐
│                      Sync Layer                                 │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │              Custom Sync Adapter                          │   │
│  │  • pullChanges() - GET /sync?since={timestamp}           │   │
│  │  • pushChanges() - POST /sync/push                       │   │
│  │  • Conflict resolution (last-write-wins)                 │   │
│  └─────────────────────────────────────────────────────────┘   │
└────────────────────────────────┬────────────────────────────────┘
                                 │
                                 ▼
┌─────────────────────────────────────────────────────────────────┐
│                      Backend API                                │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │              Custom Postgres API                          │   │
│  │  • REST or GraphQL endpoints                              │   │
│  │  • Authentication (JWT/OAuth)                             │   │
│  │  • Conflict detection & resolution                        │   │
│  └─────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘
```

## Database Schema

### Tables

```sql
-- Categories table
CREATE TABLE categories (
  id TEXT PRIMARY KEY,
  name TEXT NOT NULL,
  color TEXT NOT NULL,
  "order" INTEGER NOT NULL DEFAULT 0,
  created_at INTEGER NOT NULL,
  updated_at INTEGER NOT NULL
);

-- Tasks table
CREATE TABLE tasks (
  id TEXT PRIMARY KEY,
  title TEXT NOT NULL,
  description TEXT NOT NULL DEFAULT '',
  category_id TEXT NOT NULL,
  priority TEXT NOT NULL DEFAULT 'none',
  completed INTEGER NOT NULL DEFAULT 0,
  due_date INTEGER NOT NULL DEFAULT 0,
  due_time TEXT NOT NULL DEFAULT '',
  created_at INTEGER NOT NULL,
  updated_at INTEGER NOT NULL,
  FOREIGN KEY (category_id) REFERENCES categories(id)
);

CREATE INDEX idx_tasks_category ON tasks(category_id);
CREATE INDEX idx_tasks_due_date ON tasks(due_date);
CREATE INDEX idx_tasks_completed ON tasks(completed);

-- Subtasks table
CREATE TABLE subtasks (
  id TEXT PRIMARY KEY,
  task_id TEXT NOT NULL,
  title TEXT NOT NULL,
  completed INTEGER NOT NULL DEFAULT 0,
  "order" INTEGER NOT NULL DEFAULT 0,
  created_at INTEGER NOT NULL,
  updated_at INTEGER NOT NULL,
  FOREIGN KEY (task_id) REFERENCES tasks(id)
);

CREATE INDEX idx_subtasks_task ON subtasks(task_id);
```

## Key Components

### DatabaseProvider (`src/hooks/useDatabase.tsx`)

Central context provider managing:
- Database initialization
- Default category seeding
- Collection access
- Ready state

```typescript
interface DatabaseContextType {
  database: Database;
  collections: {
    categories: Collection<Category>;
    tasks: Collection<Task>;
    subtasks: Collection<Subtask>;
  };
  isReady: boolean;
  initializeDatabase: () => Promise<void>;
}
```

### useTasks Hook (`src/hooks/useTasks.tsx`)

Reactive task queries with loading states:

```typescript
function useTasks(categoryId?: string, showCompleted = false): {
  tasks: Task[];
  loading: boolean;
}
```

### WatermelonDB Models

All models use decorators for field mapping:

```typescript
@field('column_name') propertyName!: Type;
@date('column_name') dateProperty!: Date;
@children('table_name') relationName!: Query<Model>;
```

## Sync Implementation

### Pull Strategy
1. Client sends `lastPulledAt` timestamp
2. Server returns all changes since timestamp
3. Client applies changes in transaction:
   - Upsert categories (by id)
   - Upsert tasks (by id)
   - Upsert subtasks (by id)

### Push Strategy
1. Client collects local changes (created/updated/deleted)
2. Sends batched changes with `lastPulledAt`
3. Server applies and returns new timestamp

### Conflict Resolution
Default: Last-write-wins based on `updatedAt`
Customizable in `src/database/sync.ts`

## Navigation Structure

```
app/
├── _layout.tsx                    # Stack navigator + DatabaseProvider
│   ├── (tabs)/                    # Tab group
│   │   ├── _layout.tsx            # Tabs navigator
│   │   ├── index.tsx              # / (Tasks)
│   │   ├── calendar.tsx           # /calendar
│   │   └── settings.tsx           # /settings
│   └── add-task.tsx               # /add-task (modal push)
```

### Navigation Patterns
- **Tabs**: Persistent bottom navigation
- **Add Task**: Push onto stack (modal on iOS)
- **Edit Task**: Push onto stack (future)

## Form Handling

### Add Task Form (`app/add-task.tsx`)

Uses `react-hook-form` with `zod` resolver:

```typescript
const schema = z.object({
  title: z.string().min(1).max(100),
  description: z.string().max(1000).optional(),
  categoryId: z.string().min(1),
  priority: z.enum(['none', 'low', 'medium', 'high', 'critical']),
  dueDate: z.date().nullable().optional(),
  dueTime: z.string().optional(),
  subtasks: z.array(z.object({ title: z.string() })).optional(),
});
```

### Field Components
Each field is a controlled component using `Controller`:
- `CategorySelector` - Horizontal chip selection
- `TaskNameInput` - Text input with validation
- `SubtasksSection` - FieldArray for dynamic subtasks
- `DateTimePicker` - Native date/time pickers
- `PrioritySelector` - Segmented control
- `DescriptionInput` - Multiline text area

## Animations

### Reanimated 3 Patterns

1. **FAB Rotation** (`FloatingActionButton.tsx`)
```typescript
const rotateAnim = useSharedValue(0);
rotateAnim.value = (rotateAnim.value + 0.25) % 1;
```

2. **Category Selection** (`CategoryFilter.tsx`)
```typescript
const scaleAnim = useSharedValue(1);
scaleAnim.value = withTiming(selected ? 1.05 : 1);
```

3. **Checkbox Toggle** (`TaskItem.tsx`)
```typescript
const checkedAnim = useSharedValue(0);
checkedAnim.value = withTiming(task.completed ? 1 : 0);
```

## Platform-Specific Considerations

### iOS
- DateTimePicker: `display="spinner"`
- Keyboard: `behavior="padding"`
- Safe areas: Automatic via `react-native-safe-area-context`

### Android
- DateTimePicker: `display="default"`
- Keyboard: `behavior="height"`
- Elevation shadows for Material Design

### Web
- React Native Web for DOM rendering
- DateTimePicker falls back to HTML inputs
- No native SQLite (uses IndexedDB via expo-sqlite web polyfill)

## Performance Optimizations

1. **Lazy Loading**: Components loaded on demand
2. **Memoization**: `React.memo` for list items
3. **Virtualized Lists**: FlatList with `windowSize`
4. **Query Optimization**: Indexed columns for common queries
5. **Batch Writes**: Database transactions for multiple operations

## Testing Strategy

### Unit Tests
- Hooks: `useTasks`, `useCategories`
- Validators: Zod schemas
- Utilities: Date formatting, priority sorting

### Integration Tests
- Database CRUD operations
- Sync adapter with mock server
- Form submission flow

### E2E Tests
- Critical user flows (add task, complete, filter)
- Offline/online transitions
- Cross-platform consistency

## Deployment Checklist

- [ ] Configure `app.json` with production values
- [ ] Set `EXPO_PUBLIC_API_URL` environment variable
- [ ] Enable EAS Build for iOS/Android
- [ ] Configure code signing certificates
- [ ] Set up CI/CD pipeline
- [ ] Test offline sync scenarios
- [ ] Verify push notifications (if enabled)
- [ ] Performance profiling on device

## Troubleshooting

### Common Issues

**Database not initializing**
- Check `expo-sqlite` installation
- Verify `DatabaseProvider` wraps app root
- Check Metro bundler cache: `npx expo start -c`

**Sync failing**
- Verify API endpoint accessibility
- Check CORS headers on server
- Inspect network requests in React Native Debugger

**TypeScript errors with WatermelonDB**
- Ensure `experimentalDecorators: true` in tsconfig
- Check `@nozbe/watermelondb` version compatibility
- Run `npx expo-doctor` for dependency issues

**Animation not working**
- Verify `react-native-reanimated` babel plugin
- Check `useNativeDriver: true` for supported properties
- Ensure worklet functions are properly extracted