add separator in js for handle showing value is number

This commit is contained in:
arifal
2025-06-24 12:02:17 +07:00
parent b895f61701
commit e5baf5318f
10 changed files with 105 additions and 74 deletions

BIN
build.zip

Binary file not shown.

View File

@@ -81,25 +81,29 @@ class BigdataResume {
return data.data.map((item) => [ return data.data.map((item) => [
item.id, item.id,
item.year, item.year,
item.potention_count, addThousandSeparators(item.potention_count),
addThousandSeparators(item.potention_sum), addThousandSeparators(item.potention_sum),
item.non_verified_count, addThousandSeparators(item.non_verified_count),
addThousandSeparators(item.non_verified_sum), addThousandSeparators(item.non_verified_sum),
item.verified_count, addThousandSeparators(item.verified_count),
addThousandSeparators(item.verified_sum), addThousandSeparators(item.verified_sum),
item.business_count, addThousandSeparators(item.business_count),
addThousandSeparators(item.business_sum), addThousandSeparators(item.business_sum),
item.non_business_count, addThousandSeparators(item.non_business_count),
addThousandSeparators(item.non_business_sum), addThousandSeparators(item.non_business_sum),
item.spatial_count, addThousandSeparators(item.spatial_count),
addThousandSeparators(item.spatial_sum), addThousandSeparators(item.spatial_sum),
item.waiting_click_dpmptsp_count, addThousandSeparators(item.waiting_click_dpmptsp_count),
addThousandSeparators(item.waiting_click_dpmptsp_sum), addThousandSeparators(item.waiting_click_dpmptsp_sum),
item.issuance_realization_pbg_count, addThousandSeparators(
item.issuance_realization_pbg_count
),
addThousandSeparators( addThousandSeparators(
item.issuance_realization_pbg_sum item.issuance_realization_pbg_sum
), ),
item.process_in_technical_office_count, addThousandSeparators(
item.process_in_technical_office_count
),
addThousandSeparators( addThousandSeparators(
item.process_in_technical_office_sum item.process_in_technical_office_sum
), ),

View File

@@ -1,7 +1,7 @@
import { Grid } from "gridjs/dist/gridjs.umd.js"; import { Grid } from "gridjs/dist/gridjs.umd.js";
import gridjs from "gridjs/dist/gridjs.umd.js"; import gridjs from "gridjs/dist/gridjs.umd.js";
import "gridjs/dist/gridjs.umd.js"; import "gridjs/dist/gridjs.umd.js";
import GlobalConfig from "../global-config.js"; import GlobalConfig, { addThousandSeparators } from "../global-config.js";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
class BusinessIndustries { class BusinessIndustries {
@@ -106,23 +106,25 @@ class BusinessIndustries {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
then: (data) => then: (data) =>
data.data.map((item) => [ data.data.map((item) => {
item.id, return [
item.nama_kecamatan, item.id,
item.nama_kelurahan, item.nama_kecamatan,
item.nop, item.nama_kelurahan,
item.nama_wajib_pajak, item.nop,
item.alamat_wajib_pajak, item.nama_wajib_pajak,
item.alamat_objek_pajak, item.alamat_wajib_pajak,
item.luas_bumi, item.alamat_objek_pajak,
item.luas_bangunan, addThousandSeparators(item.luas_bumi),
item.njop_bumi, addThousandSeparators(item.luas_bangunan),
item.njop_bangunan, addThousandSeparators(item.njop_bumi),
item.ketetapan, addThousandSeparators(item.njop_bangunan),
item.tahun_pajak, addThousandSeparators(item.ketetapan),
item.created_at, item.tahun_pajak,
item.id, // ID for Actions column item.created_at,
]), item.id, // ID for Actions column
];
}),
total: (data) => data.total, total: (data) => data.total,
}, },
}).render(tableContainer); }).render(tableContainer);

View File

@@ -1,7 +1,7 @@
import { Grid } from "gridjs/dist/gridjs.umd.js"; import { Grid } from "gridjs/dist/gridjs.umd.js";
import gridjs from "gridjs/dist/gridjs.umd.js"; import gridjs from "gridjs/dist/gridjs.umd.js";
import "gridjs/dist/gridjs.umd.js"; import "gridjs/dist/gridjs.umd.js";
import GlobalConfig from "../global-config.js"; import GlobalConfig, { addThousandSeparators } from "../global-config.js";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
class DataSettings { class DataSettings {
@@ -10,7 +10,7 @@ class DataSettings {
this.toastElement = document.getElementById("toastNotification"); this.toastElement = document.getElementById("toastNotification");
this.toast = new bootstrap.Toast(this.toastElement); this.toast = new bootstrap.Toast(this.toastElement);
this.table = null; this.table = null;
// Initialize immediately // Initialize immediately
this.init(); this.init();
} }
@@ -29,7 +29,7 @@ class DataSettings {
*/ */
getApiToken() { getApiToken() {
const tokenMeta = document.querySelector('meta[name="api-token"]'); const tokenMeta = document.querySelector('meta[name="api-token"]');
return tokenMeta ? tokenMeta.getAttribute('content') : null; return tokenMeta ? tokenMeta.getAttribute("content") : null;
} }
/** /**
@@ -38,19 +38,21 @@ class DataSettings {
*/ */
getAuthHeaders() { getAuthHeaders() {
const token = this.getApiToken(); const token = this.getApiToken();
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); const csrfToken = document
.querySelector('meta[name="csrf-token"]')
?.getAttribute("content");
const headers = { const headers = {
'Content-Type': 'application/json', "Content-Type": "application/json",
'Accept': 'application/json', Accept: "application/json",
}; };
if (token) { if (token) {
headers['Authorization'] = `Bearer ${token}`; headers["Authorization"] = `Bearer ${token}`;
} }
if (csrfToken) { if (csrfToken) {
headers['X-CSRF-TOKEN'] = csrfToken; headers["X-CSRF-TOKEN"] = csrfToken;
} }
return headers; return headers;
@@ -58,33 +60,37 @@ class DataSettings {
/** /**
* Make API request with authentication * Make API request with authentication
* @param {string} url * @param {string} url
* @param {object} options * @param {object} options
* @returns {Promise} * @returns {Promise}
*/ */
async makeApiRequest(url, options = {}) { async makeApiRequest(url, options = {}) {
const defaultOptions = { const defaultOptions = {
headers: this.getAuthHeaders(), headers: this.getAuthHeaders(),
...options ...options,
}; };
try { try {
const response = await fetch(url, defaultOptions); const response = await fetch(url, defaultOptions);
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`); throw new Error(
`HTTP ${response.status}: ${response.statusText}`
);
} }
return response; return response;
} catch (error) { } catch (error) {
console.error('API Request failed:', error); console.error("API Request failed:", error);
throw error; throw error;
} }
} }
initEvents() { initEvents() {
document.body.addEventListener("click", async (event) => { document.body.addEventListener("click", async (event) => {
const deleteButton = event.target.closest(".btn-delete-data-settings"); const deleteButton = event.target.closest(
".btn-delete-data-settings"
);
if (deleteButton) { if (deleteButton) {
event.preventDefault(); event.preventDefault();
await this.handleDelete(deleteButton); await this.handleDelete(deleteButton);
@@ -99,7 +105,7 @@ class DataSettings {
let canUpdate = tableContainer.getAttribute("data-updater") === "1"; let canUpdate = tableContainer.getAttribute("data-updater") === "1";
let canDelete = tableContainer.getAttribute("data-destroyer") === "1"; let canDelete = tableContainer.getAttribute("data-destroyer") === "1";
let menuId = tableContainer.getAttribute("data-menuId"); let menuId = tableContainer.getAttribute("data-menuId");
// Create a new Grid.js instance // Create a new Grid.js instance
this.table = new Grid({ this.table = new Grid({
columns: [ columns: [
@@ -143,7 +149,9 @@ class DataSettings {
limit: 15, limit: 15,
server: { server: {
url: (prev, page) => url: (prev, page) =>
`${prev}${prev.includes("?") ? "&" : "?"}page=${page + 1}`, `${prev}${prev.includes("?") ? "&" : "?"}page=${
page + 1
}`,
}, },
}, },
sort: true, sort: true,
@@ -160,7 +168,9 @@ class DataSettings {
data.data.map((item) => [ data.data.map((item) => [
item.id, item.id,
item.key, item.key,
item.value, item.type === "decimal"
? addThousandSeparators(item.value, 0)
: item.value,
item.created_at, item.created_at,
item.id, item.id,
]), ]),
@@ -190,7 +200,8 @@ class DataSettings {
); );
const result = await response.json(); const result = await response.json();
this.toastMessage.innerText = result.message || "Deleted successfully!"; this.toastMessage.innerText =
result.message || "Deleted successfully!";
this.toast.show(); this.toast.show();
// Refresh Grid.js table // Refresh Grid.js table
@@ -199,7 +210,8 @@ class DataSettings {
} }
} catch (error) { } catch (error) {
console.error("Error deleting item:", error); console.error("Error deleting item:", error);
this.toastMessage.innerText = error.message || "An error occurred!"; this.toastMessage.innerText =
error.message || "An error occurred!";
this.toast.show(); this.toast.show();
} }
} }

View File

@@ -1,7 +1,7 @@
import { Grid } from "gridjs/dist/gridjs.umd.js"; import { Grid } from "gridjs/dist/gridjs.umd.js";
import gridjs from "gridjs/dist/gridjs.umd.js"; import gridjs from "gridjs/dist/gridjs.umd.js";
import "gridjs/dist/gridjs.umd.js"; import "gridjs/dist/gridjs.umd.js";
import GlobalConfig from "../../global-config.js"; import GlobalConfig, { addThousandSeparators } from "../../global-config.js";
import GeneralTable from "../../table-generator.js"; import GeneralTable from "../../table-generator.js";
// Ambil hak akses dari data-attribute // Ambil hak akses dari data-attribute
@@ -78,7 +78,7 @@ document.addEventListener("DOMContentLoaded", () => {
item.name, item.name,
item.kbli, item.kbli,
item.activities, item.activities,
item.area, addThousandSeparators(item.area),
item.location, item.location,
item.number, item.number,
item.date, item.date,

View File

@@ -1,7 +1,7 @@
import { Grid } from "gridjs/dist/gridjs.umd.js"; import { Grid } from "gridjs/dist/gridjs.umd.js";
import gridjs from "gridjs/dist/gridjs.umd.js"; import gridjs from "gridjs/dist/gridjs.umd.js";
import "gridjs/dist/gridjs.umd.js"; import "gridjs/dist/gridjs.umd.js";
import GlobalConfig from "../../global-config.js"; import GlobalConfig, { addThousandSeparators } from "../../global-config.js";
import GeneralTable from "../../table-generator.js"; import GeneralTable from "../../table-generator.js";
import L from "leaflet"; import L from "leaflet";
import "leaflet/dist/leaflet.css"; import "leaflet/dist/leaflet.css";
@@ -108,7 +108,7 @@ document.addEventListener("DOMContentLoaded", () => {
item.district_name, item.district_name,
item.village_name, item.village_name,
item.land_area_in_m2, item.land_area_in_m2,
item.investment_amount, addThousandSeparators(item.investment_amount),
item.tki, item.tki,
item.longitude, item.longitude,
item.latitude, item.latitude,

View File

@@ -1,24 +1,37 @@
export default GlobalConfig = window.GlobalConfig; export default GlobalConfig = window.GlobalConfig;
export function addThousandSeparators(value, fractionDigits = 2) { export function addThousandSeparators(value, fractionDigits = 2) {
if (!value) return null; // Handle empty or null values if (!value && value !== 0) return null; // Handle empty or null values, but allow 0
// Remove any non-numeric characters except commas and dots // Convert to string first if it's a number
value = value.replace(/[^0-9,.]/g, ""); if (typeof value === "number") {
return new Intl.NumberFormat("en-US", {
// If the value contains multiple dots, assume dots are thousand separators minimumFractionDigits: fractionDigits,
if ((value.match(/\./g) || []).length > 1) { maximumFractionDigits: fractionDigits,
value = value.replace(/\./g, ""); }).format(value);
} }
// Convert to a proper decimal number // If it's already a string, process it
let number = parseFloat(value.replace(",", ".")); if (typeof value === "string") {
// Remove any non-numeric characters except commas and dots
value = value.replace(/[^0-9,.]/g, "");
if (isNaN(number)) return null; // Return null if conversion fails // If the value contains multiple dots, assume dots are thousand separators
if ((value.match(/\./g) || []).length > 1) {
value = value.replace(/\./g, "");
}
// Format the number with thousand separators // Convert to a proper decimal number
return new Intl.NumberFormat("en-US", { let number = parseFloat(value.replace(",", "."));
minimumFractionDigits: fractionDigits,
maximumFractionDigits: fractionDigits, if (isNaN(number)) return null; // Return null if conversion fails
}).format(number);
// Format the number with thousand separators
return new Intl.NumberFormat("en-US", {
minimumFractionDigits: fractionDigits,
maximumFractionDigits: fractionDigits,
}).format(number);
}
return null; // Return null for unsupported types
} }

View File

@@ -18,7 +18,7 @@ class ReportPbgPTSP {
{ name: "Status" }, { name: "Status" },
{ {
name: "Total", name: "Total",
formatter: (cell) => cell, formatter: (cell) => addThousandSeparators(cell),
}, },
], ],
pagination: { pagination: {

View File

@@ -1,5 +1,5 @@
import ApexCharts from "apexcharts"; import ApexCharts from "apexcharts";
import { addThousandSeparators } from "../../global-config.js";
class GrowthReport { class GrowthReport {
init() { init() {
this.loadChart(); this.loadChart();
@@ -65,7 +65,7 @@ class GrowthReport {
}, },
labels: { labels: {
formatter: function (value) { formatter: function (value) {
return "Rp. " + value.toLocaleString("id-ID"); return "Rp. " + addThousandSeparators(value);
}, },
}, },
}, },

View File

@@ -1,5 +1,6 @@
import gridjs from "gridjs/dist/gridjs.umd.js"; import gridjs from "gridjs/dist/gridjs.umd.js";
import "gridjs/dist/gridjs.umd.js"; import "gridjs/dist/gridjs.umd.js";
import { addThousandSeparators } from "../../global-config.js";
// Mengambil data dari input dengan id="business_type_counts" // Mengambil data dari input dengan id="business_type_counts"
const businessTypeCountsElement = document.getElementById("tourism_based_KBLI"); const businessTypeCountsElement = document.getElementById("tourism_based_KBLI");
@@ -8,10 +9,9 @@ const businessTypeCounts = JSON.parse(businessTypeCountsElement.value); // Cek a
// Membuat Grid.js instance // Membuat Grid.js instance
new gridjs.Grid({ new gridjs.Grid({
columns: ["Jenis Bisnis Pariwisata", "Jumlah Total"], // Nama kolom columns: ["Jenis Bisnis Pariwisata", "Jumlah Total"], // Nama kolom
data: businessTypeCounts.map((item) => [ data: businessTypeCounts.map((item) => {
item.kbli_title, return [item.kbli_title, addThousandSeparators(item.total_records)];
item.total_records, }), // Mengubah data untuk Grid.js
]), // Mengubah data untuk Grid.js
search: true, // Menambahkan fitur pencarian search: true, // Menambahkan fitur pencarian
pagination: true, // Menambahkan fitur pagination pagination: true, // Menambahkan fitur pagination
sort: true, // Menambahkan fitur sorting sort: true, // Menambahkan fitur sorting