# Phase 3: Tables & Availability (Filament + API)

## Objective
Deliver complete table management and restaurant availability configuration from **both** Filament admin and the mobile API. Restaurant managers can create/edit tables, manage zones, configure opening hours, and set exceptional closures — from either interface.

---

## Filament Admin

### 3.1 TablesRelationManager

**File:** `app/Filament/Resources/RestaurantResource/RelationManagers/TablesRelationManager.php`

**Form:**
- `number` (TextInput, numeric, required — unique per restaurant)
- `label` (TextInput, nullable — e.g., "Fenêtre côté jardin")
- `seats` (TextInput, numeric, required — number of covers)
- `zone` (Select from RestaurantTableZone enum)
- `status` (Select from RestaurantTableStatus enum)
- `is_active` (Toggle)

**Table Columns:**
- Number, Label, Seats, Zone (badge with color), Status (badge), is_active (icon)

**Bulk Actions:**
- Set zone, Set status (maintenance/available), Toggle active

**Filters:**
- Zone, Status, is_active

**Header Stats:**
- Total tables, Total seats, Tables by zone

### 3.2 Restaurant Opening Hours in RestaurantResource

Already part of RestaurantResource form (Phase 2), but here we detail the implementation:

**Opening Hours Repeater:**
```
For each day (Monday–Sunday):
  - is_open (Toggle)
  - slots (Repeater):
    - open_at (TimePicker)
    - close_at (TimePicker)
```

Stored as JSON in `opening_hours` field, same format as Service model.

### 3.3 Service Periods Configuration

In RestaurantResource form:

**Service Periods Section:**
```
For each RestaurantServicePeriod:
  - enabled (Toggle)
  - start_time (TimePicker)
  - end_time (TimePicker)
```

Stored as JSON in `service_periods` field:
```json
{
  "breakfast": { "enabled": true, "start": "07:00", "end": "10:30" },
  "lunch": { "enabled": true, "start": "12:00", "end": "14:30" },
  "dinner": { "enabled": true, "start": "19:00", "end": "22:30" }
}
```

### 3.4 Exceptional Closures

**File:** `app/Filament/Resources/RestaurantResource/RelationManagers/ExceptionalClosuresRelationManager.php`

Reuse or extend existing `ExceptionalClosingHour` model pattern from Service.

**Form:**
- `date` (DatePicker)
- `reason` (TextInput, nullable)
- `full_day` (Toggle)
- If not full day: `closed_from` (TimePicker), `closed_to` (TimePicker)

---

## API Endpoints (Restaurant Manager)

### 3.5 List Tables

**Controller:** `app/Http/Controllers/Api/Employee/RestaurantManager/ListTablesController.php`

- `GET /v1/places/{place}/restaurants/{restaurant}/tables`
- Query params: `zone`, `status`, `include_inactive`
- Returns all tables with current status

### 3.6 Get Tables Status (Real-time)

**Controller:** `app/Http/Controllers/Api/Employee/RestaurantManager/TablesStatusController.php`

- `GET /v1/places/{place}/restaurants/{restaurant}/tables/status`
- Returns all tables with:
  - Current status (available/occupied/reserved/maintenance)
  - Current reservation info if occupied/reserved (party name, party_size, start_at)
  - Current order info if occupied (order items count, order total so far)
- Summary: total_tables, available, occupied, reserved, total_seats, available_seats

### 3.7 Create Table

**Controller:** `app/Http/Controllers/Api/Employee/RestaurantManager/CreateTableController.php`

- `POST /v1/places/{place}/restaurants/{restaurant}/tables`
- Body: `{ number, label?, seats, zone }`

### 3.8 Update Table

**Controller:** `app/Http/Controllers/Api/Employee/RestaurantManager/UpdateTableController.php`

- `PUT /v1/places/{place}/restaurants/{restaurant}/tables/{table}`
- Body: `{ number?, label?, seats?, zone?, status?, is_active? }`

### 3.9 Delete Table

**Controller:** `app/Http/Controllers/Api/Employee/RestaurantManager/DeleteTableController.php`

- `DELETE /v1/places/{place}/restaurants/{restaurant}/tables/{table}`
- Soft deletes. Fails if table has future reservations.

### 3.10 Update Table Status

**Controller:** `app/Http/Controllers/Api/Employee/RestaurantManager/UpdateTableStatusController.php`

- `PATCH /v1/places/{place}/restaurants/{restaurant}/tables/{table}/status`
- Body: `{ status: "available|occupied|reserved|maintenance" }`

### 3.11 Get Restaurant Hours

