{{-- Smart Report v2 - Urinalysis (UA/PEU). --}} {{-- Mirrors SmartReportService::GetUrinalysisPDF (lines 4930-6023). --}} {{-- Two pages: --}} {{-- page 1 = Color, Clarity, SG, pH, LEU, NIT, PRO, GC, KET, UR, BIL, BLD --}} {{-- page 2 = PC, URBC, EP, CST, CRS, UAM, OT, UCRT, UCAT --}} @php /** @var array $group Group view-model from WebController v2 dispatch */ /** @var \App\Services\SmartReportV2Service $service */ $service = $service ?? app(\App\Services\SmartReportV2Service::class); $Package = $group['package'] ?? ($group['firstPackage'] ?? null); $bg1 = public_path('img/smart-report-pdf/bg/urinalysis/page-1.png'); $bg2 = public_path('img/smart-report-pdf/bg/urinalysis/page-2.png'); $model = $Package ? $service->buildUrinalysisModel($Package) : ['page1' => [], 'page2' => []]; $p1 = $model['page1'] ?? []; $p2 = $model['page2'] ?? []; // LNH meter left-offset (normal 1-9, high 1-3, low 1-3) — used by UR. $meterLeft = function ($type, $move) { $move = (int) round($move); if ($type === 'normal') return 24 + ($move - 1) * 4; if ($type === 'high') return 52 + ($move - 1) * 3; return 22 - ($move - 1) * 3; }; $meterColor = fn ($c) => $c === 'green' ? 'rgb(120,201,38)' : 'rgb(221,52,68)'; // v1 plus/minus label positions reused by LEU/NIT/PRO/KET/GC/BIL/BLD/UR/CST/CRS. // Map a NAME_EN → x-offset (ymm supplied per block). $plusPosX = [ 'Negative' => 25, 'Nil' => 24, 'Normal' => 25, 'Positive' => 40, '0' => 37, '+1' => 34, '+2' => 40, '+3' => 46, '+4' => 52, '+5' => 59, '+6' => 43, '+7' => 46, '+8' => 49, '+9' => 52, '+10' => 55, '+11' => 59, ]; $plusColorMap = [ 'Negative' => 'rgb(120,201,38)', 'Normal' => 'rgb(120,201,38)', 'Nil' => 'rgb(120,201,38)', 'Positive' => 'rgb(228,111,1)', '0' => 'rgb(221,52,68)', '+1' => 'rgb(221,52,68)', '+2' => 'rgb(221,52,68)', '+3' => 'rgb(221,52,68)', '+4' => 'rgb(221,52,68)', '+5' => 'rgb(221,52,68)', '+6' => 'rgb(221,52,68)', '+7' => 'rgb(221,52,68)', '+8' => 'rgb(221,52,68)', '+9' => 'rgb(221,52,68)', '+10' => 'rgb(221,52,68)', '+11' => 'rgb(221,52,68)', ]; // Cell/NH5 meter x-offset for PC/URBC/EP numeric variants. Mirrors the // v1 0.5-step switch (see GetUrinalysisPDF lines 5698-5715 et al.). $cellMeterLeft = function ($result) { $max = 8; $min = 0.5; $rounded = (int) round($result); if ($rounded < $max) $max = round($result, 2); if ($rounded < $min) $max = $min; $map = [ '0.5' => 24, '1' => 24, '1.5' => 27, '2' => 30, '2.5' => 33, '3' => 36, '3.5' => 39, '4' => 42, '4.5' => 45, '5' => 45, '5.5' => 51, '6' => 54, '6.5' => 57, '7' => 60, '7.5' => 60, '8' => 63, ]; $key = (string) $max; return $map[$key] ?? 24; }; @endphp {{-- ═══════════════════════════ PAGE 1 ═══════════════════════════ --}}
@if (is_file($bg1)) @endif @include('pdf.smart_report.components.patient_header', [ 'Order' => $Order, 'Profile' => $Profile, 'firstPackage' => $Package, 'Category' => $group['category_ar'] ?? '', 'Description' => $group['category_description_ar'] ?? '', 'setAdvice' => false, ]) {{-- ── Color ──────────────────────────────────────────────────── --}} @if (!empty($p1['color'])) @php $hex = $p1['color']['hex_code'] ?? '#000000'; $hexTrimmed = ltrim($hex, '#'); $r = hexdec(substr($hexTrimmed, 0, 2)); $g = hexdec(substr($hexTrimmed, 2, 2)); $b = hexdec(substr($hexTrimmed, 4, 2)); @endphp @if (!empty($p1['color']['image']) && is_file($p1['color']['image'])) @endif
{{ $p1['color']['name_ar'] }}
{{ $p1['color']['name_en'] }}
@endif {{-- ── Clarity ────────────────────────────────────────────────── --}} @if (!empty($p1['clarity'])) @php $clarImg = $p1['clarity']['image_url'] ?? ''; @endphp @if ($clarImg === 'success.png' && !empty($p1['clarity']['image']) && is_file($p1['clarity']['image'])) @elseif ($clarImg === 'error.png' && !empty($p1['clarity']['image']) && is_file($p1['clarity']['image'])) @endif
{{ $p1['clarity']['name_ar'] }}
{{ $p1['clarity']['name_en'] }}
@endif {{-- ── SG (Specific Gravity) ──────────────────────────────────── --}} @if (!empty($p1['sg'])) @php $sgValid = $p1['sg']['is_valid'] ?? false; $sgX = $sgValid ? 20 : 24; $sgY = $sgValid ? 139 : 136; $sgColor = $sgValid ? 'rgb(120,201,38)' : 'rgb(221,52,68)'; @endphp
{{ $p1['sg']['name_en'] }}
@if (!empty($p1['sg']['image']) && is_file($p1['sg']['image'])) @endif @if (!empty($p1['sg']['desc_ar']))
{!! $service->isolateLtrRuns($p1['sg']['desc_ar']) !!}
@endif @endif {{-- ── pH ─────────────────────────────────────────────────────── --}} @if (!empty($p1['ph']))
{{ $p1['ph']['name_en'] }}
@if (!empty($p1['ph']['image']) && is_file($p1['ph']['image'])) @endif @if (!empty($p1['ph']['desc_ar']))
{!! $service->isolateLtrRuns($p1['ph']['desc_ar']) !!}
@endif @endif {{-- ── LEU (Leukocytes) ───────────────────────────────────────── --}} @if (!empty($p1['leu'])) @php $leuName = $p1['leu']['name_en'] ?? ''; $leuX = $plusPosX[$leuName] ?? 25; $leuColor = $plusColorMap[$leuName] ?? 'rgb(0,0,0)'; @endphp
{{-- original v1 label output is commented out, kept empty on purpose --}}
@if (!empty($p1['leu']['image']) && is_file($p1['leu']['image'])) @endif @if (!empty($p1['leu']['desc_ar']))
{!! $service->isolateLtrRuns($p1['leu']['desc_ar']) !!}
@endif @endif {{-- ── NIT (Nitrites) ─────────────────────────────────────────── --}} @if (!empty($p1['nit'])) @php $nitName = $p1['nit']['name_en'] ?? ''; $nitX = $plusPosX[$nitName] ?? 28; if ($nitName === 'Negative') $nitX = 28; if ($nitName === 'Positive') $nitX = 40; $nitColor = $plusColorMap[$nitName] ?? 'rgb(0,0,0)'; @endphp @if (!empty($p1['nit']['image']) && is_file($p1['nit']['image'])) @endif @if (!empty($p1['nit']['desc_ar']))
{!! $service->isolateLtrRuns($p1['nit']['desc_ar']) !!}
@endif @endif {{-- ── PRO (Protein) ──────────────────────────────────────────── --}} @if (!empty($p1['pro'])) @php $proName = $p1['pro']['name_en'] ?? ''; $proX = $plusPosX[$proName] ?? 25; $proColor = $plusColorMap[$proName] ?? 'rgb(0,0,0)'; @endphp
{{-- v1 label output is commented out --}}
@if (!empty($p1['pro']['image']) && is_file($p1['pro']['image'])) @endif @if (!empty($p1['pro']['desc_ar']))
{!! $service->isolateLtrRuns($p1['pro']['desc_ar']) !!}
@endif @endif {{-- ── GC (Glucose) ───────────────────────────────────────────── --}} @if (!empty($p1['gc'])) @if (($p1['gc']['variant'] ?? '') === 'option') @php $gcName = $p1['gc']['name_en'] ?? ''; $gcX = $plusPosX[$gcName] ?? 25; $gcColor = $plusColorMap[$gcName] ?? 'rgb(0,0,0)'; @endphp
{{-- v1 label output commented out --}}
@if (!empty($p1['gc']['image']) && is_file($p1['gc']['image'])) @endif @else
{{ $p1['gc']['min_normal'] }}
{{ $p1['gc']['max_normal'] }}
@php // Mirror v1 GC numeric switch: map 0.1..1.5 to an x offset. $gcMaxRaw = round((float) ($p1['gc']['result'] ?? 0), 1); $gcMax = max(0.1, min(1.5, $gcMaxRaw)); $gcMapX = [ '0.1' => 16, '0.2' => 19, '0.3' => 22, '0.4' => 25, '0.5' => 28, '0.6' => 31, '0.7' => 34, '0.8' => 37, '0.9' => 40, '1' => 43, '1.1' => 46, '1.2' => 49, '1.3' => 52, '1.4' => 55, '1.5' => 62, ]; $gcKey = rtrim(rtrim(sprintf('%.1f', $gcMax), '0'), '.'); if ($gcKey === '') $gcKey = '0'; $gcResultX = $gcMapX[$gcKey] ?? 16; $gcResultColor = ($gcMax <= 0.8) ? 'rgb(120,201,38)' : 'rgb(221,52,68)'; @endphp
{{ $p1['gc']['result'] }} {{ $p1['gc']['unit'] ?? '' }}
@if (!empty($p1['gc']['image']) && is_file($p1['gc']['image'])) @endif @endif @if (!empty($p1['gc']['desc_ar']))
{!! $service->isolateLtrRuns($p1['gc']['desc_ar']) !!}
@endif @endif {{-- ── KET (Ketones) ──────────────────────────────────────────── --}} @if (!empty($p1['ket'])) @if (!empty($p1['ket']['name_en'])) @php $ketName = $p1['ket']['name_en'] ?? ''; $ketX = $plusPosX[$ketName] ?? 25; $ketColor = $plusColorMap[$ketName] ?? 'rgb(0,0,0)'; @endphp
{{-- v1 label output commented out --}}
@if (!empty($p1['ket']['image']) && is_file($p1['ket']['image'])) @endif @if (!empty($p1['ket']['desc_ar']))
{!! $service->isolateLtrRuns($p1['ket']['desc_ar']) !!}
@endif @endif @endif {{-- ── UR (Urobilinogen) ──────────────────────────────────────── --}} @if (!empty($p1['ur'])) @if (($p1['ur']['variant'] ?? '') === 'option') @if (!empty($p1['ur']['image']) && is_file($p1['ur']['image'])) @endif @else
{{ $p1['ur']['min_normal'] }}
{{ $p1['ur']['max_normal'] }}
@if (!empty($p1['ur']['image']) && is_file($p1['ur']['image'])) @endif @php $urLeft = $meterLeft($p1['ur']['type'] ?? 'normal', $p1['ur']['move'] ?? 1); @endphp
{{ $p1['ur']['result'] }} {{ $p1['ur']['unit'] ?? '' }}
@endif @if (!empty($p1['ur']['desc_ar']))
{!! $service->isolateLtrRuns($p1['ur']['desc_ar']) !!}
@endif @endif {{-- ── BIL (Bilirubin) ────────────────────────────────────────── --}} @if (!empty($p1['bil'])) @php $bilName = $p1['bil']['name_en'] ?? ''; $bilX = $plusPosX[$bilName] ?? 25; $bilColor = $plusColorMap[$bilName] ?? 'rgb(0,0,0)'; @endphp
{{-- v1 label output commented out --}}
@if (!empty($p1['bil']['image']) && is_file($p1['bil']['image'])) @endif @if (!empty($p1['bil']['desc_ar']))
{!! $service->isolateLtrRuns($p1['bil']['desc_ar']) !!}
@endif @endif {{-- ── BLD (Blood) ────────────────────────────────────────────── --}} @if (!empty($p1['bld'])) @php $bldName = $p1['bld']['name_en'] ?? ''; $bldX = $plusPosX[$bldName] ?? 25; $bldColor = $plusColorMap[$bldName] ?? 'rgb(0,0,0)'; @endphp
{{-- v1 label output commented out --}}
@if (!empty($p1['bld']['image']) && is_file($p1['bld']['image'])) @endif @if (!empty($p1['bld']['desc_ar'])) @php // This is the LAST (bottom) urinalysis row: its description sits // at 255mm, just above the footer/signature band (~266mm). A long // description would overflow into the signatures, so shrink the // font a step for long text and cap the block height so it can // never run into the footer. $bldDescLen = mb_strlen(strip_tags($p1['bld']['desc_ar']), 'UTF-8'); $bldDescFont = $bldDescLen > 260 ? 6 : ($bldDescLen > 170 ? 7 : 8); @endphp
{!! $service->isolateLtrRuns($p1['bld']['desc_ar']) !!}
@endif @endif
{{-- ═══════════════════════════ PAGE 2 ═══════════════════════════ --}}
@if (is_file($bg2)) @endif @include('pdf.smart_report.components.patient_header', [ 'Order' => $Order, 'Profile' => $Profile, 'firstPackage' => $Package, 'Category' => $group['category_ar'] ?? '', 'Description' => $group['category_description_ar'] ?? '', 'setAdvice' => true, ]) {{-- ── PC (Pus Cells) ─────────────────────────────────────────── --}} @if (!empty($p2['pc'])) @if (($p2['pc']['variant'] ?? '') === 'option') @php $pcName = $p2['pc']['name_en'] ?? ''; $pcColor = ($pcName === 'Negative') ? 'rgb(120,201,38)' : (in_array($pcName, ['+1','+2','+3','+4','+5'], true) ? 'rgb(228,111,1)' : 'rgb(221,52,68)'); @endphp
{{ $pcName }} {{ $p2['pc']['unit'] ?? '' }}
@else @php $pcLeft = $cellMeterLeft($p2['pc']['result'] ?? 0); $pcColor = ((float) ($p2['pc']['result'] ?? 0) <= 5) ? 'rgb(120,201,38)' : 'rgb(221,52,68)'; @endphp
{{ $p2['pc']['result'] }} {{ $p2['pc']['unit'] ?? '' }}
@if (!empty($p2['pc']['image']) && is_file($p2['pc']['image'])) @endif @endif @if (!empty($p2['pc']['desc_ar']))
{!! $service->isolateLtrRuns($p2['pc']['desc_ar']) !!}
@endif @endif {{-- ── URBC (Urinary RBC) ─────────────────────────────────────── --}} @if (!empty($p2['urbc'])) @if (($p2['urbc']['variant'] ?? '') === 'option') @php $rbcName = $p2['urbc']['name_en'] ?? ''; $rbcColor = ($rbcName === 'Negative') ? 'rgb(120,201,38)' : (in_array($rbcName, ['+1','+2','+3','+4','+5'], true) ? 'rgb(228,111,1)' : 'rgb(221,52,68)'); @endphp
{{ $rbcName }} {{ $p2['urbc']['unit'] ?? '' }}
@else @php $rbcLeft = $cellMeterLeft($p2['urbc']['result'] ?? 0); $rbcColor = ((float) ($p2['urbc']['result'] ?? 0) <= 5) ? 'rgb(120,201,38)' : 'rgb(221,52,68)'; @endphp
{{ $p2['urbc']['result'] }} {{ $p2['urbc']['unit'] ?? '' }}
@if (!empty($p2['urbc']['image']) && is_file($p2['urbc']['image'])) @endif @endif @if (!empty($p2['urbc']['desc_ar']))
{!! $service->isolateLtrRuns($p2['urbc']['desc_ar']) !!}
@endif @endif {{-- ── EP (Epithelial Cells) ──────────────────────────────────── --}} @if (!empty($p2['ep'])) @php $epVariant = $p2['ep']['variant'] ?? ''; @endphp @if ($epVariant === 'cstparts') @if (!empty($p2['ep']['image']) && is_file($p2['ep']['image'])) @endif @elseif ($epVariant === 'all-normal') @php $epName = $p2['ep']['name_en'] ?? ''; $epX = $plusPosX[$epName] ?? 24; $epColor = ($epName === 'Nil' || $epName === 'Negative') ? 'rgb(120,201,38)' : ($plusColorMap[$epName] ?? 'rgb(120,201,38)'); @endphp
{{-- v1 label output commented out --}}
@if (!empty($p2['ep']['image']) && is_file($p2['ep']['image'])) @endif @elseif ($epVariant === 'numeric') @php $epLeft = $cellMeterLeft($p2['ep']['result'] ?? 0); $epRColor = ((float) ($p2['ep']['result'] ?? 0) <= 5) ? 'rgb(120,201,38)' : 'rgb(221,52,68)'; @endphp
{{ $p2['ep']['result'] }} {{ $p2['ep']['unit'] ?? '' }}
@if (!empty($p2['ep']['image']) && is_file($p2['ep']['image'])) @endif @endif @if (!empty($p2['ep']['desc_ar']))
{!! $service->isolateLtrRuns($p2['ep']['desc_ar']) !!}
@endif @endif {{-- ── CST (Casts) ────────────────────────────────────────────── --}} @if (!empty($p2['cst'])) @if (($p2['cst']['variant'] ?? '') === 'label') @php $cstName = $p2['cst']['name_en'] ?? ''; $cstX = $plusPosX[$cstName] ?? 24; $cstColor = $plusColorMap[$cstName] ?? 'rgb(0,0,0)'; @endphp
{{-- v1 label output commented out --}}
@if (!empty($p2['cst']['image']) && is_file($p2['cst']['image'])) @endif @else @if (!empty($p2['cst']['unseen']) && is_file($p2['cst']['unseen'])) @endif @if (!empty($p2['cst']['seen']) && is_file($p2['cst']['seen'])) @endif @endif @if (!empty($p2['cst']['desc_ar']))
{!! $service->isolateLtrRuns($p2['cst']['desc_ar']) !!}
@endif @endif {{-- ── CRS (Crystals) ─────────────────────────────────────────── --}} @if (!empty($p2['crs'])) @if (($p2['crs']['variant'] ?? '') === 'label') @php $crsName = $p2['crs']['name_en'] ?? ''; $crsX = $plusPosX[$crsName] ?? 24; if ($crsName === '+4') $crsX = 55; $crsColor = $plusColorMap[$crsName] ?? 'rgb(0,0,0)'; @endphp
{{-- v1 label output commented out --}}
@if (!empty($p2['crs']['image']) && is_file($p2['crs']['image'])) @endif @else @if (!empty($p2['crs']['unseen']) && is_file($p2['crs']['unseen'])) @endif @if (!empty($p2['crs']['seen']) && is_file($p2['crs']['seen'])) @endif @endif @if (!empty($p2['crs']['desc_ar']))
{!! $service->isolateLtrRuns($p2['crs']['desc_ar']) !!}
@endif @endif {{-- ── UCRT (Crystal Types) ───────────────────────────────────── --}} @if (!empty($p2['ucrt']) && !empty($p2['ucrt']['items']))
{{ $p2['ucrt']['name_ar'] }}
{{ $p2['ucrt']['name_en'] }}
{{ $p2['ucrt']['joined'] }}
@endif {{-- ── UCAT (Cast Types) ──────────────────────────────────────── --}} @if (!empty($p2['ucat']) && !empty($p2['ucat']['items']))
{{ $p2['ucat']['name_ar'] }}
{{ $p2['ucat']['name_en'] }}
{{ $p2['ucat']['joined'] }}
@endif {{-- ── UAM (Amorphous Materials) ──────────────────────────────── --}} @if (!empty($p2['uam']) && !empty($p2['uam']['items']))
{{ $p2['uam']['name_ar'] }}
{{ $p2['uam']['name_en'] }}
{{ $p2['uam']['joined'] }}
@endif {{-- ── OT (Others) ────────────────────────────────────────────── --}} @if (!empty($p2['ot']) && !empty($p2['ot']['items']))
{{ $p2['ot']['name_ar'] }}
{{ $p2['ot']['name_en'] }}
{{ $p2['ot']['joined'] }}
@endif