# Implementation Plan: 004-schedule-viewing

## Validation Checklist

- [x] All specification file paths are correct and exist
- [x] Context priming section is complete
- [x] All implementation phases are defined
- [x] Each phase follows TDD: Prime → Test → Implement → Validate
- [x] Dependencies between phases are clear (no circular dependencies)
- [x] Parallel work is properly tagged with `[parallel: true]`
- [x] Activity hints provided for specialist selection `[activity: type]`
- [ ] Every phase references relevant SDD sections (N/A - PRD/SDD skipped)
- [ ] Every test references PRD acceptance criteria (N/A - PRD skipped)
- [x] Integration & E2E tests defined in final phase
- [x] Project commands match actual project setup
- [x] A developer could follow this plan independently

---

## Context Priming

*GATE: You MUST fully read all files mentioned in this section before starting any implementation.*

**Reference Implementation (CRITICAL - use these as patterns)**:
- `lib/presentation/providers/open_shifts_provider.dart` - Provider pattern with sealed states
- `lib/data/models/open_shift_model.dart` - Freezed model pattern
- `lib/domain/entities/open_shift.dart` - Equatable entity pattern
- `lib/data/repositories/open_shifts_repository_impl.dart` - Repository implementation pattern
- `lib/data/mappers/open_shift_mapper.dart` - Mapper pattern
- `lib/core/errors/app_exceptions.dart` - Exception handling pattern
- `lib/presentation/screens/open_shifts/open_shifts_screen.dart` - Screen pattern

**API Specification**:
- `docs/employee-api.yaml` - Lines 187-280 (Schedule endpoints)

**Key API Endpoints**:
| Endpoint | Purpose |
|----------|---------|
| `POST /{typeNum}/schedule` | Get shifts for date range |
| `POST /{typeNum}/schedule/weekly` | Get weekly summary with day breakdown |
| `POST /{typeNum}/schedule/upcoming` | Get next N upcoming shifts |
| `POST /{typeNum}/schedule/today` | Get today's shift |

**Key Design Decisions**:
- Use weekly summary endpoint (`/{typeNum}/schedule/weekly`) as primary data source
- Support navigation to past/future weeks via `weekStart` parameter
- Follow existing patterns from open_shifts and clock features
- Auto-fetch when store changes (via `ref.listen(currentStoreProvider)`)

**Implementation Context**:
- Commands: `flutter analyze`, `flutter test`, `dart run build_runner build --delete-conflicting-outputs`
- Patterns: Riverpod 3.x Notifier, Freezed 3.x abstract class, Equatable entities
- Theme: AppColors, AppTheme spacing/radius constants

---

## Metadata Reference

- `[parallel: true]` - Tasks that can run concurrently
- `[component: component-name]` - For multi-component features
- `[ref: document/section; lines: X-Y]` - Links to specifications or patterns
- `[activity: type]` - Activity hint for specialist agent selection

---

## Implementation Phases

### Phase 1: Domain & Data Layer Foundation ✅ COMPLETED

- [x] T1 Domain & Data Layer Setup

    - [x] T1.1 Prime Context
        - [x] T1.1.1 Read API spec for ScheduleShift, WeeklySummaryResponse `[ref: docs/employee-api.yaml; lines: 1201-1288]`
        - [x] T1.1.2 Read open_shift_model.dart for Freezed pattern `[ref: lib/data/models/open_shift_model.dart]`
        - [x] T1.1.3 Read open_shift.dart for entity pattern `[ref: lib/domain/entities/open_shift.dart]`
        - [x] T1.1.4 Read mapper pattern `[ref: lib/data/mappers/open_shift_mapper.dart]`

    - [x] T1.2 Create Domain Entities `[component: domain]`
        - [x] T1.2.1 Create `lib/domain/entities/schedule.dart` with:
            - `ScheduledShift` entity (shiftId, date, startTime, endTime, position, positionColor, totalHours, isPublished, notes)
            - `WeeklySchedule` entity (weekStart, weekEnd, isPublished, totalHours, shiftCount, days)
            - `DaySchedule` entity (date, shifts list)
            - Helper methods: `hasShifts`, `shiftsForDate()`, navigation helpers
            `[activity: backend-api]`

    - [x] T1.3 Create Data Models `[component: data]`
        - [x] T1.3.1 Create `lib/data/models/schedule_model.dart` with:
            - `ScheduleShiftModel` (Freezed) matching API response
            - `WeeklySummaryModel` (Freezed) matching API response
            - `WeeklySummaryRequestModel` (Freezed) for request body
            - `ScheduleRequestModel` (Freezed) for date range requests
            `[activity: backend-api]`
        - [x] T1.3.2 Run `dart run build_runner build --delete-conflicting-outputs` `[activity: build]`

    - [x] T1.4 Create Mapper `[component: data]`
        - [x] T1.4.1 Create `lib/data/mappers/schedule_mapper.dart` with:
            - `toShiftEntity(ScheduleShiftModel)` → `ScheduledShift`
            - `toWeeklyScheduleEntity(WeeklySummaryModel)` → `WeeklySchedule`
            - `toShiftEntityList(List<ScheduleShiftModel>)` → `List<ScheduledShift>`
            `[activity: backend-api]`

    - [x] T1.5 Validate Phase 1
        - [x] T1.5.1 Run `flutter analyze` - no errors `[activity: lint-code]`
        - [x] T1.5.2 Verify models generate correctly (check .freezed.dart, .g.dart files) `[activity: build]`
        - [x] T1.5.3 Verify entity props match API response fields `[activity: review-code]`

