# Implementation Plan: 003-open-shifts

## 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 - 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

---

## Specification Compliance Guidelines

### How to Ensure Specification Adherence

Since PRD and SDD were skipped for this feature, compliance is based on:
1. **API Contract**: `docs/employee-api.yaml` defines the backend API
2. **Existing Patterns**: Follow established patterns from 002-login-auth-flow
3. **User Story**: Team members view and claim open shifts at their store(s)

### Deviation Protocol

If implementation cannot follow API contract or patterns exactly:
1. Document the deviation and reason
2. Get approval before proceeding
3. Update this plan if the deviation is an improvement
4. Never deviate without documentation

## Metadata Reference

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

---

## Context Priming

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

**Specification**:

- `docs/specs/003-open-shifts/README.md` - Specification overview and decisions
- `docs/employee-api.yaml` - API contract (lines 2100-2400 for open shifts endpoints)

**API Endpoints**:

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/{typeNum}/open-shifts` | POST | Get available open shifts with filters |
| `/{typeNum}/open-shifts/{shiftId}/claim` | POST | Claim an open shift |

**API Request/Response Schemas** (from employee-api.yaml):

```yaml
# OpenShiftsRequest
OpenShiftsRequest:
  properties:
    startDate: string (YYYY-MM-DD)
    endDate: string (YYYY-MM-DD)
    positionId: integer (optional filter)

# OpenShift
OpenShift:
  properties:
    shiftId: integer
    date: string (YYYY-MM-DD)
    startTime: string (HH:mm)
    endTime: string (HH:mm)
    positionId: integer
    positionName: string
    positionColor: string
    durationHours: number
    notes: string (optional)

# ClaimOpenShiftResponse
ClaimOpenShiftResponse:
  properties:
    success: boolean
    message: string
    shift: OpenShift (claimed shift details)
