alterzick commited on
Commit
2771c13
·
verified ·
1 Parent(s): 06f5d4b

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +594 -19
  3. prompts.txt +3 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Balancepos V1
3
- emoji: 🦀
4
- colorFrom: gray
5
- colorTo: pink
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: balancepos-v1
3
+ emoji: ⚛️
4
+ colorFrom: green
5
+ colorTo: yellow
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - QwenSite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,594 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="id">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Dashboard Balancepos Interaktif</title>
6
+ <style>
7
+ body {
8
+ font-family: Arial, sans-serif;
9
+ font-size: 12px;
10
+ padding: 10px;
11
+ background: #f5f5f5;
12
+ margin: 0;
13
+ }
14
+ h2 { margin-top: 0; }
15
+ .toolbar {
16
+ display: flex;
17
+ flex-wrap: wrap;
18
+ gap: 8px;
19
+ align-items: center;
20
+ margin-bottom: 8px;
21
+ padding: 10px;
22
+ background: white;
23
+ border-radius: 4px;
24
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
25
+ }
26
+ .toolbar label {
27
+ font-weight: bold;
28
+ margin-right: 4px;
29
+ min-width: 60px;
30
+ }
31
+ input[type="text"], select {
32
+ padding: 3px 5px;
33
+ font-size: 12px;
34
+ border: 1px solid #ccc;
35
+ border-radius: 3px;
36
+ }
37
+ input[type="number"] {
38
+ width: 90px;
39
+ padding: 3px 5px;
40
+ border: 1px solid #ccc;
41
+ border-radius: 3px;
42
+ }
43
+ button {
44
+ padding: 4px 8px;
45
+ font-size: 12px;
46
+ cursor: pointer;
47
+ border: 1px solid #ccc;
48
+ border-radius: 3px;
49
+ background: #f0f0f0;
50
+ }
51
+ button:hover {
52
+ background: #e0e0e0;
53
+ }
54
+ table {
55
+ border-collapse: collapse;
56
+ width: 100%;
57
+ margin-top: 5px;
58
+ background: white;
59
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
60
+ }
61
+ th, td {
62
+ border: 1px solid #ccc;
63
+ padding: 4px 6px;
64
+ white-space: nowrap;
65
+ font-size: 11px;
66
+ }
67
+ th {
68
+ background: #e0e0e0;
69
+ position: sticky;
70
+ top: 0;
71
+ z-index: 2;
72
+ cursor: pointer;
73
+ user-select: none;
74
+ }
75
+ th.sort-asc::after {
76
+ content: " ▲";
77
+ font-size: 10px;
78
+ color: #0066cc;
79
+ }
80
+ th.sort-desc::after {
81
+ content: " ▼";
82
+ font-size: 10px;
83
+ color: #0066cc;
84
+ }
85
+ tr:hover {
86
+ background: #fafad2;
87
+ }
88
+ .wrap {
89
+ max-height: 65vh;
90
+ overflow: auto;
91
+ border: 1px solid #ccc;
92
+ background: white;
93
+ border-radius: 4px;
94
+ margin-bottom: 10px;
95
+ }
96
+ #info {
97
+ margin: 6px 0;
98
+ color: #555;
99
+ font-weight: bold;
100
+ }
101
+ .pagination {
102
+ display: flex;
103
+ align-items: center;
104
+ gap: 5px;
105
+ margin-top: 6px;
106
+ padding: 8px;
107
+ background: white;
108
+ border-radius: 4px;
109
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
110
+ }
111
+ .pagination button {
112
+ padding: 4px 8px;
113
+ }
114
+ .add-form {
115
+ margin-top: 10px;
116
+ padding: 12px;
117
+ background: #ffffff;
118
+ border: 1px solid #ccc;
119
+ border-radius: 4px;
120
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
121
+ }
122
+ .add-form h3 {
123
+ margin-top: 0;
124
+ margin-bottom: 10px;
125
+ color: #333;
126
+ }
127
+ .add-form-row {
128
+ display: flex;
129
+ flex-wrap: wrap;
130
+ gap: 8px;
131
+ margin-bottom: 6px;
132
+ }
133
+ .add-form-row label {
134
+ min-width: 80px;
135
+ font-weight: bold;
136
+ }
137
+ .add-form-row input, .add-form-row select {
138
+ min-width: 120px;
139
+ }
140
+ .chip {
141
+ background: #eee;
142
+ padding: 2px 6px;
143
+ border-radius: 10px;
144
+ font-size: 11px;
145
+ }
146
+ .filter-section {
147
+ display: flex;
148
+ flex-wrap: wrap;
149
+ gap: 12px;
150
+ align-items: center;
151
+ }
152
+ .filter-group {
153
+ display: flex;
154
+ align-items: center;
155
+ gap: 4px;
156
+ }
157
+ </style>
158
+ </head>
159
+ <body>
160
+
161
+ <h2>Dashboard Balancepos Interaktif</h2>
162
+
163
+ <div class="toolbar">
164
+ <div class="filter-section">
165
+ <div class="filter-group">
166
+ <label>Upload TXT:</label>
167
+ <input type="file" id="fileInput" accept=".txt">
168
+ </div>
169
+ <div class="filter-group">
170
+ <label>Cari:</label>
171
+ <input type="text" id="searchInput" placeholder="Kode / Type / dll">
172
+ </div>
173
+ <div class="filter-group">
174
+ <label>Filter Type:</label>
175
+ <select id="typeFilter">
176
+ <option value="">(Semua)</option>
177
+ </select>
178
+ </div>
179
+ <div class="filter-group">
180
+ <label>Filter Date:</label>
181
+ <input type="text" id="dateFilter" placeholder="30-JUN-2025">
182
+ </div>
183
+ <div class="filter-group">
184
+ <label>Filter Code:</label>
185
+ <input type="text" id="codeFilter" placeholder="AALI">
186
+ </div>
187
+ <div class="filter-group">
188
+ <label>Rows/page:</label>
189
+ <select id="pageSize">
190
+ <option value="10">10</option>
191
+ <option value="25" selected>25</option>
192
+ <option value="50">50</option>
193
+ <option value="100">100</option>
194
+ <option value="200">200</option>
195
+ </select>
196
+ </div>
197
+ </div>
198
+ </div>
199
+
200
+ <div id="info"></div>
201
+
202
+ <div class="wrap">
203
+ <table id="tbl"></table>
204
+ </div>
205
+
206
+ <div class="pagination">
207
+ <button id="firstPage">|&lt;</button>
208
+ <button id="prevPage">&lt;</button>
209
+ <span id="pageInfo" class="chip"></span>
210
+ <button id="nextPage">&gt;</button>
211
+ <button id="lastPage">&gt;|</button>
212
+ </div>
213
+
214
+ <div class="add-form">
215
+ <h3>Tambah Data Manual</h3>
216
+ <div class="add-form-row">
217
+ <label for="addDate">Date:</label>
218
+ <input type="text" id="addDate" placeholder="30-JUN-2025">
219
+ <label for="addCode">Code:</label>
220
+ <input type="text" id="addCode" placeholder="AALI">
221
+ <label for="addType">Type:</label>
222
+ <input type="text" id="addType" placeholder="EQUITY">
223
+ <label for="addSecNum">Sec. Num:</label>
224
+ <input type="number" id="addSecNum" placeholder="0">
225
+ <label for="addPrice">Price:</label>
226
+ <input type="number" id="addPrice" placeholder="0">
227
+ </div>
228
+ <div class="add-form-row">
229
+ <label>Local IS..OT (9 kolom):</label>
230
+ <input type="number" id="addLocalIS" placeholder="Local IS">
231
+ <input type="number" id="addLocalCP" placeholder="Local CP">
232
+ <input type="number" id="addLocalPF" placeholder="Local PF">
233
+ <input type="number" id="addLocalIB" placeholder="Local IB">
234
+ <input type="number" id="addLocalID" placeholder="Local ID">
235
+ <input type="number" id="addLocalMF" placeholder="Local MF">
236
+ <input type="number" id="addLocalSC" placeholder="Local SC">
237
+ <input type="number" id="addLocalFD" placeholder="Local FD">
238
+ <input type="number" id="addLocalOT" placeholder="Local OT">
239
+ </div>
240
+ <div class="add-form-row">
241
+ <label>Foreign IS..OT (9 kolom):</label>
242
+ <input type="number" id="addForeignIS" placeholder="Foreign IS">
243
+ <input type="number" id="addForeignCP" placeholder="Foreign CP">
244
+ <input type="number" id="addForeignPF" placeholder="Foreign PF">
245
+ <input type="number" id="addForeignIB" placeholder="Foreign IB">
246
+ <input type="number" id="addForeignID" placeholder="Foreign ID">
247
+ <input type="number" id="addForeignMF" placeholder="Foreign MF">
248
+ <input type="number" id="addForeignSC" placeholder="Foreign SC">
249
+ <input type="number" id="addForeignFD" placeholder="Foreign FD">
250
+ <input type="number" id="addForeignOT" placeholder="Foreign OT">
251
+ </div>
252
+ <button id="btnAddRow">Tambah Baris</button>
253
+ </div>
254
+
255
+ <script>
256
+ let rawRows = []; // data mentah dari TXT
257
+ let dashboardRows = []; // data + kolom hitung
258
+ let currentPage = 1;
259
+ let sortCol = null;
260
+ let sortDir = 1; // 1 = asc, -1 = desc
261
+
262
+ const IDX = {
263
+ localStart: 5, // F
264
+ localEnd: 13, // N
265
+ foreignStart: 15,// P
266
+ foreignEnd: 23 // X
267
+ };
268
+
269
+ function parseTxt(raw) {
270
+ const lines = raw.split(/\r?\n/).map(l => l.trim()).filter(l => l);
271
+ if (!lines.length) return [];
272
+ return lines.map(l => l.split("|"));
273
+ }
274
+
275
+ function pct(val, totalAll) {
276
+ val = Number(val);
277
+ totalAll = Number(totalAll);
278
+ if (!totalAll || isNaN(val) || isNaN(totalAll)) return "0,00%";
279
+ const p = val / totalAll * 100;
280
+ return p.toFixed(2).replace(".", ",") + "%";
281
+ }
282
+
283
+ // membangun struktur dashboardRows dari rawRows (perhitungan total & %)
284
+ function buildDashboardRows() {
285
+ const header = rawRows[0];
286
+ dashboardRows = [];
287
+
288
+ for (let i = 1; i < rawRows.length; i++) {
289
+ const r = rawRows[i];
290
+ if (!r.length) continue;
291
+
292
+ let sumLocal = 0;
293
+ for (let c = IDX.localStart; c <= IDX.localEnd; c++) {
294
+ sumLocal += Number(r[c] || 0);
295
+ }
296
+ let sumForeign = 0;
297
+ for (let c = IDX.foreignStart; c <= IDX.foreignEnd; c++) {
298
+ sumForeign += Number(r[c] || 0);
299
+ }
300
+ const sumAll = sumLocal + sumForeign;
301
+
302
+ const localPct = [];
303
+ const foreignPct = [];
304
+ let sumPctAll = 0;
305
+
306
+ for (let c = IDX.localStart; c <= IDX.localEnd; c++) {
307
+ const ps = pct(r[c], sumAll);
308
+ localPct.push(ps);
309
+ sumPctAll += Number(ps.replace(",", ".").replace("%", "")) || 0;
310
+ }
311
+ for (let c = IDX.foreignStart; c <= IDX.foreignEnd; c++) {
312
+ const ps = pct(r[c], sumAll);
313
+ foreignPct.push(ps);
314
+ sumPctAll += Number(ps.replace(",", ".").replace("%", "")) || 0;
315
+ }
316
+ const totalPct = sumPctAll.toFixed(2).replace(".", ",") + "%";
317
+
318
+ dashboardRows.push({
319
+ raw: r,
320
+ sumLocal,
321
+ sumForeign,
322
+ sumAll,
323
+ localPct,
324
+ foreignPct,
325
+ totalPct
326
+ });
327
+ }
328
+ populateTypeFilter();
329
+ }
330
+
331
+ // filtering + search + sorting + pagination
332
+ function getFilteredSortedRows() {
333
+ const searchText = document.getElementById("searchInput").value.toLowerCase();
334
+ const typeFilter = document.getElementById("typeFilter").value;
335
+ const dateFilter = document.getElementById("dateFilter").value.toLowerCase();
336
+ const codeFilter = document.getElementById("codeFilter").value.toLowerCase();
337
+
338
+ let rows = dashboardRows.filter(obj => {
339
+ const r = obj.raw;
340
+
341
+ // Filter berdasarkan type
342
+ if (typeFilter && r[2] !== typeFilter) return false;
343
+
344
+ // Filter berdasarkan date
345
+ if (dateFilter && !r[0].toLowerCase().includes(dateFilter)) return false;
346
+
347
+ // Filter berdasarkan code
348
+ if (codeFilter && !r[1].toLowerCase().includes(codeFilter)) return false;
349
+
350
+ // Filter berdasarkan search text
351
+ if (searchText) {
352
+ const joined = r.join("|").toLowerCase();
353
+ if (!joined.includes(searchText)) return false;
354
+ }
355
+ return true;
356
+ });
357
+
358
+ if (sortCol !== null) {
359
+ rows.sort((a, b) => {
360
+ // mapping kolom ke nilai
361
+ const getVal = (obj, col) => {
362
+ const r = obj.raw;
363
+ const baseCols = 25; // A–Y
364
+ if (col < baseCols) return r[col] || "";
365
+ const idxExtra = col - baseCols;
366
+ if (idxExtra === 0) return obj.sumLocal;
367
+ if (idxExtra === 1) return obj.sumForeign;
368
+ if (idxExtra === 2) return obj.sumAll;
369
+ if (idxExtra >= 3 && idxExtra <= 11) {
370
+ return obj.localPct[idxExtra - 3];
371
+ }
372
+ if (idxExtra >= 12 && idxExtra <= 20) {
373
+ return obj.foreignPct[idxExtra - 12];
374
+ }
375
+ if (idxExtra === 21) return obj.totalPct;
376
+ return "";
377
+ };
378
+ let va = getVal(a, sortCol);
379
+ let vb = getVal(b, sortCol);
380
+ const na = Number(String(va).replace(",", ".").replace("%", ""));
381
+ const nb = Number(String(vb).replace(",", ".").replace("%", ""));
382
+ if (!isNaN(na) && !isNaN(nb)) {
383
+ return (na - nb) * sortDir;
384
+ }
385
+ va = String(va);
386
+ vb = String(vb);
387
+ return va.localeCompare(vb) * sortDir;
388
+ });
389
+ }
390
+
391
+ return rows;
392
+ }
393
+
394
+ function renderTable() {
395
+ const tbl = document.getElementById("tbl");
396
+ tbl.innerHTML = "";
397
+ if (!rawRows.length) return;
398
+
399
+ const headerBase = rawRows[0].slice(0, 25);
400
+ const headerExtra = [
401
+ "Total Local (recalc)","Total Foreign (recalc)","Total All (Local+Foreign)",
402
+ "Local IS %","Local CP %","Local PF %","Local IB %","Local ID %",
403
+ "Local MF %","Local SC %","Local FD %","Local OT %",
404
+ "Foreign IS %","Foreign CP %","Foreign PF %","Foreign IB %","Foreign ID %",
405
+ "Foreign MF %","Foreign SC %","Foreign FD %","Foreign OT %",
406
+ "Total % (Local+Foreign)"
407
+ ];
408
+
409
+ const thead = document.createElement("thead");
410
+ const trh = document.createElement("tr");
411
+ const allHeaders = headerBase.concat(headerExtra);
412
+
413
+ allHeaders.forEach((h, colIdx) => {
414
+ const th = document.createElement("th");
415
+ th.textContent = h;
416
+ if (sortCol === colIdx) {
417
+ th.classList.add(sortDir === 1 ? "sort-asc" : "sort-desc");
418
+ }
419
+ th.addEventListener("click", () => {
420
+ if (sortCol === colIdx) sortDir = -sortDir;
421
+ else { sortCol = colIdx; sortDir = 1; }
422
+ renderTable();
423
+ });
424
+ trh.appendChild(th);
425
+ });
426
+ thead.appendChild(trh);
427
+ tbl.appendChild(thead);
428
+
429
+ const tbody = document.createElement("tbody");
430
+ const rows = getFilteredSortedRows();
431
+ const pageSize = Number(document.getElementById("pageSize").value) || 25;
432
+ const totalPages = Math.max(1, Math.ceil(rows.length / pageSize));
433
+ if (currentPage > totalPages) currentPage = totalPages;
434
+
435
+ const start = (currentPage - 1) * pageSize;
436
+ const end = start + pageSize;
437
+
438
+ rows.slice(start, end).forEach(obj => {
439
+ const r = obj.raw;
440
+ const tr = document.createElement("tr");
441
+
442
+ // A–Y
443
+ for (let c = 0; c <= 24; c++) {
444
+ const td = document.createElement("td");
445
+ td.textContent = r[c] || "";
446
+ tr.appendChild(td);
447
+ }
448
+
449
+ // total dan persen
450
+ const add = val => {
451
+ const td = document.createElement("td");
452
+ td.textContent = val;
453
+ tr.appendChild(td);
454
+ };
455
+ add(obj.sumLocal.toString());
456
+ add(obj.sumForeign.toString());
457
+ add(obj.sumAll.toString());
458
+ obj.localPct.forEach(p => add(p));
459
+ obj.foreignPct.forEach(p => add(p));
460
+ add(obj.totalPct);
461
+
462
+ tbody.appendChild(tr);
463
+ });
464
+
465
+ tbl.appendChild(tbody);
466
+
467
+ // info & pagination
468
+ document.getElementById("info").textContent =
469
+ "Baris: " + rows.length + " | Halaman " + currentPage + " / " + Math.max(1, Math.ceil(rows.length / pageSize));
470
+
471
+ document.getElementById("pageInfo").textContent =
472
+ currentPage + " / " + Math.max(1, Math.ceil(rows.length / pageSize));
473
+ }
474
+
475
+ // isi dropdown Type dari data
476
+ function populateTypeFilter() {
477
+ const sel = document.getElementById("typeFilter");
478
+ const types = new Set();
479
+ for (let i = 1; i < rawRows.length; i++) {
480
+ const t = rawRows[i][2];
481
+ if (t) types.add(t);
482
+ }
483
+ sel.innerHTML = '<option value="">(Semua)</option>';
484
+ Array.from(types).sort().forEach(t => {
485
+ const opt = document.createElement("option");
486
+ opt.value = t;
487
+ opt.textContent = t;
488
+ sel.appendChild(opt);
489
+ });
490
+ }
491
+
492
+ // event handler upload
493
+ document.getElementById("fileInput").addEventListener("change", e => {
494
+ const file = e.target.files[0];
495
+ const info = document.getElementById("info");
496
+ const tbl = document.getElementById("tbl");
497
+ tbl.innerHTML = "";
498
+ if (!file) { info.textContent = "Tidak ada file."; return; }
499
+
500
+ const reader = new FileReader();
501
+ reader.onload = ev => {
502
+ rawRows = parseTxt(ev.target.result);
503
+ if (!rawRows.length) { info.textContent = "File kosong / format salah."; return; }
504
+ currentPage = 1;
505
+ sortCol = null;
506
+ buildDashboardRows();
507
+ renderTable();
508
+ };
509
+ reader.readAsText(file);
510
+ });
511
+
512
+ // search & filter & pagination events
513
+ document.getElementById("searchInput").addEventListener("input", () => {
514
+ currentPage = 1;
515
+ renderTable();
516
+ });
517
+ document.getElementById("typeFilter").addEventListener("change", () => {
518
+ currentPage = 1;
519
+ renderTable();
520
+ });
521
+ document.getElementById("dateFilter").addEventListener("input", () => {
522
+ currentPage = 1;
523
+ renderTable();
524
+ });
525
+ document.getElementById("codeFilter").addEventListener("input", () => {
526
+ currentPage = 1;
527
+ renderTable();
528
+ });
529
+ document.getElementById("pageSize").addEventListener("change", () => {
530
+ currentPage = 1;
531
+ renderTable();
532
+ });
533
+ document.getElementById("prevPage").addEventListener("click", () => {
534
+ if (currentPage > 1) { currentPage--; renderTable(); }
535
+ });
536
+ document.getElementById("nextPage").addEventListener("click", () => {
537
+ const rows = getFilteredSortedRows();
538
+ const pageSize = Number(document.getElementById("pageSize").value) || 25;
539
+ const totalPages = Math.max(1, Math.ceil(rows.length / pageSize));
540
+ if (currentPage < totalPages) { currentPage++; renderTable(); }
541
+ });
542
+ document.getElementById("firstPage").addEventListener("click", () => {
543
+ currentPage = 1;
544
+ renderTable();
545
+ });
546
+ document.getElementById("lastPage").addEventListener("click", () => {
547
+ const rows = getFilteredSortedRows();
548
+ const pageSize = Number(document.getElementById("pageSize").value) || 25;
549
+ const totalPages = Math.max(1, Math.ceil(rows.length / pageSize));
550
+ currentPage = totalPages;
551
+ renderTable();
552
+ });
553
+
554
+ // tambah data manual
555
+ document.getElementById("btnAddRow").addEventListener("click", () => {
556
+ if (!rawRows.length) {
557
+ alert("Upload TXT dulu sebelum tambah data.");
558
+ return;
559
+ }
560
+ const getVal = id => document.getElementById(id).value.trim();
561
+
562
+ const row = [];
563
+ row[0] = getVal("addDate") || "";
564
+ row[1] = getVal("addCode") || "";
565
+ row[2] = getVal("addType") || "";
566
+ row[3] = getVal("addSecNum") || "0";
567
+ row[4] = getVal("addPrice") || "0";
568
+
569
+ const localIds = ["addLocalIS","addLocalCP","addLocalPF","addLocalIB","addLocalID","addLocalMF","addLocalSC","addLocalFD","addLocalOT"];
570
+ const foreignIds = ["addForeignIS","addForeignCP","addForeignPF","addForeignIB","addForeignID","addForeignMF","addForeignSC","addForeignFD","addForeignOT"];
571
+
572
+ localIds.forEach((id, i) => { row[5 + i] = getVal(id) || "0"; });
573
+ // kolom total lama (O) kita isi 0, nanti dihitung ulang
574
+ row[14] = "0";
575
+ foreignIds.forEach((id, i) => { row[15 + i] = getVal(id) || "0"; });
576
+ row[24] = "0";
577
+
578
+ rawRows.push(row);
579
+ buildDashboardRows();
580
+ renderTable();
581
+
582
+ // Clear form after adding
583
+ document.getElementById("addDate").value = "";
584
+ document.getElementById("addCode").value = "";
585
+ document.getElementById("addType").value = "";
586
+ document.getElementById("addSecNum").value = "";
587
+ document.getElementById("addPrice").value = "";
588
+ localIds.forEach(id => document.getElementById(id).value = "");
589
+ foreignIds.forEach(id => document.getElementById(id).value = "");
590
+ });
591
+ </script>
592
+
593
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-qwensite.hf.space/logo.svg" alt="qwensite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-qwensite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >QwenSite</a> - 🧬 <a href="https://enzostvs-qwensite.hf.space?remix=alterzick/balancepos-v1" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
594
+ </html>
prompts.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ saya ingin membuat aplikasi seperti excel otomatis yang bisa saya tambah kolomnya dan isinya dan bisa saya jadikan template untuk data setelahnya
2
+ tambahkan penambahan data , pembanding data dan filtering data untuk ascending atau decending profesional sehingga bisa melihat perbedaan antar data yang sudah di input
3
+ dari html yang ada tolong tambahkan fitur penyimpanan data yang sudah di upload, edit dan delete sehingga bisa di cek basis data