---

### Phase 2: Repository Layer

- [ ] T2 Repository Implementation

    - [ ] T2.1 Prime Context
        - [ ] T2.1.1 Read repository interface pattern `[ref: lib/domain/repositories/open_shifts_repository.dart]`
        - [ ] T2.1.2 Read repository impl pattern `[ref: lib/data/repositories/open_shifts_repository_impl.dart]`
        - [ ] T2.1.3 Read api_client usage `[ref: lib/core/network/api_client.dart]`
        - [ ] T2.1.4 Read api_constants pattern `[ref: lib/core/constants/api_constants.dart]`

    - [ ] T2.2 Add API Constants
        - [ ] T2.2.1 Add schedule endpoints to `lib/core/constants/api_constants.dart`:
            ```dart
            static String schedule(String typeNum) => '$apiBasePath/$typeNum/schedule';
            static String scheduleWeekly(String typeNum) => '$apiBasePath/$typeNum/schedule/weekly';
            static String scheduleUpcoming(String typeNum) => '$apiBasePath/$typeNum/schedule/upcoming';
            static String scheduleToday(String typeNum) => '$apiBasePath/$typeNum/schedule/today';
            ```
            `[activity: backend-api]`

    - [ ] T2.3 Create Exception Type
        - [ ] T2.3.1 Add `ScheduleException` to `lib/core/errors/app_exceptions.dart`:
            - Factory: `notFound()`, `noSchedulePublished()`, `fetchFailed()`
            `[activity: backend-api]`

    - [ ] T2.4 Create Repository Interface `[component: domain]`
        - [ ] T2.4.1 Create `lib/domain/repositories/schedule_repository.dart`:
            ```dart
            abstract class ScheduleRepository {
              Future<WeeklySchedule> getWeeklySchedule({
                required String typeNum,
                DateTime? weekStart,
              });
              Future<List<ScheduledShift>> getSchedule({
                required String typeNum,
                required DateTime startDate,
                required DateTime endDate,
              });
              Future<List<ScheduledShift>> getUpcomingShifts({
                required String typeNum,
                int? limit,
              });
              Future<ScheduledShift?> getTodayShift({
                required String typeNum,
              });
            }
            ```
            `[activity: backend-api]`

    - [ ] T2.5 Create Repository Implementation `[component: data]`
        - [ ] T2.5.1 Create `lib/data/repositories/schedule_repository_impl.dart`:
            - Implement all methods with API calls
            - Use ScheduleMapper for conversions
            - Handle errors with ScheduleException
            - Create `scheduleRepositoryProvider`
            `[activity: backend-api]`

    - [ ] T2.6 Write Unit Tests
        - [ ] T2.6.1 Create `test/schedule/schedule_repository_test.dart`:
            - Test successful weekly schedule fetch
            - Test date range schedule fetch
            - Test empty schedule response
            - Test error handling (401, 404, network errors)
            `[activity: test-unit]`

    - [ ] T2.7 Validate Phase 2
        - [ ] T2.7.1 Run `flutter analyze` `[activity: lint-code]`
        - [ ] T2.7.2 Run `flutter test test/schedule/` `[activity: run-tests]`

---

### Phase 3: Provider Layer (State Management)

