{{-- Follow-up reminder bell. Included from partials.topbar, so it appears on every screen in both layouts. It is always rendered — an empty bell is a place a person can learn, whereas a control that appears only once something is wrong is one nobody looks for. When the account has follow-ups switched off the panel says so and offers the switch rather than showing a permanently empty list. The first paint is rendered server-side from the same two facts the poller reads, so the count is right immediately rather than a second later; the poller in partials.follow-up-notifications takes over from there. A Bootstrap dropdown rather than a bespoke panel: both layouts already load the Bootstrap bundle, and a reminder is not worth new CSS. --}} @php // Same shape as the overdue count in partials.sidebar, and wrapped for the // same reason: the topbar must render on an install that has not run the // follow-up migrations. $fuEnabled = false; $fuCount = 0; $fuOverdue = 0; $fuIsAdmin = Auth::check() && Auth::user()->auth_id == 0; try { $fuOwnerId = $fuIsAdmin ? (int) Auth::id() : (int) Auth::user()->auth_id; $fuSettings = \App\Models\FollowUpSetting::resolveFor($fuOwnerId); $fuEnabled = $fuSettings !== null && $fuSettings->enabled; if ($fuEnabled) { $fuMailboxes = $fuIsAdmin ? \App\Models\User::where('id', $fuOwnerId)->orWhere('auth_id', $fuOwnerId)->pluck('id')->all() : [Auth::id()]; // The bell's horizon is the account's own lead time, exactly as the // endpoint's is, so the first paint and the first poll agree. $fuHorizon = now()->addHours(max(1, (int) $fuSettings->reminder_lead_hours)); $fuCount = \App\Models\FollowUp::query() ->open() ->whereIn('user_id', $fuMailboxes) ->whereNotNull('due_at') ->where('due_at', '<=', $fuHorizon) ->count(); $fuOverdue = \App\Models\FollowUp::query() ->whereIn('user_id', $fuMailboxes) ->overdue() ->count(); } } catch (\Throwable $e) { $fuEnabled = false; } $fuTone = $fuOverdue > 0 ? 'danger' : 'warning'; @endphp