@extends('layouts.app') @section('title', __('portal::messages.review.title')) @php /* | The filter actually in force. | | An empty status means pending — the controller's default, because this | screen exists to be emptied. The cards and the dropdown both have to show | that, or the page would open with nothing selected while plainly being | filtered. */ $current = $filters['status'] !== '' ? $filters['status'] : 'pending'; // Keeps the patient scope on every link out of this screen. $carry = fn (string $status): array => array_filter([ 'status' => $status, 'patient' => $filters['patient'], ]); @endphp @section('content') {{-- ── Page head ──────────────────────────────────────────────────────── --}}

{{ __('portal::messages.review.title') }}

{{-- Says whose queue this is. Reviewing the wrong patient's file is the one mistake this screen can make, so the scope is stated in the same breath as the title rather than left to a filter. --}} @if ($filters['patient'] !== '')

{{ __('portal::messages.review.scoped', [ 'patient' => $only?->name ?? __('portal::messages.review.unknown_patient'), ]) }}

@else

{{ __('portal::messages.review.subtitle') }}

@endif
@if ($filters['patient'] !== '') {{ __('portal::messages.review.show_all') }} @endif
{{-- ── Status: the filter and what it is filtering ────────────────────── --}}
{{-- Carried through the filter, or changing the status would quietly drop the patient and hand back the whole queue. --}}
{{-- The counts, and the filter said a second way. Each card is a link to its own status rather than a decorative figure: the number and the way to act on it are the same thing, and a reviewer who sees "3 declined" wants to read those three. Counts follow the patient scope above — cards counted over the whole table beside a list showing one patient would disagree, and the bigger numbers would be the half people believed. --}}
@foreach ([ ['status' => 'pending', 'tone' => 'violet', 'icon' => 'bi-clock-history', 'count' => $tally['pending'], 'label' => __('portal::messages.statuses.pending')], ['status' => 'accepted', 'tone' => 'green', 'icon' => 'bi-check-circle', 'count' => $tally['accepted'], 'label' => __('portal::messages.statuses.accepted')], ['status' => 'rejected', 'tone' => 'red', 'icon' => 'bi-x-circle', 'count' => $tally['rejected'], 'label' => __('portal::messages.statuses.rejected')], ['status' => 'all', 'tone' => 'blue', 'icon' => 'bi-file-earmark-text', 'count' => $tally['total'], 'label' => __('portal::messages.review.total')], ] as $card) @endforeach
{{-- ── The queue ──────────────────────────────────────────────────────── --}}
@if ($uploads->isEmpty())
{{-- Two different nothings. An empty pending queue is the goal and gets the standing instructions; an empty Declined tab is just a filter that matched nothing, and those instructions would be noise. --}} @if ($current === 'pending')

{{ __('portal::messages.review.empty_title') }}

{{ __('portal::messages.review.empty_text') }}

@else

{{ __('portal::messages.review.empty_filtered_title') }}

{{ __('portal::messages.review.empty_filtered_text') }}

@endif
@else
@foreach ($uploads as $upload) @php $patient = $patients[$upload->patient_id] ?? null; $mime = (string) $upload->mime_type; $tile = match (true) { $mime === 'application/pdf' => ['px-uploads__tile--pdf', 'bi-file-earmark-pdf'], str_starts_with($mime, 'image/') => ['px-uploads__tile--image', 'bi-file-earmark-image'], default => ['', 'bi-file-earmark'], }; // Sent since yesterday and still untouched: worth // marking, because it is the row most likely to be // the one somebody has just been telephoned about. $isNew = $upload->status->isPending() && $upload->created_at?->gt(now()->subDay()); @endphp {{-- Marked as a row so the live region can count it: this listing has no to count instead. --}}
{{-- Patient --}}
{{ $patient?->name ?? '—' }} {{ $patient?->mrn }} @if ($isNew) {{ __('portal::messages.review.new_upload') }} @endif
{{-- File details --}}
{{ $upload->original_name }} {{ $upload->readableSize() }} · {{ $upload->created_at?->format('d M Y, H:i') }} @if ($upload->patient_note) “{{ $upload->patient_note }}” @endif
{{-- Status --}}
{{ $upload->status->label() }} @if ($upload->rejection_reason) {{ $upload->rejection_reason }} @elseif ($upload->reviewedBy) {{ $upload->reviewedBy->name }} @endif
{{-- Actions --}}
@if ($upload->status->isPending()) {{-- Name it, read it, then decide. The link sits inside the accept form so the four controls are one flex row in the order the work happens; an anchor is flow content and submits nothing. --}}
@csrf {{-- The name this file will carry in the record, editable before it goes in — "2928.pdf" tells a clinician nothing a year from now. --}}
{{-- Its own tab: the decision is made with the queue still on screen, and a streamed file is not something the page swapper can put in this layout. --}} {{ __('portal::messages.review.open') }}
{{-- Two gates on a decline: a reason, which the endpoint requires, and then the confirmation — the file is deleted and the patient may well ask why. --}}
{{ __('portal::messages.review.reject') }}
@csrf
@else {{ $upload->reviewed_at?->format('d M Y') }} @endif
@endforeach
{{ trans_choice('portal::messages.review.showing', $uploads->total(), [ 'shown' => number_format($uploads->count()), 'total' => number_format($uploads->total()), ]) }} @if ($uploads->hasPages())
{{ $uploads->links() }}
@endif
@endif
@endsection