{% extends "backend/base/base.html.twig" %}
{% block body %}
<style>
/* Animasi fade-in */
.fade-in {
opacity: 0;
transition: opacity 0.5s ease-in-out;
}
.fade-in.show {
opacity: 1;
}
</style>
<div class="row">
{{ include('backend/dashboard/_filter.html.twig', {last_update: last_update, tipe_tahun: tipe_tahun, tahun: tahun, tanggal_awal: tanggal_awal, tanggal_akhir: tanggal_akhir, full:0}) }}
{{ include('backend/dashboard/_filter_perbandingan.html.twig', {bulan_list:bulan_list}) }}
{{ include('backend/dashboard/_card1.html.twig', {ungroup: ungroup, res_dash:res_dash}) }}
<div class="col-12 col-lg-6 col-xxl-4 d-flex">
<div class="card rounded-4 w-100">
<div class="card-body">
<div class="card-header p-3 bg-transparent">
<div class="d-flex align-items-center justify-content-between">
<div class="">
<h5 class="mb-0">Waktu Proses</h5>
</div>
</div>
</div>
<div id="card_waktu_proses"></div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 col-xxl-4 d-flex flex-column d-flex align-items-stretch">
<div class="card rounded-4 w-100">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between mb-3" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-theme="dark" title="Nilai Saving Terhadap Anggaran diambil dari Total Anggaran - Total Realisasi Berdasarkan Filter Tahun Anggaran atau Tahun Kalender ">
<div>
<h3 class="mb-0">{{ (res_dash['saving_thd_anggaran']/1000000000) | number_format(2, '.', ',') }}M</h3>
<p class="mb-1">Saving Terhadap Anggaran</p>
</div>
{# <div class="wh-42 d-flex align-items-center justify-content-center rounded-circle bg-grd-danger">
<span class="material-icons-outlined fs-5 text-white">shopping_cart</span>
</div> #}
<div class="sebelumnya d-none">
<p
id="sebelumnya-content-anggaran" class="dash-lable d-flex align-items-center gap-1 rounded mb-0 fade-in"><!-- ajax isi di sini -->
</p>
</div>
</div>
<div class="mt-4" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-theme="dark" title="Nilai Saving Terhadap Anggaran (%) diambil dari (Nilai Saving Terhadap Anggaran / Total Anggaran) * 100 Berdasarkan Filter Tahun Anggaran atau Tahun Kalender ">
<p class="mb-2 d-flex align-items-center justify-content-between">
Saving(%) terhadap Anggaran
<span>{{ res_dash['saving_thd_anggaran_persen'] }}%</span>
</p>
<div class="progress w-100" style="height: 6px;">
<div class="progress-bar bg-grd-danger" style="width: {{ res_dash['saving_thd_anggaran_persen'] }}%"></div>
</div>
</div>
</div>
</div>
<div class="card rounded-4 w-100 d-flex align-items-stretch">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between mb-3" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-theme="dark" title="Nilai Saving Terhadap HPS diambil dari Total HPS - Total Realisasi Berdasarkan Filter Tahun Anggaran atau Tahun Kalender ">
<div>
<h3 class="mb-0">{{ (res_dash['saving_thd_hps']/1000000000) | number_format(2, '.', ',') }}M</h3>
<p class="mb-1">Saving Terhadap HPS</p>
</div>
{# <div class="wh-42 d-flex align-items-center justify-content-center rounded-circle bg-grd-danger">
<span class="material-icons-outlined fs-5 text-white">shopping_cart</span>
</div> #}
<div class="sebelumnya d-none">
<p
id="sebelumnya-content-hps" class="dash-lable d-flex align-items-center gap-1 rounded mb-0 fade-in"><!-- ajax isi di sini -->
</p>
</div>
</div>
<div class="mt-4" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-theme="dark" title="Nilai Saving Terhadap HPS (%) diambil dari (Nilai Saving Terhadap HPS / Total HPS) * 100 Berdasarkan Filter Tahun Anggaran atau Tahun Kalender">
<p class="mb-2 d-flex align-items-center justify-content-between">
Saving(%) terhadap HPS
<span>{{ res_dash['saving_thd_hps_persen'] }}%</span>
</p>
<div class="progress w-100" style="height: 6px;">
<div class="progress-bar bg-grd-danger" style="width: {{ res_dash['saving_thd_hps_persen'] }}%"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-12 col-xxl-8 col-xxl-4 col-xxl-2 d-flex align-items-stretch">
<div class="card w-100 rounded-4">
<div class="card-body">
<div class="d-flex flex-column gap-3">
<div class="d-flex align-items-start justify-content-between">
<div class="">
<h5 class="mb-0">Komposisi PK dan Metode Pemilihan</h5>
<h7 class="mb-0">Dihitung berdasarkan paket selesai</h7>
</div>
</div>
</div>
<div class="position-relative">
<div class="piechart-legend">
{% set colors = ['#ff6a00', '#98ec2d', '#3494e6', '#8e44ad', '#f1c40f'] %}
{% set total = 0 %}
{% for row in res_dash['range_nilai_pk'] %}
{% set total = total + row.jumlah_pk %}
{% endfor %}
Total
</div>
<div
class="d-flex align-items-center justify-content-between gap-3">
<!-- Bagian Donut Chart (Nomor 1) -->
<div id="chart5" style="flex: 1; min-width: 200px;"></div>
<!-- Bagian Progress List (Nomor 2) -->
<div class="d-flex flex-column gap-3" style="flex: 0.7; font-size: 0.85rem;">
{% for row in res_dash['range_nilai_pk'] %}
{% set persen = total ? ((row.jumlah_pk / total) * 100)|round(0) : 0 %}
<div>
<div class="d-flex justify-content-between mb-1">
<span class="d-flex align-items-center gap-2">
<span class="material-icons-outlined fs-6" style="color: {{ colors[loop.index0] ?? '#000' }}">
fiber_manual_record
</span>
{{ row.range_nilai }}
</span>
<span>{{ persen }}%</span>
</div>
<div class="progress" style="height: 6px;">
<div class="progress-bar" role="progressbar" style="width: {{ persen }}%; background-color: {{ colors[loop.index0] ?? '#000' }}" aria-valuenow="{{ persen }}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
{% endfor %}
</div>
</div>
{% set tender = res_dash['metode_tender'] %}
{% set pl = res_dash['metode_pl'] %}
{% set total = tender + pl %}
{% set nilai_tender = res_dash['nilai_metode_tender'] + 0 %}
{% set nilai_pl = res_dash['nilai_metode_pl'] + 0 %}
{% set total_nilai = nilai_tender + nilai_pl %}
<div class="d-flex flex-column flex-lg-row align-items-start justify-content-around border p-3 rounded-4 mt-3 gap-3">
<!-- Tender -->
<div class="d-flex align-items-center gap-4">
<div>
<p class="mb-0 data-attributes">
<span data-peity='{ "fill": ["#2196f3", "rgb(255 255 255 / 12%)"], "innerRadius": 32, "radius": 40 }'>{{tender}}/{{total}}</span>
</p>
</div>
<div>
<p class="mb-1 fs-6 fw-bold">Tender</p>
<h2 class="mb-0" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-theme="dark" title="Jumlah PK diambil dari Kolom no_pk Berdasarkan Filter status_pr (approve,submit) Tahun Anggaran atau Tahun Kalender(tgl_approval_sppbj)">{{ tender }}</h2>
<p class="mb-0">
<span class="text-success me-2 fw-medium">
{{ total > 0 ? (tender / total * 100)|number_format(1, '.', ',') : 0 }}%
</span>
<span data-bs-toggle="tooltip" data-bs-placement="top" data-bs-theme="dark" title="Nilai Paket Pengadaan diambil dari Kolom Total Nilai Berdasarkan Filter status_pr (approve,submit) Tahun Anggaran atau Tahun Kalender(tgl_approval_sppbj)">
{{(nilai_tender / 1000000000)|number_format(2, '.', ',')}}M
</span>
</p>
</div>
</div>
<div class="vr"></div>
<!-- PL -->
<div class="d-flex align-items-center gap-4">
<div>
<p class="mb-0 data-attributes">
<span data-peity='{ "fill": ["#ffd200", "rgb(255 255 255 / 12%)"], "innerRadius": 32, "radius": 40 }'>{{pl}}/{{total}}</span>
</p>
</div>
<div>
<p class="mb-1 fs-6 fw-bold">PL</p>
<h2 class="mb-0" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-theme="dark" title="Jumlah PK diambil dari Kolom no_pk Berdasarkan Filter status_pr (approve,submit) Tahun Anggaran atau Tahun Kalender(tgl_approval_sppbj)">{{ pl }}</h2>
<p class="mb-0">
<span class="text-success me-2 fw-medium">
{{ total > 0 ? (pl / total * 100)|number_format(1, '.', ',') : 0 }}%
</span>
<span data-bs-toggle="tooltip" data-bs-placement="top" data-bs-theme="dark" title="Nilai Paket Pengadaan diambil dari Kolom Total Nilai Berdasarkan Filter status_pr (approve,submit) Tahun Anggaran atau Tahun Kalender(tgl_approval_sppbj)">
{{ (nilai_pl / 1000000000)|number_format(2, '.', ',') }}M
</span>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-12 col-xxl-6 col-xxl-4 col-xs-4 col-xxl-2 d-flex align-items-stretch">
<div class="card w-100 rounded-4">
<div class="card-body">
<div class="d-flex align-items-start justify-content-between mb-1">
<div class="">
<h5 class="mb-0">Nilai Realisasi dan Jumlah PK</h5>
<p class="mb-0">Kantor Pusat dan Pabrik Gula</p>
</div>
</div>
{# <div class="chart-container2"> #}
<div id="chart_realisai_pg"></div>
{# </div> #}
{# <div class="text-center"> #}
<p class="mb-0 font-12">hitung Jumlah PK dan Realisasi Kantor Pusat(HO) dan Pabrik Gula(PG) berdasarkan Tahun anggaran atau Tahun Kalender (Sesuai Filter)</p>
{# </div> #}
</div>
</div>
</div>
<div class="col-xl-12 col-xxl-6 col-xxl-4 col-xxl-2 d-flex align-items-stretch">
<div class="card w-100 rounded-4">
<div class="card-body">
<div class="d-flex align-items-start justify-content-between mb-1">
<div class="">
<h5 class="mb-0">Nilai Realisasi dan Jumlah PK</h5>
<p class="mb-0">MKSO</p>
</div>
</div>
<div id="chart_realisai_mkso"></div>
{# {{ include('backend/dashboard/_chart_realisasi_efisiensi.html.twig', {res_kotak_bawah:res_kotak_bawah,group:group}) }} #}
<p>hitung Jumlah PK dan Realisasi Kebun (MKSO) berdasarkan Tahun anggaran atau Tahun Kalender (Sesuai Filter)</p>
</div>
</div>
</div>
<div class="col-lg-12 col-xxl-12 d-flex align-items-stretch">
<div class="card w-100 rounded-4">
<div class="card-body">
<div class="card-header p-3 bg-transparent">
<div class="d-flex align-items-center justify-content-between">
<div class="">
<h5 class="mb-0">Realisasi dan Saving</h5>
</div>
</div>
</div>
<div id="table_realisasi"></div>
{# {{ include('backend/dashboard/_table.html.twig', {res_kotak_tabel: res_kotak_tabel}) }} #}
</div>
</div>
</div>
</div>
</div>
<!--end overlay-->
<script>
$(document).ready(function () {
// chart 5
var series = [{% for row in res_dash['range_nilai_pk'] %}{{ row.jumlah_pk }}{% if not loop.last %},{% endif %}{% endfor %}];
var labels = [{% for row in res_dash['range_nilai_pk'] %}"{{ row.range_nilai }}"{% if not loop.last %},{% endif %}{% endfor %}];
var colors = [{% for c in colors %}"{{ c }}"{% if not loop.last %},{% endif %}{% endfor %}];
var options = {
series: series,
chart: {
height: 290,
type: 'donut'
},
labels: labels,
colors: colors,
legend: {
show: false // ❌ matikan legend bawaan
},
dataLabels: {
enabled: false // ❌ matikan label di luar slice
},
plotOptions: {
pie: {
donut: {
size: "85%",
labels: {
show: true,
name: {
show: false
}, // ❌ jangan tampilkan nama di tengah
value: {
show: true
}, // ✅ hanya angka total/series
total: {
show: true,
// label: 'Total',
fontSize: '16px',
color: '#fff',
formatter: function (w) {
return w.globals.seriesTotals.reduce((a, b) => a + b, 0);
}
}
}
}
}
}
};
var chart = new ApexCharts(document.querySelector("#chart5"), options);
chart.render();
// chart 6
var seriesData6 = [{{ res_dash['metode_pl'] }}, {{ res_dash['metode_tender'] }}];
var total6 = seriesData6.reduce((a, b) => a + b, 0);
var options6 = {
series: seriesData6,
chart: {
height: 290,
type: 'donut'
},
labels: [
"PL", "Tender"
],
legend: {
show: false
},
fill: {
type: 'gradient',
gradient: {
shade: 'dark',
gradientToColors: [
'#ee0979', '#17ad37'
],
shadeIntensity: 1,
type: 'vertical',
opacityFrom: 1,
opacityTo: 1
}
},
colors: [
"#ff6a00", "#98ec2d"
],
dataLabels: {
enabled: false
},
plotOptions: {
pie: {
donut: {
size: "85%",
labels: {
show: true,
total: {
show: true,
label: 'Total',
formatter: function () {
return total6;
}
},
name: {
show: false
},
value: {
show: false
}
}
}
}
}
};
var chart6 = new ApexCharts(document.querySelector("#chart6"), options6);
chart6.render();
// === isi otomatis persen bawah ===
document.addEventListener("DOMContentLoaded", function () {
var plPercent = total6 ? ((seriesData6[0] / total6) * 100).toFixed(0) : 0;
var tenderPercent = total6 ? ((seriesData6[1] / total6) * 100).toFixed(0) : 0;
document.querySelector("#legend6-pl").innerText = plPercent + "%";
document.querySelector("#legend6-tender").innerText = tenderPercent + "%";
document.querySelector("#bar6-pl").style.width = plPercent + "%";
document.querySelector("#bar6-tender").style.width = tenderPercent + "%";
});
});
//table realisasi
$(document).ready(function() {
let tahun = "{{ tahun }}";
let tanggal_awal = "{{ tanggal_awal }}";
let tanggal_akhir= "{{ tanggal_akhir }}";
let sumber_dana = "{{ sumber_dana }}";
let tipe_tahun = "{{ tipe_tahun }}";
// table
$.ajax({
url: "{{ path('dashboard_table_realisasi') }}",
method: "POST",
data: {
tahun: tahun,
tanggal_awal: tanggal_awal,
tanggal_akhir: tanggal_akhir,
sumber_dana: sumber_dana,
tipe_tahun: tipe_tahun
},
beforeSend: function() {
// tampilkan loading
$("#table_realisasi").html('<div class="text-center p-3"><div class="spinner-border text-primary" role="status"></div><br/>Loading...</div>');
},
success: function(html) {
$("#table_realisasi").html(html);
}
});
// load pertama kali
$.ajax({
url: "{{ path('dashboard_chart_realisasi_efisiensi_pg') }}",
method: "POST",
data: {
tahun: tahun,
tanggal_awal: tanggal_awal,
tanggal_akhir: tanggal_akhir,
sumber_dana: sumber_dana,
tipe_tahun: tipe_tahun
},
beforeSend: function() {
// tampilkan loading
$("#chart_realisai_pg").html('<div class="text-center p-3"><div class="spinner-border text-primary" role="status"></div><br/>Loading...</div>');
},
success: function(html) {
$("#chart_realisai_pg").html(html);
}
});
// load pertama kali
$.ajax({
url: "{{ path('dashboard_chart_realisasi_efisiensi_mkso') }}",
method: "POST",
data: {
tahun: tahun,
tanggal_awal: tanggal_awal,
tanggal_akhir: tanggal_akhir,
sumber_dana: sumber_dana,
tipe_tahun: tipe_tahun
},
beforeSend: function() {
// tampilkan loading
$("#chart_realisai_mkso").html('<div class="text-center p-3"><div class="spinner-border text-primary" role="status"></div><br/>Loading...</div>');
},
success: function(html) {
$("#chart_realisai_mkso").html(html);
}
});
// load card_waktu_proses
$.ajax({
url: "{{ path('dashboard_card_waktu_proses') }}",
method: "POST",
data: {
tahun: tahun,
tanggal_awal: tanggal_awal,
tanggal_akhir: tanggal_akhir,
sumber_dana: sumber_dana,
tipe_tahun: tipe_tahun
},
beforeSend: function() {
// tampilkan loading
$("#card_waktu_proses").html('<div class="text-center p-3"><div class="spinner-border text-primary" role="status"></div><br/>Loading...</div>');
},
success: function(html) {
$("#card_waktu_proses").html(html);
}
});
});
</script>
<script>
$(function() {
let tahun = "{{ tahun }}";
let tanggal_awal = "{{ tanggal_awal }}";
let tanggal_akhir= "{{ tanggal_akhir }}";
let sumber_dana = "{{ sumber_dana }}";
let tipe_tahun = "{{ tipe_tahun }}";
$("#flexSwitchCheckChecked").on("change", function() {
if ($(this).is(":checked")) {
// tampilkan div dan spinner
$(".filter_komparasi").removeClass("d-none");
$(".sebelumnya").removeClass("d-none");
$("#sebelumnya-content-anggaran")
.attr("class", "dash-lable d-flex align-items-center gap-1 rounded mb-0")
.html('<div class="spinner-border spinner-border-sm text-primary" role="status"></div>');
$("#sebelumnya-content-hps")
.attr("class", "dash-lable d-flex align-items-center gap-1 rounded mb-0")
.html('<div class="spinner-border spinner-border-sm text-primary" role="status"></div>');
$.ajax({
url: "{{ path('dashboard_chart_perbandingan') }}",
type: "POST",
dataType: "json",
data: {
tahun: tahun,
tanggal_awal: tanggal_awal,
tanggal_akhir: tanggal_akhir,
sumber_dana: sumber_dana,
tipe_tahun: tipe_tahun
},
success: function(data) {
let current = parseFloat(data.saving_thd_anggaran) / 1000000000;
let last = parseFloat(data.saving_thd_anggaran_sebelumnya) / 1000000000;
let current_hps = parseFloat(data.saving_thd_hps) / 1000000000;
let last_hps = parseFloat(data.saving_thd_hps_sebelumnya) / 1000000000;
let diff = current - last;
// format angka 2 digit
// let formattedDiff = new Intl.NumberFormat('id-ID', {
// minimumFractionDigits: 2,
// maximumFractionDigits: 2
// }).format(Math.abs(diff));
let formattedDiff = new Intl.NumberFormat('id-ID', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(Math.abs(last));
let formattedHps = new Intl.NumberFormat('id-ID', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(Math.abs(last_hps));
// ikon & warna berdasarkan selisih
// let icon = diff >= 0 ? "arrow_upward" : "arrow_downward";
// let colorClass = diff >= 0
// ? "text-success bg-success bg-opacity-10"
// : "text-danger bg-danger bg-opacity-10";
let icon = last > current ? "arrow_upward" : "arrow_downward";
let colorClass = last > current
? "text-success bg-success bg-opacity-10"
: "text-danger bg-danger bg-opacity-10";
let icon_hps = last_hps > current_hps ? "arrow_upward" : "arrow_downward";
let colorClass_hps = last_hps > current_hps
? "text-success bg-success bg-opacity-10"
: "text-danger bg-danger bg-opacity-10";
$("#sebelumnya-content-anggaran")
.attr("class", "dash-lable d-flex align-items-center gap-1 rounded mb-0 " + colorClass)
.html('<span class="material-icons-outlined fs-6">' + icon + '</span>' + formattedDiff + ' M');
$("#sebelumnya-content-hps")
.attr("class", "dash-lable d-flex align-items-center gap-1 rounded mb-0 " + colorClass_hps)
.html('<span class="material-icons-outlined fs-6">' + icon_hps + '</span>' + formattedHps + ' M');
},
error: function(xhr) {
$("#sebelumnya-content-anggaran").html('<span class="text-danger">Error load data</span>');
console.error(xhr.responseText);
$("#sebelumnya-content-hps").html('<span class="text-danger">Error load data</span>');
console.error(xhr.responseText);
}
});
} else {
$(".filter_komparasi").addClass("d-none");
$(".sebelumnya").addClass("d-none");
$("#sebelumnya-content-anggaran").html("");
$("#sebelumnya-content-hps").html("");
}
});
});
</script>
{% endblock %}