342 lines
15 KiB
PHP
342 lines
15 KiB
PHP
@extends('layouts.vertical-individual', ['page_title' => $title ?? 'Titans Brand Units Report'])
|
|
|
|
@section('css')
|
|
<style>
|
|
body .account-pages > .container {
|
|
max-width: 100%;
|
|
padding-left: 0;
|
|
padding-right: 0;
|
|
}
|
|
|
|
.titans-brand-units-report-page .row {
|
|
--bs-gutter-x: 0;
|
|
margin-left: 0;
|
|
margin-right: 0;
|
|
}
|
|
|
|
.titans-brand-units-report-page .card {
|
|
border-left: 0;
|
|
border-right: 0;
|
|
border-radius: 0;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.titans-brand-units-report-page .card-body {
|
|
padding-left: 0;
|
|
padding-right: 0;
|
|
}
|
|
|
|
.titans-brand-units-report-page .page-header {
|
|
padding-left: 12px;
|
|
padding-right: 12px;
|
|
}
|
|
|
|
.titans-brand-units-report-table th,
|
|
.titans-brand-units-report-table td {
|
|
white-space: nowrap;
|
|
vertical-align: middle;
|
|
border: 1px solid #dee2e6;
|
|
}
|
|
|
|
.titans-brand-units-report-table thead th {
|
|
text-align: center;
|
|
background: #f8f9fa;
|
|
}
|
|
|
|
.titans-brand-units-report-table .doctor-col {
|
|
position: sticky;
|
|
left: 0;
|
|
z-index: 2;
|
|
background: #fff;
|
|
min-width: 200px;
|
|
max-width: 40vw;
|
|
white-space: normal;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.titans-brand-units-report-table .meta-col {
|
|
min-width: 120px;
|
|
}
|
|
|
|
.titans-brand-units-report-table thead .doctor-col {
|
|
z-index: 3;
|
|
background: #f8f9fa;
|
|
}
|
|
|
|
.titans-brand-units-report-scroll {
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.titans-brand-units-report-pagination {
|
|
padding: 12px 16px;
|
|
border-top: 1px solid #dee2e6;
|
|
background: #fff;
|
|
position: sticky;
|
|
bottom: 0;
|
|
z-index: 5;
|
|
}
|
|
|
|
.titans-brand-units-report-pagination-top {
|
|
border-top: 0;
|
|
border-bottom: 1px solid #dee2e6;
|
|
}
|
|
|
|
.titans-brand-units-report-pagination .pagination {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
#titans-brand-units-report-loader {
|
|
align-items: center;
|
|
background: rgba(255, 255, 255, 0.85);
|
|
display: none;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
height: 100%;
|
|
justify-content: center;
|
|
left: 0;
|
|
position: fixed;
|
|
top: 0;
|
|
width: 100%;
|
|
z-index: 9999;
|
|
}
|
|
|
|
#titans-brand-units-report-loader.is-visible {
|
|
display: flex;
|
|
}
|
|
|
|
#titans-brand-units-report-loader img {
|
|
height: 64px;
|
|
width: 64px;
|
|
}
|
|
</style>
|
|
@endsection
|
|
|
|
@section('content')
|
|
@php
|
|
$pagination = $pagination ?? (object) ['page' => 1, 'per_page' => 50, 'total' => 0, 'total_pages' => 0];
|
|
$currentPage = (int) ($pagination->page ?? 1);
|
|
$totalPages = (int) ($pagination->total_pages ?? 0);
|
|
$perPage = (int) ($perPage ?? $pagination->per_page ?? 50);
|
|
$totalDoctors = (int) ($pagination->total ?? 0);
|
|
$search = trim((string) ($search ?? ''));
|
|
$pageQuery = http_build_query(array_filter([
|
|
'per_page' => $perPage,
|
|
'search' => $search !== '' ? $search : null,
|
|
'token' => !empty($token ?? '') ? $token : null,
|
|
], fn ($value) => $value !== null && $value !== ''));
|
|
$pageBase = $base_url . '/report?' . $pageQuery;
|
|
$metaColumnCount = 8;
|
|
$brandGroups = $brandGroups ?? [];
|
|
$months = $months ?? [];
|
|
$monthCount = count($months);
|
|
|
|
$formatShortMonth = function ($month) {
|
|
$key = is_object($month) ? ($month->key ?? '') : (string) $month;
|
|
if (!preg_match('/^(\d{4})-(\d{2})$/', $key, $matches)) {
|
|
return is_object($month) ? ($month->label ?? $key) : $key;
|
|
}
|
|
$ts = strtotime($key . '-01 UTC');
|
|
return date('M', $ts) . "'" . substr($matches[1], -2);
|
|
};
|
|
|
|
$metricColumnCount = 0;
|
|
foreach ($brandGroups as $group) {
|
|
$metricColumnCount += count($group->brands ?? []) * $monthCount;
|
|
}
|
|
@endphp
|
|
<div id="titans-brand-units-report-loader" class="is-visible" aria-live="polite" aria-busy="true">
|
|
<img src="/images/loader-large.gif" alt="">
|
|
<span class="text-muted">Loading report...</span>
|
|
</div>
|
|
<div class="titans-brand-units-report-page">
|
|
<div class="row mb-3 page-header">
|
|
<div class="col-md-6">
|
|
<h4 class="page-title">{{ $title }}</h4>
|
|
<p class="text-muted mb-0">Doctor units from April 2026 through the current month.</p>
|
|
@if ($totalDoctors > 0)
|
|
<p class="text-muted mb-0 small">
|
|
Showing {{ count($doctors) }} of {{ number_format($totalDoctors) }} doctors
|
|
(page {{ $currentPage }} of {{ max($totalPages, 1) }})
|
|
@if ($search !== '')
|
|
matching "{{ $search }}"
|
|
@endif
|
|
</p>
|
|
@elseif ($search !== '')
|
|
<p class="text-muted mb-0 small">No doctors found matching "{{ $search }}".</p>
|
|
@endif
|
|
</div>
|
|
<div class="col-md-6 d-flex justify-content-end align-items-center gap-2 flex-wrap">
|
|
<form method="get" action="{{ $base_url }}/report" id="titans-search-form" class="d-flex align-items-center gap-2 titans-brand-units-report-nav-form">
|
|
<input type="hidden" name="page" value="1">
|
|
<input type="hidden" name="per_page" value="{{ $perPage }}">
|
|
@if (!empty($token ?? ''))
|
|
<input type="hidden" name="token" value="{{ $token }}">
|
|
@endif
|
|
<label for="titans-report-search" class="form-label mb-0 small text-muted">Search</label>
|
|
<input type="search" name="search" id="titans-report-search" class="form-control form-control-sm" style="width: 220px;" value="{{ $search }}" placeholder="Doctor, MSL, user, zone...">
|
|
<button type="submit" class="btn btn-outline-secondary btn-sm">Apply</button>
|
|
@if ($search !== '')
|
|
<a href="{{ $base_url }}/report?{{ http_build_query(array_filter(['per_page' => $perPage, 'token' => !empty($token ?? '') ? $token : null])) }}" class="btn btn-link btn-sm text-decoration-none">Clear</a>
|
|
@endif
|
|
</form>
|
|
<form method="get" action="{{ $base_url }}/report" id="titans-per-page-form" class="d-flex align-items-center gap-2 titans-brand-units-report-nav-form">
|
|
<input type="hidden" name="page" value="1">
|
|
@if (!empty($token ?? ''))
|
|
<input type="hidden" name="token" value="{{ $token }}">
|
|
@endif
|
|
@if ($search !== '')
|
|
<input type="hidden" name="search" value="{{ $search }}">
|
|
@endif
|
|
<label for="per_page" class="form-label mb-0 small text-muted">Per page</label>
|
|
<select name="per_page" id="per_page" class="form-select form-select-sm" style="width: auto;" onchange="this.form.submit()">
|
|
@foreach ([25, 50, 100, 200] as $size)
|
|
<option value="{{ $size }}"@if($perPage === $size) selected @endif>{{ $size }}</option>
|
|
@endforeach
|
|
</select>
|
|
</form>
|
|
<a href="{{ $base_url }}/export?{{ http_build_query(array_filter(['search' => $search !== '' ? $search : null, 'token' => !empty($token ?? '') ? $token : null])) }}" class="btn btn-dark btn-sm">
|
|
Export All
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
@include('titansbrandunitsreport._pagination', ['paginationPosition' => 'titans-brand-units-report-pagination-top'])
|
|
<div class="card-body titans-brand-units-report-scroll">
|
|
<table class="table table-sm table-bordered titans-brand-units-report-table mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th class="doctor-col" rowspan="3">Doctor Name</th>
|
|
<th class="meta-col" rowspan="3">MSL Code</th>
|
|
<th class="meta-col" rowspan="3">User</th>
|
|
<th class="meta-col" rowspan="3">Employee Code</th>
|
|
<th class="meta-col" rowspan="3">Zone</th>
|
|
<th class="meta-col" rowspan="3">Region</th>
|
|
<th class="meta-col" rowspan="3">Area</th>
|
|
<th class="meta-col" rowspan="3">Territory</th>
|
|
@foreach ($brandGroups as $group)
|
|
<th colspan="{{ count($group->brands ?? []) * max($monthCount, 1) }}">{{ $group->name }}</th>
|
|
@endforeach
|
|
</tr>
|
|
<tr>
|
|
@foreach ($brandGroups as $group)
|
|
@foreach ($group->brands ?? [] as $brand)
|
|
<th colspan="{{ max($monthCount, 1) }}">{{ $brand->name }}</th>
|
|
@endforeach
|
|
@endforeach
|
|
</tr>
|
|
<tr>
|
|
@foreach ($brandGroups as $group)
|
|
@foreach ($group->brands ?? [] as $brand)
|
|
@foreach ($months as $month)
|
|
<th>{{ $formatShortMonth($month) }}</th>
|
|
@endforeach
|
|
@endforeach
|
|
@endforeach
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@forelse ($doctors as $doctor)
|
|
<tr>
|
|
<td class="doctor-col">{{ $doctor->name }}</td>
|
|
<td class="meta-col">{{ $doctor->msl_code ?? '-' }}</td>
|
|
<td class="meta-col">{{ $doctor->user ?? '-' }}</td>
|
|
<td class="meta-col">{{ $doctor->employee_code ?? '-' }}</td>
|
|
<td class="meta-col">{{ $doctor->zone ?? '-' }}</td>
|
|
<td class="meta-col">{{ $doctor->region ?? '-' }}</td>
|
|
<td class="meta-col">{{ $doctor->area ?? '-' }}</td>
|
|
<td class="meta-col">{{ $doctor->territory ?? '-' }}</td>
|
|
@foreach ($brandGroups as $group)
|
|
@foreach ($group->brands ?? [] as $brand)
|
|
@foreach ($months as $month)
|
|
@php
|
|
$monthKey = is_object($month) ? ($month->key ?? '') : (string) $month;
|
|
$doctorData = $data->{$doctor->id} ?? null;
|
|
$monthData = is_object($doctorData) ? ($doctorData->{$monthKey} ?? null) : null;
|
|
$metricId = $brand->metric_id ?? '';
|
|
$value = is_object($monthData) ? ($monthData->{$metricId} ?? null) : null;
|
|
@endphp
|
|
<td class="text-center">{{ $value !== null && $value !== '' ? $value : '-' }}</td>
|
|
@endforeach
|
|
@endforeach
|
|
@endforeach
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="{{ $metaColumnCount + max($metricColumnCount, 1) }}" class="text-center text-muted">
|
|
@if ($search !== '')
|
|
No doctors found matching "{{ $search }}".
|
|
@else
|
|
No doctor data found.
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
@include('titansbrandunitsreport._pagination')
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
@section('script-bottom')
|
|
<script>
|
|
(function () {
|
|
var loader = document.getElementById('titans-brand-units-report-loader');
|
|
if (!loader) {
|
|
return;
|
|
}
|
|
|
|
function hideLoader() {
|
|
loader.classList.remove('is-visible');
|
|
loader.setAttribute('aria-busy', 'false');
|
|
}
|
|
|
|
function showLoader() {
|
|
loader.classList.add('is-visible');
|
|
loader.setAttribute('aria-busy', 'true');
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', hideLoader, { once: true });
|
|
} else {
|
|
hideLoader();
|
|
}
|
|
|
|
window.addEventListener('pageshow', function (event) {
|
|
if (event.persisted) {
|
|
hideLoader();
|
|
}
|
|
});
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var link = event.target.closest('.titans-brand-units-report-pagination a.page-link[href]:not([href="#"])');
|
|
if (link) {
|
|
showLoader();
|
|
}
|
|
});
|
|
|
|
var searchForm = document.getElementById('titans-search-form');
|
|
if (searchForm) {
|
|
searchForm.addEventListener('submit', function () {
|
|
showLoader();
|
|
});
|
|
}
|
|
|
|
var perPageForm = document.getElementById('titans-per-page-form');
|
|
if (perPageForm) {
|
|
perPageForm.addEventListener('change', function (event) {
|
|
if (event.target && event.target.name === 'per_page') {
|
|
showLoader();
|
|
}
|
|
});
|
|
}
|
|
})();
|
|
</script>
|
|
@endsection
|