{{-- The Documents tab's table — docs/wireframes-v12/edit-booking.html (~lines 356-372). Shared by the edit and the show screens because it is a *read* of the booking's documents and not a form field: the twin rule of recipe §9 governs the create/edit form pair, and this panel is identical on both screens by definition — the same rows, the same actions, the same permissions. @include('bookings.partials.documents', ['booking' => $booking]) The **Name** column is whose document the row is — the main customer or the co-owner picked in the upload screen's Co-Applicant select, which `customer_docs.customer_id` has always recorded and the tab simply never showed (CR-11). A client addition beyond the wireframe's table, and the name alone: main customer and co-owner render identically, because the client asked for the person and not for a role label. ## What each action is * **View** streams the file back as an attachment (`bookings.documents.download`). A link and not a form, because it reads and nothing else; the route binding is scoped to the booking, so a document id from another booking is a 404 from the router. * **Delete** is a plain button that opens the shared confirmation dialog and, on Confirm, sends the DELETE by ajax — never a link, because a GET that destroys data would be fired by any crawler or prefetch. It was a `
` with a `confirm()` guard until CR-15.3 item H2. The client's instruction is verbatim: *"Same this delete popup implement in documents tab inside booking edit and view screen and don't reload page once delete just remove that row from table and show success message as a toaster message getting error then show error toaster."* The route, the gate and the controller method are unchanged — only the answer shape is new (`ajax() && wantsJson()`), so a browser with no Javascript still has nothing here to press and the server still refuses exactly what it refused before. The two `data-role` markers below are what nrems-document-delete.js acts on: `document-row` is the `` it removes, `document-table` is where it looks to decide whether the table is now empty, and `data-empty` carries the very sentence the `@if` above renders so the two states cannot drift. ## The three gates moved in CR-15 (decision D3) Upload was `bookings.edit`, Download `bookings.view` and Delete `bookings.delete`; they are now `customer_documents.create`, `.view` and `.delete`. The client's instruction is one permission scheme for documents everywhere, and this tab writes the same rows the standalone Customer Documents module writes. **The tab itself is not gated on any of the three** — it is part of the booking edit and show screens, which keep their own `bookings.*` gates — so a holder of `bookings.view` alone still reads the table and simply gets no controls on it. See BookingDocumentController's docblock, which carries the whole change. A **cancelled** booking is view-only (CR-8 §3.1): the Upload button and the per-row Delete disappear, and the downloads stay. Read-only does not mean unreadable. Every value here is escaped: the original filename is the one genuinely attacker-supplied string on the page and it goes out through `{{ }}` like everything else, including into the delete button's `data-name`, which the dialog then writes with `textContent`. ## What the including screen must also render `customer-documents/partials/delete-modal.blade.php`, at the END of its content section — outside every `.card`, for the clipping reason that partial's own header records. bookings/edit.blade.php and bookings/show.blade.php both do. Without it the delete buttons here do nothing at all, which is the honest failure for a missing dialog: no confirmation, so no deletion. --}} @php /** @var \App\Models\Booking $booking */ $cancelled = $booking->isCancelled(); $emptyMessage = 'No documents have been uploaded for this booking yet.'; @endphp
Documents
@can('customer_documents.create') @unless ($cancelled) Upload Document @endunless @endcan
@if ($booking->documents->isEmpty())

{{ $emptyMessage }}

@else
@foreach ($booking->documents as $document) @endforeach
Document Type Name File Name Uploaded By Date Actions
{{ $document->docType?->name ?? '—' }} {{ $document->customer?->name ?? '—' }} {{ $document->original_name }} {{ $document->creator?->name ?? '—' }} {{ $document->created_at?->format('d M Y') ?? '—' }}
@can('customer_documents.view') @endcan @can('customer_documents.delete') @unless ($cancelled) @endunless @endcan
@endif