# Phase 2: Room Types & Rooms — DONE

**Completed:** 2026-03-16

## Summary

Filament admin CRUD for hotels, API endpoints for hotel managers (5 endpoints) and customers (3 endpoints), API resources, form requests, routes, and comprehensive Pest tests have been created for the Room Types & Rooms phase.

## Files Created

### Filament Admin (6)
- `app/Filament/Resources/HotelResource.php` — Main resource with translatable name/description, media, place selector, stars, contact info, check-in/out times, cancellation policy
- `app/Filament/Resources/HotelResource/Pages/ListHotels.php` — Standard list page
- `app/Filament/Resources/HotelResource/Pages/CreateHotel.php` — Create page with auto-slug from name
- `app/Filament/Resources/HotelResource/Pages/EditHotel.php` — Edit page with combined relation managers
- `app/Filament/Resources/HotelResource/RelationManagers/RoomTypesRelationManager.php` — Inline CRUD for room types with 3-tier pricing, occupancy, bed type, amenities, media
- `app/Filament/Resources/HotelResource/RelationManagers/RoomsRelationManager.php` — Inline CRUD for rooms with status/housekeeping badges
- `app/Filament/Resources/PlaceResource/Pages/Management/ManageHotels.php` — Management page on PlaceResource

### API Resources (4)
- `app/Http/Resources/HotelManager/HotelResource.php` — Full hotel detail for managers
- `app/Http/Resources/HotelManager/HotelRoomTypeResource.php` — Room type with availability counts and optional rooms list
- `app/Http/Resources/HotelManager/HotelRoomResource.php` — Room detail with optional current occupant info
- `app/Http/Resources/HotelManager/HotelRoomTypeSummaryResource.php` — Customer-facing room type with member-aware pricing

### Form Requests (1)
- `app/Http/Requests/HotelManager/UpdateRoomStatusRequest.php` — Validates status (HotelRoomStatus enum) and optional notes

### Hotel Manager Controllers (5)
- `app/Http/Controllers/Api/Employee/HotelManager/ListRoomTypesController.php` — GET `/manage/room-types` — List room types with availability summary
- `app/Http/Controllers/Api/Employee/HotelManager/ShowRoomTypeController.php` — GET `/manage/room-types/{roomType}` — Room type detail with all rooms
- `app/Http/Controllers/Api/Employee/HotelManager/ListRoomsController.php` — GET `/manage/rooms` — List rooms with filters (status, housekeeping, room_type_id, floor)
- `app/Http/Controllers/Api/Employee/HotelManager/ShowRoomController.php` — GET `/manage/rooms/{room}` — Room detail with housekeeping logs and current occupant
- `app/Http/Controllers/Api/Employee/HotelManager/UpdateRoomStatusController.php` — PATCH `/manage/rooms/{room}/status` — Update status with automatic housekeeping log creation

### Customer Controllers (3)
- `app/Http/Controllers/Api/Hotel/ListHotelsController.php` — GET `/hotels` — List active hotels at a place
- `app/Http/Controllers/Api/Hotel/ShowHotelController.php` — GET `/hotels/{hotel}` — Active hotel detail
- `app/Http/Controllers/Api/Hotel/ListHotelRoomTypesController.php` — GET `/hotels/{hotel}/room-types` — Active room types with member-aware pricing

### Tests (1)
- `tests/Feature/Controllers/HotelManager/RoomTypesAndRoomsTest.php` — 14 tests covering middleware auth, manager endpoints, and customer endpoints

## Files Modified

- `app/Filament/Resources/PlaceResource.php` — Added ManageHotels page registration
- `routes/api.php` — Added 5 manager routes under `/manage` prefix + 3 customer routes
- `tests/Feature/Controllers/HotelManager/HotelManagerAuthorizationTest.php` — Un-skipped 3 middleware tests, updated URLs to use `/manage/` prefix

## API Routes

### Hotel Manager (requires `hotel_manager` role + place attachment)
| Method | URL | Controller |
|--------|-----|-----------|
| GET | `/v1/places/{place}/hotels/{hotel}/manage/room-types` | ListRoomTypesController |
| GET | `/v1/places/{place}/hotels/{hotel}/manage/room-types/{roomType}` | ShowRoomTypeController |
| GET | `/v1/places/{place}/hotels/{hotel}/manage/rooms` | ListRoomsController |
| GET | `/v1/places/{place}/hotels/{hotel}/manage/rooms/{room}` | ShowRoomController |
| PATCH | `/v1/places/{place}/hotels/{hotel}/manage/rooms/{room}/status` | UpdateRoomStatusController |

### Customer (authenticated users)
| Method | URL | Controller |
|--------|-----|-----------|
| GET | `/v1/places/{place}/hotels` | ListHotelsController |
| GET | `/v1/places/{place}/hotels/{hotel}` | ShowHotelController |
| GET | `/v1/places/{place}/hotels/{hotel}/room-types` | ListHotelRoomTypesController |

## Quality Checks

- **Pint:** PASS (0 issues)
- **PHPStan level 7:** PASS (0 errors)
- **Pest tests:** 32 passing (18 from Phase 1 + 14 new)

## Design Decisions

- **`/manage/` prefix**: Manager routes use `/manage/` prefix (e.g., `/hotels/{hotel}/manage/rooms`) to avoid URL collision with customer routes at `/hotels/{hotel}/room-types`.
- **`setRelation` over `setAttribute`**: Dynamic reservation data on rooms uses `setRelation('currentReservation', ...)` instead of `setAttribute()` to avoid `MissingAttributeException` on models with `$preventsAccessingMissingAttributes`.
- **Collection wrapping**: API collections are wrapped in `items` key (per `ResourceCollection::wrap('items')` in AppServiceProvider).
- **Member-aware pricing**: Customer room type listing shows member price when the authenticated user has `is_member` true, otherwise base price.

## Notes

- No commits created — user will commit manually.
- Swagger annotations updated to reflect `/manage/` prefix on all 5 manager controllers.
