{{-- The Follow Up History timeline (CR-6 §5.3, §5.5). ONE partial for two screens. view-inquiry.html draws it in the right-hand card and follow-up.html draws it under the option list, and the two wireframes' markup differs only in the class names of the inner text (`.fu-title`/`.fu-meta`/`.fu-note` versus `.fu-info-title`/`.fu-info-meta`/`.fu-info-note`) and in the dot's connector (`.fu-line` versus `.fu-dot-line`). Those are two names for one thing, so the view-inquiry set is used on both — it is the richer of the two (it is the only one that draws the `.fu-action-detail` block and the badge strip) and CR-6 §5.5 asks for the two screens to share a partial by name. Props (passed via @include): $inquiry the inquiry, for the pinned hold entry below $entries its follow-ups, newest first, with `creator`, `assignee` and `completedBy` already loaded — this partial runs no queries of its own, so a caller that forgot to eager-load gets an N+1 that the show page's query-count test catches rather than a silent one ## The two CR-10 states Every entry now reads as one of three things, and the third is the one CR-10 added: pending the task has not been done (App\Models\FollowUp::isPending(), the mirror of the scope the dashboard queries with). A `badge badge-warning` "Pending" and — for a viewer the policy lets act — the same ✓ the dashboard card offers, through the shared partials/task-action.blade.php. completed `completed_at` is set: a meta line saying when and by whom, plus the conclusion if one was recorded. "By whom" is omitted rather than guessed when `completed_by` is null, which it legitimately is for the booking-confirm auto-complete and for a user since deleted. neither a document entry saved WITH a date, and every Not Interested. Those were never tasks, so they render exactly as they did before CR-10 and gain no badge, no button and no meta line. **The Pending badge and its ✓ stay visible whatever the inquiry's status is** (CR-10 §3.5). Not Interested drops a task off the DASHBOARD and writes nothing; the journey is still the journey, and a timeline that hid entries on a closed inquiry would be hiding the reason it closed. ## The pinned Tentative Booking entry CR-6 §5.3 asks the timeline to carry "unit + hold-until for holds", and view-inquiry.html draws exactly such an entry (its Entry 4). But a hold is NOT a `follow_ups` row — §5.4 says the hold modal "updates the two inquiry columns only", and FollowUpType has no case for one. The two statements only reconcile one way: the hold is rendered from the inquiry's own columns, as a pinned entry at the top of the list, and it appears only while the inquiry actually holds a unit. That is an interpretation, and it is written down here rather than resolved silently. It reads correctly: a live hold *is* the most recent thing that happened to the inquiry, and the alternative — the CR's own detail chip having nothing to attach to — would have been a requirement quietly dropped. ## Escaping Every value here is a user-supplied string (a location somebody typed, a reason somebody typed, a customer's assignee's name) and every one of them goes out through `{{ }}`. There is no `{!! !!}` in this file and no value reaches a script: nothing here is a rawColumn, so Blade's escaping is the whole of the defence and it is sufficient. --}} @php /** @var \App\Models\Inquiry $inquiry */ /** @var iterable<\App\Models\FollowUp> $entries */ $dateFormat = config('nrems.date_format'); $hasHold = $inquiry->holdsAUnit(); $isEmpty = $hasHold === false && count($entries) === 0; // Wire every entry back to the inquiry it already belongs to, BEFORE // anything asks the gate about it. // // FollowUpPolicy::complete() reads `$followUp->inquiry` for the two // inquiry-column branches of its row scope, and an entry loaded through // `$inquiry->followUps` does not carry the INVERSE relation. Without this // line an ordinary in-scope viewer — an inquiry's own creator, who holds no // `follow_ups.manage` and so cannot short-circuit the policy at its first // branch — would fire one `select * from inquiries` per pending entry, and // the "runs no queries" promise above would be false for exactly the user // this feature was written for. An Admin never noticed, because the // permission check answers before `inquiry` is ever touched. // // setRelation() is pure memory: it hands over the model this partial was // already given rather than fetching one. It is done here rather than in // the two controllers precisely because it is not an eager load — there is // nothing to load — and because a third caller cannot then forget it. foreach ($entries as $entry) { $entry->setRelation('inquiry', $inquiry); } @endphp
{{ __('inquiries.history.empty') }}
@endif