bank-sampah/Views/Main/Dashboard/Index.cshtml

376 lines
14 KiB
Plaintext

@model BankSampahApp.Models.DashboardChartViewModel
@using System.Text.Json
@{
ViewData["Title"] = "Dashboard";
var chartJson = JsonSerializer.Serialize(Model.YearlyData, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
});
}
<div class="flex gap-2 flex-row justify-between md:gap-0 mt-2 mb-2">
<div class="prose">
<span class="text-xl font-semibold text-black">Dashboard Dinas</span>
</div>
<div class="flex gap-2">
<button class="btn btn-sm rounded-full bg-white" onclick="modal_filter.showModal()">
<i class="ph ph-funnel-simple"></i>
Filter
</button>
</div>
</div>
<div class="h-6"></div>
<div class="card bg-white md:bg-[url(/images/image-welcome-dashboard.png)] md:bg-local md:bg-right md:bg-no-repeat">
<div class="card-body gap-0">
<span class="text-gray-500">Selamat Datang</span>
<span class="bg-linear-to-r from-[#089A7B] to-[#46C881] bg-clip-text text-2xl font-semibold text-transparent">Admin Dimas</span>
</div>
</div>
<div class="h-6"></div>
<!-- Modal Filter -->
<dialog id="modal_filter" class="modal modal-bottom sm:modal-middle">
<div class="modal-box w-full sm:max-w-sm">
<h3 class="text-lg font-bold">Filter</h3>
<form id="formFilter" onsubmit="applyFilter(event)">
<fieldset class="fieldset">
<legend class="fieldset-legend">
Kota
</legend>
<select id="kabupaten" class="select w-full" required>
<option value="" disabled selected>Pilih salah satu</option>
<option value="Kota Adm Jakarta Timur">Kota Adm Jakarta Timur</option>
<option value="Kota Adm Jakarta Barat">Kota Adm Jakarta Barat</option>
<option value="Kota Adm Jakarta Selatan">Kota Adm Jakarta Selatan</option>
<option value="Kota Adm Jakarta Utara">Kota Adm Jakarta Utara</option>
<option value="Kota Adm Jakarta Pusat">Kota Adm Jakarta Pusat</option>
</select>
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Kecamatan</legend>
<select id="filterKecamatan" class="select w-full">
<option value="">Pilih salah satu</option>
</select>
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Kelurahan</legend>
<select id="filterKelurahan" class="select w-full">
<option value="">Pilih salah satu</option>
</select>
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Rukun Warga(RW)</legend>
<select id="filterRW" class="select w-full">
<option value="">Pilih salah satu</option>
</select>
</fieldset>
<div class="modal-action">
<button type="button" class="btn btn-outline rounded-full" onclick="modal_filter.close()">Reset</button>
<button type="submit" class="btn bg-bank-sampah-primary-500 rounded-full text-white">Terapkan</button>
</div>
</form>
</div>
</dialog>
<!-- /modal filter -->
<div class="grid grid-cols-1 gap-4 md:grid-cols-4">
<div class="card bg-linear-to-tl from-[#88C293] to-[#247332] text-white">
<div class="card-body">
<div class="card-title">
<i class="ph ph-building-office text-2xl"></i>
</div>
<div class="flex">
<div class="flex w-3/5 flex-col gap-0 self-end">
<span>Total BSI</span>
<span class="text-3xl">1203 Unit</span>
</div>
<div class="divider divider-horizontal before:bg-white after:bg-white"></div>
<div class="grid w-2/5 grid-rows-3 gap-2 text-[12px]">
<div class="flex flex-col">
<span class="font-semibold">Sudah Verifikasi</span>
<span>145 Unit</span>
</div>
<div class="flex flex-col">
<span class="font-semibold">Belum Verifikasi</span>
<span>5432 Unit</span>
</div>
</div>
</div>
</div>
</div>
<div class="card bg-linear-to-tl from-indigo-200 to-blue-700 text-white">
<div class="card-body">
<div class="card-title">
<i class="ph ph-building-office text-2xl"></i>
</div>
<div class="flex">
<div class="flex w-3/5 flex-col gap-0 self-end">
<span>Total BSU</span>
<span class="text-3xl">1203 Unit</span>
</div>
<div class="divider divider-horizontal before:bg-white after:bg-white"></div>
<div class="grid w-2/5 grid-rows-3 gap-2 text-[12px]">
<div class="flex flex-col">
<span class="font-semibold">Sudah Aktif</span>
<span>145 Unit</span>
</div>
<div class="flex flex-col">
<span class="font-semibold">Belum Aktif</span>
<span>5432 Unit</span>
</div>
<div class="flex flex-col">
<span class="font-semibold">Ditolak</span>
<span>5432 Unit</span>
</div>
</div>
</div>
</div>
</div>
<div class="card bg-linear-to-tl from-amber-200 to-amber-700 text-white">
<div class="card-body">
<div class="card-title">
<i class="ph ph-factory text-2xl"></i>
</div>
<div class="flex">
<div class="flex w-3/5 flex-col gap-0 self-end">
<span>Total Offtaker</span>
<span class="text-3xl">39 Unit</span>
</div>
<div class="divider divider-horizontal before:bg-white after:bg-white"></div>
<div class="grid w-2/5 grid-rows-3 gap-2 text-[12px]">
<div class="flex flex-col">
<span class="font-semibold">Sudah Aktif</span>
<span>145 Unit</span>
</div>
<div class="flex flex-col">
<span class="font-semibold">Belum Aktif</span>
<span>5432 Unit</span>
</div>
<div class="flex flex-col">
<span class="font-semibold">Ditolak</span>
<span>5432 Unit</span>
</div>
</div>
</div>
</div>
</div>
<div class="card bg-linear-to-tl from-violet-200 to-violet-700 text-white">
<div class="card-body">
<div class="card-title">
<i class="ph ph-users-three text-2xl"></i>
</div>
<div class="flex">
<div class="flex w-3/5 flex-col gap-0 self-end">
<span>Total Nasabah</span>
<span class="text-3xl">2780 Unit</span>
</div>
<div class="divider divider-horizontal before:bg-white after:bg-white"></div>
<div class="grid w-2/5 grid-rows-3 gap-2 text-[12px]">
<div class="flex flex-col">
<span class="font-semibold">Sudah Aktif</span>
<span>145 Unit</span>
</div>
<div class="flex flex-col">
<span class="font-semibold">Belum Aktif</span>
<span>5432 Unit</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="h-6"></div>
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
<div class="stats bg-white">
<div class="stat">
<div class="stat-title">Total Sampah BSI</div>
<div class="stat-value">5,812 Kg</div>
<div class="stat-desc">
<span class="text-green-600">
<i class="ph ph-arrow-up"></i>
40%
</span>
vs bulan kemarin
</div>
</div>
</div>
<div class="stats bg-white">
<div class="stat">
<div class="stat-title">Total Sampah BSU</div>
<div class="stat-value">5,812 Kg</div>
<div class="stat-desc">
<span class="text-green-600">
<i class="ph ph-arrow-up"></i>
40%
</span>
vs bulan kemarin
</div>
</div>
</div>
<div class="stats bg-white">
<div class="stat">
<div class="stat-title">Total Sampah Offtaker</div>
<div class="stat-value">89.4 Kg</div>
<div class="stat-desc">
<span class="text-green-600">
<i class="ph ph-arrow-up"></i>
40%
</span>
vs bulan kemarin
</div>
</div>
</div>
</div>
<div class="h-6"></div>
<div class="card bg-white">
<div class="card-body">
<div class="flex flex-col gap-3 md:flex-row md:items-center md:justify-between md:gap-4">
<div class="prose max-w-2xl">
<span class="text-xl font-semibold text-gray-900 font-['Plus_Jakarta_Sans']">
Grafik Total Sampah per Bulan (BSI, BSU, Offtaker)
</span>
<p class="mt-1 text-sm text-gray-500">
Menampilkan total tonase sampah yang dikelola setiap bulan berdasarkan sumber BSI, BSU, dan Offtaker.
</p>
</div>
<fieldset class="fieldset w-full lg:w-48">
<label class="fieldset-label text-gray-500 text-xs uppercase tracking-wide" for="chartYear">
Filter Tahun
</label>
<select id="chartYear" class="select select-sm" onchange="handleYearChange(event)">
@foreach (var year in Model.AvailableYears)
{
if (year == Model.SelectedYear)
{
<option value="@year" selected>@year</option>
}
else
{
<option value="@year">@year</option>
}
}
</select>
</fieldset>
</div>
<div class="w-full overflow-x-auto">
<div class="min-w-[900px]">
<div class="h-64 md:h-96 relative">
<canvas id="chartBankSampah" class="w-full h-full"></canvas>
</div>
</div>
</div>
</div>
</div>
<script src="~/js/chart.js"></script>
<script>
const chartDataByYear = @Html.Raw(chartJson);
const chartCanvas = document.getElementById('chartBankSampah');
const chartCtx = chartCanvas.getContext('2d');
let chartInstance = null;
const datasetStyles = {
BSI: {
borderColor: '#247332',
gradientStart: 'rgba(36, 115, 50, 1)',
gradientEnd: 'rgba(136, 194, 147, 0.25)'
},
BSU: {
borderColor: '#386BCA',
gradientStart: 'rgba(56, 107, 202, 1)',
gradientEnd: 'rgba(138, 164, 242, 0.25)'
},
Offtaker: {
borderColor: '#F79009',
gradientStart: 'rgba(247, 144, 9, 1)',
gradientEnd: 'rgba(255, 219, 172, 0.25)'
}
};
const defaultDatasetStyle = {
borderColor: '#0F172A',
gradientStart: 'rgba(15, 23, 42, 0.85)',
gradientEnd: 'rgba(15, 23, 42, 0.15)'
};
const buildDatasets = (payload) => payload.datasets.map((dataset) => {
const style = datasetStyles[dataset.label] ?? defaultDatasetStyle;
const gradient = chartCtx.createLinearGradient(0, 0, 0, chartCanvas.clientHeight || 400);
gradient.addColorStop(0, style.gradientStart);
gradient.addColorStop(1, style.gradientEnd);
return {
label: dataset.label,
data: dataset.data,
borderColor: style.borderColor,
backgroundColor: gradient,
borderWidth: 2,
};
});
const renderChart = (year) => {
const payload = chartDataByYear[year];
if (!payload) {
return;
}
const updatedData = {
labels: payload.labels,
datasets: buildDatasets(payload)
};
if (chartInstance) {
chartInstance.data = updatedData;
chartInstance.update();
return;
}
chartInstance = new Chart(chartCtx, {
type: 'bar',
data: updatedData,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom',
},
tooltip: {
callbacks: {
label: (context) => `${context.dataset.label}: ${context.formattedValue} Kg`
}
}
},
scales: {
x: {
grid: {
display: false
}
},
y: {
beginAtZero: true,
ticks: {
callback: (value) => `${value} Kg`
}
}
}
}
});
};
window.handleYearChange = (event) => {
renderChart(event.target.value);
};
document.addEventListener('DOMContentLoaded', () => {
renderChart(@Model.SelectedYear);
});
</script>