Files
2026-08-20 18:39:37 +07:00

831 lines
27 KiB
PHP

<!-- Content Header (Page header) -->
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h4 class="m-0">Dashboard</h4>
</div>
</div><!-- /.row -->
</div><!-- /.container-fluid -->
</div>
<!-- /.content-header -->
<?php
// print_r($_SESSION);
$bulan = date('Y-m');
$tahun = date('Y');
$stmt = $pdo->prepare("SELECT
SUM(order_aktif) AS order_aktif
FROM v_jumlah_order_list $SqlDataWHIdM");
$stmt->execute();
$data = $stmt->fetchAll();
$stmt = $pdo->prepare("SELECT
SUM(user_regis) AS user_regis,
SUM(user_aktif) AS user_aktif,
SUM(user_tidak_aktif) AS user_tidak_aktif,
SUM(user_konek) AS user_konek,
SUM(user_diskonek) AS user_diskonek,
SUM(user_hs_regis) AS user_hs_regis,
SUM(user_hs_aktif) AS user_hs_aktif,
SUM(user_hs_tidak_aktif) AS user_hs_tidak_aktif,
SUM(user_hs_konek) AS user_hs_konek,
SUM(user_hs_diskonek) AS user_hs_diskonek
FROM v_jumlah_pelanggan $SqlDataWHIdM");
$stmt->execute();
$datauser = $stmt->fetchAll();
$stmt = $pdo->prepare("SELECT
SUM(pemasukan) AS pemasukan,
SUM(pengeluaran) AS pengeluaran,
SUM(saldo) AS saldo
FROM v_jumlah_transaksi_bulanan WHERE bulan = '$bulan' $SqlDataId");
$stmt->execute();
$jumbulan = $stmt->fetchAll();
$stmt = $pdo->prepare("SELECT
SUM(pemasukan) AS pemasukan,
SUM(pengeluaran) AS pengeluaran,
SUM(saldo) AS saldo
FROM v_jumlah_transaksi_tahunan WHERE tahun = '$tahun' $SqlDataId");
$stmt->execute();
$jumtahun = $stmt->fetchAll();
?>
<!-- Main content -->
<section class="content">
<div class="container-fluid">
<?php if(!in_array("Hidden Summary", $json_array[1]['sub_menu'])){ ?>
<!-- Small boxes (Stat box) -->
<div class="row">
<div class="col-lg-2 col-6">
<!-- small box -->
<div class="small-box bg-info">
<div class="inner">
<p class="mb-1">List Order</p>
<i class="mb-1">Layanan PPPOE</i>
<h3><?php if(!empty($data[0]['order_aktif'])) { echo $data[0]['order_aktif']; } else { echo "0";} ?></h3>
<?php if($datauser[0]['user_hs_aktif'] > 0) { ?>
<i class="mb-1">Layanan Hotspot</i>
<h3><?php if(!empty($data[0]['order_hs_aktif'])) { echo $data[0]['order_hs_aktif']; } else { echo "0";} ?></h3>
<?php } ?>
</div>
<div class="icon">
<i class="ion ion-bag"></i>
</div>
</div>
</div>
<!-- ./col -->
<div class="col-lg-2 col-6">
<!-- small box -->
<div class="small-box bg-warning">
<div class="inner">
<p class="mb-1">On Instalation</p>
<i class="mb-1">Layanan PPPOE</i>
<h3><?php if(!empty($datauser[0]['user_regis'])) { echo $datauser[0]['user_regis']; } else { echo "0";} ?></h3>
<?php if($datauser[0]['user_hs_aktif'] > 0) { ?>
<i class="mb-1">Layanan Hotspot</i>
<h3><?php if(!empty($datauser[0]['user_hs_regis'])) { echo $datauser[0]['user_hs_regis']; } else { echo "0";} ?></h3>
<?php } ?>
</div>
<div class="icon">
<i class="ion ion-hammer"></i>
</div>
</div>
</div>
<!-- ./col -->
<div class="col-lg-2 col-6">
<!-- small box -->
<div class="small-box bg-success">
<div class="inner">
<p class="mb-1">Aktif</p>
<i class="mb-1">Layanan PPPOE</i>
<h3><?php if(!empty($datauser[0]['user_aktif'])) { echo $datauser[0]['user_aktif']; } else { echo "0";} ?></h3>
<?php if($datauser[0]['user_hs_aktif'] > 0) { ?>
<i class="mb-1">Layanan Hotspot</i>
<h3><?php if(!empty($datauser[0]['user_hs_aktif'])) { echo $datauser[0]['user_hs_aktif']; } else { echo "0";} ?></h3>
<?php } ?>
</div>
<div class="icon">
<i class="ion ion-ios-people"></i>
</div>
</div>
</div>
<!-- ./col -->
<div class="col-lg-2 col-6">
<!-- small box -->
<div class="small-box bg-warning">
<div class="inner">
<p class="mb-1">Tidak Aktif</p>
<i class="mb-1">Layanan PPPOE</i>
<h3><?php if(!empty($datauser[0]['user_tidak_aktif'])) { echo $datauser[0]['user_tidak_aktif']; } else { echo "0";} ?></h3>
<?php if($datauser[0]['user_hs_aktif'] > 0) { ?>
<i class="mb-1">Layanan Hotspot</i>
<h3><?php if(!empty($datauser[0]['user_hs_tidak_aktif'])) { echo $datauser[0]['user_hs_tidak_aktif']; } else { echo "0";} ?></h3>
<?php } ?>
</div>
<div class="icon">
<i class="ion ion-ios-people"></i>
</div>
</div>
</div>
<!-- ./col -->
<div class="col-lg-2 col-6">
<!-- small box -->
<div class="small-box bg-success">
<div class="inner">
<p class="mb-1">Connected</p>
<i class="mb-1">Layanan PPPOE</i>
<h3><?php if(!empty($datauser[0]['user_konek'])) { echo $datauser[0]['user_konek']; } else { echo "0";} ?></h3>
<?php if($datauser[0]['user_hs_aktif'] > 0) { ?>
<i class="mb-1">Layanan Hotspot</i>
<h3><?php if(!empty($datauser[0]['user_hs_konek'])) { echo $datauser[0]['user_hs_konek']; } else { echo "0";} ?></h3>
<?php } ?>
</div>
<div class="icon">
<i class="ion ion-wifi"></i>
</div>
</div>
</div>
<!-- ./col -->
<div class="col-lg-2 col-6">
<!-- small box -->
<div class="small-box bg-danger">
<div class="inner">
<p class="mb-1">Disconnected</p>
<i class="mb-1">Layanan PPPOE</i>
<h3><?php if(!empty($datauser[0]['user_diskonek'])) { echo $datauser[0]['user_diskonek']; } else { echo "0";} ?></h3>
<?php if($datauser[0]['user_hs_aktif'] > 0) { ?>
<i class="mb-1">Layanan Hotspot</i>
<h3><?php if(!empty($datauser[0]['user_hs_diskonek'])) { echo $datauser[0]['user_hs_diskonek']; } else { echo "0";} ?></h3>
<?php } ?>
</div>
<div class="icon">
<i class="ion ion-wifi"></i>
</div>
</div>
</div>
<!-- ./col -->
</div>
<?php } ?>
<!--DIBUAT KHUSUS UNTUK SEARCH AJA-->
<?php if(in_array("Cari Pelanggan", $json_array[1]['sub_menu'])){ ?>
<style>
/* ===============================
BASE (TETAP)
================================ */
.search-wrapper {
width: 100%;
margin: 10px auto;
font-family: Arial, sans-serif;
}
.search-box input {
width: 60%;
padding: 12px 14px;
border-radius: 6px;
border: 1px solid #ccc;
font-size: 14px;
text-align: center;
}
.result-wrapper {
margin-top: 15px;
}
/* TABLE */
.result-table {
width: 100%;
border-collapse: collapse;
}
.result-table th,
.result-table td {
padding: 10px 12px;
font-size: 13px;
border-bottom: 1px solid #eee;
}
.result-table thead {
background: #f5f5f5;
}
.result-table tbody tr:hover {
background: #fafafa;
}
.badge {
padding: 4px 10px;
font-size: 11px;
border-radius: 20px;
color: #fff;
}
.badge-success { background: #28a745; }
.badge-danger { background: #dc3545; }
.btn-action {
padding: 6px 12px;
font-size: 12px;
border-radius: 6px;
border: none;
cursor: pointer;
background: #007bff;
color: #fff;
}
/* ===============================
MOBILE CARD STYLE
================================ */
.mobile-cards {
display: none;
}
.customer-card {
border: 1px solid #e3e3e3;
border-radius: 12px;
padding: 12px;
margin-bottom: 12px;
box-shadow: 0 2px 6px rgba(0,0,0,.05);
}
.customer-card h4 {
font-size: 15px;
margin: 0 0 5px;
}
.customer-card small {
color: #666;
}
.customer-row {
display: flex;
justify-content: space-between;
font-size: 13px;
margin-top: 6px;
}
.customer-row span:first-child {
color: #777;
}
.customer-actions {
margin-top: 10px;
text-align: right;
}
/* ===============================
RESPONSIVE SWITCH
================================ */
@media (max-width: 767px) {
.result-table {
display: none;
}
.search-box input {
width: 100%;
}
.mobile-cards {
display: block;
zoom: 90%;
}
.search-wrapper {
zoom: 80%;
}
}
</style>
<div class="card" style="border-radius: 20px;">
<div class="card-body py-2 px-2">
<!--<div class="search-wrapper">-->
<!-- <center>-->
<!-- <label>Cari Pelanggan</label>-->
<!-- <div class="search-box px-2">-->
<!-- <input -->
<!-- type="text" -->
<!-- id="searchInput" -->
<!-- placeholder="Cari pelanggan (Nama / ID Pelanggan)..."-->
<!-- autocomplete="off"-->
<!-- >-->
<!-- </center>-->
<!--</div>-->
<div id="searchResult" class="result-wrapper" style="display:none;">
<!-- TABLE (DESKTOP) -->
<table class="result-table">
<thead>
<tr>
<th>ID</th>
<th>Nama Server</th>
<th>Nama Pelanggan</th>
<th>WhatsApp</th>
<th>Alamat</th>
<th>Layanan</th>
<th>Status</th>
<th>Aksi</th>
</tr>
</thead>
<tbody id="resultBody"></tbody>
</table>
<!-- CARD (MOBILE) -->
<div id="mobileCards" class="mobile-cards"></div>
</div>
</div>
</div>
<script>
const searchInput = document.getElementById('searchInput');
const resultWrapper = document.getElementById('searchResult');
const resultBody = document.getElementById('resultBody');
const mobileCards = document.getElementById('mobileCards');
let typingTimer;
const delay = 500;
searchInput.addEventListener('keyup', function () {
clearTimeout(typingTimer);
const keyword = this.value.trim();
if (keyword.length < 3) {
resultWrapper.style.display = 'none';
resultBody.innerHTML = '';
mobileCards.innerHTML = '';
return;
}
typingTimer = setTimeout(() => {
searchCustomer(keyword);
}, delay);
});
async function searchCustomer(keyword) {
resultWrapper.style.display = 'block';
resultBody.innerHTML = `<tr><td colspan="8">Mencari data...</td></tr>`;
mobileCards.innerHTML = `Mencari data...`;
try {
const res = await fetch(`../controller/customers.php?ids=<?= $SvId ?>&search=${encodeURIComponent(keyword)}`);
const json = await res.json();
if (!json.status || !json.data.length) {
resultBody.innerHTML = `<tr><td colspan="8">Data tidak ditemukan</td></tr>`;
mobileCards.innerHTML = `Data tidak ditemukan`;
return;
}
let tableHtml = '';
let cardHtml = '';
json.data.forEach(row => {
/* ===== TABLE ===== */
tableHtml += `
<tr>
<td>${row.akun}</td>
<td>${row.nama_server}</td>
<td>${row.name}</td>
<td>${row.nomor_whatsapp}</td>
<td>${row.alamat}</td>
<td>${row.service}</td>
<td>
<span class="badge ${row.status === 'aktif' ? 'badge-success' : 'badge-danger'}">
${row.status}
</span>
</td>
<td>
<button class="btn-action" onclick="openCustomer('${row.button_detail}')">
Detail
</button>
</td>
</tr>
`;
/* ===== MOBILE CARD ===== */
cardHtml += `
<div class="customer-card m-2">
<h4>${row.name}</h4>
<small>${row.nama_server}</small>
<div class="customer-row">
<span>ID</span>
<span>${row.akun}</span>
</div>
<div class="customer-row">
<span>WhatsApp</span>
<span>${row.nomor_whatsapp}</span>
</div>
<div class="customer-row">
<span>Layanan</span>
<span>${row.service}</span>
</div>
<div class="customer-row">
<span>Status</span>
<span class="badge ${row.status === 'aktif' ? 'badge-success' : 'badge-danger'}">
${row.status}
</span>
</div>
<div class="customer-actions">
<button class="btn-action" onclick="openCustomer('${row.button_detail}')">
Detail
</button>
</div>
</div>
`;
});
resultBody.innerHTML = tableHtml;
mobileCards.innerHTML = cardHtml;
} catch (e) {
resultBody.innerHTML = `<tr><td colspan="8">Gagal mengambil data</td></tr>`;
mobileCards.innerHTML = `Gagal mengambil data`;
}
}
function openCustomer(url) {
window.location.href = `?${url}`;
}
</script>
<?php } ?>
<div class="row equal-height">
<?php if(in_array("52", $json_array[52])) { ?>
<div class="col-md-8">
<div class="p-2 border bg-light">
<div class="card" id="reportChartid">
<div class="card-body">
<center>
<h5>Grafik Keuangan Tahunan</h5>
</center>
<label><small>Tahun :</small></label>
<select id="yearSelect">
<option value="2024">2024</option>
<option value="2025">2025</option>
<option value="2026" selected>2026</option>
</select>
<button id="fullscreenBtn" style="float: right;" class="btn btn-sm btn-secondary">Fullscreen</button>
<canvas id="reportChart"></canvas>
</div>
</div>
<div id="accordion">
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<center>
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseOne" aria-expanded="false" aria-controls="collapseOne">
<h5><b>Akumulasi Laporan Keuangan</b></h5>
</button>
</center>
</h5>
</div>
<div id="collapseOne" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
<center>
<h5>Akumulasi keuangan bulan ini</h5>
</center>
<div class="row">
<div class="col-md-4">
<div class="card" style="background-color: rgba(76, 175, 80, 0.9);">
<div class="card-body">
<center>
<h6>Pemasukan</h6><hr style="margin: 5px;">
<h4>Rp. <?php echo number_format($jumbulan[0]['pemasukan']); ?></h4>
</center>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card" style="background-color: rgba(255, 193, 7, 0.7);">
<div class="card-body">
<center>
<h6>Pengeluaran</h6><hr style="margin: 5px;">
<h4>Rp. <?php echo number_format($jumbulan[0]['pengeluaran']); ?></h4>
</center>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card" style="background-color: rgba(23, 162, 184, 0.7);">
<div class="card-body">
<center>
<h6>Saldo</h6><hr style="margin: 5px;">
<h4>Rp. <?php echo number_format($jumbulan[0]['saldo']); ?></h4>
</center>
</div>
</div>
</div>
</div>
<center>
<h5>Akumulasi keuangan tahun ini</h5>
</center>
<div class="row">
<div class="col-md-4">
<div class="card bg-success">
<div class="card-body">
<center>
<h6>Pemasukan</h6><hr style="margin: 5px;">
<h4>Rp. <?php echo number_format($jumtahun[0]['pemasukan']); ?></h4>
</center>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card bg-warning">
<div class="card-body">
<center>
<h6>Pengeluaran</h6><hr style="margin: 5px;">
<h4>Rp. <?php echo number_format($jumtahun[0]['pengeluaran']); ?></h4>
</center>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card bg-info">
<div class="card-body">
<center>
<h6>Saldo</h6><hr style="margin: 5px;">
<h4>Rp. <?php echo number_format($jumtahun[0]['saldo']); ?></h4>
</center>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<?php } if(in_array("36", $json_array[36])) { ?>
<div class="col-md-4">
<div class="p-2 border bg-light">
<?php if(in_array("Cari Pelanggan", $json_array[1]['sub_menu'])){ }?>
<div class="m-2">
<a href="?<?php echo encrypt_url('laporan/dashboard_onu'); ?>" class="btn btn-sm btn-success btn-block">Laporan ONU</a>
</div>
<?php if($_SESSION['user'] == 1) { ?>
<?php } ?>
<div>
<a href="?<?php echo encrypt_url('maps_marker_topologi'); ?>" class="btn btn-sm btn-block">
<img src="dist/img/maps-monitoring.png" width="100%">
<h6>Maps Monitoring Titik Koordinat Pelanggan</h6>
</a>
<br>
</div>
<div class="card direct-chat direct-chat-primary">
<div class="card-header bg-danger">
<h3 class="card-title">Tiket Gangguan</h3>
<div class="card-tools">
<?php
$stmt = $pdo->prepare("SELECT COUNT(id) AS jumlahtiket FROM v_tiket_gangguan WHERE status = '1' $SqlDataId ");
$stmt->execute();
$datatiket = $stmt->fetchAll();
?>
<span title="3 New Messages" class="badge badge-light"><?php echo $datatiket[0]['jumlahtiket']; ?></span>
</div>
</div>
<!-- /.card-header -->
<div class="card-body">
<div class="direct-chat-messages" style="height: 450px">
<?php
$stmt = $pdo->prepare("SELECT * FROM v_tiket_gangguan WHERE status = '1' $SqlDataId ORDER BY COALESCE(level, 999) ASC, start_time DESC");
$stmt->execute();
while ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
// Tentukan warna garis berdasarkan level
if ($data['level'] == 1) {
$borderColor = '#dc3545'; // Bootstrap danger
} elseif ($data['level'] == 2) {
$borderColor = '#ffc107'; // Bootstrap warning
} else {
$borderColor = '#0dcaf0'; // Bootstrap info
}
?>
<a href="?<?php echo encrypt_url('tiket_buat') ?>">
<div class="card p-2 text-dark" style="border-left: 8px solid; border-left-color: <?= $borderColor; ?>;">
<div class="row">
<div class="col-6">
<p class="m-0 text-danger"><?php echo $data['jenis_tiket']; ?></p>
<p class="m-0"><?php echo $data['nama_pelanggan'].' ('.$data['nama_server'].')'; ?></p>
<p class="m-0"><?php echo $data['start_time']; ?></p>
</div>
<div class="col-6 text-right">
<p class="m-0"><?php echo $data['permasalahan']; ?></p>
</div>
</div>
</div>
</a>
<?php } ?>
</div>
</div>
</div>
</div>
</div>
<?php } if(in_array("27", $json_array[27]) && in_array("28", $json_array[28])) { ?>
<!--<div class="col-md-8"> -->
<!-- <div class="p-2 border bg-light">-->
<!-- <div class="card-body">-->
<!-- <center>-->
<!-- <h5>Grafik Keuangan Tahunan</h5>-->
<!-- </center>-->
<!-- <label>Tahun</label>-->
<!-- <select id="yearSelect">-->
<!-- <option value="2024">2024</option>-->
<!-- <option value="2025">2025</option>-->
<!-- <option value="2026">2026</option>-->
<!-- </select>-->
<!-- <canvas id="reportChart"></canvas>-->
<!-- </div>-->
<!-- </div>-->
<!--</div>-->
<?php } ?>
</div>
</div><!-- /.container-fluid -->
</section>
<!-- /.content -->
<style>
.equal-height {
display: flex;
flex-wrap: wrap;
}
.equal-height .col-md-8 {
display: flex;
flex-direction: column;
}
.equal-height .col-md-4 {
display: flex;
flex-direction: column;
}
.equal-height .p-2 {
flex: 1; /* Membuat kolom mengisi tinggi yang sama */
}
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
const canvas = document.getElementById('reportChart'); // Mendapatkan elemen canvas
const rcrt = canvas.getContext('2d'); // Mendapatkan konteks dari canvas
const yearSelect = document.getElementById('yearSelect');
const fullscreenBtn = document.getElementById('fullscreenBtn');
// Mengatur ukuran awal canvas
canvas.style.maxHeight = '350px'; // Kembali ke ukuran asli
canvas.style.width = '100%'; // Kembali ke ukuran asli
let reportChart; // Simpan referensi chart di sini
// Fungsi untuk mengambil data dari file PHP berdasarkan tahun
async function fetchData(year) {
try {
const response = await fetch(`load/data_report_dashboard.php?year=${year}&s=<?php echo $SqlDataId; ?>`);
const data = await response.json();
// console.log(data); // Log data yang diterima
const bulanSingkatan = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'];
const bulanArray = bulanSingkatan.map((singkatan, index) => `${year}-${String(index + 1).padStart(2, '0')}`);
const pemasukan = new Array(12).fill(0);
const pengeluaran = new Array(12).fill(0);
const saldo = new Array(12).fill(0);
data.bulan.forEach((bulan, index) => {
const monthIndex = bulanArray.indexOf(bulan);
if (monthIndex !== -1) {
pemasukan[monthIndex] = data.pemasukan[index];
pengeluaran[monthIndex] = data.pengeluaran[index];
saldo[monthIndex] = data.saldo[index];
}
});
const report = {
labels: bulanSingkatan,
datasets: [
{
label: 'Pemasukan',
data: pemasukan,
backgroundColor: 'rgba(75, 192, 192)',
borderColor: 'rgb(75, 192, 192)',
borderWidth: 1
},
{
label: 'Pengeluaran',
data: pengeluaran,
backgroundColor: 'rgba(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
borderWidth: 1
},
{
label: 'Saldo',
data: saldo,
backgroundColor: 'rgba(54, 162, 235)',
borderColor: 'rgb(54, 162, 235)',
borderWidth: 1
}
]
};
// Hapus chart lama jika sudah ada
if (reportChart) {
reportChart.destroy();
}
const rconfig = {
type: 'bar',
data: report,
options: {
scales: {
y: {
beginAtZero: true,
ticks: {
callback: function(value) {
const absValue = Math.abs(value);
if (absValue >= 1000000) {
return (value / 1000000) + 'M';
} else if (absValue >= 1000) {
return (value / 1000) + 'K';
} else {
return value;
}
}
}
}
}
}
};
// Membuat chart baru
reportChart = new Chart(rcrt, rconfig);
} catch (error) {
console.error('Error fetching data:', error);
}
}
// Fungsi untuk mengaktifkan mode fullscreen
function toggleFullscreen() {
const canvasContainer = document.getElementById('reportChartid');
if (!document.fullscreenElement) {
canvasContainer.requestFullscreen().catch(err => {
console.error(`Error attempting to enable full-screen mode: ${err.message}`);
});
} else {
document.exitFullscreen();
}
}
// Event listener untuk tombol fullscreen
fullscreenBtn.addEventListener('click', toggleFullscreen);
// Memanggil fungsi untuk mengambil data saat halaman dimuat
fetchData(yearSelect.value);
// Menangani perubahan tahun
yearSelect.addEventListener('change', () => {
fetchData(yearSelect.value);
});
// Mengatur tinggi canvas saat masuk dan keluar fullscreen
document.addEventListener('fullscreenchange', () => {
if (document.fullscreenElement) {
canvas.style.height = ''; // Kembali ke ukuran asli
canvas.style.maxHeight = '100%';
canvas.style.width = '100%'; // Atur lebar canvas menjadi 100vw
fullscreenBtn.textContent = 'Close Fullscreen';
} else {
canvas.style.height = ''; // Kembali ke ukuran asli
canvas.style.maxHeight = '350px'; // Kembali ke max-height asli
canvas.style.width = '100%'; // Kembali ke lebar asli
fullscreenBtn.textContent = 'Fullscreen';
}
});
});
</script>