# Broadcast Reference

All channels are **private** — the client authenticates via the endpoint in
[01-realtime-setup.md](01-realtime-setup.md), and `routes/channels.php` decides who may join each
one (read it directly for the exact authorization query per channel).

## Channels

| Channel | Who can join | Purpose |
|---|---|---|
| `App.Models.User.{id}` | that exact user | Laravel's default notification channel — any `->notify()` call using a `broadcast` channel lands here |
| `order.{orderId}` | the order's client, the restaurant owner, any of that restaurant's staff, or the assigned driver | Order status changes, live driver position |
| `restaurant.{restaurantId}.dispatch` | the restaurant owner, its staff, or its own drivers | Dispatch board: offers going out, a driver claiming, offers expiring |
| `driver.{driverId}` | that exact driver | Pickup/arrival confirmation prompts |
| `conversation.{conversationId}` | any participant of that thread | Chat messages — restaurant-side participants are the owner + every staff member |

## Events

Every event implements `ShouldBroadcastNow` (fires synchronously) and is dispatched from inside a
**service**, never a controller. See [03-services-orders-and-dispatch.md](03-services-orders-and-dispatch.md)
for exactly which service method fires which.

| Event | Channel | `broadcastAs()` | Payload |
|---|---|---|---|
| `OrderStatusUpdated` | `order.{id}` | `OrderStatusUpdated` | Full order resource (client, restaurant, driver, products loaded) |
| `OrderDispatchUpdated` | `restaurant.{id}.dispatch` | `OrderDispatchUpdated` | `{order_id, state, driver_id, offered_driver_id}` — `state` is `offered` / `claimed` / `expired` |
| `DriverLocationUpdated` | `order.{id}` | `DriverLocationUpdated` | `{driver_id, lat, lng, at}` |
| `DriverPromptRequested` | `driver.{id}` | `DriverPromptRequested` | `{order_id, prompt}` — `prompt` is `pickup` or `arrival` |
| `MessageSentEvent` | `conversation.{id}` | `message.sent` | Full message resource |

All of them are wrapped in error handling where dispatched — a broadcast failure never fails the
underlying action (an order still gets accepted even if Reverb is down).

## What already listens to these

`resources/js/app.js` already subscribes to `App.Models.User.{id}` and reacts to several
notification types (new order, driver accepted, order delivered, etc.) by dispatching a Livewire
browser event that the relevant admin index page listens for — see
[07-existing-admin-panel.md](07-existing-admin-panel.md) for what's already wired up this way.
Nothing currently subscribes to `order.{id}`, `restaurant.{id}.dispatch`, `driver.{id}`, or
`conversation.{id}` from the Livewire panel — those are all net-new.
