-
-
- Memuat data...
+
+
+
+
+
+ data per halaman
+
+
+
+
+
+
+
+
+
+
+ | No |
+ Perusahaan |
+ Alamat |
+ Berlaku Hingga |
+
+
+
+
+
+
+
+
+
+
+
Memuat data...
+
+
+
+
+
+
Tidak ada data yang ditemukan
+
+
+
+
diff --git a/wwwroot/website/css/watch.css b/wwwroot/website/css/watch.css
index dbe1f04..436b5f1 100644
--- a/wwwroot/website/css/watch.css
+++ b/wwwroot/website/css/watch.css
@@ -85,17 +85,14 @@
--color-indigo-50: oklch(96.2% 0.018 272.314);
--color-indigo-100: oklch(93% 0.034 272.788);
--color-indigo-300: oklch(78.5% 0.115 274.713);
- --color-indigo-800: oklch(39.8% 0.195 277.366);
--color-purple-50: oklch(97.7% 0.014 308.299);
--color-purple-100: oklch(94.6% 0.033 307.174);
--color-purple-200: oklch(90.2% 0.063 306.703);
--color-purple-500: oklch(62.7% 0.265 303.9);
--color-purple-600: oklch(55.8% 0.288 302.321);
- --color-purple-700: oklch(49.6% 0.265 301.924);
--color-purple-800: oklch(43.8% 0.218 303.724);
--color-purple-900: oklch(38.1% 0.176 304.987);
--color-pink-50: oklch(97.1% 0.014 343.198);
- --color-pink-500: oklch(65.6% 0.241 354.308);
--color-rose-50: oklch(96.9% 0.015 12.422);
--color-rose-500: oklch(64.5% 0.246 16.439);
--color-rose-600: oklch(58.6% 0.253 17.585);
@@ -117,9 +114,6 @@
--color-gray-700: oklch(37.3% 0.034 259.733);
--color-gray-800: oklch(27.8% 0.033 256.848);
--color-gray-900: oklch(21% 0.034 264.665);
- --color-neutral-200: oklch(92.2% 0 0);
- --color-neutral-600: oklch(43.9% 0 0);
- --color-neutral-800: oklch(26.9% 0 0);
--color-black: #000;
--color-white: #fff;
--spacing: 0.25rem;
@@ -408,9 +402,6 @@
.top-0 {
top: calc(var(--spacing) * 0);
}
- .top-1 {
- top: calc(var(--spacing) * 1);
- }
.top-1\/2 {
top: calc(1/2 * 100%);
}
@@ -465,9 +456,6 @@
.right-full {
right: 100%;
}
- .-bottom-0 {
- bottom: calc(var(--spacing) * -0);
- }
.-bottom-0\.5 {
bottom: calc(var(--spacing) * -0.5);
}
@@ -504,9 +492,6 @@
.left-0 {
left: calc(var(--spacing) * 0);
}
- .left-1 {
- left: calc(var(--spacing) * 1);
- }
.left-1\/2 {
left: calc(1/2 * 100%);
}
@@ -624,9 +609,6 @@
.col-span-2 {
grid-column: span 2 / span 2;
}
- .col-span-12 {
- grid-column: span 12 / span 12;
- }
.float-end {
float: inline-end;
}
@@ -918,9 +900,6 @@
.aspect-video {
aspect-ratio: var(--aspect-video);
}
- .h-0 {
- height: calc(var(--spacing) * 0);
- }
.h-0\.5 {
height: calc(var(--spacing) * 0.5);
}
@@ -1095,6 +1074,9 @@
.w-75 {
width: calc(var(--spacing) * 75);
}
+ .w-80 {
+ width: calc(var(--spacing) * 80);
+ }
.w-100 {
width: calc(var(--spacing) * 100);
}
@@ -1161,9 +1143,6 @@
.shrink {
flex-shrink: 1;
}
- .shrink-0 {
- flex-shrink: 0;
- }
.flex-grow {
flex-grow: 1;
}
@@ -1185,16 +1164,9 @@
.border-collapse {
border-collapse: collapse;
}
- .border-separate {
- border-collapse: separate;
- }
.origin-top {
transform-origin: top;
}
- .-translate-x-1 {
- --tw-translate-x: calc(var(--spacing) * -1);
- translate: var(--tw-translate-x) var(--tw-translate-y);
- }
.-translate-x-1\/2 {
--tw-translate-x: calc(calc(1/2 * 100%) * -1);
translate: var(--tw-translate-x) var(--tw-translate-y);
@@ -1207,10 +1179,6 @@
--tw-translate-x: calc(var(--spacing) * 16);
translate: var(--tw-translate-x) var(--tw-translate-y);
}
- .-translate-y-1 {
- --tw-translate-y: calc(var(--spacing) * -1);
- translate: var(--tw-translate-x) var(--tw-translate-y);
- }
.-translate-y-1\/2 {
--tw-translate-y: calc(calc(1/2 * 100%) * -1);
translate: var(--tw-translate-x) var(--tw-translate-y);
@@ -1289,9 +1257,6 @@
.grid-cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
- .grid-cols-12 {
- grid-template-columns: repeat(12, minmax(0, 1fr));
- }
.flex-col {
flex-direction: column;
}
@@ -1397,6 +1362,13 @@
margin-block-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)));
}
}
+ .space-x-1 {
+ :where(& > :not(:last-child)) {
+ --tw-space-x-reverse: 0;
+ margin-inline-start: calc(calc(var(--spacing) * 1) * var(--tw-space-x-reverse));
+ margin-inline-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-x-reverse)));
+ }
+ }
.space-x-2 {
:where(& > :not(:last-child)) {
--tw-space-x-reverse: 0;
@@ -1651,9 +1623,6 @@
border-color: color-mix(in oklab, var(--color-cyan-600) 50%, transparent);
}
}
- .border-cyan-700 {
- border-color: var(--color-cyan-700);
- }
.border-cyan-700\/50 {
border-color: color-mix(in srgb, oklch(52% 0.105 223.128) 50%, transparent);
@supports (color: color-mix(in lab, red, red)) {
@@ -1693,9 +1662,6 @@
.border-green-400 {
border-color: var(--color-green-400);
}
- .border-neutral-200 {
- border-color: var(--color-neutral-200);
- }
.border-orange-200 {
border-color: var(--color-orange-200);
}
@@ -1807,9 +1773,6 @@
.bg-blue-600 {
background-color: var(--color-blue-600);
}
- .bg-current {
- background-color: currentcolor;
- }
.bg-cyan-50 {
background-color: var(--color-cyan-50);
}
@@ -1825,6 +1788,9 @@
.bg-cyan-500 {
background-color: var(--color-cyan-500);
}
+ .bg-cyan-600 {
+ background-color: var(--color-cyan-600);
+ }
.bg-cyan-700 {
background-color: var(--color-cyan-700);
}
@@ -2247,6 +2213,10 @@
--tw-gradient-to: var(--color-emerald-600);
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
}
+ .to-gray-50 {
+ --tw-gradient-to: var(--color-gray-50);
+ --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
+ }
.to-gray-100 {
--tw-gradient-to: var(--color-gray-100);
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
@@ -2571,6 +2541,9 @@
.pl-9 {
padding-left: calc(var(--spacing) * 9);
}
+ .pl-10 {
+ padding-left: calc(var(--spacing) * 10);
+ }
.text-center {
text-align: center;
}
@@ -2694,9 +2667,6 @@
.break-all {
word-break: break-all;
}
- .whitespace-nowrap {
- white-space: nowrap;
- }
.text-amber-400 {
color: var(--color-amber-400);
}
@@ -2796,9 +2766,6 @@
.text-green-900 {
color: var(--color-green-900);
}
- .text-neutral-800 {
- color: var(--color-neutral-800);
- }
.text-orange-100 {
color: var(--color-orange-100);
}
@@ -2826,6 +2793,9 @@
.text-purple-900 {
color: var(--color-purple-900);
}
+ .text-red-400 {
+ color: var(--color-red-400);
+ }
.text-red-500 {
color: var(--color-red-500);
}
@@ -3085,10 +3055,6 @@
--tw-outline-style: none;
outline-style: none;
}
- .select-all {
- -webkit-user-select: all;
- user-select: all;
- }
.select-none {
-webkit-user-select: none;
user-select: none;
@@ -3228,6 +3194,13 @@
}
}
}
+ .hover\:border-cyan-300 {
+ &:hover {
+ @media (hover: hover) {
+ border-color: var(--color-cyan-300);
+ }
+ }
+ }
.hover\:border-cyan-400 {
&:hover {
@media (hover: hover) {
@@ -3284,6 +3257,13 @@
}
}
}
+ .hover\:bg-cyan-50 {
+ &:hover {
+ @media (hover: hover) {
+ background-color: var(--color-cyan-50);
+ }
+ }
+ }
.hover\:bg-cyan-500 {
&:hover {
@media (hover: hover) {
@@ -3298,6 +3278,13 @@
}
}
}
+ .hover\:bg-cyan-700 {
+ &:hover {
+ @media (hover: hover) {
+ background-color: var(--color-cyan-700);
+ }
+ }
+ }
.hover\:bg-gray-50 {
&:hover {
@media (hover: hover) {
@@ -3700,6 +3687,20 @@
max-width: var(--container-md);
}
}
+ .sm\:flex-row {
+ @media (width >= 40rem) {
+ flex-direction: row;
+ }
+ }
+ .sm\:space-y-0 {
+ @media (width >= 40rem) {
+ :where(& > :not(:last-child)) {
+ --tw-space-y-reverse: 0;
+ margin-block-start: calc(calc(var(--spacing) * 0) * var(--tw-space-y-reverse));
+ margin-block-end: calc(calc(var(--spacing) * 0) * calc(1 - var(--tw-space-y-reverse)));
+ }
+ }
+ }
.sm\:space-y-6 {
@media (width >= 40rem) {
:where(& > :not(:last-child)) {
@@ -3709,6 +3710,15 @@
}
}
}
+ .sm\:space-x-4 {
+ @media (width >= 40rem) {
+ :where(& > :not(:last-child)) {
+ --tw-space-x-reverse: 0;
+ margin-inline-start: calc(calc(var(--spacing) * 4) * var(--tw-space-x-reverse));
+ margin-inline-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-x-reverse)));
+ }
+ }
+ }
.sm\:rounded-3xl {
@media (width >= 40rem) {
border-radius: var(--radius-3xl);
@@ -3972,16 +3982,6 @@
padding-inline: calc(var(--spacing) * 8);
}
}
- .dark\:border-neutral-600 {
- @media (prefers-color-scheme: dark) {
- border-color: var(--color-neutral-600);
- }
- }
- .dark\:text-white {
- @media (prefers-color-scheme: dark) {
- color: var(--color-white);
- }
- }
}
@property --tw-translate-x {
syntax: "*";
diff --git a/wwwroot/website/js/datatables_pengolahan.js b/wwwroot/website/js/datatables_pengolahan.js
index fb58325..f62d8b3 100644
--- a/wwwroot/website/js/datatables_pengolahan.js
+++ b/wwwroot/website/js/datatables_pengolahan.js
@@ -1,353 +1,523 @@
-document.addEventListener("DOMContentLoaded", function () {
- initializePengolahanDataTable();
-});
+class CustomTable {
+ constructor(tableId, apiUrl) {
+ this.tableId = tableId;
+ this.apiUrl = apiUrl;
+ this.currentPage = 1;
+ this.pageSize = 10;
+ this.draw = 1;
+ this.searchTerm = "";
+ this.totalRecords = 0;
+ this.filteredRecords = 0;
+ this.data = [];
+ this.isLoading = false;
+ this.paginationClickTimeout = null;
-// helper: parse date string in format dd/mm/yyyy to a Date object (local)
-function parseDateDMY(dateStr) {
- if (!dateStr) return new Date(dateStr);
- // accept either dd/mm/yyyy or ISO
- if (dateStr.indexOf("/") !== -1) {
- const parts = dateStr.split("/");
- // parts[0]=dd, [1]=mm, [2]=yyyy
- const d = parseInt(parts[0], 10);
- const m = parseInt(parts[1], 10) - 1;
- const y = parseInt(parts[2], 10);
- return new Date(y, m, d);
+ this.init();
}
- return new Date(dateStr);
-}
-function initializePengolahanDataTable() {
- if (!document.getElementById("pengolahanTable")) return;
+ init() {
+ this.injectStyles();
+ this.createTableStructure();
+ this.createPaginationControls();
+ this.createSearchInput();
+ this.bindEvents();
+ this.loadData();
+ }
- if (typeof $ !== "undefined" && $.fn.DataTable) {
- $("#pengolahanTable").DataTable({
- ajax: {
- url: "/api/web/jasa/olah",
- type: "POST",
- dataSrc: function (json) {
- if (!json) return [];
- return json.data || json;
- },
- error: function (xhr, error, thrown) {
- console.error("Error fetching pengolahan data:", error || thrown);
- },
- },
- columns: [
- {
- data: null,
- className: "px-3 py-4 text-sm text-gray-900 text-center font-medium",
- title: "No",
- width: "5%",
- render: function (data, type, row, meta) {
- return meta.row + 1;
- },
- },
- {
- data: "nama",
- className: "px-3 py-4 text-sm text-gray-900 font-medium break-words",
- title: "Nama Perusahaan",
- width: "25%",
- },
- {
- data: "alamat",
- className: "px-3 py-4 text-sm text-gray-700 break-words",
- title: "Alamat",
- width: "50%",
- },
- {
- data: "tglBerlakuIzin",
- className: "px-3 py-4 text-sm text-gray-900 text-center",
- title: "Berlaku Hingga",
- width: "20%",
- render: function (data, type, row) {
- if (type === "display") {
- const date = parseDateDMY(data);
- const formattedDate = date.toLocaleDateString("id-ID", {
- year: "numeric",
- month: "2-digit",
- day: "2-digit",
- });
-
- const today = new Date();
- const expiry = parseDateDMY(data);
- const daysUntilExpiry = Math.ceil(
- (expiry - today) / (1000 * 60 * 60 * 24)
- );
-
- let statusClass = "bg-green-100 text-green-800";
- if (daysUntilExpiry < 30) {
- statusClass = "bg-red-100 text-red-800";
- } else if (daysUntilExpiry < 90) {
- statusClass = "bg-yellow-100 text-yellow-800";
- }
-
- return `
-
${formattedDate}
-
- ${
- daysUntilExpiry > 0
- ? `${daysUntilExpiry} hari`
- : "Expired"
- }
-
-
`;
+ injectStyles() {
+ const styles = `
+
+ `;
- const wrapper = $(".dataTables_wrapper");
+ const existingStyles = document.getElementById("custom-table-styles");
+ if (existingStyles) {
+ existingStyles.remove();
+ }
+ document.head.insertAdjacentHTML("beforeend", styles);
+ }
- wrapper
- .find('input[type="search"]')
- .addClass(
- "block w-full px-4 py-2 text-sm border border-gray-300 rounded-lg bg-white focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200"
- )
- .attr("placeholder", "Cari perusahaan pengolahan...");
+ createTableStructure() {
+ const table = document.getElementById(this.tableId);
+ table.classList.add("modern-table");
- wrapper
- .find("select")
- .addClass(
- "px-3 py-2 text-sm border border-gray-300 rounded-lg bg-white focus:ring-2 focus:ring-blue-500 focus:border-transparent"
- );
+ let tbody = table.querySelector("tbody");
+ if (tbody) {
+ tbody.id = `${this.tableId}-tbody`;
+ }
- wrapper
- .find(".dt-paging .dt-paging-button")
- .addClass(
- "px-3 py-2 mx-1 text-sm border border-gray-300 rounded-md bg-white text-gray-700 hover:bg-blue-50 hover:text-blue-600 hover:border-blue-300 transition-all duration-200"
- );
+ this.showLoading();
+ }
- wrapper
- .find(".dt-paging .dt-paging-button.current")
- .addClass("bg-blue-600 text-white border-blue-600 hover:bg-blue-700")
- .removeClass("bg-white text-gray-700");
+ createSearchInput() {}
- wrapper
- .find(".dt-paging .dt-paging-button.disabled")
- .addClass("opacity-50 cursor-not-allowed");
+ createPaginationControls() {}
- if (window.innerWidth <= 768) {
- wrapper.find(".dt-paging").addClass("text-center");
- wrapper.find(".dt-info").addClass("text-center text-sm");
- wrapper.find(".dt-length").addClass("text-center");
- wrapper.find(".dt-search").addClass("text-center");
+ bindEvents() {
+ const searchInput = document.getElementById("searchInput");
+ const pageSizeSelect = document.getElementById("perPage");
+
+ if (searchInput) {
+ searchInput.addEventListener("keypress", (e) => {
+ if (e.key === "Enter") {
+ this.searchTerm = searchInput.value;
+ this.currentPage = 1;
+ this.draw++;
+ this.loadData();
}
+ });
- wrapper.find(".dt-length").addClass("flex items-center space-x-2");
- wrapper.find(".dt-search").addClass("flex items-center space-x-2");
- wrapper.find(".dt-info").addClass("text-sm text-gray-600");
+ searchInput.addEventListener("input", (e) => {
+ clearTimeout(this.searchTimeout);
+ this.searchTimeout = setTimeout(() => {
+ this.searchTerm = searchInput.value;
+ this.currentPage = 1;
+ this.draw++;
+ this.loadData();
+ }, 500);
+ });
+ }
- $("#pengolahanTable").removeClass("dataTable").addClass("w-full");
- $("#pengolahanTable thead th").addClass(
- "bg-cyan-400 text-white font-semibold text-sm uppercase tracking-wider border-b"
- );
-
- wrapper.find(".dtr-control").remove();
-
- $("#pengolahanTable tbody tr").addClass("transition-all duration-200");
-
- $(window).on("resize", function () {
- const wrapper = $(".dataTables_wrapper");
- if (window.innerWidth <= 768) {
- wrapper.find(".dt-paging").addClass("text-center");
- wrapper.find(".dt-info").addClass("text-center text-sm");
- wrapper.find(".dt-length").addClass("text-center");
- wrapper.find(".dt-search").addClass("text-center");
- } else {
- wrapper.find(".dt-paging").removeClass("text-center");
- wrapper.find(".dt-info").removeClass("text-center text-sm");
- wrapper.find(".dt-length").removeClass("text-center");
- wrapper.find(".dt-search").removeClass("text-center");
- }
- });
- },
- drawCallback: function () {
- $("#pengolahanTable tbody tr")
- .removeClass("bg-blue-50")
- .hover(
- function () {
- $(this).addClass(
- "bg-blue-50 shadow-sm transform transition-all duration-200"
- );
- },
- function () {
- $(this).removeClass("bg-blue-50 shadow-sm transform");
- }
- );
-
- $("#pengolahanTable tbody tr:even").addClass("bg-gray-50");
- $("#pengolahanTable tbody tr:odd").addClass("bg-white");
- },
- });
- } else {
- loadPengolahanDataManually();
+ if (pageSizeSelect) {
+ pageSizeSelect.addEventListener("change", (e) => {
+ this.pageSize = parseInt(e.target.value);
+ this.currentPage = 1;
+ this.draw++;
+ this.loadData();
+ });
+ }
}
-}
-function loadPengolahanDataManually() {
- fetch("/website/data/pengolahan-data.json")
- .then((response) => {
+ async loadData() {
+ if (this.isLoading) {
+ console.log("Already loading, skipping...");
+ return;
+ }
+
+ console.log("Starting loadData...", {
+ currentPage: this.currentPage,
+ pageSize: this.pageSize,
+ searchTerm: this.searchTerm,
+ draw: this.draw,
+ });
+
+ this.isLoading = true;
+ this.showLoading();
+
+ try {
+ const start = (this.currentPage - 1) * this.pageSize;
+
+ const formData = new URLSearchParams();
+ formData.append("draw", this.draw.toString());
+ formData.append("start", start.toString());
+ formData.append("length", this.pageSize.toString());
+
+ if (this.searchTerm) {
+ formData.append("search[value]", this.searchTerm);
+ }
+
+ const response = await fetch(this.apiUrl, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded",
+ },
+ body: formData,
+ });
+
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
- return response.json();
- })
- .then((data) => {
- const tbody = document.querySelector("#pengolahanTable tbody");
- tbody.innerHTML = "";
- data.forEach((item, index) => {
- const row = document.createElement("tr");
- row.className = `${
- index % 2 === 0 ? "bg-gray-50" : "bg-white"
- } hover:bg-blue-50 transition-all duration-200`;
+ const result = await response.json();
- const date = parseDateDMY(item.tglBerlakuIzin);
- const formattedDate = date.toLocaleDateString("id-ID", {
- year: "numeric",
- month: "2-digit",
- day: "2-digit",
- });
+ this.data = result.data || [];
+ this.totalRecords = result.recordsTotal || 0;
+ this.filteredRecords = result.recordsFiltered || 0;
- const today = new Date();
- const expiry = new Date(item.tglBerlakuIzin);
- const daysUntilExpiry = Math.ceil(
- (expiry - today) / (1000 * 60 * 60 * 24)
- );
-
- let statusClass = "bg-green-100 text-green-800";
- let statusText = `${daysUntilExpiry} hari`;
-
- if (daysUntilExpiry < 0) {
- statusClass = "bg-red-100 text-red-800";
- statusText = "Expired";
- } else if (daysUntilExpiry < 30) {
- statusClass = "bg-red-100 text-red-800";
- } else if (daysUntilExpiry < 90) {
- statusClass = "bg-yellow-100 text-yellow-800";
- }
-
- row.innerHTML = `
-
${
- index + 1
- } |
-
${
- item.nama
- } |
-
${
- item.alamat
- } |
-
- ${formattedDate}
-
- ${statusText}
-
- |
- `;
-
- tbody.appendChild(row);
+ console.log("Data loaded successfully:", {
+ dataLength: this.data.length,
+ totalRecords: this.totalRecords,
+ filteredRecords: this.filteredRecords,
});
- const loadingIndicator = document.getElementById("loadingIndicator");
- if (loadingIndicator) {
- loadingIndicator.style.display = "none";
- }
-
- addManualSearch(data);
- })
- .catch((error) => {
+ this.renderTable();
+ this.renderPagination();
+ this.hideLoading();
+ } catch (error) {
console.error("Error loading data:", error);
- const loadingIndicator = document.getElementById("loadingIndicator");
- if (loadingIndicator) {
- loadingIndicator.innerHTML = `
-
-
- Error memuat data: ${error.message}
-
- `;
- }
- });
-}
+ this.showError("Gagal memuat data. Silakan coba lagi.");
+ } finally {
+ this.isLoading = false;
+ }
+ }
-function addManualSearch(data) {
- const tableContainer = document
- .querySelector("#pengolahanTable")
- .closest(".bg-white");
- if (!document.getElementById("manualSearchInput")) {
- const searchContainer = document.createElement("div");
- searchContainer.className = "mb-4 flex justify-end";
- searchContainer.innerHTML = `
-
- `;
+ showLoading() {
+ const loadingIndicator = document.getElementById("loadingIndicator");
+ const emptyState = document.getElementById("emptyState");
+ const tableContainer = document.querySelector(".overflow-x-auto");
+ const pagination = document.getElementById("pagination");
- tableContainer.insertBefore(
- searchContainer,
- document.querySelector(".overflow-x-auto")
- );
+ if (loadingIndicator) loadingIndicator.classList.remove("hidden");
+ if (emptyState) emptyState.classList.add("hidden");
+ if (tableContainer) tableContainer.style.display = "none";
- document
- .getElementById("manualSearchInput")
- .addEventListener("input", function (e) {
- const searchTerm = e.target.value.toLowerCase();
- const rows = document.querySelectorAll("#pengolahanTable tbody tr");
-
- rows.forEach((row) => {
- const text = row.textContent.toLowerCase();
- if (text.includes(searchTerm)) {
- row.style.display = "";
- } else {
- row.style.display = "none";
- }
- });
+ if (pagination) {
+ const buttons = pagination.querySelectorAll("button");
+ buttons.forEach((btn) => {
+ btn.style.opacity = "0.5";
+ btn.style.pointerEvents = "none";
});
+ }
+ }
+
+ showError(message) {
+ const loadingIndicator = document.getElementById("loadingIndicator");
+ const emptyState = document.getElementById("emptyState");
+ const tableContainer = document.querySelector(".overflow-x-auto");
+
+ if (loadingIndicator) {
+ loadingIndicator.classList.add("hidden");
+ }
+ if (emptyState) {
+ emptyState.classList.remove("hidden");
+ emptyState.innerHTML = `
+
+ `;
+ }
+ if (tableContainer) tableContainer.style.display = "none";
+ }
+
+ hideLoading() {
+ const loadingIndicator = document.getElementById("loadingIndicator");
+ const emptyState = document.getElementById("emptyState");
+ const tableContainer = document.querySelector(".overflow-x-auto");
+ const pagination = document.getElementById("pagination");
+
+ if (loadingIndicator) loadingIndicator.classList.add("hidden");
+ if (emptyState) emptyState.classList.add("hidden");
+ if (tableContainer) tableContainer.style.display = "block";
+
+ if (pagination) {
+ const buttons = pagination.querySelectorAll("button");
+ buttons.forEach((btn) => {
+ if (!btn.hasAttribute("disabled")) {
+ btn.style.opacity = "1";
+ btn.style.pointerEvents = "auto";
+ }
+ });
+ }
+ }
+
+ renderTable() {
+ const tbody =
+ document.querySelector(`#${this.tableId} tbody`) ||
+ document.getElementById(`${this.tableId}-tbody`);
+ const emptyState = document.getElementById("emptyState");
+ const tableContainer = document.querySelector(".overflow-x-auto");
+
+ if (this.data.length === 0) {
+ if (tableContainer) tableContainer.style.display = "none";
+ if (emptyState) emptyState.classList.remove("hidden");
+ this.updateTableInfo();
+ this.renderPagination();
+ return;
+ }
+
+ if (tableContainer) tableContainer.style.display = "block";
+ if (emptyState) emptyState.classList.add("hidden");
+
+ const start = (this.currentPage - 1) * this.pageSize;
+ let html = "";
+
+ this.data.forEach((row, index) => {
+ const no = start + index + 1;
+ const dateInfo = this.formatDate(row.tglBerlakuIzin);
+
+ html += `
+
+ | ${no} |
+
+ ${this.escapeHtml(
+ row.nama || "-"
+ )}
+ |
+
+ ${this.escapeHtml(
+ row.alamat || "-"
+ )}
+ |
+
+
+ ${
+ dateInfo.formatted
+ }
+
+ ${dateInfo.statusText}
+
+
+ |
+
+ `;
+ });
+
+ tbody.innerHTML = html;
+
+ this.updateTableInfo();
+ }
+
+ renderPagination() {
+ const container = document.getElementById("pagination");
+ const totalPages = Math.ceil(this.filteredRecords / this.pageSize);
+
+ if (!container) return;
+
+ let paginationHtml = "";
+
+ paginationHtml += `
+
+ `;
+
+ const startPage = Math.max(1, this.currentPage - 2);
+ const endPage = Math.min(totalPages, this.currentPage + 2);
+
+ if (startPage > 1) {
+ paginationHtml += `
`;
+ if (startPage > 2) {
+ paginationHtml += `
...`;
+ }
+ }
+
+ for (let i = startPage; i <= endPage; i++) {
+ paginationHtml += `
+
+ `;
+ }
+
+ if (endPage < totalPages) {
+ if (endPage < totalPages - 1) {
+ paginationHtml += `
...`;
+ }
+ paginationHtml += `
`;
+ }
+
+ paginationHtml += `
+
+ `;
+
+ container.innerHTML = paginationHtml;
+
+ if (container._clickHandler) {
+ container.removeEventListener("click", container._clickHandler);
+ }
+ if (container._touchHandler) {
+ container.removeEventListener("touchstart", container._touchHandler);
+ }
+ if (container._touchEndHandler) {
+ container.removeEventListener("touchend", container._touchEndHandler);
+ }
+
+ container._clickHandler = (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+
+ console.log("Pagination clicked:", e.target);
+
+ let clickedButton = e.target;
+ if (e.target.tagName === "SVG" || e.target.tagName === "PATH") {
+ clickedButton = e.target.closest("button");
+ }
+
+ if (
+ clickedButton &&
+ clickedButton.tagName === "BUTTON" &&
+ clickedButton.dataset.page
+ ) {
+ console.log("Button clicked:", {
+ page: clickedButton.dataset.page,
+ disabled: clickedButton.disabled,
+ hasAttribute: clickedButton.hasAttribute("disabled"),
+ });
+
+ const page = parseInt(clickedButton.dataset.page);
+
+ if (
+ page &&
+ page !== this.currentPage &&
+ page >= 1 &&
+ page <= totalPages &&
+ !clickedButton.disabled &&
+ !clickedButton.hasAttribute("disabled") &&
+ !this.isLoading
+ ) {
+ console.log("Navigating to page:", page);
+
+ if (this.paginationClickTimeout) {
+ clearTimeout(this.paginationClickTimeout);
+ }
+
+ this.paginationClickTimeout = setTimeout(() => {
+ this.currentPage = page;
+ this.draw++;
+ this.loadData();
+ }, 100);
+ } else {
+ console.log("Click ignored:", {
+ samePage: page === this.currentPage,
+ outOfRange: page < 1 || page > totalPages,
+ disabled:
+ clickedButton.disabled || clickedButton.hasAttribute("disabled"),
+ loading: this.isLoading,
+ });
+ }
+ }
+ };
+
+ container._touchHandler = (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+ };
+
+ container.addEventListener("click", container._clickHandler);
+ container.addEventListener("touchstart", container._touchHandler, {
+ passive: false,
+ });
+
+ container._touchEndHandler = (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+ };
+ container.addEventListener("touchend", container._touchEndHandler, {
+ passive: false,
+ });
+ }
+
+ updateTableInfo() {
+ const infoContainer = document.getElementById("tableInfo");
+ if (infoContainer) {
+ const start = (this.currentPage - 1) * this.pageSize + 1;
+ const end = Math.min(
+ this.currentPage * this.pageSize,
+ this.filteredRecords
+ );
+ infoContainer.innerHTML = `Menampilkan ${start} hingga ${end} dari ${this.filteredRecords} data`;
+ }
+ }
+
+ formatDate(dateString) {
+ if (!dateString || dateString === "0001-01-01") {
+ return {
+ formatted: "-",
+ statusClass: "bg-gray-100 text-gray-800",
+ statusText: "Tidak diketahui",
+ };
+ }
+
+ try {
+ const date = new Date(dateString);
+ const formattedDate = date.toLocaleDateString("id-ID", {
+ year: "numeric",
+ month: "2-digit",
+ day: "2-digit",
+ });
+
+ const today = new Date();
+ const daysUntilExpiry = Math.ceil((date - today) / (1000 * 60 * 60 * 24));
+
+ let statusClass = "bg-green-100 text-green-800";
+ let statusText = `${daysUntilExpiry} hari`;
+
+ if (daysUntilExpiry < 0) {
+ statusClass = "bg-red-100 text-red-800";
+ statusText = "Expired";
+ } else if (daysUntilExpiry < 30) {
+ statusClass = "bg-red-100 text-red-800";
+ } else if (daysUntilExpiry < 90) {
+ statusClass = "bg-yellow-100 text-yellow-800";
+ }
+
+ return {
+ formatted: formattedDate,
+ statusClass: statusClass,
+ statusText: statusText,
+ };
+ } catch (error) {
+ return {
+ formatted: dateString,
+ statusClass: "bg-gray-100 text-gray-800",
+ statusText: "Invalid",
+ };
+ }
+ }
+
+ escapeHtml(text) {
+ const div = document.createElement("div");
+ div.textContent = text;
+ return div.innerHTML;
}
}
+
+document.addEventListener("DOMContentLoaded", function () {
+ const tableElement = document.getElementById("pengolahanTable");
+ if (tableElement && !tableElement.customTableInitialized) {
+ tableElement.customTableInitialized = true;
+ console.log("Initializing CustomTable...");
+ new CustomTable(
+ "pengolahanTable",
+ "https://pesapakawan.dinaslhdki.id/api/web/jasa/olah"
+ );
+ }
+});