Files
sibedas/resources/js/dashboards/potentials/inside_system.js
2025-08-20 02:37:42 +07:00

428 lines
16 KiB
JavaScript

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";
});
// Fix Flatpickr calendar scaling issue (Enhanced for server environment)
const flatpickrCalendars = document.querySelectorAll(".flatpickr-calendar");
flatpickrCalendars.forEach((calendar) => {
// Force reset all transformation properties
calendar.style.transform = "none";
calendar.style.scale = "1";
calendar.style.position = "fixed";
calendar.style.zIndex = "10000";
calendar.style.fontSize = "14px";
calendar.style.lineHeight = "normal";
// Apply to all child elements
const allElements = calendar.querySelectorAll("*");
allElements.forEach((element) => {
element.style.transform = "none";
element.style.scale = "1";
});
// Fix SVG inside Flatpickr with more specific targeting
const flatpickrSvgs = calendar.querySelectorAll(
"svg, .flatpickr-prev-month svg, .flatpickr-next-month svg"
);
flatpickrSvgs.forEach((svg) => {
svg.style.transform = "none";
svg.style.scale = "1";
svg.style.width = "17px";
svg.style.height = "17px";
svg.style.maxWidth = "17px";
svg.style.maxHeight = "17px";
svg.style.minWidth = "17px";
svg.style.minHeight = "17px";
});
});
// Ensure horizontal scrolling is allowed if necessary
if (document.body) {
document.body.style.overflowX = "auto";
}
}
// Debounced function for better server performance
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// Additional function to force fix Flatpickr on server
function forceFlatpickrFix() {
const calendars = document.querySelectorAll(".flatpickr-calendar");
calendars.forEach((calendar) => {
calendar.style.setProperty("transform", "none", "important");
calendar.style.setProperty("scale", "1", "important");
calendar.style.setProperty("position", "fixed", "important");
calendar.style.setProperty("z-index", "10000", "important");
const svgs = calendar.querySelectorAll("svg");
svgs.forEach((svg) => {
svg.style.setProperty("width", "17px", "important");
svg.style.setProperty("height", "17px", "important");
svg.style.setProperty("transform", "none", "important");
svg.style.setProperty("scale", "1", "important");
});
});
}
window.addEventListener("load", resizeDashboard);
window.addEventListener("resize", debounce(resizeDashboard, 100));
// Force fix on various events for server environment
window.addEventListener("load", forceFlatpickrFix);
document.addEventListener("click", debounce(forceFlatpickrFix, 50));
window.addEventListener("scroll", debounce(forceFlatpickrFix, 100));
// Fix Flatpickr when it's opened dynamically
document.addEventListener("DOMContentLoaded", function () {
// Add mutation observer to handle dynamically created Flatpickr calendars
const observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
if (mutation.type === "childList") {
mutation.addedNodes.forEach(function (node) {
if (
node.nodeType === 1 &&
node.classList &&
node.classList.contains("flatpickr-calendar")
) {
// Fix newly created Flatpickr calendar (Enhanced for server)
node.style.transform = "none";
node.style.scale = "1";
node.style.position = "fixed";
node.style.zIndex = "10000";
node.style.fontSize = "14px";
node.style.lineHeight = "normal";
// Apply to all child elements immediately
const allElements = node.querySelectorAll("*");
allElements.forEach((element) => {
element.style.transform = "none";
element.style.scale = "1";
});
// Fix SVG inside the new calendar with enhanced targeting
const svgs = node.querySelectorAll(
"svg, .flatpickr-prev-month svg, .flatpickr-next-month svg"
);
svgs.forEach((svg) => {
svg.style.transform = "none";
svg.style.scale = "1";
svg.style.width = "17px";
svg.style.height = "17px";
svg.style.maxWidth = "17px";
svg.style.maxHeight = "17px";
svg.style.minWidth = "17px";
svg.style.minHeight = "17px";
});
}
});
}
});
});
// Observe document body for new Flatpickr calendars
observer.observe(document.body, {
childList: true,
subtree: true,
});
});