{{-- New Booking — docs/wireframes-v12/new-booking.html (the card at ~lines 105-353: six form sections and the footer). ## Shape ONE `.card`. Inside it, a `.form-section` per heading — each with its `.form-section-title` and the wireframe's own icon — and a `.card-footer` at the bottom. Fields are laid out by v12's `.form-row.form-row-2/-3` grids, not by Bootstrap columns, which is why no field carries a `group-class`: the row owns the columns and `.form-group` owns its own margin. ## The twin rule (recipe §9) This file and bookings/edit.blade.php are twins. Every field is written out in both, and neither includes a shared form partial. **A field added, removed or renamed here must be mirrored in edit.blade.php in the same commit.** The one thing they do share is bookings/partials/co-owner-block.blade.php, and that partial's header says why a repeater row is the exception. ### What this screen has that its twin does not * it posts to `bookings.store` as a POST, where the twin PUTs to `bookings.update` and therefore carries a `_method` field; * it is a single card, where the twin is a tab strip over three panels (Basic Details / Documents / History) per edit-booking.html; * Booking Information is ordered entity type / date / inquiry, which is this wireframe's order; the twin's is date / inquiry / entity type, which is that one's; * its footer submits "Confirm Booking"; the twin's says "Update Booking" (CR-9 §4 — the draft, and the `action` field that chose between the two buttons, are both gone); * every control renders empty — unless the user arrived from an inquiry's "Proceed to Booking" button, in which case the server has prefilled six of them (CR-8 §3.5); * the Co-Owner Details section starts with **no blocks at all** (client: "Default Co-Owner Details blank"), where the twin renders one per stored co-owner. ## Deliberate differences from the wireframe * **Occupation is a select, not a free-text input** (decision D5). new-booking.html draws a text box for the main customer and a select for every co-owner, and edit-booking.html draws a select for both; the select wins, for data sanity and because the Occupation enum already exists and the inquiry module already collects it that way. * **An Assigned Sales Person row is added** (decision D6). Only edit-booking.html draws it; a field that can be set on one twin and not the other is exactly the drift the twin rule exists to stop, and a booking with no salesperson until somebody edits it is not a state the client asked for. * **One "Through its …" block, not six.** The wireframe writes all six out with `display:none` and swaps them in JS. One block retitled from a map is the same behaviour with one copy of the markup — and the map is rendered from Booking::THROUGH_MAP, so the block's title, the server's required-when rule and the detail screen's row cannot disagree. * **The wireframe's trailing script is broken** (new-booking.html:360-374 has an unbalanced `);` and a dangling function body). It is a wireframe bug; the behaviour it was reaching for is in nrems-booking-form.js. ## No lang file (CR-8 §0.1) Every string on this screen — labels, placeholders, section titles, the JS module's own strings — is written here, on the client's instruction. Do not extract them. --}} @extends('layouts.app') @section('title', 'New Booking') @section('breadcrumbs') @endsection @section('content') @php $occupations = \App\Enums\Occupation::options(); // The "Through its …" map, keyed by booking type ID for the client and // built from the name-keyed constant. Rendered from Booking::THROUGH_MAP // so the block's title, the server's required-when rule and the detail // screen's row all read the same words — see that constant on why the // canonical key is the name and not the id. $throughMap = []; foreach ($bookingTypes as $typeId => $typeName) { if (isset(\App\Models\Booking::THROUGH_MAP[$typeName])) { $throughMap[$typeId] = [ 'title' => \App\Models\Booking::THROUGH_MAP[$typeName], 'placeholder' => \App\Models\Booking::THROUGH_PLACEHOLDERS[$typeName] ?? '', ]; } } // The block's state on a freshly drawn page is decided HERE, not by the // module: no `change` event fires on page load, so the script never runs // there. The lesson CR-5 §15.4 recorded the hard way. $selectedType = old('booking_type_id', $booking->booking_type_id); $through = $throughMap[$selectedType] ?? null; // Co-owner blocks re-render server-side from old input on a rejected // submit (CR-8 §5) — a blade loop, not a JS restore pass, for the same // reason. A fresh create screen has none: the client's instruction is // that the section starts blank. $coOwnerRows = is_array(old('co_owners')) ? old('co_owners') : []; @endphp {{-- The module's client config, in three JSON data-attributes plus two scalars — the shape nrems-inquiry-form.js established. The script holds no copy of any wording, and the only url it builds is this template with the project id substituted. --}}
{{-- ===== 1. Booking Information ===== --}}
Booking Information
{{-- Written out rather than because the control needs the wireframe's helper line under it, and the select component has no hint prop — 's own docblock invites this use, and the markup below is the component's, class for class. --}}
{{-- One field in a two-column row, exactly as edit-booking.html draws it: the control keeps its half-width and the row keeps its grid. --}}
{{-- ===== 2. Booking Details (the main customer) ===== --}}
Booking Details
{{-- THREE cells, not two: new-booking.html:145 opens this section with `form-row form-row-3` and puts Common Name, the "Through its …" panel and Occupation side by side in it. The panel is a cell of the grid, not a full-bleed block between two rows — which is what makes it read as belonging to the name beside it rather than to the whole section. --}}
{{-- The one "Through its …" block. Server-rendered into the right state; retitled and shown/hidden by the module when the entity type changes. --}}
{{-- ===== 3. Co-Owner Details ===== --}}
Co-Owner Details
{{-- Starts EMPTY on a fresh screen — the client's instruction ("Default Co-Owner Details blank"). Only a rejected submit puts blocks here, and it puts back exactly what the user typed. --}}
@foreach ($coOwnerRows as $index => $row) @include('bookings.partials.co-owner-block', [ 'index' => $index, 'row' => is_array($row) ? $row : [], 'position' => $loop->iteration, 'occupations' => $occupations, ]) @endforeach
{{-- The wireframe's dashed note, always present. --}}
Click "Add More Co-Owner" to add additional co-owners.
{{-- The block the module clones. `__INDEX__` is replaced in every name, id and label `for` as it is cloned; a