**Controller:** `app/Http/Controllers/Api/Employee/RestaurantManager/GetRestaurantHoursController.php`

- `GET /v1/places/{place}/restaurants/{restaurant}/hours`
- Returns opening_hours + service_periods + exceptional closures

### 3.12 Update Restaurant Hours

**Controller:** `app/Http/Controllers/Api/Employee/RestaurantManager/UpdateRestaurantHoursController.php`

- `PUT /v1/places/{place}/restaurants/{restaurant}/hours`
- Body: `{ opening_hours: {...}, service_periods: {...} }`

### 3.13 List Exceptional Closures

**Controller:** `app/Http/Controllers/Api/Employee/RestaurantManager/ListExceptionalClosuresController.php`

- `GET /v1/places/{place}/restaurants/{restaurant}/closures`
- Returns upcoming closures

### 3.14 Create Exceptional Closure

**Controller:** `app/Http/Controllers/Api/Employee/RestaurantManager/CreateExceptionalClosureController.php`

- `POST /v1/places/{place}/restaurants/{restaurant}/closures`
- Body: `{ date, reason?, full_day?, closed_from?, closed_to? }`

### 3.15 Delete Exceptional Closure

**Controller:** `app/Http/Controllers/Api/Employee/RestaurantManager/DeleteExceptionalClosureController.php`

- `DELETE /v1/places/{place}/restaurants/{restaurant}/closures/{closure}`

---

## Services

### 3.16 RestaurantAvailabilityService

**File:** `app/Services/RestaurantManager/RestaurantAvailabilityService.php`

Shared logic for checking restaurant and table availability:

- `isOpen(Restaurant $restaurant, Carbon $dateTime): bool`
- `getAvailableTables(Restaurant $restaurant, Carbon $dateTime, int $partySize): Collection`
- `getAvailableSlots(Restaurant $restaurant, Carbon $date, int $partySize): array`
- `getCurrentServicePeriod(Restaurant $restaurant): ?RestaurantServicePeriod`
- `getServicePeriodTimeRange(Restaurant $restaurant, RestaurantServicePeriod $period): ?array`
- `isTableAvailable(RestaurantTable $table, Carbon $start, Carbon $end): bool`

Checks against:
- Restaurant opening hours
- Service periods
- Exceptional closures
- Existing reservations on tables

---

## Resources (API Serialization)

- `RestaurantTableResource` — table with status
- `RestaurantTableStatusResource` — table with live reservation/order info
- `RestaurantHoursResource` — hours + service periods
- `ExceptionalClosureResource`

---

## Tests

**File:** `tests/Feature/Controllers/RestaurantManager/TablesTest.php`

- [ ] List tables returns correct structure
- [ ] Create table with valid data works
- [ ] Create table with duplicate number returns 422
- [ ] Update table status changes status
- [ ] Delete table with future reservations fails
- [ ] Tables status returns live availability
- [ ] Tables filtered by zone works
- [ ] Update restaurant hours persists correctly
- [ ] Create exceptional closure works
- [ ] Availability service respects closures
- [ ] Availability service respects opening hours
- [ ] Availability service respects existing reservations
- [ ] Service period detection returns correct period
- [ ] Filament CRUD matches API results
- [ ] All endpoints return public_id, never id
- [ ] Non-restaurant-manager gets 403

---

## Files Created/Modified

| Action | File |
|---|---|
| Create | `app/Filament/Resources/RestaurantResource/RelationManagers/TablesRelationManager.php` |
| Create | `app/Filament/Resources/RestaurantResource/RelationManagers/ExceptionalClosuresRelationManager.php` |
| Create | Controllers: 11 API controllers |
| Create | `app/Services/RestaurantManager/RestaurantAvailabilityService.php` |
| Create | Resources: 4 API resources |
| Create | Requests: 5 form requests |
| Create | `tests/Feature/Controllers/RestaurantManager/TablesTest.php` |
| Modify | `routes/api.php` — add table & hours routes |

---

## Acceptance Criteria

- [ ] Filament: Full CRUD for tables within RestaurantResource
- [ ] Filament: Opening hours and service periods configurable
- [ ] Filament: Exceptional closures manageable
- [ ] API: All 11 endpoints functional
- [ ] Table status reflects live reservation/order state
- [ ] Availability service correctly checks hours, closures, reservations
- [ ] Unique table number per restaurant enforced
- [ ] Table with future reservations cannot be deleted
- [ ] Swagger annotations on all controllers
- [ ] All tests pass
- [ ] `vendor/bin/pint` passes on all new/modified files
- [ ] `vendor/bin/phpstan --level=7` passes on all new/modified files
