189 lines
6.9 KiB
PHP
189 lines
6.9 KiB
PHP
<?php
|
|
require_once 'db/config.php';
|
|
|
|
$error_message = null;
|
|
$top_brands = [];
|
|
$sales_by_period = [];
|
|
$chart_labels_json = '[]';
|
|
$chart_data_json = '[]';
|
|
|
|
try {
|
|
$pdo = db();
|
|
|
|
// Query 1: Top 5 Brands by Sales
|
|
$top_brands_stmt = $pdo->query('
|
|
SELECT
|
|
MERK,
|
|
SUM(QTY * CAST(REPLACE(HARGA, ",", "") AS DECIMAL(15,2))) as total_omzet
|
|
FROM
|
|
tabelmaster
|
|
GROUP BY
|
|
MERK
|
|
ORDER BY
|
|
total_omzet DESC
|
|
LIMIT 5
|
|
');
|
|
$top_brands = $top_brands_stmt->fetchAll();
|
|
|
|
// Query 2: Sales per Period for Trend Chart
|
|
$sales_by_period_stmt = $pdo->query('
|
|
SELECT
|
|
PERIODE,
|
|
SUM(QTY * CAST(REPLACE(HARGA, ",", "") AS DECIMAL(15,2))) as total_omzet
|
|
FROM
|
|
tabelmaster
|
|
WHERE PERIODE IS NOT NULL AND PERIODE != ""
|
|
GROUP BY
|
|
PERIODE
|
|
ORDER BY
|
|
PERIODE ASC
|
|
');
|
|
$sales_by_period = $sales_by_period_stmt->fetchAll();
|
|
|
|
if (!empty($sales_by_period)) {
|
|
$chart_labels = [];
|
|
$chart_data = [];
|
|
foreach ($sales_by_period as $row) {
|
|
$chart_labels[] = $row['PERIODE'];
|
|
$chart_data[] = $row['total_omzet'];
|
|
}
|
|
$chart_labels_json = json_encode($chart_labels);
|
|
$chart_data_json = json_encode($chart_data);
|
|
}
|
|
|
|
} catch (PDOException $e) {
|
|
$error_message = "Database error: " . $e->getMessage();
|
|
}
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Ringkasan Penjualan - vipanalisa</title>
|
|
<meta name="description" content="Ringkasan laporan penjualan publik.">
|
|
<meta name="keywords" content="laporan penjualan, ringkasan, sales report, public dashboard">
|
|
<meta property="og:title" content="Ringkasan Penjualan - vipanalisa">
|
|
<meta property="og:description" content="Ringkasan laporan penjualan publik.">
|
|
<meta property="og:image" content="">
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<meta name="twitter:image" content="">
|
|
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
</head>
|
|
<body>
|
|
|
|
<header class="header-gradient p-3 shadow-sm mb-4">
|
|
<div class="container">
|
|
<h1 class="navbar-brand mb-0 h1">Ringkasan Penjualan Publik</h1>
|
|
</div>
|
|
</header>
|
|
|
|
<main class="container">
|
|
<?php if (isset($error_message)): ?>
|
|
<div class="alert alert-danger" role="alert">
|
|
<?php echo htmlspecialchars($error_message); ?>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="row">
|
|
<!-- Top 5 Brands -->
|
|
<div class="col-lg-4 mb-4">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
Top 5 Merk Terlaris
|
|
</div>
|
|
<div class="card-body">
|
|
<?php if (empty($top_brands)): ?>
|
|
<p class="text-muted">Data tidak tersedia.</p>
|
|
<?php else: ?>
|
|
<ul class="list-group list-group-flush">
|
|
<?php foreach ($top_brands as $brand): ?>
|
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
|
<?php echo htmlspecialchars($brand['MERK']); ?>
|
|
<span class="badge bg-primary rounded-pill">Rp <?php echo number_format($brand['total_omzet'], 0, ",", "."); ?></span>
|
|
</li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sales Trend -->
|
|
<div class="col-lg-8 mb-4">
|
|
<div class="card h-100">
|
|
<div class="card-header">
|
|
Tren Penjualan per Periode
|
|
</div>
|
|
<div class="card-body">
|
|
<?php if (empty($sales_by_period)): ?>
|
|
<p class="text-muted">Data tren tidak tersedia.</p>
|
|
<?php else: ?>
|
|
<canvas id="salesTrendChart"></canvas>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
</main>
|
|
|
|
<footer class="container mt-4 text-center text-muted">
|
|
<p>© <?php echo date("Y"); ?> vipanalisa. Built with Flatlogic.</p>
|
|
</footer>
|
|
|
|
<script>
|
|
if (typeof Chart !== 'undefined' && <?php echo !empty($sales_by_period) ? 'true' : 'false'; ?>) {
|
|
const ctx = document.getElementById('salesTrendChart');
|
|
new Chart(ctx, {
|
|
type: 'line',
|
|
data: {
|
|
labels: <?php echo $chart_labels_json; ?>,
|
|
datasets: [{
|
|
label: 'Total Omzet',
|
|
data: <?php echo $chart_data_json; ?>,
|
|
fill: false,
|
|
borderColor: 'rgba(13, 110, 253, 1)',
|
|
tension: 0.1
|
|
}]
|
|
},
|
|
options: {
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
ticks: {
|
|
callback: function(value, index, values) {
|
|
return 'Rp ' + new Intl.NumberFormat('id-ID').format(value);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
plugins: {
|
|
tooltip: {
|
|
callbacks: {
|
|
label: function(context) {
|
|
let label = context.dataset.label || '';
|
|
if (label) {
|
|
label += ': ';
|
|
}
|
|
if (context.parsed.y !== null) {
|
|
label += 'Rp ' + new Intl.NumberFormat('id-ID').format(context.parsed.y);
|
|
}
|
|
return label;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|