ad: transactions province filter
This commit is contained in:
70
index.js
70
index.js
@@ -1084,6 +1084,7 @@ app.get("/all-payments/data", requireAllPaymentsAuth, async (req, res) => {
|
||||
let dateTo = (req.query.dateTo || "").trim();
|
||||
if (dateFrom && !dateTo) dateTo = dateFrom;
|
||||
const search = (req.query.search || "").trim();
|
||||
const province = (req.query.province || "").trim();
|
||||
|
||||
if (dateFrom || dateTo) {
|
||||
console.log("all-payments/data date filter:", { dateFrom, dateTo });
|
||||
@@ -1106,6 +1107,25 @@ app.get("/all-payments/data", requireAllPaymentsAuth, async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (province) {
|
||||
const code = String(province).trim();
|
||||
const prefixRegex = new RegExp("^" + escapeRegex(code));
|
||||
filter.$and = filter.$and || [];
|
||||
filter.$and.push({
|
||||
$or: [
|
||||
{ provincecode: prefixRegex },
|
||||
{
|
||||
$expr: {
|
||||
$regexMatch: {
|
||||
input: { $toString: "$provincecode" },
|
||||
regex: "^" + escapeRegex(code),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (search) {
|
||||
filter.$or = [
|
||||
{ amountRaw: new RegExp(escapeRegex(search), "i") },
|
||||
@@ -1113,6 +1133,13 @@ app.get("/all-payments/data", requireAllPaymentsAuth, async (req, res) => {
|
||||
{ provincecode: new RegExp(escapeRegex(search), "i") },
|
||||
{ resNum: new RegExp(escapeRegex(search), "i") },
|
||||
];
|
||||
// Province name filter: match search text against province names (e.g. همدان, تست)
|
||||
Object.keys(PROVINCE_NAMES).forEach((code) => {
|
||||
if (PROVINCE_NAMES[code].indexOf(search) !== -1) {
|
||||
filter.$or.push({ provincecode: code });
|
||||
filter.$or.push({ provincecode: parseInt(code, 10) });
|
||||
}
|
||||
});
|
||||
if (!isNaN(parseInt(search, 10))) {
|
||||
filter.$or.push({ amount: parseInt(search, 10) });
|
||||
}
|
||||
@@ -1250,7 +1277,9 @@ app.get("/all-payments", async (req, res) => {
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { font-family: 'Inter', -apple-system, sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; padding: 24px; line-height: 1.5; }
|
||||
.page { max-width: 1200px; margin: 0 auto; }
|
||||
h1 { font-size: 1.75rem; font-weight: 700; margin-bottom: 24px; letter-spacing: -0.02em; }
|
||||
.page-header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 24px; }
|
||||
.page-header h1 { font-size: 1.75rem; font-weight: 700; margin: 0; letter-spacing: -0.02em; }
|
||||
.header-actions { display: flex; gap: 10px; align-items: center; }
|
||||
.toolbar { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-bottom: 20px; }
|
||||
.filters { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; flex: 1; }
|
||||
.filter-group { display: flex; align-items: center; gap: 8px; }
|
||||
@@ -1261,6 +1290,11 @@ app.get("/all-payments", async (req, res) => {
|
||||
}
|
||||
input[type="text"]:focus, input[type="date"]:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 2px rgba(99,102,241,0.2); }
|
||||
input[type="text"]::placeholder { color: var(--text-muted); }
|
||||
select {
|
||||
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
|
||||
color: var(--text); padding: 10px 14px; font-size: 0.875rem; min-width: 140px; cursor: pointer;
|
||||
}
|
||||
select:focus { outline: none; border-color: var(--primary); }
|
||||
.btn { border: none; border-radius: var(--radius-sm); padding: 10px 18px; font-size: 0.875rem; font-weight: 500; cursor: pointer; transition: background 0.15s, opacity 0.15s; }
|
||||
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
.btn-primary { background: var(--primary); color: #fff; }
|
||||
@@ -1295,7 +1329,13 @@ app.get("/all-payments", async (req, res) => {
|
||||
</head>
|
||||
<body>
|
||||
<div class="page">
|
||||
<div class="page-header">
|
||||
<h1>همه پرداختها</h1>
|
||||
<div class="header-actions">
|
||||
<button type="button" class="btn btn-danger" id="btn-remove-all">حذف همه</button>
|
||||
<button type="button" class="btn btn-ghost" id="btn-logout">خروج</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<div class="filters">
|
||||
<div class="filter-group">
|
||||
@@ -1309,12 +1349,19 @@ app.get("/all-payments", async (req, res) => {
|
||||
<input type="hidden" id="dateToGregorian" />
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<input type="text" id="search" placeholder="جستجو (مبلغ، موبایل، استان...) " />
|
||||
<label>استان</label>
|
||||
<select id="province">
|
||||
<option value="">همه استانها</option>
|
||||
${Object.keys(PROVINCE_NAMES)
|
||||
.map((c) => `<option value="${c}">${PROVINCE_NAMES[c]}</option>`)
|
||||
.join("")}
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<input type="text" id="search" placeholder="جستجو" />
|
||||
</div>
|
||||
<button type="button" class="btn btn-ghost" id="btn-apply">اعمال فیلتر</button>
|
||||
</div>
|
||||
<button type="button" class="btn btn-danger" id="btn-remove-all">حذف همه</button>
|
||||
<button type="button" class="btn btn-ghost" id="btn-logout">خروج</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="table-wrap">
|
||||
@@ -1328,7 +1375,7 @@ app.get("/all-payments", async (req, res) => {
|
||||
<script src="https://cdn.jsdelivr.net/npm/persian-datepicker@1.2.0/dist/js/persian-datepicker.min.js"></script>
|
||||
<script>
|
||||
(function() {
|
||||
var state = { page: 1, limit: 20, dateFrom: '', dateTo: '', search: '' };
|
||||
var state = { page: 1, limit: 20, dateFrom: '', dateTo: '', search: '', province: '' };
|
||||
var contentEl = document.getElementById('table-content');
|
||||
var paginationEl = document.getElementById('pagination');
|
||||
|
||||
@@ -1357,14 +1404,18 @@ app.get("/all-payments", async (req, res) => {
|
||||
var q = 'page=' + state.page + '&limit=' + state.limit;
|
||||
if (state.dateFrom) q += '&dateFrom=' + encodeURIComponent(state.dateFrom);
|
||||
if (state.dateTo) q += '&dateTo=' + encodeURIComponent(state.dateTo);
|
||||
if (state.province) q += '&province=' + encodeURIComponent(state.province);
|
||||
if (state.search) q += '&search=' + encodeURIComponent(state.search);
|
||||
return q;
|
||||
}
|
||||
|
||||
function renderRow(item) {
|
||||
function renderRow(item, index) {
|
||||
var createdAt = item.createdAt ? new Date(item.createdAt).toLocaleString('fa-IR') : '-';
|
||||
var id = item._id;
|
||||
return '<tr data-id="' + id + '"><td>' + (item.amountRaw || item.amount) + '</td><td>' + (item.provinceName || '-') + '</td><td>' + (item.isLink ? 'بله' : 'خیر') + '</td><td>' + (item.phone || '-') + '</td><td>' + createdAt + '</td><td><div class="actions-cell"><button type="button" class="btn btn-primary btn-sm btn-send" data-id="' + id + '">ارسال به سرور</button><button type="button" class="btn btn-danger btn-sm btn-remove" data-id="' + id + '">حذف</button><div class="cell-msg" id="msg-' + id + '"></div></div></td></tr>';
|
||||
var rowNum = (state.page - 1) * state.limit + (index + 1);
|
||||
var amountVal = item.amountRaw != null ? item.amountRaw : item.amount;
|
||||
var amountStr = amountVal != null ? Number(amountVal).toLocaleString('fa-IR') : '-';
|
||||
return '<tr data-id="' + id + '"><td>' + rowNum + '</td><td>' + amountStr + '</td><td>' + (item.provinceName || '-') + '</td><td>' + (item.isLink ? 'بله' : 'خیر') + '</td><td>' + (item.phone || '-') + '</td><td>' + createdAt + '</td><td><div class="actions-cell"><button type="button" class="btn btn-primary btn-sm btn-send" data-id="' + id + '">ارسال به سرور</button><button type="button" class="btn btn-danger btn-sm btn-remove" data-id="' + id + '">حذف</button><div class="cell-msg" id="msg-' + id + '"></div></div></td></tr>';
|
||||
}
|
||||
|
||||
function bindRowEvents(fragment) {
|
||||
@@ -1443,8 +1494,8 @@ app.get("/all-payments", async (req, res) => {
|
||||
paginationEl.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
var thead = '<table><thead><tr><th>مبلغ</th><th>استان</th><th>لینک</th><th>موبایل</th><th>تاریخ</th><th>عملیات</th></tr></thead><tbody>';
|
||||
var rows = list.map(renderRow).join('');
|
||||
var thead = '<table><thead><tr><th>ردیف</th><th>مبلغ</th><th>استان</th><th>لینک</th><th>موبایل</th><th>تاریخ</th><th>عملیات</th></tr></thead><tbody>';
|
||||
var rows = list.map(function(item, i) { return renderRow(item, i); }).join('');
|
||||
contentEl.innerHTML = thead + rows + '</tbody></table>';
|
||||
bindRowEvents(contentEl);
|
||||
renderPagination(data);
|
||||
@@ -1503,6 +1554,7 @@ app.get("/all-payments", async (req, res) => {
|
||||
state.dateFrom = (document.getElementById('dateFromGregorian').value || '').trim();
|
||||
state.dateTo = (document.getElementById('dateToGregorian').value || '').trim();
|
||||
if (state.dateFrom && !state.dateTo) state.dateTo = state.dateFrom;
|
||||
state.province = (document.getElementById('province').value || '').trim();
|
||||
state.search = document.getElementById('search').value.trim();
|
||||
state.page = 1;
|
||||
load();
|
||||
|
||||
Reference in New Issue
Block a user