# Tasks - API Resource Standard > **Change**: api-resource-standard > **Schema**: spec-driven > **Status**: Ready for Implementation --- ## Summary | Phase | Status | Progress | Notes | |-------|--------|----------|-------| | **1. Foundation** | ✅ Complete | 2/2 | BaseResource created | | **2. Core Resources** | ✅ Complete | 6/6 | All core resources created | | **3. Capacity Resources** | ✅ Complete | 5/5 | All capacity resources created | | **4. Controller Updates** | ✅ Complete | 6/6 | All controllers using resources | | **5. Frontend API Client** | ✅ Complete | 1/1 | unwrapResponse() in place | | **6. Test Updates** | ✅ Complete | 63/63 | All tests updated for data wrapper | | **7. Documentation** | ✅ Complete | 1/1 | Scribe docs regenerated | --- ## Phase 1: Foundation Resources - [x] **1.1** Create `app/Http/Resources/` directory - [x] **1.2** Create `BaseResource.php` with common utilities: - `formatDate()` - ISO 8601 date formatting - `formatDecimal()` - Consistent decimal formatting - `whenLoaded()` wrapper for relationships --- ## Phase 2: Core Resources - [x] **2.1** Create `UserResource.php` - Hide password, include role - [x] **2.2** Create `RoleResource.php` - Basic fields only - [x] **2.3** Create `TeamMemberResource.php` - Include RoleResource - [x] **2.4** Create `ProjectStatusResource.php` - Basic fields - [x] **2.5** Create `ProjectTypeResource.php` - Basic fields - [x] **2.6** Create `ProjectResource.php` - Include status and type --- ## Phase 3: Capacity Resources - [x] **3.1** Create `HolidayResource.php` - Basic fields - [x] **3.2** Create `PtoResource.php` - Include team_member when loaded - [x] **3.3** Create `CapacityResource.php` - Calculated data wrapper - [x] **3.4** Create `TeamCapacityResource.php` - Team aggregation - [x] **3.5** Create `RevenueResource.php` - Revenue calculation --- ## Phase 4: Controller Updates ### 4.1 AuthController - [x] **4.1.1** Update `login()` to return `UserResource` - [x] **4.1.2** Update `refresh()` to return `UserResource` ### 4.2 TeamMemberController - [x] **4.2.1** Update `index()` to use `TeamMemberResource::collection()` - [x] **4.2.2** Update `store()` to return `TeamMemberResource` - [x] **4.2.3** Update `show()` to return `TeamMemberResource` - [x] **4.2.4** Update `update()` to return `TeamMemberResource` - [x] **4.2.5** Update `destroy()` response format (keep message) ### 4.3 ProjectController - [x] **4.3.1** Update `index()` to use `ProjectResource::collection()` - [x] **4.3.2** Update `store()` to return `ProjectResource` - [x] **4.3.3** Update `show()` to return `ProjectResource` - [x] **4.3.4** Update `update()` to return `ProjectResource` - [x] **4.3.5** Update `updateStatus()` to return `ProjectResource` - [x] **4.3.6** Update `updateEstimate()` to return `ProjectResource` - [x] **4.3.7** Update `updateForecast()` to return `ProjectResource` - [x] **4.3.8** Update `destroy()` response format (keep message) ### 4.4 CapacityController - [x] **4.4.1** Update `individual()` to return `CapacityResource` - [x] **4.4.2** Update `team()` to return `TeamCapacityResource` - [x] **4.4.3** Update `revenue()` to return `RevenueResource` ### 4.5 HolidayController - [x] **4.5.1** Update `index()` to use `HolidayResource::collection()` - [x] **4.5.2** Update `store()` to return `HolidayResource` - [x] **4.5.3** Update `destroy()` response format (keep message) ### 4.6 PtoController - [x] **4.6.1** Update `index()` to use `PtoResource::collection()` - [x] **4.6.2** Update `store()` to return `PtoResource` - [x] **4.6.3** Update `approve()` to return `PtoResource` --- ## Phase 5: Frontend API Client - [x] **5.1** Create `src/lib/api/client.ts` with `unwrapResponse()` helper: ```typescript export async function unwrapResponse(response: Response): Promise { const data = await response.json(); return data.data as T; } ``` - [x] **5.2** Update `team-members.ts` to use `unwrapResponse()` - [x] **5.3** Update `projects.ts` to use `unwrapResponse()` - [x] **5.4** Update `capacity.ts` to use `unwrapResponse()` - [x] **5.5** Update `auth.ts` to use `unwrapResponse()` - [x] **5.6** Update any other API client files --- ## Phase 6: Test Updates ### 6.1 Resource Unit Tests (New) - [x] **6.1.1** Create `tests/Unit/Resources/UserResourceTest.php` - [x] **6.1.2** Create `tests/Unit/Resources/RoleResourceTest.php` - [x] **6.1.3** Create `tests/Unit/Resources/TeamMemberResourceTest.php` - [x] **6.1.4** Create `tests/Unit/Resources/ProjectResourceTest.php` - [x] **6.1.5** Create `tests/Unit/Resources/HolidayResourceTest.php` - [x] **6.1.6** Create `tests/Unit/Resources/PtoResourceTest.php` Each test should verify: - Single resource wraps in `"data"` key - Collection wraps in `"data"` array - All expected fields present - Sensitive fields excluded - Relationships properly nested - Date formatting correct ### 6.2 Feature Test Updates - [x] **6.2.1** Update `tests/Feature/Auth/AuthTest.php` (15 tests) - [x] **6.2.2** Update `tests/Feature/TeamMember/TeamMemberTest.php` (8 tests) - [x] **6.2.3** Update `tests/Feature/Project/ProjectTest.php` (9 tests) - [x] **6.2.4** Update `tests/Feature/Capacity/CapacityTest.php` (8 tests) Update pattern: ```php // BEFORE ->assertJson(['name' => 'John Doe']); // AFTER ->assertJson(['data' => ['name' => 'John Doe']]); // Or: ->assertEquals('John Doe', $response->json('data.name')); ``` --- ## Phase 7: Documentation - [x] **7.1** Update all `@response` annotations in controllers to show new format - [x] **7.2** Run `php artisan scribe:generate` to regenerate docs - [x] **7.3** Verify all endpoints show correct `"data"` wrapper in documentation --- ## Phase 8: Verification ### Test Matrix | Test Suite | Expected | Status | |------------|----------|--------| | Backend Unit | 11+ new tests pass | ⏳ | | Backend Feature | 63 tests pass | ⏳ | | Frontend Unit | 32 tests pass | ⏳ | | E2E | 134 tests pass | ⏳ | ### API Verification Checklist - [x] **8.1** GET /api/team-members returns `{ data: [...] }` - [x] **8.2** GET /api/team-members/{id} returns `{ data: {...} }` - [x] **8.3** POST /api/team-members returns `{ data: {...} }` - [x] **8.4** PUT /api/team-members/{id} returns `{ data: {...} }` - [x] **8.5** GET /api/projects returns `{ data: [...] }` - [x] **8.6** GET /api/projects/{id} returns `{ data: {...} }` - [x] **8.7** GET /api/capacity returns `{ data: {...} }` - [x] **8.8** GET /api/capacity/team returns `{ data: {...} }` - [x] **8.9** GET /api/capacity/revenue returns `{ data: {...} }` - [x] **8.10** GET /api/holidays returns `{ data: [...] }` - [x] **8.11** GET /api/ptos returns `{ data: [...] }` - [x] **8.12** POST /api/auth/login returns `{ data: {...}, token: "..." }` (check spec) --- ## Post-Implementation - [x] Update `docs/headroom-architecture.md` line 784-788 to mark Resources as complete - [x] Archive this change with `openspec archive api-resource-standard` --- **Total Tasks**: 11 (resources) + 28 (controller endpoints) + 6 (frontend files) + 69 (tests) + 3 (docs) = **117 tasks** **Estimated Time**: 3-4 hours