349 lines
14 KiB
PHP
349 lines
14 KiB
PHP
@extends('layouts.vertical-individual', ['page_title' => $title ?? 'Titans HCP Gathering Report'])
|
|
|
|
@section('css')
|
|
<style>
|
|
body .account-pages > .container {
|
|
max-width: 100%;
|
|
padding-left: 0;
|
|
padding-right: 0;
|
|
}
|
|
|
|
.titans-hcp-report-page .row {
|
|
--bs-gutter-x: 0;
|
|
margin-left: 0;
|
|
margin-right: 0;
|
|
}
|
|
|
|
.titans-hcp-report-page .card {
|
|
border-left: 0;
|
|
border-right: 0;
|
|
border-radius: 0;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.titans-hcp-report-page .card-body {
|
|
padding-left: 0;
|
|
padding-right: 0;
|
|
}
|
|
|
|
.titans-hcp-report-page .page-header {
|
|
padding-left: 12px;
|
|
padding-right: 12px;
|
|
}
|
|
|
|
.titans-hcp-report-table th,
|
|
.titans-hcp-report-table td {
|
|
white-space: nowrap;
|
|
vertical-align: middle;
|
|
border: 1px solid #dee2e6;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.titans-hcp-report-table thead th {
|
|
text-align: center;
|
|
background: #f8f9fa;
|
|
}
|
|
|
|
.titans-hcp-report-table thead .filter-row th {
|
|
padding: 4px;
|
|
background: #fff;
|
|
font-weight: normal;
|
|
}
|
|
|
|
.titans-hcp-report-table thead .filter-row input,
|
|
.titans-hcp-report-table thead .filter-row select {
|
|
width: 100%;
|
|
min-width: 80px;
|
|
font-size: 11px;
|
|
padding: 2px 6px;
|
|
border: 1px solid #ced4da;
|
|
border-radius: 3px;
|
|
background: #fff;
|
|
}
|
|
|
|
.titans-hcp-report-scroll {
|
|
overflow-x: auto;
|
|
container-type: inline-size;
|
|
}
|
|
|
|
.titans-hcp-report-table .frozen-col {
|
|
position: sticky;
|
|
left: 0;
|
|
z-index: 2;
|
|
background: #fff;
|
|
min-width: 120px;
|
|
max-width: min(50cqw, 50vw);
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.titans-hcp-report-table thead .frozen-col {
|
|
z-index: 3;
|
|
background: #f8f9fa;
|
|
}
|
|
|
|
.titans-hcp-report-table thead .filter-row .frozen-col {
|
|
background: #fff;
|
|
}
|
|
</style>
|
|
@endsection
|
|
|
|
@section('content')
|
|
@php
|
|
$uiColumns = [
|
|
['key' => 'tm_name', 'label' => 'TM Name'],
|
|
['key' => 'hcp_name', 'label' => 'HCP NAME', 'frozen' => true],
|
|
['key' => 'legacy_code', 'label' => 'LEGACY_CODE'],
|
|
['key' => 'pcode', 'label' => 'PCODE'],
|
|
['key' => 'agreement_no', 'label' => 'AgreementNo'],
|
|
['key' => 'status', 'label' => 'Status'],
|
|
['key' => 'eas_id', 'label' => 'EAS ID'],
|
|
['key' => 'activity_report_status', 'label' => 'Activity Report Status'],
|
|
['key' => 'payment_status', 'label' => 'Payment Status'],
|
|
['key' => 'closure_done', 'label' => 'Closure Done'],
|
|
['key' => 'closure_approved', 'label' => 'Closure Approved'],
|
|
['key' => 'tm_visit', 'label' => $tm_visit_label],
|
|
];
|
|
$colCount = count($uiColumns);
|
|
@endphp
|
|
<div class="titans-hcp-report-page">
|
|
<div class="row mb-3 page-header align-items-end">
|
|
<div class="col-md-6">
|
|
<h4 class="page-title">{{ $title }}</h4>
|
|
<p class="text-muted mb-0">Report month: {{ $month }}</p>
|
|
</div>
|
|
<div class="col-md-6 d-flex justify-content-end align-items-center gap-2">
|
|
@if (!empty($months))
|
|
<form method="get" action="{{ $base_url }}/report" class="d-flex align-items-center gap-2">
|
|
<input type="hidden" name="token" value="{{ $token }}">
|
|
<select name="month" class="form-select form-select-sm" style="width: auto;" onchange="this.form.submit()">
|
|
@foreach ($months as $availableMonth)
|
|
<option value="{{ $availableMonth }}" @selected($availableMonth === $month)>{{ $availableMonth }}</option>
|
|
@endforeach
|
|
</select>
|
|
</form>
|
|
@endif
|
|
<a href="{{ $base_url }}/export?token={{ urlencode($token) }}&month={{ urlencode($month) }}" class="btn btn-dark btn-sm">
|
|
Export
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-body titans-hcp-report-scroll">
|
|
<table class="table table-sm table-bordered titans-hcp-report-table mb-0" id="titans-hcp-report-table">
|
|
<thead>
|
|
<tr>
|
|
@foreach ($uiColumns as $col)
|
|
<th @if (!empty($col['frozen'])) class="frozen-col" @endif>{{ $col['label'] }}</th>
|
|
@endforeach
|
|
</tr>
|
|
<tr class="filter-row">
|
|
@foreach ($uiColumns as $index => $col)
|
|
<th @if (!empty($col['frozen'])) class="frozen-col" @endif>
|
|
<input type="search"
|
|
class="titans-hcp-col-filter"
|
|
data-col="{{ $index }}"
|
|
data-filter-mode="contains"
|
|
placeholder="Filter..."
|
|
aria-label="Filter {{ $col['label'] }}">
|
|
</th>
|
|
@endforeach
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@forelse ($rows as $row)
|
|
<tr>
|
|
<td>{{ $row->tm_name }}</td>
|
|
<td class="frozen-col">{{ $row->hcp_name }}</td>
|
|
<td>{{ $row->legacy_code }}</td>
|
|
<td>{{ $row->pcode }}</td>
|
|
<td>{{ $row->agreement_no }}</td>
|
|
<td>{{ $row->status }}</td>
|
|
<td>{{ $row->eas_id }}</td>
|
|
<td>{{ $row->activity_report_status }}</td>
|
|
<td>{{ $row->payment_status }}</td>
|
|
<td>{{ $row->closure_done }}</td>
|
|
<td>{{ $row->closure_approved }}</td>
|
|
<td>{{ $row->tm_visit }}</td>
|
|
</tr>
|
|
@empty
|
|
<tr class="titans-hcp-empty-row">
|
|
<td colspan="{{ $colCount }}" class="text-center text-muted">No data found for this month.</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
@section('script-bottom')
|
|
<script>
|
|
(function () {
|
|
var DROPDOWN_MAX_UNIQUE = 10;
|
|
var table = document.getElementById('titans-hcp-report-table');
|
|
if (!table) {
|
|
return;
|
|
}
|
|
|
|
var tbody = table.tBodies[0];
|
|
var filterRow = table.querySelector('thead .filter-row');
|
|
if (!tbody || !filterRow) {
|
|
return;
|
|
}
|
|
|
|
function isDataRow(row) {
|
|
return !row.classList.contains('titans-hcp-empty-row')
|
|
&& !row.classList.contains('titans-hcp-no-match');
|
|
}
|
|
|
|
function getDataRows() {
|
|
return Array.prototype.filter.call(tbody.querySelectorAll('tr'), isDataRow);
|
|
}
|
|
|
|
function uniqueColumnValues(colIndex) {
|
|
var seen = {};
|
|
var values = [];
|
|
getDataRows().forEach(function (row) {
|
|
var cell = row.cells[colIndex];
|
|
var text = cell ? String(cell.textContent || '').trim() : '';
|
|
if (!Object.prototype.hasOwnProperty.call(seen, text)) {
|
|
seen[text] = true;
|
|
values.push(text);
|
|
}
|
|
});
|
|
values.sort(function (a, b) {
|
|
return a.localeCompare(b, undefined, { sensitivity: 'base', numeric: true });
|
|
});
|
|
return values;
|
|
}
|
|
|
|
function bindFilter(el) {
|
|
if (el.tagName === 'SELECT') {
|
|
el.addEventListener('change', applyFilters);
|
|
} else {
|
|
el.addEventListener('input', applyFilters);
|
|
el.addEventListener('search', applyFilters);
|
|
}
|
|
}
|
|
|
|
function convertLowCardinalityFilters() {
|
|
var cells = filterRow.querySelectorAll('th');
|
|
Array.prototype.forEach.call(cells, function (th, colIndex) {
|
|
var input = th.querySelector('.titans-hcp-col-filter');
|
|
if (!input || input.tagName === 'SELECT') {
|
|
return;
|
|
}
|
|
|
|
var values = uniqueColumnValues(colIndex);
|
|
var hasBlank = values.indexOf('') !== -1;
|
|
// Skip dropdown when column has any blank cells, or too many / no values.
|
|
if (hasBlank || values.length === 0 || values.length > DROPDOWN_MAX_UNIQUE) {
|
|
return;
|
|
}
|
|
|
|
var select = document.createElement('select');
|
|
select.className = 'titans-hcp-col-filter';
|
|
select.setAttribute('data-col', String(colIndex));
|
|
select.setAttribute('data-filter-mode', 'exact');
|
|
select.setAttribute('aria-label', input.getAttribute('aria-label') || ('Filter column ' + colIndex));
|
|
|
|
var allOption = document.createElement('option');
|
|
allOption.value = '';
|
|
allOption.textContent = 'All';
|
|
select.appendChild(allOption);
|
|
|
|
values.forEach(function (value) {
|
|
var option = document.createElement('option');
|
|
option.value = value;
|
|
option.textContent = value;
|
|
select.appendChild(option);
|
|
});
|
|
|
|
th.replaceChild(select, input);
|
|
bindFilter(select);
|
|
});
|
|
}
|
|
|
|
function getFilters() {
|
|
return filterRow.querySelectorAll('.titans-hcp-col-filter');
|
|
}
|
|
|
|
function applyFilters() {
|
|
var filters = getFilters();
|
|
var filterStates = Array.prototype.map.call(filters, function (el) {
|
|
var raw = String(el.value || '');
|
|
var mode = el.getAttribute('data-filter-mode') || 'contains';
|
|
var isActive = el.tagName === 'SELECT'
|
|
? el.selectedIndex > 0
|
|
: raw.trim() !== '';
|
|
var value = raw.trim().toLowerCase();
|
|
if (mode === 'exact' && raw === '__BLANK__') {
|
|
value = '';
|
|
}
|
|
return {
|
|
active: isActive,
|
|
mode: mode,
|
|
value: value
|
|
};
|
|
});
|
|
|
|
var rows = tbody.querySelectorAll('tr');
|
|
var visibleCount = 0;
|
|
|
|
Array.prototype.forEach.call(rows, function (row) {
|
|
if (!isDataRow(row)) {
|
|
return;
|
|
}
|
|
|
|
var cells = row.cells;
|
|
var match = true;
|
|
for (var i = 0; i < filterStates.length; i++) {
|
|
var state = filterStates[i];
|
|
if (!state.active) {
|
|
continue;
|
|
}
|
|
var cellText = cells[i] ? String(cells[i].textContent || '').trim().toLowerCase() : '';
|
|
if (state.mode === 'exact') {
|
|
if (cellText !== state.value) {
|
|
match = false;
|
|
break;
|
|
}
|
|
} else if (cellText.indexOf(state.value) === -1) {
|
|
match = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
row.style.display = match ? '' : 'none';
|
|
if (match) {
|
|
visibleCount++;
|
|
}
|
|
});
|
|
|
|
var noMatchRow = tbody.querySelector('.titans-hcp-no-match');
|
|
if (visibleCount === 0 && getDataRows().length) {
|
|
if (!noMatchRow) {
|
|
noMatchRow = document.createElement('tr');
|
|
noMatchRow.className = 'titans-hcp-no-match';
|
|
noMatchRow.innerHTML = '<td colspan="{{ $colCount }}" class="text-center text-muted">No rows match the current filters.</td>';
|
|
tbody.appendChild(noMatchRow);
|
|
}
|
|
noMatchRow.style.display = '';
|
|
} else if (noMatchRow) {
|
|
noMatchRow.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
convertLowCardinalityFilters();
|
|
Array.prototype.forEach.call(getFilters(), bindFilter);
|
|
})();
|
|
</script>
|
|
@endsection
|