Hospitality engine

Save floor-plan geometry for a batch of tables and rooms

patch/api/tables/layout

Where the floor-plan editor autosaves (migrations 0091 and 0093). A batch on purpose: a drag session touches several tables (and, since 0093, the room zones around them) and one debounced save carries them all. Positions and sizes are in grid units (one unit is a nominal 25cm; see lib/booking/floorplan.ts). Null posX/posY means "not placed" (both or neither, mirroring the database constraints); a table's null width/height means "keep deriving the size from seatsMax", while a DRAWN room must carry its size (there is no seat count to derive one from). An id deleted concurrently is skipped and simply not counted in updated, never an error.

Authorization

sessionCookie
sb-qxrvgfkjyvbngipqvslu-auth-token<token>

The dashboard's Supabase Auth session cookie, set at sign-in. Large sessions are split across numbered chunks (…auth-token.0, .1), so treat this as a cookie family rather than one name.

Every request re-validates it against the Auth server (getUser()), never by decoding the cookie locally: a JWT nothing has checked is not a credential. Tenancy is then read from the verified app_metadata.company_id claim and enforced by row-level security; it is never read from request input, on any route, ever.

role (admin / staff) is deliberately not in RLS. It gates specific actions in route code, the operations marked admin below, so hiding a button in the UI is cosmetic only, and a route's own check is the enforcement.

In: cookie

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

At least one of tables / rooms must be non-empty.

Response Body

application/json

application/json

application/json

application/json

curl -X PATCH "https://example.com/api/tables/layout" \  -H "Content-Type: application/json" \  -d '{}'
{  "ok": true,  "updated": 0}