Commit fb6e381b by tdgiang

update code

parent c40b1f40
...@@ -26,7 +26,7 @@ exports.createTransaction = function (req, res) { ...@@ -26,7 +26,7 @@ exports.createTransaction = function (req, res) {
return res.status(400).json({ code: "99", data: "MISSING_FIELDS" }); return res.status(400).json({ code: "99", data: "MISSING_FIELDS" });
} }
if (!/^[0-9]{9,12}$/.test(String(customerIdCard).trim())) { if (!/^[0-9]{12}$/.test(String(customerIdCard).trim())) {
return res.status(400).json({ code: "99", data: "INVALID_ID_CARD" }); return res.status(400).json({ code: "99", data: "INVALID_ID_CARD" });
} }
...@@ -443,6 +443,7 @@ exports.listTransactions = function (req, res) { ...@@ -443,6 +443,7 @@ exports.listTransactions = function (req, res) {
resultMsg: tx.resultMsg, resultMsg: tx.resultMsg,
createdByUsername: tx.createdByUsername, createdByUsername: tx.createdByUsername,
createdAt: moment(tx.createdAt).format("DD/MM/YYYY HH:mm"), createdAt: moment(tx.createdAt).format("DD/MM/YYYY HH:mm"),
updatedAt: moment(tx.updatedAt).format("DD/MM/YYYY HH:mm"),
paymentUrl: config.epay.req_domain + "/admin/pay/" + tx.merTrxId, paymentUrl: config.epay.req_domain + "/admin/pay/" + tx.merTrxId,
}; };
}); });
...@@ -513,13 +514,14 @@ exports.exportTransactions = function (req, res) { ...@@ -513,13 +514,14 @@ exports.exportTransactions = function (req, res) {
} }
var header = [ var header = [
"Mã giao dịch", "Thời gian", "Người tạo", "Khách hàng", "SĐT", "Mã giao dịch", "Thời gian", "Thời gian giao dịch", "Người tạo", "Khách hàng", "SĐT",
"CMND/CCCD", "Số tiền", "Trạng thái", "Ghi chú", "CMND/CCCD", "Số tiền", "Trạng thái", "Ghi chú",
]; ];
var rows = list.map(function (tx) { var rows = list.map(function (tx) {
return [ return [
tx.merTrxId, tx.merTrxId,
moment(tx.createdAt).format("DD/MM/YYYY HH:mm"), moment(tx.createdAt).format("DD/MM/YYYY HH:mm"),
moment(tx.updatedAt).format("DD/MM/YYYY HH:mm"),
tx.createdByUsername || "", tx.createdByUsername || "",
tx.customerName, tx.customerName,
tx.customerPhone, tx.customerPhone,
......
...@@ -200,6 +200,32 @@ ...@@ -200,6 +200,32 @@
.btn-ghost:hover { border-color: var(--color-primary); background: var(--color-primary-soft); } .btn-ghost:hover { border-color: var(--color-primary); background: var(--color-primary-soft); }
.btn-ghost:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; } .btn-ghost:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.export-dialog {
border: none;
border-radius: var(--radius);
box-shadow: var(--shadow-card);
padding: 24px;
width: 100%;
max-width: 340px;
}
.export-dialog::backdrop { background: rgba(15, 23, 42, 0.45); }
.export-dialog h2 { font-size: 17px; margin: 0 0 4px; }
.export-dialog .subtitle { font-size: 13px; color: var(--color-text-muted); margin: 0 0 20px; }
.export-dialog .field { margin-bottom: 16px; }
.export-dialog .field label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; }
.export-dialog .field input[type="date"] {
width: 100%;
height: 40px;
padding: 0 12px;
font-size: 14px;
font-family: inherit;
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
color: var(--color-text);
background: var(--color-surface);
}
.export-dialog .dialog-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 8px; }
/* Stat strip */ /* Stat strip */
.stats { .stats {
display: grid; display: grid;
...@@ -489,10 +515,10 @@ ...@@ -489,10 +515,10 @@
<p class="subtitle">Danh sách giao dịch đã tạo và trạng thái thanh toán</p> <p class="subtitle">Danh sách giao dịch đã tạo và trạng thái thanh toán</p>
</div> </div>
<div class="header-actions"> <div class="header-actions">
<a class="btn-ghost" href="/admin/transactions/export?staff={{selectedStaff}}&status={{selectedStatus}}&fromDate={{selectedFromDate}}&toDate={{selectedToDate}}"> <button type="button" class="btn-ghost" id="openExportDialogBtn">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
Xuất Excel Xuất Excel
</a> </button>
<a class="btn-primary" href="/admin/transactions/new"> <a class="btn-primary" href="/admin/transactions/new">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
Thêm mới giao dịch Thêm mới giao dịch
...@@ -500,6 +526,27 @@ ...@@ -500,6 +526,27 @@
</div> </div>
</div> </div>
<dialog id="exportDialog" class="export-dialog">
<form method="GET" action="/admin/transactions/export">
<h2>Xuất Excel</h2>
<p class="subtitle">Chọn khoảng thời gian giao dịch cần xuất, độc lập với bộ lọc đang xem</p>
<input type="hidden" name="staff" value="{{selectedStaff}}">
<input type="hidden" name="status" value="{{selectedStatus}}">
<div class="field">
<label for="exportFromDate">Từ ngày</label>
<input type="date" id="exportFromDate" name="fromDate" value="{{selectedFromDate}}">
</div>
<div class="field">
<label for="exportToDate">Đến ngày</label>
<input type="date" id="exportToDate" name="toDate" value="{{selectedToDate}}">
</div>
<div class="dialog-actions">
<button type="button" class="filter-clear" id="cancelExportDialogBtn">Hủy</button>
<button type="submit" class="btn-primary">Xuất Excel</button>
</div>
</form>
</dialog>
<div class="stats" id="statsStrip"> <div class="stats" id="statsStrip">
<div class="stat-card is-revenue"> <div class="stat-card is-revenue">
<p class="stat-label">Sản lượng giao dịch hôm nay</p> <p class="stat-label">Sản lượng giao dịch hôm nay</p>
...@@ -560,6 +607,7 @@ ...@@ -560,6 +607,7 @@
<tr> <tr>
<th>Hành động</th> <th>Hành động</th>
<th>Thời gian</th> <th>Thời gian</th>
<th>Thời gian giao dịch</th>
<th>Mã giao dịch</th> <th>Mã giao dịch</th>
<th>Người tạo</th> <th>Người tạo</th>
<th>Khách hàng</th> <th>Khách hàng</th>
...@@ -580,6 +628,7 @@ ...@@ -580,6 +628,7 @@
</button> </button>
</td> </td>
<td class="cell-muted">{{tx.createdAt}}</td> <td class="cell-muted">{{tx.createdAt}}</td>
<td class="cell-muted">{{tx.updatedAt}}</td>
<td class="cell-mono">{{tx.merTrxIdShort}}</td> <td class="cell-mono">{{tx.merTrxIdShort}}</td>
<td class="cell-muted">{{tx.createdByUsername}}</td> <td class="cell-muted">{{tx.createdByUsername}}</td>
<td>{{tx.customerName}}</td> <td>{{tx.customerName}}</td>
...@@ -616,6 +665,18 @@ ...@@ -616,6 +665,18 @@
<script> <script>
(function () { (function () {
var exportDialog = document.getElementById('exportDialog');
var openExportBtn = document.getElementById('openExportDialogBtn');
var cancelExportBtn = document.getElementById('cancelExportDialogBtn');
if (exportDialog && openExportBtn) {
openExportBtn.addEventListener('click', function () { exportDialog.showModal(); });
}
if (exportDialog && cancelExportBtn) {
cancelExportBtn.addEventListener('click', function () { exportDialog.close(); });
}
})();
(function () {
var rows = Array.prototype.slice.call(document.querySelectorAll('#txTableBody tr')); var rows = Array.prototype.slice.call(document.querySelectorAll('#txTableBody tr'));
if (!rows.length) return; if (!rows.length) return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment