# Onboarding Feature Module

## Overview
The onboarding feature manages the user signup workflow after email verification. It handles user preference setup (unit system, currency, timezone) and tracks onboarding completion status.

## Purpose
After a user verifies their email with Auth0, they go through an onboarding flow to:
1. Set their preferences (unit system, currency, timezone)
2. Optionally add their first vehicle (handled by vehicles feature)
3. Mark onboarding as complete

## API Endpoints

All endpoints require JWT authentication via `fastify.authenticate` preHandler.

### POST `/api/onboarding/preferences`
Save user preferences during onboarding.

**Request Body:**
```json
{
  "unitSystem": "imperial",
  "currencyCode": "USD",
  "timeZone": "America/New_York"
}
```

**Validation:**
- `unitSystem`: Must be either "imperial" or "metric"
- `currencyCode`: Must be exactly 3 uppercase letters (ISO 4217)
- `timeZone`: 1-100 characters (IANA timezone identifier)

**Response (200):**
```json
{
  "success": true,
  "preferences": {
    "unitSystem": "imperial",
    "currencyCode": "USD",
    "timeZone": "America/New_York"
  }
}
```

**Error Responses:**
- `404 Not Found` - User profile not found
- `500 Internal Server Error` - Failed to save preferences

### POST `/api/onboarding/complete`
Mark onboarding as complete for the authenticated user.

**Request Body:** None

**Response (200):**
```json
{
  "success": true,
  "completedAt": "2025-12-22T15:30:00.000Z"
}
```

**Error Responses:**
- `404 Not Found` - User profile not found
- `500 Internal Server Error` - Failed to complete onboarding

### GET `/api/onboarding/status`
Get current onboarding status for the authenticated user.

**Response (200):**
```json
{
  "preferencesSet": true,
  "onboardingCompleted": true,
  "onboardingCompletedAt": "2025-12-22T15:30:00.000Z"
}
```

**Response (200) - Incomplete:**
```json
{
  "preferencesSet": false,
  "onboardingCompleted": false,
  "onboardingCompletedAt": null
}
```

**Error Responses:**
- `404 Not Found` - User profile not found
- `500 Internal Server Error` - Failed to get status

## Architecture

### Directory Structure
```
backend/src/features/onboarding/
├── README.md              # This file
├── index.ts               # Public API exports
├── api/                   # HTTP layer
│   ├── onboarding.controller.ts    # Request handlers
│   ├── onboarding.routes.ts        # Route definitions
│   └── onboarding.validation.ts    # Zod schemas
├── domain/                # Business logic
│   ├── onboarding.service.ts       # Core logic
│   └── onboarding.types.ts         # Type definitions
└── tests/                 # Tests (to be added)
    ├── unit/
    └── integration/
```

## Integration Points

### Dependencies
- **UserProfileRepository** (`features/user-profile`) - For updating `onboarding_completed_at`
- **UserPreferencesRepository** (`core/user-preferences`) - For saving unit system, currency, timezone
- **Database Pool** (`core/config/database`) - PostgreSQL connection
- **Logger** (`core/logging/logger`) - Structured logging

### Database Tables
- `user_profiles` - Stores `onboarding_completed_at` timestamp
- `user_preferences` - Stores `unit_system`, `currency_code`, `time_zone`

## Business Logic

### Save Preferences Flow
1. Extract Auth0 user ID from JWT
2. Fetch user profile to get internal user ID
3. Check if user_preferences record exists
4. If exists, update preferences; otherwise create new record
5. Return saved preferences

### Complete Onboarding Flow
1. Extract Auth0 user ID from JWT
2. Call `UserProfileRepository.markOnboardingComplete(auth0Sub)`
3. Updates `onboarding_completed_at` to NOW() if not already set
4. Return completion timestamp

### Get Status Flow
1. Extract Auth0 user ID from JWT
2. Fetch user profile
3. Check if user_preferences record exists
4. Return status object with:
   - `preferencesSet`: boolean (preferences exist)
   - `onboardingCompleted`: boolean (onboarding_completed_at is set)
   - `onboardingCompletedAt`: timestamp or null

## Key Behaviors

### User Ownership
All operations are scoped to the authenticated user via JWT. No cross-user access is possible.

### Idempotency
- `savePreferences` - Can be called multiple times; updates existing record
- `completeOnboarding` - Can be called multiple times; returns existing completion timestamp if already completed

### Email Verification
These routes are in `VERIFICATION_EXEMPT_ROUTES` in `auth.plugin.ts` because users complete onboarding immediately after email verification.

## Error Handling

All errors are logged with structured logging:
```typescript
logger.error('Error saving onboarding preferences', {
  error,
  userId: auth0Sub.substring(0, 8) + '...',
});
```

Controller methods return appropriate HTTP status codes:
- `200 OK` - Success
- `404 Not Found` - User profile not found
- `500 Internal Server Error` - Unexpected errors

## Testing

Tests to be added:
- Unit tests for `OnboardingService` with mocked repositories
- Integration tests for API endpoints with test database

## Future Enhancements

Potential improvements:
- Add validation for IANA timezone identifiers
- Add validation for ISO 4217 currency codes against known list
- Track onboarding step completion for analytics
- Add onboarding progress percentage
- Support for skipping onboarding (mark as complete without preferences)
