i18n (Phase C batch 9): collectors, dashboard, monitoring, vouchers, cashier_reports, cashier_attendance ID/EN
This commit is contained in:
1 parent
69d6ebbd0e
commit
d09ab217f9
8 files changed
+204
-72
No files matched your search
@@ -103,14 +103,14 @@
|
||||
<!-- Today's Status -->
|
||||
<div class="card">
|
||||
<div class="card-hd">
|
||||
<h6><i class="bi bi-calendar-day"></i> Status Hari Ini</h6>
|
||||
<h6><i class="bi bi-calendar-day"></i> <%= t('admin.ca.today_status','Status Hari Ini') %></h6>
|
||||
</div>
|
||||
<div class="card-bd">
|
||||
<% if (todayAttendance) { %>
|
||||
<% if (todayAttendance.status === 'checked_in') { %>
|
||||
<span class="status-badge status-checked-in"><i class="bi bi-check-lg"></i> Sudah Check-in</span>
|
||||
<span class="status-badge status-checked-in"><i class="bi bi-check-lg"></i> <%= t('admin.ca.checked_in','Sudah Check-in') %></span>
|
||||
<% } else { %>
|
||||
<span class="status-badge status-checked-out"><i class="bi bi-check-lg"></i> Sudah Check-out</span>
|
||||
<span class="status-badge status-checked-out"><i class="bi bi-check-lg"></i> <%= t('admin.ca.checked_out','Sudah Check-out') %></span>
|
||||
<% } %>
|
||||
|
||||
<div class="info-row">
|
||||
@@ -124,7 +124,7 @@
|
||||
<span class="info-value"><%= formatDateLocal(todayAttendance.check_out_time) %></span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Durasi Kerja</span>
|
||||
<span class="info-label"><%= t('admin.ca.work_duration','Durasi Kerja') %></span>
|
||||
<span class="info-value">
|
||||
<%= Math.floor(todayAttendance.work_duration_minutes / 60) %> jam
|
||||
<%= todayAttendance.work_duration_minutes % 60 %> menit
|
||||
@@ -134,21 +134,21 @@
|
||||
|
||||
<% if (todayAttendance.check_in_note) { %>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Catatan Check-in</span>
|
||||
<span class="info-label"><%= t('admin.ca.note_in','Catatan Check-in') %></span>
|
||||
<span class="info-value"><%= todayAttendance.check_in_note %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<% if (todayAttendance.check_out_note) { %>
|
||||
<div class="info-row">
|
||||
<span class="info-label">Catatan Check-out</span>
|
||||
<span class="info-label"><%= t('admin.ca.note_out','Catatan Check-out') %></span>
|
||||
<span class="info-value"><%= todayAttendance.check_out_note %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<% if (todayAttendance.check_in_photo || todayAttendance.check_out_photo) { %>
|
||||
<div class="info-row" style="align-items:flex-start">
|
||||
<span class="info-label">Foto Absensi</span>
|
||||
<span class="info-label"><%= t('admin.ca.photo','Foto Absensi') %></span>
|
||||
<span class="info-value" style="display:flex;gap:10px;flex-wrap:wrap;justify-content:flex-end">
|
||||
<% if (todayAttendance.check_in_photo) { %>
|
||||
<a href="<%= todayAttendance.check_in_photo %>" target="_blank" style="text-decoration:none;color:var(--text);font-size:12px;text-align:center">
|
||||
@@ -167,7 +167,7 @@
|
||||
<% } %>
|
||||
|
||||
<% if (todayAttendance.status === 'checked_in') { %>
|
||||
<textarea id="checkoutNote" class="note-input" placeholder="Catatan check-out (opsional)"></textarea>
|
||||
<textarea id="checkoutNote" class="note-input" placeholder="<%= t('admin.ca.ph_note_out','Catatan check-out (opsional)') %>"></textarea>
|
||||
<input id="checkoutPhoto" type="file" accept="image/*" capture="user" style="display: none;" onchange="updatePhotoInfo('checkoutPhoto', 'checkoutPhotoInfo', 'checkoutPhotoPreviewWrap', 'checkoutPhotoPreview')">
|
||||
|
||||
<div style="text-align: center; margin: 16px 0;">
|
||||
@@ -177,7 +177,7 @@
|
||||
<div style="font-size: 11px; color: var(--muted); margin-top: 6px;"><%= t('collector.tap_camera','Ketuk tombol kamera untuk mengambil foto selfie') %></div>
|
||||
</div>
|
||||
|
||||
<div id="checkoutPhotoInfo" class="photo-help text-center">Belum ada foto diambil. Foto wajib untuk check-out.</div>
|
||||
<div id="checkoutPhotoInfo" class="photo-help text-center"><%= t('admin.ca.no_photo_out','Belum ada foto diambil. Foto wajib untuk check-out.') %></div>
|
||||
<div style="text-align: center; margin-top: 4px;">
|
||||
<div id="checkoutPhotoStatus" class="photo-help" style="display:inline-block;padding:4px 10px;border-radius:999px;background:rgba(239,68,68,0.18);color:#fecaca"><%= t('collector.selfie_required','Foto wajib') %></div>
|
||||
</div>
|
||||
@@ -195,10 +195,10 @@
|
||||
<% } %>
|
||||
|
||||
<% } else { %>
|
||||
<span class="status-badge status-not-checked-in"><i class="bi bi-x-lg"></i> Belum Check-in</span>
|
||||
<span class="status-badge status-not-checked-in"><i class="bi bi-x-lg"></i> <%= t('admin.ca.not_checked_in','Belum Check-in') %></span>
|
||||
<p style="color: var(--muted); margin: 16px 0;">Silakan lakukan check-in untuk memulai hari kerja Anda.</p>
|
||||
|
||||
<textarea id="checkinNote" class="note-input" placeholder="Catatan check-in (opsional)"></textarea>
|
||||
<textarea id="checkinNote" class="note-input" placeholder="<%= t('admin.ca.ph_note_in','Catatan check-in (opsional)') %>"></textarea>
|
||||
<input id="checkinPhoto" type="file" accept="image/*" capture="user" style="display: none;" onchange="updatePhotoInfo('checkinPhoto', 'checkinPhotoInfo', 'checkinPhotoPreviewWrap', 'checkinPhotoPreview')">
|
||||
|
||||
<div style="text-align: center; margin: 16px 0;">
|
||||
@@ -208,7 +208,7 @@
|
||||
<div style="font-size: 11px; color: var(--muted); margin-top: 6px;"><%= t('collector.tap_camera','Ketuk tombol kamera untuk mengambil foto selfie') %></div>
|
||||
</div>
|
||||
|
||||
<div id="checkinPhotoInfo" class="photo-help text-center">Belum ada foto diambil. Foto wajib untuk check-in.</div>
|
||||
<div id="checkinPhotoInfo" class="photo-help text-center"><%= t('admin.ca.no_photo_in','Belum ada foto diambil. Foto wajib untuk check-in.') %></div>
|
||||
<div style="text-align: center; margin-top: 4px;">
|
||||
<div id="checkinPhotoStatus" class="photo-help" style="display:inline-block;padding:4px 10px;border-radius:999px;background:rgba(239,68,68,0.18);color:#fecaca"><%= t('collector.selfie_required','Foto wajib') %></div>
|
||||
</div>
|
||||
@@ -235,31 +235,31 @@
|
||||
<div class="stat-grid" style="grid-template-columns:repeat(4,1fr)">
|
||||
<div class="sc p">
|
||||
<i class="bi bi-calendar-month sc-icon"></i>
|
||||
<div class="sc-label">Total Hari</div>
|
||||
<div class="sc-label"><%= t('admin.ca.total_days','Total Hari') %></div>
|
||||
<div class="sc-val"><%= summary.total_days || 0 %></div>
|
||||
<div class="sc-sub">Bulan ini</div>
|
||||
<div class="sc-sub"><%= t('admin.ca.this_month','Bulan ini') %></div>
|
||||
</div>
|
||||
<div class="sc s">
|
||||
<i class="bi bi-check-circle sc-icon"></i>
|
||||
<div class="sc-label">Hari Lengkap</div>
|
||||
<div class="sc-label"><%= t('admin.ca.full_days','Hari Lengkap') %></div>
|
||||
<div class="sc-val"><%= summary.completed_days || 0 %></div>
|
||||
<div class="sc-sub">Check-in & out</div>
|
||||
<div class="sc-sub"><%= t('admin.ca.in_out','Check-in & out') %></div>
|
||||
</div>
|
||||
<div class="sc p">
|
||||
<i class="bi bi-clock sc-icon"></i>
|
||||
<div class="sc-label">Total Jam</div>
|
||||
<div class="sc-label"><%= t('admin.ca.total_hours','Total Jam') %></div>
|
||||
<div class="sc-val">
|
||||
<%= summary.total_minutes ? Math.floor(summary.total_minutes / 60) : 0 %>
|
||||
</div>
|
||||
<div class="sc-sub">Jam kerja</div>
|
||||
<div class="sc-sub"><%= t('admin.ca.work_hours','Jam kerja') %></div>
|
||||
</div>
|
||||
<div class="sc s">
|
||||
<i class="bi bi-graph-up sc-icon"></i>
|
||||
<div class="sc-label">Rata-rata</div>
|
||||
<div class="sc-label"><%= t('admin.ca.avg','Rata-rata') %></div>
|
||||
<div class="sc-val">
|
||||
<%= summary.avg_minutes ? Math.floor(summary.avg_minutes / 60) : 0 %>
|
||||
</div>
|
||||
<div class="sc-sub">Jam/hari</div>
|
||||
<div class="sc-sub"><%= t('admin.ca.hours_per_day','Jam/hari') %></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="<%= lang || 'id' %>">
|
||||
<head>
|
||||
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Laporan Kasir | <%= company %></title>
|
||||
<title><%= t('admin.cr.title','Laporan Kasir') %> | <%= company %></title>
|
||||
<link rel="stylesheet" href="/vendor/bootstrap-icons/bootstrap-icons.min.css">
|
||||
<link rel="stylesheet" href="/css/admin.css">
|
||||
</head>
|
||||
@@ -14,7 +14,7 @@
|
||||
<div class="tb-title">
|
||||
<button class="hb-menu" onclick="toggleSidebar()"><i class="bi bi-list"></i></button>
|
||||
<i class="bi bi-journal-text"></i>
|
||||
<span>Laporan Kasir</span>
|
||||
<span><%= t('admin.cr.title','Laporan Kasir') %></span>
|
||||
</div>
|
||||
<div class="tb-right">
|
||||
<span class="adm-badge" style="font-size:12px;opacity:0.7;"><%= company %></span>
|
||||
@@ -35,7 +35,7 @@
|
||||
<div class="card-bd" style="display:flex;gap:10px;flex-wrap:wrap;align-items:center">
|
||||
<% if (cashiers && cashiers.length > 1) { %>
|
||||
<select class="fs" style="min-width:240px" onchange="location='/admin/cashiers/reports?cashierId='+encodeURIComponent(this.value)">
|
||||
<option value="">Semua Kasir</option>
|
||||
<option value=""><%= t('admin.cr.all_cashier','Semua Kasir') %></option>
|
||||
<% (cashiers || []).forEach(c => { %>
|
||||
<option value="<%= c.id %>" <%= cashierId && Number(cashierId)===Number(c.id) ? 'selected' : '' %>><%= c.name %> (@<%= c.username %>)</option>
|
||||
<% }) %>
|
||||
@@ -43,16 +43,16 @@
|
||||
<% } else if (cashiers && cashiers.length === 1) { %>
|
||||
<span class="badge bm"><%= cashiers[0].name %><%= cashiers[0].username ? (' (@' + cashiers[0].username + ')') : '' %></span>
|
||||
<% } %>
|
||||
<span class="badge bm"><%= Number(summary?.count || 0) %> transaksi</span>
|
||||
<span class="badge bm"><%= Number(summary?.count || 0) %> <%= t('admin.cr.tx','transaksi') %></span>
|
||||
<span class="badge bs">Rp <%= Number(summary?.total || 0).toLocaleString('id-ID') %></span>
|
||||
<span class="badge bm">Tagihan: <%= Number(summary?.invoice_count || 0) %> (Rp <%= Number(summary?.invoice_total || 0).toLocaleString('id-ID') %>)</span>
|
||||
<span class="badge bm">Deposit Agent: <%= Number(summary?.topup_count || 0) %> (Rp <%= Number(summary?.topup_total || 0).toLocaleString('id-ID') %>)</span>
|
||||
<span class="badge bm"><%= t('admin.cr.invoice','Tagihan:') %> <%= Number(summary?.invoice_count || 0) %> (Rp <%= Number(summary?.invoice_total || 0).toLocaleString('id-ID') %>)</span>
|
||||
<span class="badge bm"><%= t('admin.cr.topup','Deposit Agent:') %> <%= Number(summary?.topup_count || 0) %> (Rp <%= Number(summary?.topup_total || 0).toLocaleString('id-ID') %>)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-top:16px">
|
||||
<div class="card-hd">
|
||||
<h6><i class="bi bi-list-ul"></i> Riwayat Transaksi</h6>
|
||||
<h6><i class="bi bi-list-ul"></i> <%= t('admin.cr.history','Riwayat Transaksi') %></h6>
|
||||
</div>
|
||||
<div class="tbl-wrap">
|
||||
<table class="dtbl">
|
||||
@@ -60,16 +60,16 @@
|
||||
<tr>
|
||||
<th><%= t('collector.col_time','Waktu') %></th>
|
||||
<th>Kasir</th>
|
||||
<th>Jenis</th>
|
||||
<th>Detail</th>
|
||||
<th><%= t('admin.cr.th_type','Jenis') %></th>
|
||||
<th><%= t('admin.cr.th_detail','Detail') %></th>
|
||||
<th class="num"><%= t('collector.col_amount','Nominal') %></th>
|
||||
<th>Catatan</th>
|
||||
<th><%= t('admin.cr.th_note','Catatan') %></th>
|
||||
<th class="num">Ref</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if (!rows || rows.length === 0) { %>
|
||||
<tr><td colspan="7" class="text-center text-muted" style="padding:24px">Belum ada transaksi kasir.</td></tr>
|
||||
<tr><td colspan="7" class="text-center text-muted" style="padding:24px">Belum ada <%= t('admin.cr.tx','transaksi') %> kasir.</td></tr>
|
||||
<% } else { %>
|
||||
<% rows.forEach(r => { %>
|
||||
<tr>
|
||||
@@ -79,7 +79,7 @@
|
||||
<% if (r.kind === 'agent_topup') { %>
|
||||
<span class="badge bs">DEPOSIT</span>
|
||||
<% } else { %>
|
||||
<span class="badge bm">TAGIHAN</span>
|
||||
<span class="badge bm"><%= t('admin.cr.badge_invoice','TAGIHAN') %></span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td style="font-size:12px">
|
||||
|
||||
+25
-25
@@ -14,11 +14,11 @@
|
||||
<div class="tb-title">
|
||||
<button class="hb-menu" onclick="toggleSidebar()"><i class="bi bi-list"></i></button>
|
||||
<i class="bi bi-person-badge"></i>
|
||||
<span>Manajemen Kolektor</span>
|
||||
<span><%= t('admin.col.title','Manajemen Kolektor') %></span>
|
||||
</div>
|
||||
<div class="tb-right">
|
||||
<span class="adm-badge"><i class="bi bi-person-fill"></i> <%= (typeof session !== 'undefined' && session.isCashier) ? t('admin.role.cashier', 'Kasir') : t('admin.role.admin', 'Admin') %></span>
|
||||
<button class="btn btn-p btn-sm" onclick="openModal('addCollectorModal')"><i class="bi bi-plus-lg"></i> Tambah Kolektor</button>
|
||||
<button class="btn btn-p btn-sm" onclick="openModal('addCollectorModal')"><i class="bi bi-plus-lg"></i> <%= t('admin.col.add','Tambah Kolektor') %></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,19 +29,19 @@
|
||||
|
||||
<div class="card">
|
||||
<div class="card-hd">
|
||||
<h6><i class="bi bi-list-ul"></i> Daftar Kolektor</h6>
|
||||
<h6><i class="bi bi-list-ul"></i> <%= t('admin.col.list','Daftar Kolektor') %></h6>
|
||||
</div>
|
||||
<div class="hint" style="padding:12px 16px 0 16px;font-size:12px;color:var(--muted)">
|
||||
Pengaturan approval pembayaran berlaku per akun kolektor. `Langsung Lunas` berarti pembayaran dari kolektor langsung melunasi invoice, sedangkan `Perlu Approval` berarti harus disetujui admin atau kasir terlebih dahulu.
|
||||
Pengaturan approval pembayaran berlaku per akun kolektor. `<%= t('admin.col.direct','Langsung Lunas') %>` berarti pembayaran dari kolektor langsung melunasi invoice, sedangkan `<%= t('admin.col.approval','Perlu Approval') %>` berarti harus disetujui admin atau kasir terlebih dahulu.
|
||||
</div>
|
||||
<div style="padding:12px 16px 0 16px;display:flex;gap:10px;flex-wrap:wrap">
|
||||
<select id="collectorModeFilter" class="fs" style="max-width:220px">
|
||||
<option value="all">Semua Mode Pembayaran</option>
|
||||
<option value="direct">Langsung Lunas</option>
|
||||
<option value="approval">Perlu Approval</option>
|
||||
<option value="all"><%= t('admin.col.all_paymode','Semua Mode Pembayaran') %></option>
|
||||
<option value="direct"><%= t('admin.col.direct','Langsung Lunas') %></option>
|
||||
<option value="approval"><%= t('admin.col.approval','Perlu Approval') %></option>
|
||||
</select>
|
||||
<select id="collectorStatusFilter" class="fs" style="max-width:180px">
|
||||
<option value="all">Semua Status Akun</option>
|
||||
<option value="all"><%= t('admin.col.all_status','Semua Status Akun') %></option>
|
||||
<option value="active"><%= t('common.active','Aktif') %></option>
|
||||
<option value="inactive"><%= t('common.inactive','Nonaktif') %></option>
|
||||
</select>
|
||||
@@ -53,10 +53,10 @@
|
||||
<th><%= t('pwa.field.name','Nama') %></th>
|
||||
<th>Username</th>
|
||||
<th>Password</th>
|
||||
<th>No. HP</th>
|
||||
<th>Area Tugas</th>
|
||||
<th><%= t('admin.col.phone','No. HP') %></th>
|
||||
<th><%= t('admin.col.area','Area Tugas') %></th>
|
||||
<th><%= t('common.status','Status') %></th>
|
||||
<th>Mode Pembayaran</th>
|
||||
<th><%= t('admin.col.paymode','Mode Pembayaran') %></th>
|
||||
<th><%= t('common.actions','Aksi') %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -86,7 +86,7 @@
|
||||
<div class="act-menu">
|
||||
<button type="button" class="act-item" onclick='editCollector(<%- JSON.stringify(c).split('<').join('\\u003c') %>)'><i class="bi bi-pencil"></i> Edit Kolektor</button>
|
||||
<div class="act-sep"></div>
|
||||
<button type="submit" form="cdel-<%= c.id %>" class="act-item danger"><i class="bi bi-trash"></i> Hapus Kolektor</button>
|
||||
<button type="submit" form="cdel-<%= c.id %>" class="act-item danger"><i class="bi bi-trash"></i> <%= t('admin.col.del','Hapus Kolektor') %></button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -103,16 +103,16 @@
|
||||
<div class="mo" id="addCollectorModal">
|
||||
<div class="mb">
|
||||
<form action="/admin/collectors" method="POST">
|
||||
<div class="mh"><span class="mt">Tambah Kolektor Baru</span><button type="button" class="mc" onclick="closeModal('addCollectorModal')">×</button></div>
|
||||
<div class="mh"><span class="mt"><%= t('admin.col.add_new','Tambah Kolektor Baru') %></span><button type="button" class="mc" onclick="closeModal('addCollectorModal')">×</button></div>
|
||||
<div class="mbody">
|
||||
<div class="fg"><label class="fl">Nama Lengkap</label><input type="text" name="name" class="fc" required></div>
|
||||
<div class="fg"><label class="fl"><%= t('admin.col.full_name','Nama Lengkap') %></label><input type="text" name="name" class="fc" required></div>
|
||||
<div class="fg"><label class="fl">Username Login</label><input type="text" name="username" class="fc" required></div>
|
||||
<div class="fg"><label class="fl">Password</label><input type="text" name="password" class="fc" required></div>
|
||||
<div class="fg"><label class="fl">No. HP</label><input type="text" name="phone" class="fc" placeholder="08123456789"></div>
|
||||
<div class="fg"><label class="fl"><%= t('admin.col.phone','No. HP') %></label><input type="text" name="phone" class="fc" placeholder="08123456789"></div>
|
||||
<div class="fg">
|
||||
<label class="fl">Area / Wilayah Tugas</label>
|
||||
<label class="fl"><%= t('admin.col.area_region','Area / Wilayah Tugas') %></label>
|
||||
<select name="area" class="fs">
|
||||
<option value="">-- Semua Area / Bebas --</option>
|
||||
<option value=""><%= t('admin.col.opt_all_area','-- Semua Area / Bebas --') %></option>
|
||||
<% if (typeof masterAreas !== 'undefined' && masterAreas && masterAreas.length > 0) { %>
|
||||
<% masterAreas.forEach(a => { %>
|
||||
<option value="<%= a.name %>"><%= a.name %></option>
|
||||
@@ -125,8 +125,8 @@
|
||||
<i class="bi bi-check-circle"></i> Auto-Approve Pembayaran
|
||||
</label>
|
||||
<select name="auto_approve" id="add-auto-approve" class="fs" onchange="updateCollectorModeBadge('add')">
|
||||
<option value="0">Nonaktif (Perlu Approval Admin)</option>
|
||||
<option value="1">Aktif (Langsung Lunas)</option>
|
||||
<option value="0">Nonaktif (<%= t('admin.col.approval','Perlu Approval') %> Admin)</option>
|
||||
<option value="1">Aktif (<%= t('admin.col.direct','Langsung Lunas') %>)</option>
|
||||
</select>
|
||||
<div id="add-mode-badge" class="hint" style="margin-top:8px;font-size:12px;color:#fbbf24">
|
||||
Mode saat ini: Menunggu approval admin/kasir sebelum invoice menjadi lunas.
|
||||
@@ -149,14 +149,14 @@
|
||||
<form id="editForm" method="POST">
|
||||
<div class="mh"><span class="mt">Edit Data Kolektor</span><button type="button" class="mc" onclick="closeModal('editCollectorModal')">×</button></div>
|
||||
<div class="mbody">
|
||||
<div class="fg"><label class="fl">Nama Lengkap</label><input type="text" name="name" id="e-name" class="fc" required></div>
|
||||
<div class="fg"><label class="fl"><%= t('admin.col.full_name','Nama Lengkap') %></label><input type="text" name="name" id="e-name" class="fc" required></div>
|
||||
<div class="fg"><label class="fl">Username Login</label><input type="text" name="username" id="e-username" class="fc" required></div>
|
||||
<div class="fg"><label class="fl">Password</label><input type="text" name="password" id="e-password" class="fc" required></div>
|
||||
<div class="fg"><label class="fl">No. HP</label><input type="text" name="phone" id="e-phone" class="fc"></div>
|
||||
<div class="fg"><label class="fl"><%= t('admin.col.phone','No. HP') %></label><input type="text" name="phone" id="e-phone" class="fc"></div>
|
||||
<div class="fg">
|
||||
<label class="fl">Area / Wilayah Tugas</label>
|
||||
<label class="fl"><%= t('admin.col.area_region','Area / Wilayah Tugas') %></label>
|
||||
<select name="area" id="e-area" class="fs">
|
||||
<option value="">-- Semua Area / Bebas --</option>
|
||||
<option value=""><%= t('admin.col.opt_all_area','-- Semua Area / Bebas --') %></option>
|
||||
<% if (typeof masterAreas !== 'undefined' && masterAreas && masterAreas.length > 0) { %>
|
||||
<% masterAreas.forEach(a => { %>
|
||||
<option value="<%= a.name %>"><%= a.name %></option>
|
||||
@@ -176,8 +176,8 @@
|
||||
<i class="bi bi-check-circle"></i> Auto-Approve Pembayaran
|
||||
</label>
|
||||
<select name="auto_approve" id="e-auto-approve" class="fs" onchange="updateCollectorModeBadge('edit')">
|
||||
<option value="0">Nonaktif (Perlu Approval Admin)</option>
|
||||
<option value="1">Aktif (Langsung Lunas)</option>
|
||||
<option value="0">Nonaktif (<%= t('admin.col.approval','Perlu Approval') %> Admin)</option>
|
||||
<option value="1">Aktif (<%= t('admin.col.direct','Langsung Lunas') %>)</option>
|
||||
</select>
|
||||
<div id="edit-mode-badge" class="hint" style="margin-top:8px;font-size:12px;color:#fbbf24">
|
||||
Mode saat ini: Menunggu approval admin/kasir sebelum invoice menjadi lunas.
|
||||
|
||||
@@ -248,7 +248,7 @@
|
||||
<option value="online"><%= t('admin.dashboard.online', 'Online') %></option>
|
||||
<option value="offline"><%= t('admin.dashboard.offline', 'Offline') %></option>
|
||||
</select>
|
||||
<button class="btn btn-g btn-sm" onclick="openGenieACSSettings()" title="Pengaturan GenieACS">
|
||||
<button class="btn btn-g btn-sm" onclick="openGenieACSSettings()" title="<%= t('admin.dash.genieacs_title','Pengaturan GenieACS') %>">
|
||||
<i class="bi bi-gear"></i> GenieACS
|
||||
</button>
|
||||
<button class="btn btn-p btn-sm" id="btn-refresh" onclick="refreshAll()">
|
||||
@@ -802,7 +802,7 @@ async function showDetail(tag) {
|
||||
|
||||
<div style="margin-top:16px;background:var(--card-bg);border:1px solid var(--border);border-radius:12px;overflow:hidden">
|
||||
<div style="padding:14px 18px;border-bottom:1px solid var(--border);font-weight:700;color:var(--muted);display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap">
|
||||
<div><i class="bi bi-people"></i> Connected Clients (Live)</div>
|
||||
<div><i class="bi bi-people"></i> <%= t('admin.dash.conn_live','Klien Terhubung (Live)') %></div>
|
||||
<span class="badge bm">${connected.length}</span>
|
||||
</div>
|
||||
<div style="padding:16px 18px">
|
||||
@@ -1029,7 +1029,7 @@ async function saveGenieACSSettings() {
|
||||
showGenieACSMessage(result.message, 'success');
|
||||
setTimeout(() => {
|
||||
closeModal('genieacsModal');
|
||||
showToast('Pengaturan GenieACS berhasil disimpan', 's');
|
||||
showToast('<%= t('admin.dash.genieacs_title','Pengaturan GenieACS') %> berhasil disimpan', 's');
|
||||
}, 1500);
|
||||
} else {
|
||||
showGenieACSMessage(result.message, 'danger');
|
||||
|
||||
@@ -285,7 +285,7 @@
|
||||
<div class="tb-title">
|
||||
<button class="hb-menu" onclick="toggleSidebar()"><i class="bi bi-list"></i></button>
|
||||
<i class="bi bi-activity"></i>
|
||||
<span id="page-title">Monitoring Sistem</span>
|
||||
<span id="page-title"><%= t('admin.mon.title','Monitoring Sistem') %></span>
|
||||
</div>
|
||||
<div class="tb-right">
|
||||
<button onclick="location.reload()" class="btn btn-g btn-sm">
|
||||
@@ -310,17 +310,17 @@
|
||||
<i class="bi bi-<%= healthStatus.status === 'healthy' ? 'check-circle' : healthStatus.status === 'warning' ? 'exclamation-triangle' : 'x-circle' %>"></i>
|
||||
<%= healthStatus.status.toUpperCase() %>
|
||||
</div>
|
||||
<p class="text-muted mt-2 fs12">Update terakhir: <%= new Date(healthStatus.timestamp).toLocaleString('id-ID') %></p>
|
||||
<p class="text-muted mt-2 fs12"><%= t('admin.mon.updated','Update terakhir:') %> <%= new Date(healthStatus.timestamp).toLocaleString('id-ID') %></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Issues and Warnings -->
|
||||
<!-- <%= t('admin.mon.issues','Masalah') %> and <%= t('admin.mon.warnings','Peringatan') %> -->
|
||||
<% if (healthStatus.issues.length > 0 || healthStatus.warnings.length > 0) { %>
|
||||
<div class="mon-grid">
|
||||
<% if (healthStatus.issues.length > 0) { %>
|
||||
<div class="card">
|
||||
<div class="card-hd chd-d">
|
||||
<h6><i class="bi bi-exclamation-triangle-fill"></i> Issues (<%= healthStatus.issues.length %>)</h6>
|
||||
<h6><i class="bi bi-exclamation-triangle-fill"></i> <%= t('admin.mon.issues','Masalah') %> (<%= healthStatus.issues.length %>)</h6>
|
||||
</div>
|
||||
<div class="card-bd">
|
||||
<% healthStatus.issues.forEach(issue => {
|
||||
@@ -336,7 +336,7 @@
|
||||
<% if (healthStatus.warnings.length > 0) { %>
|
||||
<div class="card">
|
||||
<div class="card-hd chd-w">
|
||||
<h6><i class="bi bi-exclamation-triangle"></i> Warnings (<%= healthStatus.warnings.length %>)</h6>
|
||||
<h6><i class="bi bi-exclamation-triangle"></i> <%= t('admin.mon.warnings','Peringatan') %> (<%= healthStatus.warnings.length %>)</h6>
|
||||
</div>
|
||||
<div class="card-bd">
|
||||
<% healthStatus.warnings.forEach(warning => {
|
||||
@@ -354,7 +354,7 @@
|
||||
<!-- System Metrics -->
|
||||
<div class="card mb16">
|
||||
<div class="card-hd">
|
||||
<h6><i class="bi bi-cpu"></i> Metrik Sistem</h6>
|
||||
<h6><i class="bi bi-cpu"></i> <%= t('admin.mon.metrics','Metrik Sistem') %></h6>
|
||||
</div>
|
||||
<div class="card-bd">
|
||||
<div class="stat-grid mb0">
|
||||
@@ -491,12 +491,12 @@
|
||||
<!-- Performance Summary -->
|
||||
<div class="card mb16">
|
||||
<div class="card-hd">
|
||||
<h6><i class="bi bi-journal-text"></i> Ringkasan Performa (10 Sample Terakhir)</h6>
|
||||
<h6><i class="bi bi-journal-text"></i> <%= t('admin.mon.perf','Ringkasan Performa (10 Sample Terakhir)') %></h6>
|
||||
</div>
|
||||
<div class="card-bd">
|
||||
<div class="stat-grid stat-grid-3 mb0">
|
||||
<div>
|
||||
<p class="sc-label">Rata-rata</p>
|
||||
<p class="sc-label"><%= t('admin.mon.avg','Rata-rata') %></p>
|
||||
<table class="dtbl">
|
||||
<tr>
|
||||
<td class="text-muted">CPU</td>
|
||||
|
||||
@@ -377,11 +377,11 @@
|
||||
const sel = document.getElementById('profileName');
|
||||
sel.innerHTML = '';
|
||||
if (filtered.length === 0) {
|
||||
sel.innerHTML = '<option value="">Tidak ada profile dengan harga/durasi (Mikhmon)</option>';
|
||||
sel.innerHTML = '<option value=""><%= t('admin.vou.no_profile','Tidak ada profile dengan harga/durasi (Mikhmon)') %></option>';
|
||||
document.getElementById('profileHint').innerText = '';
|
||||
return;
|
||||
}
|
||||
sel.insertAdjacentHTML('beforeend', '<option value="">-- Pilih Profile --</option>');
|
||||
sel.insertAdjacentHTML('beforeend', '<option value=""><%= t('admin.vou.pick_profile','-- Pilih Profile --') %></option>');
|
||||
for (const x of filtered) {
|
||||
const label = `${x.raw.name} (Rp ${Number(x.meta.price || 0).toLocaleString('id-ID')} • ${x.meta.validity})`;
|
||||
sel.insertAdjacentHTML('beforeend', `<option value="${x.raw.name}">${label}</option>`);
|
||||
|
||||
Reference in new issue
Block a user