import Big from "big.js"; import GlobalConfig, { addThousandSeparators } from "../../global-config.js"; import InitDatePicker from "../../utils/InitDatePicker.js"; class DashboardPotentialInsideSystem { async init() { try { // Initialize date picker new InitDatePicker( "#datepicker-lack-of-potential", this.handleChangedDate.bind(this) ).init(); // Initialize default values this.bigTotalLackPotential = 0; // Fetch data with error handling this.totalPotensi = (await this.getDataTotalPotensi("latest")) || { total: 0, }; this.totalTargetPAD = (await this.getDataSettings("TARGET_PAD")) || 0; this.allCountData = (await this.getValueDashboard()) || {}; // Set counts with safe fallbacks this.pdamCount = this.allCountData.total_pdam ?? 0; this.tataRuangCount = this.allCountData.total_tata_ruang ?? 0; this.pajakReklameCount = this.allCountData.data_pajak_reklame ?? 0; this.surveyLapanganCount = this.allCountData.total_reklame ?? 0; this.reklameCount = this.pajakReklameCount + this.surveyLapanganCount; this.pajakRestoranCount = this.allCountData.data_pajak_restoran ?? 0; this.pajakHiburanCount = this.allCountData.data_pajak_hiburan ?? 0; this.pajakHotelCount = this.allCountData.data_pajak_hotel ?? 0; this.pajakParkirCount = this.allCountData.data_pajak_parkir ?? 0; this.tataRuangUsahaCount = this.allCountData.total_tata_ruang_usaha ?? 0; this.tataRuangNonUsahaCount = this.allCountData.total_tata_ruang_non_usaha ?? 0; // Handle tourism data safely let dataReportTourism = this.allCountData.data_report || []; this.totalVilla = dataReportTourism .filter( (item) => item.kbli_title && item.kbli_title.toLowerCase() === "vila" ) .reduce((sum, item) => sum + (item.total_records || 0), 0); this.totalRestoran = dataReportTourism .filter( (item) => item.kbli_title && item.kbli_title.toLowerCase() === "restoran" ) .reduce((sum, item) => sum + (item.total_records || 0), 0); this.totalPariwisata = dataReportTourism.reduce( (sum, item) => sum + (item.total_records || 0), 0 ); // Calculate big numbers this.bigTargetPAD = new Big(this.totalTargetPAD ?? 0); this.bigTotalPotensi = new Big(this.totalPotensi.total ?? 0); this.bigTotalLackPotential = this.bigTargetPAD.minus( this.bigTotalPotensi ); // Initialize charts and data this.initChartKekuranganPotensi(); this.initDataValueDashboard(); } catch (error) { console.error("Error initializing dashboard:", error); // Set safe fallback values this.reklameCount = 0; this.pdamCount = 0; this.tataRuangCount = 0; this.tataRuangUsahaCount = 0; this.tataRuangNonUsahaCount = 0; this.totalVilla = 0; this.totalRestoran = 0; this.totalPariwisata = 0; this.bigTotalLackPotential = new Big(0); // Still try to initialize the dashboard with safe values this.initDataValueDashboard(); } } async handleChangedDate(filterDate) { const totalPotensi = await this.getDataTotalPotensi(filterDate); this.bigTotalPotensi = new Big(totalPotensi.total ?? 0); this.bigTotalLackPotential = this.bigTargetPAD.minus( this.bigTotalPotensi ); this.initChartKekuranganPotensi(); } async getDataTotalPotensi(filterDate) { try { const response = await fetch( `${GlobalConfig.apiHost}/api/bigdata-resume?filterByDate=${filterDate}&type=simbg`, { credentials: "include", headers: { Authorization: `Bearer ${ document.querySelector("meta[name='api-token']") .content }`, "Content-Type": "application/json", }, } ); if (!response.ok) { console.error("Network response was not ok", response); } const data = await response.json(); return { total: data.total_potensi.sum, }; } catch (error) { console.error("Error fetching chart data:", error); return null; } } async getDataSettings(string_key) { try { const response = await fetch( `${GlobalConfig.apiHost}/api/data-settings?search=${string_key}`, { credentials: "include", headers: { Authorization: `Bearer ${ document.querySelector("meta[name='api-token']") .content }`, "Content-Type": "application/json", }, } ); if (!response.ok) { console.error("Network response was not ok", response); } const data = await response.json(); return data.data[0].value; } catch (error) { console.error("Error fetching chart data:", error); return 0; } } async getValueDashboard() { try { const response = await fetch( `${GlobalConfig.apiHost}/api/dashboard-potential-count`, { credentials: "include", headers: { Authorization: `Bearer ${ document.querySelector("meta[name='api-token']") .content }`, "Content-Type": "application/json", }, } ); if (!response.ok) { console.error("Network response was not ok", response); } const data = await response.json(); return data; } catch (error) { console.error("Error fetching chart data:", error); return 0; } } initChartKekuranganPotensi() { // Helper function to safely update elements with class selector const safeUpdateElements = (selector, callback) => { try { const elements = document.querySelectorAll(selector); if (elements.length > 0) { elements.forEach(callback); } else { console.warn( `No elements found with selector '${selector}'` ); } } catch (error) { console.error( `Error updating elements with selector '${selector}':`, error ); } }; safeUpdateElements( ".document-count.chart-lack-of-potential", (element) => { element.innerText = ``; } ); safeUpdateElements( ".document-total.chart-lack-of-potential", (element) => { element.innerText = `Rp.${addThousandSeparators( this.bigTotalLackPotential.toString() )}`; } ); safeUpdateElements( ".small-percentage.chart-lack-of-potential", (element) => { element.innerText = ``; } ); } initDataValueDashboard() { // Helper function to safely set element text const safeSetText = (elementId, value) => { const element = document.getElementById(elementId); if (element) { element.innerText = value; } else { console.warn(`Element with id '${elementId}' not found`); } }; safeSetText("reklame-count", this.reklameCount); safeSetText("survey-lapangan-count", this.surveyLapanganCount); safeSetText("pajak-reklame-count", this.pajakReklameCount); safeSetText("restoran-count", this.pajakRestoranCount); safeSetText("hiburan-count", this.pajakHiburanCount); safeSetText("hotel-count", this.pajakHotelCount); safeSetText("parkir-count", this.pajakParkirCount); safeSetText("pdam-count", this.pdamCount); safeSetText("tata-ruang-count", this.tataRuangCount); safeSetText("tata-ruang-usaha-count", this.tataRuangUsahaCount); safeSetText("tata-ruang-non-usaha-count", this.tataRuangNonUsahaCount); safeSetText("pariwisata-count", this.totalPariwisata); } } document.addEventListener("DOMContentLoaded", async function (e) { await new DashboardPotentialInsideSystem().init(); }); function handleCircleClick(element) { const url = element.getAttribute("data-url") || "#"; if (url !== "#") { window.location.href = url; } } function resizeDashboard() { let targetElement = document.getElementById("lack-of-potential-wrapper"); let dashboardElement = document.getElementById( "lack-of-potential-fixed-container" ); // Check if required elements exist if (!targetElement || !dashboardElement) { console.warn("Required elements for dashboard resize not found"); return; } let targetWidth = targetElement.offsetWidth; let dashboardWidth = 1400; let scaleFactor = (targetWidth / dashboardWidth).toFixed(2); // Prevent scaling beyond 1 (100%) to avoid overflow scaleFactor = Math.min(scaleFactor, 1); dashboardElement.style.transformOrigin = "left top"; dashboardElement.style.transition = "transform 0.2s ease-in-out"; dashboardElement.style.transform = `scale(${scaleFactor})`; // Fix SVG scaling issue - reset SVG transform to prevent oversized icons const svgElements = dashboardElement.querySelectorAll("svg"); svgElements.forEach((svg) => { svg.style.transform = `scale(${1 / scaleFactor})`; svg.style.transformOrigin = "center"; svg.style.width = "17px"; svg.style.height = "17px"; }); // Ensure horizontal scrolling is allowed if necessary if (document.body) { document.body.style.overflowX = "auto"; } } window.addEventListener("load", resizeDashboard); window.addEventListener("resize", resizeDashboard);