[object Object]

← back to AsSeenInMovies

asseeninmovies: /spotted/queue stats header (4-tile strip — pending/live/rejected/submitted-7d) with parallel Promise.all query and responsive @media

3d60e9bc7e0e121622c8252bad5edb20022324b0 · 2026-05-12 16:57:56 -0700 · SteveStudio2

Files touched

Diff

commit 3d60e9bc7e0e121622c8252bad5edb20022324b0
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Tue May 12 16:57:56 2026 -0700

    asseeninmovies: /spotted/queue stats header (4-tile strip — pending/live/rejected/submitted-7d) with parallel Promise.all query and responsive @media
---
 server.js | 35 ++++++++++++++++++++++++++++-------
 1 file changed, 28 insertions(+), 7 deletions(-)

diff --git a/server.js b/server.js
index 132e040..317250c 100644
--- a/server.js
+++ b/server.js
@@ -590,11 +590,20 @@ app.get('/api/spotted', async (req, res) => {
 app.get('/spotted/queue', async (req, res) => {
   if (!isAdmin(req)) return res.status(401).type('html').send(htmlShell('Admin', `<div class="empty"><p>Admin token required. Append <code>?token=&lt;ASIM_ADMIN_TOKEN&gt;</code> to the URL.</p></div>`));
   try {
-    const r = await pool.query(`
-      SELECT s.*, m.title AS movie_title, m.release_year
-        FROM asim_spotted s JOIN asim_movies m ON m.id = s.movie_id
-       WHERE s.verified_at IS NULL
-       ORDER BY s.created_at DESC LIMIT 200`);
+    const [r, sres] = await Promise.all([
+      pool.query(`
+        SELECT s.*, m.title AS movie_title, m.release_year
+          FROM asim_spotted s JOIN asim_movies m ON m.id = s.movie_id
+         WHERE s.verified_at IS NULL
+         ORDER BY s.created_at DESC LIMIT 200`),
+      pool.query(`
+        SELECT
+          (SELECT COUNT(*) FROM asim_spotted WHERE verified_at IS NULL) AS pending_total,
+          (SELECT COUNT(*) FROM asim_spotted WHERE verified_at IS NOT NULL AND (verified_by IS NULL OR verified_by NOT LIKE 'rejected%')) AS approved_total,
+          (SELECT COUNT(*) FROM asim_spotted WHERE verified_by LIKE 'rejected%') AS rejected_total,
+          (SELECT COUNT(*) FROM asim_spotted WHERE created_at >= NOW() - INTERVAL '7 days') AS submitted_7d`)
+    ]);
+    const stats = sres.rows[0] || {};
     const t = req.query.token;
     const rows = r.rows.map(s => `
       <article class="queue-row" id="row-${s.id}">
@@ -624,13 +633,25 @@ app.get('/spotted/queue', async (req, res) => {
     const body = `
       <main class="container queue-page">
         <h1>Spotted · Moderation Queue</h1>
-        <p class="hint">${r.rows.length} pending submission${r.rows.length === 1 ? '' : 's'}. Approve to publish to /spotted; reject to hide.</p>
+        <div class="stats-strip">
+          <div class="stat"><span class="num">${stats.pending_total ?? 0}</span><span class="lbl">pending</span></div>
+          <div class="stat"><span class="num">${stats.approved_total ?? 0}</span><span class="lbl">live</span></div>
+          <div class="stat"><span class="num">${stats.rejected_total ?? 0}</span><span class="lbl">rejected</span></div>
+          <div class="stat"><span class="num">${stats.submitted_7d ?? 0}</span><span class="lbl">submitted · 7d</span></div>
+        </div>
+        <p class="hint">Showing up to 200 oldest-first. Approve publishes to /spotted; reject is reversible (clear <code>verified_by</code> in psql to undo).</p>
         <section class="queue-list">${rows || '<div class="empty">Queue is empty — no pending submissions.</div>'}</section>
       </main>
       <style>
         .queue-page { max-width: 980px; padding-top: 28px; }
-        .queue-page h1 { font-family: 'Cormorant Garamond', serif; font-size: 38px; margin: 0 0 6px; }
+        .queue-page h1 { font-family: 'Cormorant Garamond', serif; font-size: 38px; margin: 0 0 14px; }
+        .queue-page .stats-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin: 0 0 18px; }
+        .queue-page .stat { padding: 12px 14px; border: 1px solid rgba(0,0,0,0.10); border-radius: 6px; background: rgba(255,255,255,0.5); display: flex; flex-direction: column; gap: 2px; }
+        .queue-page .stat .num { font-family: 'Cormorant Garamond', serif; font-size: 30px; font-weight: 600; color: #B58A50; line-height: 1.0; }
+        .queue-page .stat .lbl { font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-mute, #777); }
+        @media (max-width: 640px) { .queue-page .stats-strip { grid-template-columns: repeat(2, 1fr); } }
         .queue-page .hint { color: var(--ink-mute, #777); margin: 0 0 24px; font-size: 14px; }
+        .queue-page .hint code { background: rgba(0,0,0,0.05); padding: 2px 4px; border-radius: 3px; font-size: 12px; }
         .queue-row { border: 1px solid rgba(0,0,0,0.12); border-radius: 6px; padding: 16px 18px; margin: 0 0 14px; background: rgba(255,255,255,0.6); }
         .queue-row header { display: flex; gap: 14px; align-items: baseline; margin-bottom: 10px; font-size: 13px; }
         .queue-row .qid { font-weight: 600; color: #B58A50; }

← 0206a11 asseeninmovies: /spotted/queue admin moderation — token-gate  ·  back to AsSeenInMovies  ·  asseeninmovies: /spotted gallery — 4-tile stats strip (place 17d9d2d →