Grafik Laporan Monev (Realtime) /* CSS untuk membuat tampilan grafik lebih rapi dan modern */
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
background-color: #eef2f7;
color: #333;
}
.chart-wrapper {
width: 95%;
max-width: 900px;
padding: 25px;
background-color: #ffffff;
border-radius: 12px;
box-shadow: 0 8px 30px rgba(0,0,0,0.08);
box-sizing: border-box;
text-align: center; /* Menengahkan status */
}
.chart-header {
margin-bottom: 20px;
text-align: center;
}
.chart-header h1 {
margin: 0;
font-size: 1.5rem;
color: #1a202c;
}
.chart-header p {
margin: 5px 0 0;
font-size: 0.9rem;
color: #718096;
}
.chart-container {
position: relative;
height: 50vh; /* Tinggi grafik 50% dari tinggi layar */
min-height: 300px;
}
#status {
color: #718096;
font-style: italic;
padding-top: 20px;
font-weight: bold;
}
#status.error {
color: #c53030; /* Warna merah untuk pesan error */
}

Progres Laporan Monev Data diperbarui secara otomatis setiap 1 menit

Memuat data...



// URL dari Google Sheet Anda
const googleSheetUrl = 'https://docs.google.com/spreadsheets/d/e/2PACX-1vRj2Ii35MT90wM9W9Q9BDu4YUyrrHs-wPaKbWhR1oqt9D7dUien8_o5YUv4SbR4vgzgQ-W2V4CS6AeK/pub?gid=0&single=true&output=csv';

let myChart = null; // Variabel global untuk menyimpan objek grafik
const statusElement = document.getElementById('status');

// Fungsi untuk mengambil data menggunakan 'fetch' dan memperbarui grafik
async function fetchDataAndUpdateChart() {
// Menambahkan parameter acak untuk mencegah browser menggunakan cache lama
const urlWithCacheBuster = googleSheetUrl + '&t=' + new Date().getTime();
statusElement.textContent = 'Mengambil data dari Google Sheet...';
statusElement.classList.remove('error');

try {
const response = await fetch(urlWithCacheBuster, {
mode: 'cors', // Menambahkan mode CORS untuk keamanan
headers: {
'Content-Type': 'text/csv'
}
});
if (!response.ok) {
// Jika response tidak ok (misal: 404 Not Found), lempar error
throw new Error(`Gagal mengambil data: Status ${response.status} ${response.statusText}`);
}
const csvText = await response.text();

if (!csvText || csvText.trim() === '' || csvText.trim().startsWith('<')) {
statusElement.textContent = 'Data kosong atau bukan CSV diterima. Periksa pengaturan publikasi Google Sheet.';
statusElement.classList.add('error');
return;
}

statusElement.textContent = 'Memproses data...';

Papa.parse(csvText, {
header: true,
skipEmptyLines: true,
complete: function(results) {
const sheetData = results.data;

if (!sheetData || sheetData.length === 0 || !results.meta.fields.includes('Nama Bidang')) {
statusElement.textContent = 'Gagal memproses data. Periksa nama kolom (header) di Google Sheet Anda.';
statusElement.classList.add('error');
return;
}

statusElement.style.display = 'none'; // Sembunyikan status jika berhasil

const labels = sheetData.map(row => row['Nama Bidang']);
const dataValues = sheetData.map(row => parseInt(row['Laporan Masuk'] || row['Jumlah Laporan']) || 0);
const totalLaporan = parseInt(sheetData[0]['Total Laporan']) || 12;

if (!myChart) {
createChart(labels, dataValues, totalLaporan);
} else {
myChart.data.labels = labels;
myChart.data.datasets[0].data = dataValues;
myChart.options.scales.y.max = totalLaporan;
myChart.update();
}
},
error: function(parseError) {
console.error("Kesalahan saat memproses CSV:", parseError);
statusElement.textContent = 'Terjadi kesalahan saat memproses data CSV.';
statusElement.classList.add('error');
}
});

} catch (error) {
console.error("Kesalahan pada fungsi fetch:", error);
statusElement.textContent = `Error: ${error.message}. Periksa koneksi internet dan pastikan link Google Sheet benar & dapat diakses publik.`;
statusElement.classList.add('error');
}
}

// Fungsi terpisah untuk membuat grafik pertama kali
function createChart(labels, dataValues, totalLaporan) {
Chart.register(ChartDataLabels);

const ctx = document.getElementById('myChart').getContext('2d');
myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: 'Laporan Masuk',
data: dataValues,
backgroundColor: '#4299e1',
borderColor: '#2b6cb0',
borderWidth: 1,
borderRadius: 4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
max: totalLaporan,
ticks: { stepSize: 1 }
}
},
plugins: {
legend: { display: false },
datalabels: {
anchor: 'end',
align: 'top',
color: '#1a202c',
font: { weight: 'bold', size: 14 }
}
}
}
});
}

// 1. Jalankan fungsi pertama kali saat halaman dimuat
fetchDataAndUpdateChart();

// 2. Atur interval untuk menjalankan fungsi setiap 1 menit
setInterval(fetchDataAndUpdateChart, 60000);