- Create BaseResource with formatDate() and formatDecimal() utilities - Create 11 API Resource classes for all models - Update all 6 controllers to return wrapped responses via wrapResource() - Update frontend API client with unwrapResponse() helper - Update all 63+ backend tests to expect 'data' wrapper - Regenerate Scribe API documentation BREAKING CHANGE: All API responses now wrap data in 'data' key per architecture spec. Backend Tests: 70 passed, 5 failed (unrelated to data wrapper) Frontend Unit: 10 passed E2E Tests: 102 passed, 20 skipped API Docs: Generated successfully Refs: openspec/changes/api-resource-standard
192 lines
7.0 KiB
Markdown
192 lines
7.0 KiB
Markdown
# 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<T>(response: Response): Promise<T> {
|
|
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
|