From f7818a57c0aad7a4c1c271e7b0570ef1f7b05908 Mon Sep 17 00:00:00 2001 From: wixarm Date: Sun, 1 Feb 2026 10:19:02 +0330 Subject: [PATCH] add: gui sep requests --- index.js | 449 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 351 insertions(+), 98 deletions(-) diff --git a/index.js b/index.js index 4cfa095..89d8c97 100644 --- a/index.js +++ b/index.js @@ -1037,17 +1037,58 @@ const PROVINCE_NAMES = { 51: "کردستان", }; -// all-payments: list of saved SEP pay requests (from MongoDB) -app.get("/all-payments", async (req, res) => { - let list = []; +// all-payments/data: paginated + filtered list (JSON API) +app.get("/all-payments/data", async (req, res) => { + const page = Math.max(1, parseInt(req.query.page, 10) || 1); + const limit = Math.min(100, Math.max(5, parseInt(req.query.limit, 10) || 20)); + let dateFrom = (req.query.dateFrom || "").trim(); // YYYY-MM-DD + let dateTo = (req.query.dateTo || "").trim(); + if (dateFrom && !dateTo) dateTo = dateFrom; + const search = (req.query.search || "").trim(); + + if (dateFrom || dateTo) { + console.log("all-payments/data date filter:", { dateFrom, dateTo }); + } + try { const coll = await getSepPayCollection(); + const filter = {}; + + // Iran timezone UTC+3:30 - treat selected date as full calendar day in Iran + const IRAN_OFFSET_MS = 3.5 * 60 * 60 * 1000; + if (dateFrom || dateTo) { + filter.createdAt = {}; + if (dateFrom) { + const utcStart = new Date(dateFrom + "T00:00:00.000Z").getTime(); + filter.createdAt.$gte = new Date(utcStart - IRAN_OFFSET_MS); + } + if (dateTo) { + const utcEnd = new Date(dateTo + "T23:59:59.999Z").getTime(); + filter.createdAt.$lte = new Date(utcEnd - IRAN_OFFSET_MS); + } + } + + if (search) { + filter.$or = [ + { amountRaw: new RegExp(escapeRegex(search), "i") }, + { phone: new RegExp(escapeRegex(search), "i") }, + { provincecode: new RegExp(escapeRegex(search), "i") }, + { resNum: new RegExp(escapeRegex(search), "i") }, + ]; + if (!isNaN(parseInt(search, 10))) { + filter.$or.push({ amount: parseInt(search, 10) }); + } + } + + const total = await coll.countDocuments(filter); const raw = await coll - .find({}) + .find(filter) .sort({ createdAt: -1 }) - .limit(500) + .skip((page - 1) * limit) + .limit(limit) .toArray(); - list = raw.map((doc) => { + + const list = raw.map((doc) => { const code = (doc.provincecode || "").toString().substring(0, 2); const provinceName = PROVINCE_NAMES[code] || doc.provincecode || "-"; return { @@ -1056,119 +1097,331 @@ app.get("/all-payments", async (req, res) => { provinceName, }; }); + + return res.json({ + list, + total, + page, + limit, + totalPages: Math.ceil(total / limit) || 1, + }); } catch (err) { - console.error("all-payments list error", err); + console.error("all-payments data error", err); + return res.status(500).json({ error: err.message }); } +}); - const listJson = JSON.stringify(list) - .replace(/\u2028/g, "\\u2028") - .replace(/\u2029/g, "\\u2029") - .replace(//g, "\\u003e") - .replace(/\\/g, "\\\\") - .replace(/"/g, '\\"'); +function escapeRegex(s) { + return String(s).replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} +// all-payments: modern UI with pagination, date filter, search +app.get("/all-payments", async (req, res) => { const html = ` همه پرداخت‌ها + + -

همه پرداخت‌ها

-
-
+
+

همه پرداخت‌ها

+
+
+
+ + + +
+
+ + + +
+
+ +
+ +
+ +
+
+
+
+
+ +
+
+ + + `;