```

**Key Design Decisions**:

1. Follow clean architecture pattern from clock feature (domain entity → data model → repository → provider)
2. Use Freezed for data models, Equatable for domain entities
3. Use sealed classes for state management (OpenShiftsState)
4. Store-scoped like clock feature (requires typeNum)
5. No geolocation required for viewing/claiming (unlike clock in/out)

**Implementation Context**:

- Commands to run:
  - `dart run build_runner build --delete-conflicting-outputs` (after Freezed models)
  - `flutter test` (run tests)
  - `flutter analyze` (check for errors)
- Patterns to follow:
  - `lib/domain/entities/clock_status.dart` - Entity pattern
  - `lib/data/models/clock_model.dart` - Freezed model pattern
  - `lib/data/mappers/clock_mapper.dart` - Mapper pattern
  - `lib/domain/repositories/clock_repository.dart` - Repository interface
  - `lib/data/repositories/clock_repository_impl.dart` - Repository implementation
  - `lib/presentation/providers/clock_provider.dart` - Provider pattern
- Related specs:
  - `docs/specs/002-login-auth-flow/` - Auth flow (for store context)

---

## Implementation Phases

### Phase 1: Domain Layer (Entity & Repository Interface)

- [ ] T1 Phase 1: Domain Layer Foundation

    - [ ] T1.1 Prime Context
        - [ ] T1.1.1 Read API contract for open shifts `[ref: docs/employee-api.yaml; lines: 2100-2400]`
        - [ ] T1.1.2 Read existing entity patterns `[ref: lib/domain/entities/clock_status.dart]`
        - [ ] T1.1.3 Read existing repository interface `[ref: lib/domain/repositories/clock_repository.dart]`

    - [ ] T1.2 Write Tests
        - [ ] T1.2.1 Write unit tests for OpenShift entity value equality `[activity: unit-test]`
        - [ ] T1.2.2 Write unit tests for OpenShift computed properties (timeRange, isToday) `[activity: unit-test]`
        - [ ] T1.2.3 Write unit tests for OpenShiftFilter entity `[activity: unit-test]`

    - [ ] T1.3 Implement Domain Entities
        - [ ] T1.3.1 Create `lib/domain/entities/open_shift.dart` with OpenShift entity `[activity: domain-modeling]`
            - Properties: shiftId, date, startTime, endTime, positionId, positionName, positionColor, durationHours, notes
            - Computed: timeRange (formatted), isToday, isPast
        - [ ] T1.3.2 Create OpenShiftFilter entity in same file `[activity: domain-modeling]`
            - Properties: startDate, endDate, positionId (optional)

    - [ ] T1.4 Implement Repository Interface
        - [ ] T1.4.1 Create `lib/domain/repositories/open_shifts_repository.dart` `[activity: domain-modeling]`
            - Method: getOpenShifts(typeNum, filter) → List<OpenShift>
            - Method: claimShift(typeNum, shiftId) → ClaimResult

    - [ ] T1.5 Validate
        - [ ] T1.5.1 Run flutter analyze - no errors `[activity: lint-code]`
        - [ ] T1.5.2 Run domain entity tests `[activity: run-tests]`
        - [ ] T1.5.3 Verify entities match API contract `[activity: business-acceptance]`

---

### Phase 2: Data Layer (Models, Mapper, Repository Implementation)

- [ ] T2 Phase 2: Data Layer Implementation

    - [ ] T2.1 Prime Context
        - [ ] T2.1.1 Read existing Freezed model patterns `[ref: lib/data/models/clock_model.dart]`
        - [ ] T2.1.2 Read existing mapper patterns `[ref: lib/data/mappers/clock_mapper.dart]`
        - [ ] T2.1.3 Read existing repository implementation `[ref: lib/data/repositories/clock_repository_impl.dart]`
        - [ ] T2.1.4 Read API constants pattern `[ref: lib/core/constants/api_constants.dart]`

    - [ ] T2.2 Implement Data Models `[parallel: true]` `[component: models]`
        - [ ] T2.2.1 Create `lib/data/models/open_shift_model.dart` with Freezed `[activity: data-modeling]`
            - OpenShiftModel: matches API response
            - OpenShiftsRequestModel: matches API request
            - ClaimShiftResponseModel: matches API response
        - [ ] T2.2.2 Run build_runner to generate Freezed files `[activity: code-generation]`

    - [ ] T2.3 Implement Mapper `[parallel: true]` `[component: mapper]`
        - [ ] T2.3.1 Create `lib/data/mappers/open_shift_mapper.dart` `[activity: data-mapping]`
            - toEntity(OpenShiftModel) → OpenShift
            - toEntityList(List<OpenShiftModel>) → List<OpenShift>
            - filterToRequest(OpenShiftFilter) → OpenShiftsRequestModel

    - [ ] T2.4 Add API Constants
        - [ ] T2.4.1 Add open shifts endpoints to ApiConstants `[activity: backend-api]`
            - openShifts(typeNum) → '/{typeNum}/open-shifts'
            - claimShift(typeNum, shiftId) → '/{typeNum}/open-shifts/{shiftId}/claim'

    - [ ] T2.5 Write Repository Tests
        - [ ] T2.5.1 Write unit tests for OpenShiftsRepositoryImpl.getOpenShifts `[activity: unit-test]`
        - [ ] T2.5.2 Write unit tests for OpenShiftsRepositoryImpl.claimShift `[activity: unit-test]`
        - [ ] T2.5.3 Write tests for error handling (network, auth, validation) `[activity: unit-test]`

    - [ ] T2.6 Implement Repository
        - [ ] T2.6.1 Create `lib/data/repositories/open_shifts_repository_impl.dart` `[activity: backend-api]`
            - Inject ApiClient
            - Implement getOpenShifts with filtering
            - Implement claimShift with success/error handling
            - Add openShiftsRepositoryProvider

    - [ ] T2.7 Validate
        - [ ] T2.7.1 Run flutter analyze - no errors `[activity: lint-code]`
        - [ ] T2.7.2 Run all repository tests `[activity: run-tests]`
        - [ ] T2.7.3 Verify request/response matches API contract `[activity: business-acceptance]`

---

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

- [ ] T3 Phase 3: Provider Implementation

    - [ ] T3.1 Prime Context
        - [ ] T3.1.1 Read existing provider patterns `[ref: lib/presentation/providers/clock_provider.dart]`
        - [ ] T3.1.2 Read store provider for store context `[ref: lib/presentation/providers/store_provider.dart]`

    - [ ] T3.2 Write Provider Tests
        - [ ] T3.2.1 Write tests for OpenShiftsNotifier.fetchShifts `[activity: unit-test]`
        - [ ] T3.2.2 Write tests for OpenShiftsNotifier.claimShift `[activity: unit-test]`
        - [ ] T3.2.3 Write tests for OpenShiftsNotifier.setFilter `[activity: unit-test]`
        - [ ] T3.2.4 Write tests for state transitions (loading, ready, error, claimed) `[activity: unit-test]`
        - [ ] T3.2.5 Write tests for store change auto-refresh `[activity: unit-test]`

    - [ ] T3.3 Implement Provider
        - [ ] T3.3.1 Create `lib/presentation/providers/open_shifts_provider.dart` `[activity: state-management]`
            - OpenShiftsState sealed class hierarchy:
              - OpenShiftsInitial
              - OpenShiftsLoading
              - OpenShiftsLoaded (shifts list, filter, isRefreshing)
              - OpenShiftsError (message)
              - OpenShiftsClaiming (shiftId being claimed)
              - OpenShiftsClaimed (success result)
            - OpenShiftsNotifier extends Notifier<OpenShiftsState>
              - fetchShifts(filter?)
              - claimShift(shiftId)
              - setFilter(filter)
              - refresh()
              - clear()
        - [ ] T3.3.2 Add convenience providers `[activity: state-management]`
            - openShiftsListProvider → List<OpenShift>?
            - currentFilterProvider → OpenShiftFilter?

    - [ ] T3.4 Validate
        - [ ] T3.4.1 Run flutter analyze - no errors `[activity: lint-code]`
        - [ ] T3.4.2 Run all provider tests `[activity: run-tests]`
        - [ ] T3.4.3 Verify state machine covers all user flows `[activity: business-acceptance]`

---

### Phase 4: UI Layer (Open Shifts Screen)

- [ ] T4 Phase 4: UI Implementation

    - [ ] T4.1 Prime Context
        - [ ] T4.1.1 Read existing screen patterns `[ref: lib/presentation/screens/home/home_screen.dart]`
        - [ ] T4.1.2 Read app theme and colors `[ref: lib/core/theme/app_colors.dart]`
        - [ ] T4.1.3 Read style guide `[ref: docs/STYLE_GUIDE.md]`

    - [ ] T4.2 Implement Widgets `[parallel: true]` `[component: widgets]`
        - [ ] T4.2.1 Create `lib/presentation/widgets/open_shift_card.dart` `[activity: ui-component]`
            - Display: date, time range, position (with color), duration, notes
            - Action: "Request Shift" button
            - States: normal, claiming, claimed
        - [ ] T4.2.2 Create `lib/presentation/widgets/open_shifts_filter.dart` `[activity: ui-component]`
            - Date range picker (start/end)
            - Position filter dropdown (optional)
            - Apply/Clear buttons

    - [ ] T4.3 Implement Screen
        - [ ] T4.3.1 Create `lib/presentation/screens/open_shifts/open_shifts_screen.dart` `[activity: ui-screen]`
            - AppBar with title "Open Shifts"
            - Filter button in AppBar (opens filter sheet)
            - Pull-to-refresh
            - List of OpenShiftCard widgets
            - Empty state when no shifts available
            - Error state with retry
            - Loading skeleton
        - [ ] T4.3.2 Handle claim confirmation dialog `[activity: ui-screen]`
            - Show shift details
            - Confirm/Cancel buttons
            - Success feedback (snackbar or dialog)

    - [ ] T4.4 Add Navigation
        - [ ] T4.4.1 Add route to app_router.dart `[activity: navigation]`
            - Route: /open-shifts
            - Requires authentication
        - [ ] T4.4.2 Add navigation from home screen `[activity: navigation]`
            - Button or menu item to access open shifts

    - [ ] T4.5 Write Widget Tests
        - [ ] T4.5.1 Write widget tests for OpenShiftCard `[activity: widget-test]`
        - [ ] T4.5.2 Write widget tests for OpenShiftsFilter `[activity: widget-test]`
        - [ ] T4.5.3 Write widget tests for OpenShiftsScreen states `[activity: widget-test]`

    - [ ] T4.6 Validate
        - [ ] T4.6.1 Run flutter analyze - no errors `[activity: lint-code]`
        - [ ] T4.6.2 Run all widget tests `[activity: run-tests]`
        - [ ] T4.6.3 Visual review matches style guide `[activity: ui-review]`

---

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

- [ ] T5 Phase 5: Integration & E2E Validation

    - [ ] T5.1 Integration Tests
        - [ ] T5.1.1 Write integration test: View open shifts flow `[activity: integration-test]`
            - Authenticated → Navigate to open shifts → Load list → Verify display
        - [ ] T5.1.2 Write integration test: Claim shift flow `[activity: integration-test]`
            - Select shift → Confirm → Success → List refreshes
        - [ ] T5.1.3 Write integration test: Filter shifts flow `[activity: integration-test]`
            - Open filter → Set date range → Apply → List updates
        - [ ] T5.1.4 Write integration test: Error handling `[activity: integration-test]`
            - Network error → Retry → Success

    - [ ] T5.2 Performance Validation
        - [ ] T5.2.1 Open shifts list loads within 3 seconds `[activity: performance-test]`
        - [ ] T5.2.2 Claim action completes within 2 seconds `[activity: performance-test]`
        - [ ] T5.2.3 Filter updates list within 1 second `[activity: performance-test]`

    - [ ] T5.3 User Story Acceptance
        - [ ] T5.3.1 Verify: Team member can view open shifts at current store `[activity: business-acceptance]`
        - [ ] T5.3.2 Verify: Team member can filter by date range `[activity: business-acceptance]`
        - [ ] T5.3.3 Verify: Team member can request to pick up an open shift `[activity: business-acceptance]`
        - [ ] T5.3.4 Verify: Appropriate feedback shown after claim request `[activity: business-acceptance]`

    - [ ] T5.4 Full Test Suite
        - [ ] T5.4.1 Run `flutter test` - all tests pass `[activity: run-tests]`
        - [ ] T5.4.2 Run `flutter analyze` - no errors `[activity: lint-code]`
        - [ ] T5.4.3 Verify test coverage is adequate `[activity: run-tests]`

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

    - [ ] T5.6 Documentation
        - [ ] T5.6.1 Update CLAUDE.md with new endpoints and screens `[activity: documentation]`
        - [ ] T5.6.2 Update spec README.md with completion status `[activity: documentation]`

---

## Summary

| Phase | Description | Key Deliverables |
|-------|-------------|------------------|
| 1 | Domain Layer | OpenShift entity, repository interface |
| 2 | Data Layer | Freezed models, mapper, repository impl |
| 3 | Presentation Layer | OpenShiftsProvider, state management |
| 4 | UI Layer | OpenShiftsScreen, widgets, navigation |
| 5 | Integration & E2E | Full test coverage, user story validation |

**Estimated Test Count**: ~35-45 tests (unit + widget + integration)

**Dependencies**:
- Phase 1 must complete before Phase 2 (entities needed for models)
- Phase 2 must complete before Phase 3 (repository needed for provider)
- Phase 3 must complete before Phase 4 (provider needed for UI)
- Phase 5 requires all previous phases complete
