# PocketBase calendars (bookings page)

The **Calendars** page (`bookings.html`) loads these collections from your PocketBase API and maps them into the same shape as `bookings-config.js`. If the API is unreachable, the page uses the bundled JavaScript config as a fallback.

## Base URL

- Default: same origin as the page (`window.location.origin`), which matches typical PocketBase static hosting.
- Cross-origin: set `window.WH_POCKETBASE_URL` in `pocketbase-calendars-config.js` to your PocketBase origin (no trailing slash). Ensure PocketBase allows CORS for your static host if needed.

## API rules (required for the public site)

For each collection below, the browser calls the **List records** API without a login. Grant **guest** access on **list** and **view**:

- In PocketBase Admin: open the collection → **API rules**.
- Set **List rule** and **View rule** to `1 = 1` (always true in PocketBase’s filter syntax) if you are happy for anyone to read calendar rows (typical for this marketing page).
- If rules are empty or disallow guests, the HTTP response fails and the bookings page uses `bookings-config.js` instead.

Lock down or split collections later if you prefer private staging data.

Ordering uses **`placement`** (dropdown), not manual numbers — choose how early the row appears when lists are sorted (**first** → **early** → **normal** → **late** → **last**). Applied by migration `1739013300_calendar_placement_select.js` if you started from an older schema that used numeric `sort`.

### `wh_airbnb_settings` (single row recommended)

| Field            | Type    | Notes                                      |
| ---------------- | ------- | ------------------------------------------ |
| `check_in`       | Text    | e.g. `14:00`                               |
| `check_out`      | Text    | e.g. `10:00`                               |
| `cleaning_hours` | Number  | Hours between checkout and next check-in   |
| `min_nightly_rate` | Number (optional) | Used in config shape; UI may not show it |
| `rate_note`      | Text (optional) | Reserved / optional copy                  |
| `placement`      | Select | Optional; **`first` / `early` / `normal` / `late` / `last`** — order when multiple rows exist |

The first record (by **placement**, then `id`) wins if you use multiple rows.

### `wh_airbnb_seasons`

| Field       | Type   | Notes                                                                 |
| ----------- | ------ | --------------------------------------------------------------------- |
| `tier`      | Text   | Maps to season id: `low`, `mid`, or `high` (case-insensitive)         |
| `label`     | Text   | Display name                                                          |
| `months`    | JSON   | Array of month numbers `1`–`12`, e.g. `[5,6,7,8]`                     |
| `rate_note` | Text   | Shown as cell tooltip on the Airbnb calendar                          |
| `placement` | Select | Optional; order seasons in lists (**first** … **last**)               |

### `wh_airbnb_stays`

| Field       | Type   | Notes                          |
| ----------- | ------ | ------------------------------ |
| `check_in`  | Date   | First guest night (ISO date)   |
| `check_out` | Date   | Checkout morning (not a guest night) |
| `label`     | Text   | e.g. `Booked stay`             |
| `placement` | Select | Optional; order in internal lists |

### `wh_airbnb_blocked`

| Field       | Type   | Notes                         |
| ----------- | ------ | ----------------------------- |
| `night`     | Date   | Night held / manual block     |
| `note`      | Text   | Optional                      |
| `placement` | Select | Optional; order multiple rows |

### `wh_photoshoot_bookings`

| Field       | Type   | Notes                    |
| ----------- | ------ | ------------------------ |
| `day`       | Date   | Booked photoshoot day    |
| `note`      | Text   | Optional                 |
| `placement` | Select | Optional; order rows     |

### `wh_photoshoot_copy` (single row)

| Field       | Type   | Notes                                      |
| ----------- | ------ | ------------------------------------------ |
| `body`      | Text   | Notes shown in the Photoshoots tab         |
| `placement` | Select | Optional; if multiple rows, display order  |

### `wh_flower_species`

| Field              | Type   | Notes                                |
| ------------------ | ------ | ------------------------------------ |
| `name`             | Text   | Row label in the flower matrix       |
| `peak_months`      | JSON   | Array of `1`–`12`                    |
| `sparse_months`    | JSON   | Array of `1`–`12`                    |
| `downtime_months`  | JSON   | Array of `1`–`12`                    |
| `placement`        | Select | Optional; row order in the table     |

### `wh_flower_copy` (single row)

| Field       | Type   | Notes                         |
| ----------- | ------ | ----------------------------- |
| `body`      | Text   | Pickup / farm notes           |
| `placement` | Select | Optional; if multiple rows    |

## JSON fields in Admin

PocketBase stores JSON as JSON. Example for `months`: `[1,2,3,12]`. The front end also accepts a JSON string and parses it.

## After setup

1. Add your rows in **Admin**.
2. Reload **Calendars** — the status line should show that data loaded from PocketBase.
3. Keep `bookings-config.js` updated as a **fallback** for offline demo or API issues.