- [ ] T3 Provider Implementation

    - [ ] T3.1 Prime Context
        - [ ] T3.1.1 Read open_shifts_provider for state pattern `[ref: lib/presentation/providers/open_shifts_provider.dart]`
        - [ ] T3.1.2 Read clock_provider for auto-fetch pattern `[ref: lib/presentation/providers/clock_provider.dart]`
        - [ ] T3.1.3 Read store_provider for currentStoreProvider `[ref: lib/presentation/providers/store_provider.dart]`

    - [ ] T3.2 Create Provider
        - [ ] T3.2.1 Create `lib/presentation/providers/schedule_provider.dart` with:
            - **State Classes** (sealed + Equatable):
              - `ScheduleInitial`
              - `ScheduleLoading`
              - `ScheduleLoaded(weeklySchedule, selectedDate?, isRefreshing)`
              - `ScheduleError(message)`
            - **ScheduleNotifier** extending `Notifier<ScheduleState>`:
              - `build()` with `ref.listen(currentStoreProvider)` for auto-fetch
              - `fetchWeeklySchedule({DateTime? weekStart, bool showLoading = true})`
              - `navigateToWeek(DateTime weekStart)` - load different week
              - `navigateToPreviousWeek()` - convenience method
              - `navigateToNextWeek()` - convenience method
              - `selectDate(DateTime date)` - for highlighting selected day
              - `refresh()` - pull-to-refresh
              - `clear()` - reset state
            - **Provider declarations**:
              - `scheduleProvider` - main state provider
              - `currentWeeklyScheduleProvider` - derived provider for easy access
              - `selectedDateShiftsProvider` - shifts for selected date
            `[activity: frontend-state]`

    - [ ] T3.3 Write Unit Tests
        - [ ] T3.3.1 Create `test/schedule/schedule_provider_test.dart`:
            - Test initial state
            - Test loading state transition
            - Test successful fetch
            - Test error state
            - Test week navigation (previous/next)
            - Test auto-fetch on store change
            - Test refresh behavior
            - Test selected date filtering
            `[activity: test-unit]`

    - [ ] T3.4 Validate Phase 3
        - [ ] T3.4.1 Run `flutter analyze` `[activity: lint-code]`
        - [ ] T3.4.2 Run `flutter test test/schedule/` `[activity: run-tests]`

---

### Phase 4: UI Implementation

- [ ] T4 Screen & Widgets

    - [ ] T4.1 Prime Context
        - [ ] T4.1.1 Read open_shifts_screen for UI pattern `[ref: lib/presentation/screens/open_shifts/open_shifts_screen.dart]`
        - [ ] T4.1.2 Read app_colors for status colors `[ref: lib/core/theme/app_colors.dart]`
        - [ ] T4.1.3 Read app_theme for spacing/radius `[ref: lib/core/theme/app_theme.dart]`

    - [ ] T4.2 Create Widgets `[parallel: true]` `[component: ui-widgets]`
        - [ ] T4.2.1 Create `lib/presentation/widgets/schedule/week_navigation_header.dart`:
            - Shows "Week of Dec 23 - Dec 29"
            - Left/right arrows for week navigation
            - "Today" button to return to current week
            - Total hours badge
            `[activity: frontend-ui]`
        - [ ] T4.2.2 Create `lib/presentation/widgets/schedule/day_schedule_card.dart`:
            - Day name and date header
            - List of shifts for that day
            - Empty state if no shifts
            - Visual indicator if it's today
            `[activity: frontend-ui]`
        - [ ] T4.2.3 Create `lib/presentation/widgets/schedule/shift_tile.dart`:
            - Time range (9:00 AM - 5:00 PM)
            - Position with color indicator
            - Duration (8h)
            - Published/unpublished indicator
            - Notes if present
            `[activity: frontend-ui]`
        - [ ] T4.2.4 Create `lib/presentation/widgets/schedule/schedule_empty_state.dart`:
            - "No shifts scheduled" message
            - Differentiate between unpublished and truly empty
            `[activity: frontend-ui]`

    - [ ] T4.3 Update Schedule Screen
        - [ ] T4.3.1 Replace `lib/presentation/screens/schedule/schedule_screen.dart`:
            - ConsumerWidget with state-based rendering
            - WeekNavigationHeader at top
            - Scrollable list of DayScheduleCards (7 days)
            - Pull-to-refresh with RefreshIndicator
            - Loading, error, and empty states
            - Store selector integration (if multiple stores)
            `[activity: frontend-ui]`

    - [ ] T4.4 Write Widget Tests
        - [ ] T4.4.1 Create `test/schedule/schedule_screen_test.dart`:
            - Test loading state renders spinner
            - Test schedule displays correctly
            - Test week navigation buttons work
            - Test pull-to-refresh triggers fetch
            - Test empty state displays correctly
            - Test error state displays message
            `[activity: test-widget]`

    - [ ] T4.5 Validate Phase 4
        - [ ] T4.5.1 Run `flutter analyze` `[activity: lint-code]`
        - [ ] T4.5.2 Run `flutter test test/schedule/` `[activity: run-tests]`

---

### Phase 5: Router & Navigation Integration

