# Phase 2: Menu System (Filament + API) — DONE

**Completed:** 2026-03-13

## What was delivered

### Filament Admin

#### RestaurantResource (CRUD)
- `app/Filament/Resources/RestaurantResource.php` — Full CRUD with tabs (General, Reservations, Schedule, Service Periods), navigationGroup = 'Restaurant'
- `app/Filament/Resources/RestaurantResource/Pages/ListRestaurants.php`
- `app/Filament/Resources/RestaurantResource/Pages/CreateRestaurant.php` — Auto-generates slug from name
- `app/Filament/Resources/RestaurantResource/Pages/EditRestaurant.php` — Combined relation manager tabs

#### PlaceResource Integration
- `app/Filament/Resources/PlaceResource/Pages/Management/ManageRestaurants.php` — Management page at `/{record}/restaurants`
- `app/Filament/Resources/PlaceResource/Widgets/RestaurantSalesWidget.php` — Revenue (30d), Active Restaurants, Restaurant Orders (30d)
- Modified `app/Filament/Resources/PlaceResource.php` — Added ManageRestaurants page + RestaurantSalesWidget

#### RelationManagers (3)
- `app/Filament/Resources/RestaurantResource/RelationManagers/MenuCategoriesRelationManager.php` — CRUD with translatable fields, parent/child, type badge
- `app/Filament/Resources/RestaurantResource/RelationManagers/MenuItemsRelationManager.php` — CRUD with pricing, allergens (EU 14), dietary labels, media
- `app/Filament/Resources/RestaurantResource/RelationManagers/MenusRelationManager.php` — CRUD with sections repeater, service periods, duplicate action

### API Resources (9)
- `app/Http/Resources/RestaurantManager/RestaurantResource.php` — Summary
- `app/Http/Resources/RestaurantManager/RestaurantDetailResource.php` — Full detail
- `app/Http/Resources/RestaurantManager/MenuCategoryResource.php` — With children/items count
- `app/Http/Resources/RestaurantManager/MenuItemResource.php` — With category, allergens, dietary labels, 3-tier pricing
- `app/Http/Resources/RestaurantManager/MenuResource.php` — With sections
- `app/Http/Resources/RestaurantManager/MenuSectionResource.php` — With items
- `app/Http/Resources/Restaurant/CustomerRestaurantResource.php` — Customer-facing
- `app/Http/Resources/Restaurant/CustomerMenuResource.php` — Customer-facing, active items only
- `app/Http/Resources/Restaurant/CustomerMenuItemResource.php` — Member pricing, allergen badges

### FormRequests (7)
- `CreateMenuCategoryRequest`, `UpdateMenuCategoryRequest`
- `CreateMenuItemRequest`, `UpdateMenuItemRequest`
- `CreateMenuRequest`, `UpdateMenuRequest`
- `DuplicateMenuRequest`

### Actions (1)
- `app/Actions/RestaurantManager/DuplicateMenuAction.php` — Deep copy: menu + sections + section items with pivot data

### API Controllers — Restaurant Manager (16)

#### Menu Categories (4)
- `ListMenuCategoriesController` — GET with type/parent_id/include_inactive filters
- `CreateMenuCategoryController` — POST with parent resolution
- `UpdateMenuCategoryController` — PUT
- `DeleteMenuCategoryController` — DELETE (fails if active items exist)

#### Menu Items (6)
- `ListMenuItemsController` — GET with search, category, type, allergen, dietary_label filters + sorting
- `ShowMenuItemController` — GET single item
- `CreateMenuItemController` — POST (multipart for image)
- `UpdateMenuItemController` — PUT (multipart for image)
- `DeleteMenuItemController` — DELETE (soft)
- `ToggleMenuItemController` — PATCH toggle is_active

#### Menus (6)
- `ListMenusController` — GET with date, service_period, include_inactive filters
- `TodayMenuController` — GET today's active menu with sections
- `CreateMenuController` — POST with sections and items
- `UpdateMenuController` — PUT (replaces sections entirely)
- `DeleteMenuController` — DELETE (soft)
- `DuplicateMenuController` — POST deep copy to new date

### API Controllers — Customer (3)
- `ListRestaurantsController` — GET active restaurants for a place
- `ShowRestaurantController` — GET restaurant detail
- `RestaurantMenuController` — GET today's menu with active items, member pricing

### Routes
- 16 Restaurant Manager routes registered under `v1/places/{place}/restaurants/{restaurant}/`
- 3 Customer routes registered under `v1/places/{place}/restaurants/`

### Tests
- `tests/Feature/Controllers/RestaurantManager/MenuSystemTest.php` — 25 test cases covering:
  - Category CRUD, parent/child, invalid type validation
  - Menu item list/search/filter by category/allergen, create/update/toggle/delete
  - Menu create with sections, today's menu, duplicate, delete
  - Customer: list restaurants, show detail, inactive hidden, menu with active items only
  - Authorization: non-restaurant-manager gets 403
  - Public ID: never exposes internal ID
  - Allergen enum: 14 EU allergens

## Quality Checks
- `vendor/bin/pint` — PASS (48 files, 11 auto-fixed style issues)
- `vendor/bin/phpstan --level=7` — PASS (0 errors, 45 files analysed)

## Files Summary

| Type | Count |
|---|---|
| Filament Resources/Pages/RelationManagers/Widgets | 8 |
| API Resources | 9 |
| FormRequests | 7 |
| Actions | 1 |
| API Controllers (Manager) | 16 |
| API Controllers (Customer) | 3 |
| Tests | 1 (25 test cases) |
| Modified files | 2 (PlaceResource.php, routes/api.php) |
| **Total new files** | **45** |
