Files
hpt_inventory/resources/views/dashboard.blade.php
2026-06-10 16:42:20 +07:00

533 lines
25 KiB
PHP

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
@include('layout.header')
<style>
.content-wrapper .card {
border: 0px !important;
}
</style>
</head>
<body>
<div class="row" id="x" style="display: none;">
<div class="col-12">
<span class="d-flex align-items-center purchase-popup">
<i class="typcn typcn-delete-outline" id="bannerClose"></i>
</span>
</div>
</div>
<div class="container-scroller">
@include('layout.navbar')
<!-- partial -->
@include('layout.breadscrum')
<div class="container-fluid page-body-wrapper">
@include('layout.sidebar')
<!-- partial -->
<div class="main-panel">
<div class="content-wrapper">
<div class="row">
<div class="col-xl-12 mb-0 grid-margin stretch-card flex-column">
<div class="row">
<div class="col-md-3 grid-margin stretch-card">
<div class="card shadow rounded" style="border-radius: 25px" >
<div class="card-body">
<div class="dropdown pull-right">
<button class="btn bg-white p-0 pb-1 text-muted btn-sm dropdown-toggle" type="button" id="dropdownMenuSizeButton4" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuSizeButton4">
<a class="dropdown-item" href="#" onclick="filterSample('today')">{{__('general.chart_filter_today')}}</a>
<a class="dropdown-item" href="#" onclick="filterSample('this_month')">{{__('general.chart_filter_this_month')}}</a>
<a class="dropdown-item" href="#" onclick="filterSample('this_year')">{{__('general.chart_filter_this_year')}}</a>
{{-- <a class="dropdown-item" href="#" onclick="filterSample('last_year')">{{__('general.chart_filter_last_year')}}</a> --}}
</div>
</div>
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-uppercase mb-1"> {{ __('general.total_samples') }}</div>
<div class="d-flex justify-content-between align-items-center mb-2">
<h5 class="mb- font-weight-bold text-info" id="totalSample">{{number_format($totalSample,0)}}</h5>
<div class="d-flex align-items-baseline" id="growthSampleBox">
@if($growthSample>=0)
<i class="typcn typcn-arrow-up-thick text-primary"></i>
<p class="text-primary mb-0">{{$growthSample}}%</p>
@else
<i class="typcn typcn-arrow-down-thick text-danger"></i>
<p class="text-danger mb-0">{{$growthSample}}%</p>
@endif
</div>
</div>
</div>
</div>
<div class="row">
<p class="font-weight-bold ml-2 text-info" id="sampleData">{{__($displaySample)}}</p>
</div>
</div>
</div>
</div>
<div class="col-md-3 grid-margin stretch-card">
<div class="card shadow rounded" style="border-radius: 25px" >
<div class="card-body">
<div class="dropdown pull-right">
<button class="btn bg-white p-0 pb-1 text-muted btn-sm dropdown-toggle" type="button" id="dropdownMenuSizeButton4" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuSizeButton4">
<a class="dropdown-item" href="#" onclick="filterIncome('today')">{{__('general.chart_filter_today')}}</a>
<a class="dropdown-item" href="#" onclick="filterIncome('this_month')">{{__('general.chart_filter_this_month')}}</a>
<a class="dropdown-item" href="#" onclick="filterIncome('this_year')">{{__('general.chart_filter_this_year')}}</a>
{{-- <a class="dropdown-item" href="{{url('dashboard?filter=income&dt=last_year')}}">{{__('general.chart_filter_last_year')}}</a> --}}
</div>
</div>
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-uppercase mb-1"> {{ __('general.total_income') }}</div>
<div class="d-flex justify-content-between align-items-center mb-2">
<h5 class="mb- font-weight-bold text-info" id="totalIncome">$ {{number_format($totalIncome,2)}}</h5>
<div class="d-flex align-items-baseline" id="growthIncomeBox">
@if($growthIncome>=0)
<i class="typcn typcn-arrow-up-thick text-primary"></i>
<p class="text-primary mb-0">{{$growthIncome}}%</p>
@else
<i class="typcn typcn-arrow-down-thick text-danger"></i>
<p class="text-danger mb-0">{{$growthIncome}}%</p>
@endif
</div>
</div>
</div>
</div>
<div class="row">
<p class="text-info font-weight-bold ml-2" id="displayIncome">{{__($displayIncome)}}</p>
</div>
</div>
</div>
</div>
<div class="col-md-3 grid-margin stretch-card">
<div class="card shadow rounded" style="border-radius: 25px" >
<div class="card-body">
<div class="dropdown pull-right">
<button class="btn bg-white p-0 pb-1 text-muted btn-sm dropdown-toggle" type="button" id="dropdownMenuSizeButton4" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuSizeButton4">
<a class="dropdown-item" href="#" onclick="filterPatient('today')">{{__('general.chart_filter_today')}}</a>
<a class="dropdown-item" href="#" onclick="filterPatient('this_month')">{{__('general.chart_filter_this_month')}}</a>
<a class="dropdown-item" href="#" onclick="filterPatient('this_year')">{{__('general.chart_filter_this_year')}}</a>
{{-- <a class="dropdown-item" href="#" onclick="filterPatient('last_year')">{{__('general.chart_filter_last_year')}}</a> --}}
</div>
</div>
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-uppercase mb-1"> {{ __('general.total_patient') }}</div>
<div class="d-flex justify-content-between align-items-center mb-2">
<h5 class="mb- font-weight-bold text-info" id="totalPatient">{{number_format($totalPatient,0)}}</h5>
<div class="d-flex align-items-baseline" id="growthPatientBox">
@if($growthPatient>=0)
<i class="typcn typcn-arrow-up-thick text-primary"></i>
<p class="text-primary mb-0">{{$growthPatient}}%</p>
@else
<i class="typcn typcn-arrow-down-thick text-danger"></i>
<p class="text-danger mb-0">{{$growthPatient}}%</p>
@endif
</div>
</div>
</div>
</div>
<div class="row">
<p class="text-info font-weight-bold ml-2" id="displayPatient">{{__($displayPatient)}}</p>
</div>
</div>
</div>
</div>
<div class="col-md-3 grid-margin stretch-card">
<div class="card shadow rounded" style="border-radius: 25px" >
<div class="card-body">
<div class="dropdown pull-right">
<button class="btn bg-white p-0 pb-1 text-muted btn-sm dropdown-toggle" type="button" id="dropdownMenuSizeButton4" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuSizeButton4">
<a class="dropdown-item" href="#" onclick="filterRejectedSample('today')">{{__('general.chart_filter_today')}}</a>
<a class="dropdown-item" href="#" onclick="filterRejectedSample('this_month')">{{__('general.chart_filter_this_month')}}</a>
<a class="dropdown-item" href="#" onclick="filterRejectedSample('this_year')">{{__('general.chart_filter_this_year')}}</a>
{{-- <a class="dropdown-item" href="#" onclick="filterRejectedSample('last_year')">{{__('general.chart_filter_last_year')}}</a> --}}
</div>
</div>
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-uppercase mb-1"> {{ __('general.total_rejected_sample') }}</div>
<div class="d-flex justify-content-between align-items-center mb-2">
<h5 class="mb- font-weight-bold text-info" id="totalRejectedSample">{{number_format($totalRejectedSample,0)}}</h5>
<div class="d-flex align-items-baseline" id="growthRejectedSampleBox">
@if($growthRejectedSample>=0)
<i class="typcn typcn-arrow-up-thick text-primary"></i>
<p class="text-primary mb-0">{{$growthRejectedSample}}%</p>
@else
<i class="typcn typcn-arrow-down-thick text-danger"></i>
<p class="text-danger mb-0">{{$growthRejectedSample}}%</p>
@endif
</div>
</div>
</div>
</div>
<div class="row">
<p class="text-info font-weight-bold ml-2" id="displayRejectedSample">{{($displayRejectedSample)}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-xl-6 grid-margin stretch-card">
<div class="card bg-inverse-light shadow rounded" style="border-radius:25px">
<div class="card-body border-bottom">
<div class="d-flex justify-content-between align-items-center flex-wrap">
<h6 class="mb-2 mb-md-0 text-uppercase font-weight-medium">{{ __('general.monthly_sample_trend') }}</h6>
</div>
</div>
<div class="card-body">
<canvas id="samplesCompare"></canvas>
</div>
</div>
</div>
<div class="col-md-6 col-xl-6 grid-margin stretch-card">
<div class="card bg-inverse-light shadow rounded" style="border-radius:25px">
<div class="card-body border-bottom">
<div class="d-flex justify-content-between align-items-center flex-wrap">
<h6 class="mb-2 mb-md-0 text-uppercase font-weight-medium">{{ __('general.monthly_income_trend') }}</h6>
</div>
</div>
<div class="card-body">
<canvas id="revenueCompare"></canvas>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-xl-6 grid-margin stretch-card">
<div class="card bg-inverse-light shadow rounded" style="border-radius:25px">
<div class="card-body border-bottom">
<div class="d-flex justify-content-between align-items-center flex-wrap">
<h6 class="mb-2 mb-md-0 text-uppercase font-weight-medium">{{ __('general.sample_source_distribution') }}</h6>
</div>
</div>
<div class="card-body">
<canvas id="sourceDistributor"></canvas>
</div>
</div>
</div>
<div class="col-md-6 col-xl-6 grid-margin stretch-card">
<div class="card bg-inverse-light shadow rounded" style="border-radius:25px">
<div class="card-body border-bottom">
<div class="d-flex justify-content-between align-items-center flex-wrap">
<h6 class="mb-2 mb-md-0 text-uppercase font-weight-medium">{{ __('general.panel_distribution') }}</h6>
</div>
</div>
<div class="card-body">
<canvas id="topTests"></canvas>
</div>
</div>
</div>
</div>
</div>
@include('layout.footer')
</div>
</div>
</div>
@include('layout.common_script')
<script src="{{url(env("APP_URL").'storage/assets/libs/chart.js/Chart.min.js')}}"></script>
{{-- <script src="{{url(env("APP_URL").'storage/assets/js/chart.js')}}"></script> --}}
<script>
function generateColorCodeByYear(year) {
const seed = parseInt(year.toString().slice(-2));
const red = (Math.sin(seed * 1) * 127 + 128) | 0;
const green = (Math.sin(seed * 2) * 127 + 128) | 0;
const blue = (Math.sin(seed * 3) * 127 + 128) | 0;
return `#${red.toString(16).padStart(2, '0')}${green.toString(16).padStart(2, '0')}${blue.toString(16).padStart(2, '0')}`;
}
function generateColors(count) {
const baseColors = [
'#2563eb',
'#16a34a',
'#f59e0b',
'#dc2626',
'#8b5cf6',
'#14b8a6',
'#e11d48',
'#10b981',
'#f97316',
'#3b82f6',
'#22c55e',
'#fbbf24',
'#ef4444',
'#a855f7',
'#06b6d4',
'#e53935',
];
return Array.from({ length: count }, (_, i) =>
baseColors[i % baseColors.length]
);
}
</script>
<script>
var urlSourceDistribution = "{{url('dashboard/source-distribution')}}";
fetch(urlSourceDistribution)
.then(res => res.json())
.then(data => {
const labels = data.map(d => d.sample_source);
const counts = data.map(d => d.total_samples);
const colors = generateColors(labels.length);
new Chart(document.getElementById('sourceDistributor'), {
type: 'line',
data: {
labels: labels,
datasets: [{
label: '{{__("general.total_samples")}}',
data: counts,
backgroundColor: colors
}]
},
options: {
responsive: true,
legend: { position: 'bottom' }
}
});
});
</script>
<script>
var urlTopTests = "{{url('dashboard/panel-distribution')}}";
fetch(urlTopTests)
.then(res => res.json())
.then(data => {
const labels = data.map(d => d.panel);
const counts = data.map(d => d.total_samples);
const panelDisColors = generateColors(labels.length);
new Chart(document.getElementById('topTests'), {
type: 'doughnut',
data: {
labels: labels,
datasets: [{
label: '{{__("general.total_samples")}}',
data: counts,
backgroundColor: panelDisColors
}]
},
options: {
responsive: true,
legend: { position: 'bottom' },
scales: {
y: { beginAtZero: true }
}
}
});
});
</script>
<script>
function renderGrowth(growthData, boxId) {
let icon = '';
let colorClass = '';
if (growthData>= 0) {
icon = '<i class="typcn typcn-arrow-up-thick text-primary"></i>';
colorClass = 'text-primary';
} else {
icon = '<i class="typcn typcn-arrow-down-thick text-danger"></i>';
colorClass = 'text-danger';
}
boxId.innerHTML = `
${icon}
<p class="${colorClass} mb-0">${growthData}%</p>
`;
}
var urlFilterSample = "{{url('dashboard/filter/samples')}}";
function filterSample(filter) {
fetch(`${urlFilterSample}?dt=${filter}`)
.then(res => res.json())
.then(data => {
renderGrowth(data.growthSample, document.getElementById('growthSampleBox'));
$('#sampleData').text(data.displaySample);
$('#totalSample').text(data.displaySampleResult);
});
}
var urlFilterIncome = "{{url('dashboard/filter/income')}}";
function filterIncome(filter) {
fetch(`${urlFilterIncome}?dt=${filter}`)
.then(res => res.json())
.then(data => {
renderGrowth(data.growthIncome, document.getElementById('growthIncomeBox'));
$('#displayIncome').text(data.displayIncome);
$('#totalIncome').text('$ ' + data.displayIncomeResult);
});
}
var urlFilterPatient = "{{url('dashboard/filter/patient')}}";
function filterPatient(filter) {
fetch(`${urlFilterPatient}?dt=${filter}`)
.then(res => res.json())
.then(data => {
renderGrowth(data.growthPatient, document.getElementById('growthPatientBox'));
$('#displayPatient').text(data.displayPatient);
$('#totalPatient').text(data.displayPatientResult);
});
}
var urlFilterRejectedSample = "{{url('dashboard/filter/rejected-sample')}}";
function filterRejectedSample(filter) {
fetch(`${urlFilterRejectedSample}?dt=${filter}`)
.then(res => res.json())
.then(data => {
renderGrowth(data.growthRejectedSample, document.getElementById('growthRejectedSampleBox'));
$('#displayRejectedSample').text(data.displayRejectedSample);
$('#totalRejectedSample').text(data.displayRejectedSampleResult);
});
}
</script>
<script>
const now = new Date();
const trend_thisYear = now.getFullYear();
const trend_lastYear = trend_thisYear - 1;
var urlTrend = "{{url('dashboard/trend/samples-comparison')}}";
fetch(urlTrend)
.then(res => res.json())
.then(data => {
const labels = data.map(d => d.month);
const thisYear = data.map(d => d.this_year);
const lastYear = data.map(d => d.last_year);
new Chart(document.getElementById('samplesCompare'), {
type: 'bar',
data: {
labels: labels,
datasets: [
{
label: trend_thisYear,
data: thisYear,
borderColor: '#ffffff', //green
backgroundColor: 'rgba(235,156,37,0.85)',
tension: 0.4,
fill: true
},
{
label: trend_lastYear,
data: lastYear,
borderColor: '#ffffff', //green
backgroundColor: 'rgba(4,100,144,0.96)',
tension: 0.4,
fill: true
}
]
},
options: {
responsive: true,
legend: { position: 'bottom' },
scales: {
y: { beginAtZero: true }
}
}
});
});
</script>
<script>
var urlRevenueTrend = "{{url('dashboard/trend/revenue-comparison')}}";
fetch(urlRevenueTrend)
.then(res => res.json())
.then(data => {
const labels = data.map(d => d.month);
const thisYear = data.map(d => d.this_year);
const lastYear = data.map(d => d.last_year);
new Chart(document.getElementById('revenueCompare'), {
type: 'line',
data: {
labels: labels,
datasets: [
{
label: trend_thisYear,
data: thisYear,
borderColor: '#2563eb', // blue
backgroundColor: 'rgba(37, 99, 235, 0.1)',
tension: 0.4,
fill: true
},
{
label: trend_lastYear,
data: lastYear,
borderColor: '#10b981', //green
backgroundColor: 'rgba(16, 185, 129, 0.1)',
tension: 0.4,
fill: true
}
]
},
options: {
responsive: true,
legend: { position: 'bottom' },
scales: {
y: { beginAtZero: true }
}
}
});
});
</script>
</body>
</html>