- [ ] T5 Router Integration

    - [ ] T5.1 Prime Context
        - [ ] T5.1.1 Read app_router configuration `[ref: lib/router/app_router.dart]`

    - [ ] T5.2 Update Router
        - [ ] T5.2.1 Verify schedule route exists and is properly configured in `lib/router/app_router.dart`
            - Route: `/schedule`
            - Auth guard in place
            - Accessible from home screen
            `[activity: navigation]`

    - [ ] T5.3 Write Navigation Tests
        - [ ] T5.3.1 Create `test/navigation/schedule_navigation_test.dart`:
            - Test navigation from home to schedule
            - Test auth guard redirects unauthenticated users
            `[activity: test-integration]`

    - [ ] T5.4 Validate Phase 5
        - [ ] T5.4.1 Run `flutter analyze` `[activity: lint-code]`
        - [ ] T5.4.2 Run `flutter test test/navigation/` `[activity: run-tests]`

---

### Phase 6: Integration & End-to-End Validation

- [ ] T6 Final Validation

    - [ ] T6.1 Run All Unit Tests
        - [ ] T6.1.1 `flutter test test/schedule/` `[activity: run-tests]`
        - [ ] T6.1.2 `flutter test test/navigation/` `[activity: run-tests]`

    - [ ] T6.2 Integration Tests
        - [ ] T6.2.1 Create `test/integration/schedule_flow_test.dart`:
            - Test complete flow: navigate → load schedule → navigate weeks → refresh
            - Test provider + repository integration
            `[activity: test-integration]`

    - [ ] T6.3 Manual Testing Checklist
        - [ ] T6.3.1 Verify schedule loads on screen open
        - [ ] T6.3.2 Verify week navigation (previous/next) works
        - [ ] T6.3.3 Verify "Today" button returns to current week
        - [ ] T6.3.4 Verify pull-to-refresh updates data
        - [ ] T6.3.5 Verify empty state displays when no shifts
        - [ ] T6.3.6 Verify error state displays on API failure
        - [ ] T6.3.7 Verify store change triggers schedule refresh
        - [ ] T6.3.8 Verify shift details display correctly (time, position, color)

    - [ ] T6.4 Code Quality
        - [ ] T6.4.1 Run `flutter analyze` - zero errors `[activity: lint-code]`
        - [ ] T6.4.2 Review code follows established patterns `[activity: review-code]`
        - [ ] T6.4.3 Ensure all new files follow naming conventions `[activity: review-code]`

    - [ ] T6.5 Build Verification
        - [ ] T6.5.1 Run `flutter build ios --debug --no-codesign` `[activity: build]`
        - [ ] T6.5.2 Run `flutter build apk --debug` `[activity: build]`

---

## Files to Create/Modify Summary

### New Files

| File | Purpose |
|------|---------|
| `lib/domain/entities/schedule.dart` | ScheduledShift, WeeklySchedule, DaySchedule entities |
| `lib/data/models/schedule_model.dart` | Freezed models for API responses |
| `lib/data/mappers/schedule_mapper.dart` | Model → Entity converters |
| `lib/domain/repositories/schedule_repository.dart` | Repository interface |
| `lib/data/repositories/schedule_repository_impl.dart` | Repository implementation |
| `lib/presentation/providers/schedule_provider.dart` | State management |
| `lib/presentation/widgets/schedule/week_navigation_header.dart` | Week nav UI |
| `lib/presentation/widgets/schedule/day_schedule_card.dart` | Day display card |
| `lib/presentation/widgets/schedule/shift_tile.dart` | Individual shift UI |
| `lib/presentation/widgets/schedule/schedule_empty_state.dart` | Empty state UI |
| `test/schedule/schedule_repository_test.dart` | Repository tests |
| `test/schedule/schedule_provider_test.dart` | Provider tests |
| `test/schedule/schedule_screen_test.dart` | Widget tests |
| `test/integration/schedule_flow_test.dart` | Integration tests |

### Modified Files

| File | Changes |
|------|---------|
| `lib/core/constants/api_constants.dart` | Add schedule endpoints |
| `lib/core/errors/app_exceptions.dart` | Add ScheduleException |
| `lib/presentation/screens/schedule/schedule_screen.dart` | Full implementation |
| `lib/router/app_router.dart` | Verify route config |

---

## Dependency Graph

```
Phase 1 (Domain/Data)
    ↓
Phase 2 (Repository)
    ↓
Phase 3 (Provider)
    ↓
Phase 4 (UI) ←─┐
    ↓         │
Phase 5 (Router) ─→ Phase 6 (Validation)
```

All phases are sequential. Phase 4 widgets can be built in parallel (marked with `[parallel: true]`).
