@puninar-logistics/pds-sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # PDS SDK
2
+ **@puninar-logistics/pds-sdk**
3
+
4
+ SDK internal yang berisi shared components, hooks, utilities, dan design system yang digunakan lintas project frontend di lingkungan PDS.
5
+
6
+ ---
7
+
8
+ ## 🎯 Tujuan
9
+
10
+ - Menyediakan komponen UI yang konsisten lintas project
11
+ - Mengurangi duplikasi kode
12
+ - Menjadi single source of truth untuk design system dan shared logic
13
+
14
+ ---
15
+
16
+ ## 📦 Tech Stack
17
+
18
+ | Teknologi | Deskripsi |
19
+ |----------|-----------|
20
+ | React 19 | Library UI |
21
+ | TypeScript | Static typing |
22
+ | Vite | Dev & testing |
23
+ | Tsup | Build SDK |
24
+ | shadcn/ui | UI system |
25
+ | Tailwind CSS | Styling |
26
+
27
+ ---
28
+
29
+ ## 📁 Struktur Folder
30
+
31
+ ```
32
+ src/
33
+ ├─ api/
34
+ ├─ assets/
35
+ ├─ auth/
36
+ ├─ components/
37
+ │ ├─ animation/
38
+ │ ├─ core/ # custom components internal
39
+ │ ├─ error-pages/
40
+ │ ├─ form/
41
+ │ ├─ ui/ # shadcn components
42
+ │ └─ other/
43
+ ├─ hoc/
44
+ ├─ hooks/
45
+ ├─ lib/
46
+ ├─ types/
47
+ ├─ utils/ # helper & formatter functions
48
+ ├─ global.css
49
+ ├─ custom.css
50
+ ├─ App.tsx
51
+ ├─ main.tsx
52
+ └─ index.ts
53
+ ```
54
+
55
+ ---
56
+
57
+ ## 🛠 Scripts
58
+
59
+ | Command | Fungsi |
60
+ |--------|---------|
61
+ | `npm run dev` | Jalankan Vite untuk test SDK |
62
+ | `npm run watch` | Watch & rebuild SDK dengan Tsup |
63
+ | `npm run build-tsup` | Build SDK production |
64
+ | `npm run lint` | Lint |
65
+
66
+ ---
67
+
68
+ ## 🔗 Local Development Setup
69
+
70
+ ### 1. Install & Link SDK
71
+
72
+ ```bash
73
+ cd pds-sdk
74
+ npm install
75
+ npm link
76
+ ```
77
+
78
+ ---
79
+
80
+ ### 2. Jalankan Watch Mode
81
+
82
+ ```bash
83
+ npm run watch
84
+ ```
85
+
86
+ ---
87
+
88
+ ### 3. Gunakan SDK di Project Lain
89
+
90
+ ```bash
91
+ npm uninstall @puninar-logistics/pds-sdk
92
+ npm link @puninar-logistics/pds-sdk
93
+ ```
94
+
95
+ ---
96
+
97
+ ## ⚙️ Troubleshooting
98
+
99
+ ### SDK tidak ter-update di project
100
+
101
+ - Pastikan `npm run watch` berjalan
102
+ - Pastikan tidak ada error build
103
+ - Relink jika perlu:
104
+
105
+ ```bash
106
+ npm unlink @puninar-logistics/pds-sdk
107
+ npm link @puninar-logistics/pds-sdk
108
+ ```
109
+
110
+ ---
111
+
112
+ ## 🧪 Development Notes
113
+
114
+ - Gunakan export dari `src/index.ts` sebagai public API
115
+ - Hindari import internal path langsung (`src/components/...`)
116
+ - Selalu bump version jika ada breaking changes
117
+
118
+ ---
119
+
120
+ ## 📄 License
121
+
122
+ Internal — PT Puninar Logistics.
123
+
124
+ ---
125
+
126
+ ## 👨‍💻 Maintainer
127
+
128
+ Frontend Team — PDS
@@ -0,0 +1,441 @@
1
+ // src/utils/localStorage.ts
2
+ var setLocalStorage = (key, value) => {
3
+ try {
4
+ const serializedValue = typeof value === "string" ? value : JSON.stringify(value);
5
+ localStorage.setItem(key, serializedValue);
6
+ } catch (error) {
7
+ console.error(`Gagal menyimpan ke localStorage: ${key}`, error);
8
+ }
9
+ };
10
+ var getLocalStorage = (key, defaultValue = null) => {
11
+ try {
12
+ const value = localStorage.getItem(key);
13
+ if (value === null) return defaultValue;
14
+ try {
15
+ return JSON.parse(value);
16
+ } catch {
17
+ return value;
18
+ }
19
+ } catch (error) {
20
+ console.error(`Gagal membaca dari localStorage: ${key}`, error);
21
+ return defaultValue;
22
+ }
23
+ };
24
+ var removeLocalStorage = (key) => {
25
+ try {
26
+ localStorage.removeItem(key);
27
+ } catch (error) {
28
+ console.error(`Gagal menghapus localStorage: ${key}`, error);
29
+ }
30
+ };
31
+ var clearLocalStorage = () => {
32
+ try {
33
+ localStorage.clear();
34
+ } catch (error) {
35
+ console.error("Gagal membersihkan localStorage", error);
36
+ }
37
+ };
38
+
39
+ // src/utils/accessCheck.ts
40
+ var getByPath = (obj, path) => {
41
+ const keys = path.split(".");
42
+ let current = obj;
43
+ for (const key of keys) {
44
+ if (current == null || !(key in current)) return null;
45
+ current = current[key];
46
+ }
47
+ return current;
48
+ };
49
+ var accessCheck = (keyPath, requiredAccess) => {
50
+ try {
51
+ const list = getLocalStorage("menu-access");
52
+ if (!list) return false;
53
+ const accessRoot = Object.assign({}, ...list);
54
+ const node = getByPath(accessRoot, keyPath);
55
+ if (!node || !Array.isArray(node.access)) return false;
56
+ const userAccessList = node.access;
57
+ if (Array.isArray(requiredAccess)) {
58
+ return requiredAccess.some((a) => userAccessList.includes(a));
59
+ }
60
+ return userAccessList.includes(requiredAccess);
61
+ } catch (error) {
62
+ console.error("Invalid menu-access format:", error);
63
+ return false;
64
+ }
65
+ };
66
+
67
+ // src/utils/aliasBundlingTypeArchive.ts
68
+ var aliasBundlingTypeArchive = (bundlingTypeArchive) => {
69
+ const alias = {
70
+ TRUCKING_ONLY: "Trucking Only",
71
+ CUSTOMS_CLEARANCE: "Customs Clearance"
72
+ };
73
+ return bundlingTypeArchive ? alias[bundlingTypeArchive] : "N/A";
74
+ };
75
+
76
+ // src/utils/base64DecodeWithSecret.ts
77
+ function base64DecodeWithSecret(encodedData, secretKey) {
78
+ const decodedData = atob(encodedData);
79
+ const originalData = decodedData.slice(0, -secretKey.length);
80
+ return JSON.parse(originalData);
81
+ }
82
+
83
+ // src/utils/convertToArrayOfObject.ts
84
+ function convertToArrayOfObject(arr, fields) {
85
+ if (!Array.isArray(arr) || arr.length === 0) {
86
+ return [];
87
+ }
88
+ return arr.map((item) => {
89
+ if (typeof item !== "string") return {};
90
+ const parts = item.split("|");
91
+ const obj = {};
92
+ parts.forEach((value, index) => {
93
+ const key = fields && fields[index] ? fields[index] : `field${index + 1}`;
94
+ obj[key] = value?.trim?.() ?? "";
95
+ });
96
+ return obj;
97
+ });
98
+ }
99
+
100
+ // src/utils/dateFormat.ts
101
+ function formatDateTime(date) {
102
+ const day = String(date.getDate()).padStart(2, "0");
103
+ const year = date.getFullYear();
104
+ const months = [
105
+ "Januari",
106
+ "Februari",
107
+ "Maret",
108
+ "April",
109
+ "Mei",
110
+ "Juni",
111
+ "Juli",
112
+ "Agustus",
113
+ "September",
114
+ "Oktober",
115
+ "November",
116
+ "Desember"
117
+ ];
118
+ const month = months[date.getMonth()];
119
+ const hours = String(date.getHours()).padStart(2, "0");
120
+ const minutes = String(date.getMinutes()).padStart(2, "0");
121
+ const seconds = String(date.getSeconds()).padStart(2, "0");
122
+ return `${day} ${month} ${year}, ${hours}:${minutes}:${seconds}`;
123
+ }
124
+
125
+ // src/utils/decodeFlateBase64.ts
126
+ import pako from "pako";
127
+ function decodeFlateBase64(encoded) {
128
+ if (!encoded) return null;
129
+ const binary = atob(encoded);
130
+ const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));
131
+ const text = pako.inflateRaw(bytes, { to: "string" });
132
+ return JSON.parse(text);
133
+ }
134
+
135
+ // src/utils/encodeDecode.ts
136
+ function encodeData(data) {
137
+ try {
138
+ const json = JSON.stringify(data);
139
+ return btoa(unescape(encodeURIComponent(json)));
140
+ } catch (error) {
141
+ console.error("Failed to encode data:", error);
142
+ return "";
143
+ }
144
+ }
145
+ function decodeData(encoded) {
146
+ try {
147
+ const decoded = decodeURIComponent(escape(atob(encoded)));
148
+ const parsed = JSON.parse(decoded);
149
+ if (typeof parsed === "string" || typeof parsed === "number" || Array.isArray(parsed) || typeof parsed === "object") {
150
+ return parsed;
151
+ }
152
+ return decoded;
153
+ } catch (error) {
154
+ console.error("Failed to decode data:", error);
155
+ return null;
156
+ }
157
+ }
158
+
159
+ // src/utils/formatCurrency.ts
160
+ function formatCurrency(value, decimals = 2, withLabel = true) {
161
+ if (value === null || value === void 0 || value === "") return withLabel ? "Rp0" : "0";
162
+ const number = typeof value === "string" ? parseFloat(value) : value;
163
+ if (isNaN(number)) return withLabel ? "Rp0" : "0";
164
+ return (withLabel ? "Rp" : "") + number.toFixed(decimals).replace(".", ",").replace(/\B(?=(\d{3})+(?!\d))/g, ".");
165
+ }
166
+
167
+ // src/utils/formatDate.ts
168
+ import dayjs from "dayjs";
169
+ import "dayjs/locale/id";
170
+ dayjs.locale("id");
171
+ var formatDate = (value, format = "DD MMM YYYY HH:mm") => {
172
+ if (!value) return "-";
173
+ let sanitized = value;
174
+ if (typeof value === "string" && value.endsWith("Z")) {
175
+ sanitized = value.replace(/Z$/, "");
176
+ }
177
+ const parsed = dayjs(sanitized);
178
+ if (!parsed.isValid()) return "-";
179
+ return parsed.format(format);
180
+ };
181
+
182
+ // src/utils/formatRupiah.ts
183
+ var formatRupiah = (value) => {
184
+ if (value === null || value === void 0 || value === "") {
185
+ return "";
186
+ }
187
+ let numberValue;
188
+ if (typeof value === "number") {
189
+ numberValue = value;
190
+ } else {
191
+ const normalized = value.toString().replace(/\s/g, "").replace(/Rp/gi, "").replace(/\./g, "").replace(/,/g, ".").replace(/[^0-9.-]/g, "");
192
+ numberValue = Number(normalized);
193
+ }
194
+ if (Number.isNaN(numberValue)) {
195
+ return "";
196
+ }
197
+ const hasDecimal = Math.round(numberValue * 100) % 100 !== 0;
198
+ return new Intl.NumberFormat("id-ID", {
199
+ style: "currency",
200
+ currency: "IDR",
201
+ minimumFractionDigits: hasDecimal ? 2 : 0,
202
+ maximumFractionDigits: 2
203
+ }).format(numberValue);
204
+ };
205
+ var transformThousands = (value, mode = "format") => {
206
+ if (value === null || value === void 0) {
207
+ return mode === "format" ? "" : 0;
208
+ }
209
+ const str = value.toString();
210
+ if (mode === "parse") {
211
+ const normalized = str.replace(/\./g, "").replace(/,/g, ".").replace(/[^0-9.]/g, "");
212
+ const num = Number(normalized);
213
+ return isNaN(num) ? 0 : num;
214
+ }
215
+ const endsWithComma = str.endsWith(",");
216
+ const cleaned = str.replace(/[^0-9,]/g, "");
217
+ const [intRaw = "", decRaw = ""] = cleaned.split(",");
218
+ const intPart = intRaw.replace(/\D/g, "");
219
+ const formattedInt = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
220
+ let decimalPart = decRaw.replace(/\D/g, "").slice(0, 2);
221
+ if (endsWithComma && decimalPart.length === 0) {
222
+ return `${formattedInt},`;
223
+ }
224
+ if (decimalPart.length > 0) {
225
+ return `${formattedInt},${decimalPart}`;
226
+ }
227
+ return formattedInt;
228
+ };
229
+
230
+ // src/utils/formatter.ts
231
+ var MASK = "___.___-__.________";
232
+ var DIGIT_INDEXES = [
233
+ 0,
234
+ 1,
235
+ 2,
236
+ // ___
237
+ 4,
238
+ 5,
239
+ 6,
240
+ // ___
241
+ 8,
242
+ 9,
243
+ // __
244
+ 11,
245
+ 12,
246
+ 13,
247
+ 14,
248
+ 15,
249
+ 16,
250
+ 17,
251
+ 18
252
+ // ________
253
+ ];
254
+ function applyEFakturMask(raw) {
255
+ const digits = raw.replace(/\D/g, "").slice(0, DIGIT_INDEXES.length);
256
+ const chars = MASK.split("");
257
+ digits.split("").forEach((d, i) => {
258
+ chars[DIGIT_INDEXES[i]] = d;
259
+ });
260
+ return chars.join("");
261
+ }
262
+ var CORETAX_MASK = "____-____-____-____";
263
+ var CORETAX_INDEXES = [
264
+ 0,
265
+ 1,
266
+ 2,
267
+ 3,
268
+ 5,
269
+ 6,
270
+ 7,
271
+ 8,
272
+ 10,
273
+ 11,
274
+ 12,
275
+ 13,
276
+ 15,
277
+ 16,
278
+ 17,
279
+ 18
280
+ ];
281
+ function applyCoretaxMask(raw) {
282
+ const digits = raw.replace(/\D/g, "").slice(0, 16);
283
+ const chars = CORETAX_MASK.split("");
284
+ digits.split("").forEach((d, i) => {
285
+ chars[CORETAX_INDEXES[i]] = d;
286
+ });
287
+ return chars.join("");
288
+ }
289
+
290
+ // src/utils/generateHeaders.ts
291
+ import SHA256 from "crypto-js/sha256";
292
+ import Hex from "crypto-js/enc-hex";
293
+ var KEY_SSO_PUNINAR = "SYd3VPunSS0#@!";
294
+ function generateHeaders() {
295
+ const date = /* @__PURE__ */ new Date();
296
+ const timestamp = date.toISOString().slice(0, 19).replace("T", " ");
297
+ const encryptionKey = `${KEY_SSO_PUNINAR}${timestamp}`;
298
+ const keyPun = SHA256(encryptionKey).toString(Hex);
299
+ return {
300
+ // "Content-Type": "application/json",
301
+ "Authorization": `Bearer ${getLocalStorage("odong-token")}`,
302
+ "key-puninar": keyPun,
303
+ timestamp
304
+ };
305
+ }
306
+
307
+ // src/utils/generateUUID.ts
308
+ var generateUUID = () => {
309
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
310
+ return crypto.randomUUID();
311
+ }
312
+ return `temp-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
313
+ };
314
+
315
+ // src/utils/getInitials.ts
316
+ function getInitials(name) {
317
+ if (!name) return "";
318
+ const parts = name.trim().split(/\s+/);
319
+ if (parts.length === 1) {
320
+ return parts[0][0].toUpperCase();
321
+ }
322
+ const first = parts[0][0].toUpperCase();
323
+ const last = parts[parts.length - 1][0].toUpperCase();
324
+ return first + last;
325
+ }
326
+
327
+ // src/utils/rolesCheck.ts
328
+ function matchRole(selectedRole, comparator, mode = "exact") {
329
+ if (!selectedRole) return false;
330
+ const role = selectedRole.toUpperCase();
331
+ const comparators = Array.isArray(comparator) ? comparator.map((c) => c.toUpperCase()) : [comparator.toUpperCase()];
332
+ return comparators.some((c) => {
333
+ switch (mode) {
334
+ case "exact":
335
+ return role === c;
336
+ case "startsWith":
337
+ return role.startsWith(c);
338
+ case "includes":
339
+ return role.includes(c);
340
+ case "regex":
341
+ return new RegExp(c, "i").test(selectedRole);
342
+ default:
343
+ return false;
344
+ }
345
+ });
346
+ }
347
+
348
+ // src/utils/taxFormat.ts
349
+ var pphFormat = (str) => {
350
+ const match = str.match(/(?:PPH|WHT.*?PPH)(\d+)_(\d+)%$/);
351
+ return match ? `${match[1]}_${match[2]}%` : null;
352
+ };
353
+
354
+ // src/utils/terbilang.ts
355
+ var terbilang = (angka) => {
356
+ angka = typeof angka === "string" ? parseInt(angka.replace(/[^\d]/g, "")) : angka;
357
+ if (isNaN(angka) || angka === 0) return "Nol Rupiah";
358
+ const kata = ["", "Satu", "Dua", "Tiga", "Empat", "Lima", "Enam", "Tujuh", "Delapan", "Sembilan"];
359
+ const tingkat = ["", "Ribu", "Juta", "Miliar", "Triliun"];
360
+ const terbilangRatusan = (num) => {
361
+ let result = "";
362
+ const ratus = Math.floor(num / 100);
363
+ const sisa = num % 100;
364
+ if (ratus > 0) {
365
+ result += ratus === 1 ? "Seratus " : `${kata[ratus]} Ratus `;
366
+ }
367
+ if (sisa > 0) {
368
+ if (sisa < 10) {
369
+ result += kata[sisa];
370
+ } else if (sisa === 10) {
371
+ result += "Sepuluh";
372
+ } else if (sisa === 11) {
373
+ result += "Sebelas";
374
+ } else if (sisa < 20) {
375
+ result += `${kata[sisa - 10]} Belas`;
376
+ } else {
377
+ const puluh = Math.floor(sisa / 10);
378
+ const satuan = sisa % 10;
379
+ result += `${kata[puluh]} Puluh`;
380
+ if (satuan > 0) {
381
+ result += ` ${kata[satuan]}`;
382
+ }
383
+ }
384
+ }
385
+ return result.trim();
386
+ };
387
+ let kalimat = "";
388
+ let tingkatIndex = 0;
389
+ while (angka > 0) {
390
+ const bagian = angka % 1e3;
391
+ if (bagian > 0) {
392
+ let teks = terbilangRatusan(bagian);
393
+ if (tingkatIndex === 1 && bagian === 1) {
394
+ teks = "Seribu";
395
+ }
396
+ kalimat = `${teks} ${tingkat[tingkatIndex]} ${kalimat}`.trim();
397
+ }
398
+ angka = Math.floor(angka / 1e3);
399
+ tingkatIndex++;
400
+ }
401
+ return kalimat.replace(/\s+/g, " ") + " Rupiah";
402
+ };
403
+
404
+ // src/utils/visibleTable.ts
405
+ function visibleTable(columns, role) {
406
+ return columns.filter((col) => {
407
+ if (role === "VENDOR" && col.id === "status_dokumen") {
408
+ return false;
409
+ }
410
+ return true;
411
+ });
412
+ }
413
+
414
+ export {
415
+ setLocalStorage,
416
+ getLocalStorage,
417
+ removeLocalStorage,
418
+ clearLocalStorage,
419
+ accessCheck,
420
+ aliasBundlingTypeArchive,
421
+ base64DecodeWithSecret,
422
+ convertToArrayOfObject,
423
+ formatDateTime,
424
+ decodeFlateBase64,
425
+ encodeData,
426
+ decodeData,
427
+ formatCurrency,
428
+ formatDate,
429
+ formatRupiah,
430
+ transformThousands,
431
+ applyEFakturMask,
432
+ applyCoretaxMask,
433
+ generateHeaders,
434
+ generateUUID,
435
+ getInitials,
436
+ matchRole,
437
+ pphFormat,
438
+ terbilang,
439
+ visibleTable
440
+ };
441
+ //# sourceMappingURL=chunk-6NBFV4YQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/localStorage.ts","../src/utils/accessCheck.ts","../src/utils/aliasBundlingTypeArchive.ts","../src/utils/base64DecodeWithSecret.ts","../src/utils/convertToArrayOfObject.ts","../src/utils/dateFormat.ts","../src/utils/decodeFlateBase64.ts","../src/utils/encodeDecode.ts","../src/utils/formatCurrency.ts","../src/utils/formatDate.ts","../src/utils/formatRupiah.ts","../src/utils/formatter.ts","../src/utils/generateHeaders.ts","../src/utils/generateUUID.ts","../src/utils/getInitials.ts","../src/utils/rolesCheck.ts","../src/utils/taxFormat.ts","../src/utils/terbilang.ts","../src/utils/visibleTable.ts"],"sourcesContent":["// utils/localStorage.ts\r\n\r\n/**\r\n * Simpan data ke localStorage dengan aman.\r\n */\r\nexport const setLocalStorage = (key: string, value: unknown): void => {\r\n try {\r\n const serializedValue =\r\n typeof value === \"string\" ? value : JSON.stringify(value);\r\n localStorage.setItem(key, serializedValue);\r\n } catch (error) {\r\n console.error(`Gagal menyimpan ke localStorage: ${key}`, error);\r\n }\r\n};\r\n\r\n/**\r\n * Ambil data dari localStorage dengan aman (auto-parse JSON jika valid).\r\n * Generic <T> agar hasil bisa ditentukan tipenya.\r\n */\r\nexport const getLocalStorage = <T = unknown>(\r\n key: string,\r\n defaultValue: T | null = null\r\n): T | string | null => {\r\n try {\r\n const value = localStorage.getItem(key);\r\n if (value === null) return defaultValue;\r\n\r\n try {\r\n return JSON.parse(value) as T;\r\n } catch {\r\n return value; // Jika bukan JSON, kembalikan string\r\n }\r\n } catch (error) {\r\n console.error(`Gagal membaca dari localStorage: ${key}`, error);\r\n return defaultValue;\r\n }\r\n};\r\n\r\n/**\r\n * Hapus data dari localStorage.\r\n */\r\nexport const removeLocalStorage = (key: string): void => {\r\n try {\r\n localStorage.removeItem(key);\r\n } catch (error) {\r\n console.error(`Gagal menghapus localStorage: ${key}`, error);\r\n }\r\n};\r\n\r\n/**\r\n * Hapus seluruh localStorage.\r\n */\r\nexport const clearLocalStorage = (): void => {\r\n try {\r\n localStorage.clear();\r\n } catch (error) {\r\n console.error(\"Gagal membersihkan localStorage\", error);\r\n }\r\n};","import { getLocalStorage } from \"./localStorage\";\r\n\r\ntype AnyObject = Record<string, any>;\r\n\r\n/**\r\n * Ambil value dari object berdasarkan path (misal: \"a.b.c\")\r\n */\r\nconst getByPath = (obj: AnyObject, path: string): any => {\r\n const keys = path.split(\".\");\r\n let current: any = obj;\r\n\r\n for (const key of keys) {\r\n if (current == null || !(key in current)) return null;\r\n current = current[key];\r\n }\r\n\r\n return current;\r\n};\r\n\r\ninterface AccessNode {\r\n access?: string[];\r\n}\r\n\r\n/**\r\n * Cek otorisasi akses berdasarkan path dan list akses user.\r\n */\r\nexport const accessCheck = (\r\n keyPath: string,\r\n requiredAccess: string | string[]\r\n): boolean => {\r\n try {\r\n const list = getLocalStorage<AnyObject[]>(\"menu-access\");\r\n if (!list) return false;\r\n\r\n // Gabungkan array of object menjadi satu object\r\n const accessRoot: AnyObject = Object.assign({}, ...list);\r\n\r\n const node = getByPath(accessRoot, keyPath) as AccessNode | null;\r\n if (!node || !Array.isArray(node.access)) return false;\r\n\r\n const userAccessList = node.access;\r\n\r\n if (Array.isArray(requiredAccess)) {\r\n return requiredAccess.some((a) => userAccessList.includes(a));\r\n }\r\n\r\n return userAccessList.includes(requiredAccess);\r\n } catch (error) {\r\n console.error(\"Invalid menu-access format:\", error);\r\n return false;\r\n }\r\n};\r\n","type BundlingTypeArchive = 'TRUCKING_ONLY' | 'CUSTOMS_CLEARANCE';\r\n\r\nexport const aliasBundlingTypeArchive = (bundlingTypeArchive: BundlingTypeArchive | undefined): string => {\r\n const alias: Record<BundlingTypeArchive, string> = {\r\n TRUCKING_ONLY: 'Trucking Only',\r\n CUSTOMS_CLEARANCE: 'Customs Clearance',\r\n };\r\n\r\n return bundlingTypeArchive ? alias[bundlingTypeArchive] : 'N/A';\r\n};\r\n","export function base64DecodeWithSecret<T = unknown>(\r\n encodedData: string,\r\n secretKey: string\r\n): T {\r\n const decodedData = atob(encodedData);\r\n const originalData = decodedData.slice(0, -secretKey.length);\r\n return JSON.parse(originalData) as T;\r\n}\r\n","// utils.ts\r\n\r\n/**\r\n * Convert an array of pipe-separated strings into an array of objects.\r\n * If field names are provided, they will be used instead of generic field1, field2, etc.\r\n * Example:\r\n * convertToArrayOfObject([\"1|01|PUJA|PUNINAR JAYA\"], [\"id\",\"code\",\"short_name\",\"full_name\"])\r\n * → [{ id: \"1\", code: \"01\", short_name: \"PUJA\", full_name: \"PUNINAR JAYA\" }]\r\n */\r\nexport function convertToArrayOfObject(\r\n arr?: string[] | null,\r\n fields?: string[]\r\n): Record<string, string>[] {\r\n if (!Array.isArray(arr) || arr.length === 0) {\r\n return [];\r\n }\r\n\r\n return arr.map((item) => {\r\n if (typeof item !== \"string\") return {};\r\n\r\n const parts = item.split(\"|\");\r\n const obj: Record<string, string> = {};\r\n\r\n parts.forEach((value, index) => {\r\n const key =\r\n fields && fields[index]\r\n ? fields[index]\r\n : `field${index + 1}`;\r\n obj[key] = value?.trim?.() ?? \"\";\r\n });\r\n\r\n return obj;\r\n });\r\n}\r\n","export function formatDateTime(date: Date): string {\r\n const day: string = String(date.getDate()).padStart(2, '0')\r\n const year: number = date.getFullYear()\r\n\r\n const months: string[] = [\r\n 'Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni',\r\n 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'\r\n ]\r\n\r\n const month: string = months[date.getMonth()]\r\n\r\n const hours: string = String(date.getHours()).padStart(2, '0')\r\n const minutes: string = String(date.getMinutes()).padStart(2, '0')\r\n const seconds: string = String(date.getSeconds()).padStart(2, '0')\r\n\r\n return `${day} ${month} ${year}, ${hours}:${minutes}:${seconds}`\r\n}\r\n","import pako from \"pako\";\r\n\r\nexport function decodeFlateBase64<T = any>(encoded: string): T {\r\n if (!encoded) return null as T;\r\n\r\n const binary = atob(encoded);\r\n\r\n const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));\r\n const text = pako.inflateRaw(bytes, { to: \"string\" });\r\n\r\n return JSON.parse(text) as T;\r\n}\r\n","// utils/encodeDecode.ts\r\nexport function encodeData(data: unknown): string {\r\n try {\r\n // pastikan semua tipe diubah ke string JSON\r\n const json = JSON.stringify(data);\r\n return btoa(unescape(encodeURIComponent(json)));\r\n } catch (error) {\r\n console.error(\"Failed to encode data:\", error);\r\n return \"\";\r\n }\r\n}\r\n\r\nexport function decodeData<T = unknown>(encoded: string): T | string | number | null {\r\n try {\r\n const decoded = decodeURIComponent(escape(atob(encoded)));\r\n const parsed = JSON.parse(decoded);\r\n\r\n // Kalau hasilnya string atau number biasa, langsung return\r\n if (typeof parsed === \"string\" || typeof parsed === \"number\" || Array.isArray(parsed) || typeof parsed === \"object\") {\r\n return parsed as T;\r\n }\r\n\r\n return decoded; // fallback kalau bukan JSON\r\n } catch (error) {\r\n console.error(\"Failed to decode data:\", error);\r\n return null;\r\n }\r\n}\r\n","export function formatCurrency(\r\n value: number | string,\r\n decimals: number = 2,\r\n withLabel: boolean = true\r\n): string {\r\n if (value === null || value === undefined || value === \"\") return withLabel ? \"Rp0\" : \"0\"\r\n\r\n const number = typeof value === \"string\" ? parseFloat(value) : value\r\n\r\n if (isNaN(number)) return withLabel ? \"Rp0\" : \"0\"\r\n\r\n // Format angka dengan jumlah desimal dinamis\r\n return (withLabel ? \"Rp\": \"\") + number\r\n .toFixed(decimals)\r\n .replace(\".\", \",\") // ubah titik jadi koma untuk desimal\r\n .replace(/\\B(?=(\\d{3})+(?!\\d))/g, \".\") // tambahkan titik pemisah ribuan\r\n}\r\n","import dayjs from \"dayjs\";\r\nimport \"dayjs/locale/id\";\r\n\r\ndayjs.locale(\"id\");\r\n\r\nexport const formatDate = (\r\n value?: string | Date | null,\r\n format = \"DD MMM YYYY HH:mm\"\r\n): string => {\r\n if (!value) return \"-\";\r\n\r\n let sanitized = value;\r\n\r\n if (typeof value === \"string\" && value.endsWith(\"Z\")) {\r\n sanitized = value.replace(/Z$/, \"\");\r\n }\r\n\r\n const parsed = dayjs(sanitized);\r\n\r\n if (!parsed.isValid()) return \"-\";\r\n\r\n return parsed.format(format);\r\n};","export const formatRupiah = (\r\n value: number | string | null | undefined\r\n): string => {\r\n if (value === null || value === undefined || value === '') {\r\n return '';\r\n }\r\n\r\n let numberValue: number;\r\n\r\n if (typeof value === 'number') {\r\n numberValue = value;\r\n } else {\r\n // support \"1.234,56\", \"1234.56\", \"Rp 1.234,56\"\r\n const normalized = value\r\n .toString()\r\n .replace(/\\s/g, '')\r\n .replace(/Rp/gi, '')\r\n .replace(/\\./g, '')\r\n .replace(/,/g, '.')\r\n .replace(/[^0-9.-]/g, '');\r\n\r\n numberValue = Number(normalized);\r\n }\r\n\r\n if (Number.isNaN(numberValue)) {\r\n return '';\r\n }\r\n\r\n const hasDecimal = Math.round(numberValue * 100) % 100 !== 0;\r\n\r\n return new Intl.NumberFormat('id-ID', {\r\n style: 'currency',\r\n currency: 'IDR',\r\n minimumFractionDigits: hasDecimal ? 2 : 0,\r\n maximumFractionDigits: 2,\r\n }).format(numberValue);\r\n};\r\n\r\nexport const transformThousands = (\r\n value: string | number | null | undefined,\r\n mode: \"format\" | \"parse\" = \"format\"\r\n): string | number => {\r\n if (value === null || value === undefined) {\r\n return mode === \"format\" ? \"\" : 0;\r\n }\r\n\r\n const str = value.toString();\r\n\r\n if (mode === \"parse\") {\r\n const normalized = str\r\n .replace(/\\./g, \"\")\r\n .replace(/,/g, \".\")\r\n .replace(/[^0-9.]/g, \"\");\r\n\r\n const num = Number(normalized);\r\n return isNaN(num) ? 0 : num;\r\n }\r\n\r\n // ===== FORMAT MODE =====\r\n\r\n const endsWithComma = str.endsWith(\",\");\r\n\r\n const cleaned = str.replace(/[^0-9,]/g, \"\");\r\n const [intRaw = \"\", decRaw = \"\"] = cleaned.split(\",\");\r\n\r\n const intPart = intRaw.replace(/\\D/g, \"\");\r\n const formattedInt = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \".\");\r\n\r\n let decimalPart = decRaw.replace(/\\D/g, \"\").slice(0, 2);\r\n\r\n // Case: user baru mengetik koma → simpan koma\r\n if (endsWithComma && decimalPart.length === 0) {\r\n return `${formattedInt},`;\r\n }\r\n\r\n if (decimalPart.length > 0) {\r\n return `${formattedInt},${decimalPart}`;\r\n }\r\n\r\n return formattedInt;\r\n};\r\n","// EFaktur: XXX.XXX-XX.XXXXXXXX\r\nconst MASK = '___.___-__.________'\r\nconst DIGIT_INDEXES = [\r\n 0, 1, 2, // ___\r\n 4, 5, 6, // ___\r\n 8, 9, // __\r\n 11, 12, 13, 14, 15, 16, 17, 18 // ________\r\n]\r\n\r\nexport function applyEFakturMask(\r\n raw: string\r\n): string {\r\n const digits = raw.replace(/\\D/g, '').slice(0, DIGIT_INDEXES.length)\r\n\r\n const chars = MASK.split('')\r\n\r\n digits.split('').forEach((d, i) => {\r\n chars[DIGIT_INDEXES[i]] = d\r\n })\r\n\r\n return chars.join('')\r\n}\r\n\r\n\r\n// Coretax: 16 digit angka\r\nconst CORETAX_MASK = '____-____-____-____'\r\nconst CORETAX_INDEXES = [\r\n 0, 1, 2, 3,\r\n 5, 6, 7, 8,\r\n 10, 11, 12, 13,\r\n 15, 16, 17, 18\r\n]\r\n\r\nexport function applyCoretaxMask(raw: string): string {\r\n const digits = raw.replace(/\\D/g, '').slice(0, 16)\r\n const chars = CORETAX_MASK.split('')\r\n\r\n digits.split('').forEach((d, i) => {\r\n chars[CORETAX_INDEXES[i]] = d\r\n })\r\n\r\n return chars.join('')\r\n}","import SHA256 from \"crypto-js/sha256\";\r\nimport Hex from \"crypto-js/enc-hex\";\r\nimport { getLocalStorage } from \"./localStorage\";\r\n\r\nconst KEY_SSO_PUNINAR = \"SYd3VPunSS0#@!\" as string;\r\n\r\n\r\nexport function generateHeaders(): Record<string, string> {\r\n const date = new Date();\r\n const timestamp = date.toISOString().slice(0, 19).replace(\"T\", \" \"); // 2025-10-02 12:34:56\r\n const encryptionKey = `${KEY_SSO_PUNINAR}${timestamp}`;\r\n const keyPun = SHA256(encryptionKey).toString(Hex);\r\n\r\n return {\r\n // \"Content-Type\": \"application/json\",\r\n \"Authorization\": `Bearer ${getLocalStorage(\"odong-token\")}`,\r\n \"key-puninar\": keyPun,\r\n timestamp,\r\n };\r\n}","export const generateUUID = (): string => {\r\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\r\n return crypto.randomUUID();\r\n }\r\n // Fallback sederhana (bukan UUID asli, tapi cukup unik untuk UI)\r\n return `temp-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\r\n};","/**\r\n * Generate initials from a name\r\n * @param name - Full name\r\n * @returns Initials (first and last letter)\r\n */\r\nexport function getInitials(name?: string): string {\r\n if (!name) return \"\";\r\n\r\n const parts = name.trim().split(/\\s+/); // pisah berdasarkan spasi\r\n\r\n if (parts.length === 1) {\r\n return parts[0][0].toUpperCase(); // satu kata → ambil huruf pertama\r\n }\r\n\r\n const first = parts[0][0].toUpperCase();\r\n const last = parts[parts.length - 1][0].toUpperCase();\r\n return first + last;\r\n}","type MatchMode = \"exact\" | \"startsWith\" | \"includes\" | \"regex\";\r\n\r\nexport function matchRole(\r\n selectedRole: string | undefined,\r\n comparator: string | string[],\r\n mode: MatchMode = \"exact\"\r\n): boolean {\r\n if (!selectedRole) return false;\r\n\r\n const role = selectedRole.toUpperCase();\r\n const comparators = Array.isArray(comparator)\r\n ? comparator.map((c) => c.toUpperCase())\r\n : [comparator.toUpperCase()];\r\n\r\n return comparators.some((c) => {\r\n switch (mode) {\r\n case \"exact\":\r\n return role === c;\r\n\r\n case \"startsWith\":\r\n return role.startsWith(c);\r\n\r\n case \"includes\":\r\n return role.includes(c);\r\n\r\n case \"regex\":\r\n return new RegExp(c, \"i\").test(selectedRole);\r\n\r\n default:\r\n return false;\r\n }\r\n });\r\n}\r\n","export const pphFormat = (str: string): string | null => {\r\n // Match pola seperti PPH23_15% atau WHT_PPH23_15%\r\n const match = str.match(/(?:PPH|WHT.*?PPH)(\\d+)_(\\d+)%$/);\r\n return match ? `${match[1]}_${match[2]}%` : null;\r\n};\r\n","export const terbilang = (angka: number | string): string => {\r\n angka = typeof angka === 'string'\r\n ? parseInt(angka.replace(/[^\\d]/g, ''))\r\n : angka;\r\n\r\n if (isNaN(angka) || angka === 0) return 'Nol Rupiah';\r\n\r\n const kata = ['', 'Satu', 'Dua', 'Tiga', 'Empat', 'Lima', 'Enam', 'Tujuh', 'Delapan', 'Sembilan'];\r\n const tingkat = ['', 'Ribu', 'Juta', 'Miliar', 'Triliun'];\r\n\r\n const terbilangRatusan = (num: number): string => {\r\n let result = '';\r\n\r\n const ratus = Math.floor(num / 100);\r\n const sisa = num % 100;\r\n\r\n if (ratus > 0) {\r\n result += ratus === 1 ? 'Seratus ' : `${kata[ratus]} Ratus `;\r\n }\r\n\r\n if (sisa > 0) {\r\n if (sisa < 10) {\r\n result += kata[sisa];\r\n } else if (sisa === 10) {\r\n result += 'Sepuluh';\r\n } else if (sisa === 11) {\r\n result += 'Sebelas';\r\n } else if (sisa < 20) {\r\n result += `${kata[sisa - 10]} Belas`;\r\n } else {\r\n const puluh = Math.floor(sisa / 10);\r\n const satuan = sisa % 10;\r\n result += `${kata[puluh]} Puluh`;\r\n if (satuan > 0) {\r\n result += ` ${kata[satuan]}`;\r\n }\r\n }\r\n }\r\n\r\n return result.trim();\r\n };\r\n\r\n let kalimat = '';\r\n let tingkatIndex = 0;\r\n\r\n while (angka > 0) {\r\n const bagian = angka % 1000;\r\n\r\n if (bagian > 0) {\r\n let teks = terbilangRatusan(bagian);\r\n\r\n if (tingkatIndex === 1 && bagian === 1) {\r\n teks = 'Seribu';\r\n }\r\n\r\n kalimat = `${teks} ${tingkat[tingkatIndex]} ${kalimat}`.trim();\r\n }\r\n\r\n angka = Math.floor(angka / 1000);\r\n tingkatIndex++;\r\n }\r\n\r\n return kalimat.replace(/\\s+/g, ' ') + ' Rupiah';\r\n}\r\n","type Role = \"ADMIN\" | \"VENDOR\" | \"FINANCE\"\r\n\r\nexport function visibleTable(\r\n columns: any[],\r\n role?: Role\r\n) {\r\n return columns.filter((col) => {\r\n // Hide Status Dokumen untuk VENDOR\r\n if (role === \"VENDOR\" && col.id === \"status_dokumen\") {\r\n return false\r\n }\r\n\r\n // Contoh tambahan rule\r\n // if (role === \"VENDOR\" && col.id === \"action\") return false\r\n\r\n return true\r\n })\r\n}\r\n"],"mappings":"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","names":[]}