← back to Ventura Claw Leads

views/admin/leads.ejs

121 lines

<%- include('../partials/head', { title }) %>
<%- include('../partials/header') %>

<section class="long-form" style="max-width:1100px">
  <p class="kicker">Leads</p>
  <h1 class="display-sm">Inbox</h1>
  <p class="lede">Every customer message routed to <%= currentBusiness.business_name %>. Replies via your email client go straight to the customer.</p>

  <%
    function rangeHref(r) {
      var p = new URLSearchParams();
      if (filter === 'unread') p.set('filter', 'unread');
      if (r !== 'all') p.set('range', r);
      if (q) p.set('q', q);
      var s = p.toString();
      return '/admin/leads' + (s ? '?' + s : '');
    }
    function filterHref(f) {
      var p = new URLSearchParams();
      if (f === 'unread') p.set('filter', 'unread');
      if (range !== 'all') p.set('range', range);
      if (q) p.set('q', q);
      var s = p.toString();
      return '/admin/leads' + (s ? '?' + s : '');
    }
  %>

  <form method="get" action="/admin/leads" style="margin-top:12px;display:flex;gap:8px;flex-wrap:wrap;align-items:center">
    <% if (filter === 'unread') { %><input type="hidden" name="filter" value="unread"><% } %>
    <% if (range !== 'all') { %><input type="hidden" name="range" value="<%= range %>"><% } %>
    <input type="search" name="q" value="<%= q %>" placeholder="Search name, email, message, ZIP…" style="flex:1;min-width:240px;padding:8px 12px;border:1px solid var(--border);border-radius:4px;font-size:13px">
    <button type="submit" class="btn btn-ghost btn-sm">Search</button>
    <% if (q) { %>
      <a href="<%= filterHref(filter) %>" class="btn btn-ghost btn-sm" style="font-size:11px">Clear search</a>
    <% } %>
  </form>
  <div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:12px">
    <a href="<%= filterHref('all') %>"    class="btn btn-ghost btn-sm" style="<%= filter === 'all' ? 'border-color:var(--fg)' : '' %>">All <span class="muted" style="font-size:11px">(<%= counts.total %>)</span></a>
    <a href="<%= filterHref('unread') %>" class="btn btn-ghost btn-sm" style="<%= filter === 'unread' ? 'border-color:var(--brass);color:var(--brass)' : '' %>">Unread <span class="muted" style="font-size:11px">(<%= counts.unread %>)</span></a>
    <span style="border-left:1px solid var(--border);height:24px;margin:0 4px"></span>
    <a href="<%= rangeHref('7') %>"   class="btn btn-ghost btn-sm" style="<%= range === '7' ? 'border-color:var(--fg)' : '' %>">7d <span class="muted" style="font-size:11px">(<%= counts.last_7 %>)</span></a>
    <a href="<%= rangeHref('30') %>"  class="btn btn-ghost btn-sm" style="<%= range === '30' ? 'border-color:var(--fg)' : '' %>">30d <span class="muted" style="font-size:11px">(<%= counts.last_30 %>)</span></a>
    <a href="<%= rangeHref('90') %>"  class="btn btn-ghost btn-sm" style="<%= range === '90' ? 'border-color:var(--fg)' : '' %>">90d <span class="muted" style="font-size:11px">(<%= counts.last_90 %>)</span></a>
    <a href="<%= rangeHref('all') %>" class="btn btn-ghost btn-sm" style="<%= range === 'all' ? 'border-color:var(--fg)' : '' %>">All time</a>
    <a href="/admin/leads.csv" class="btn btn-ghost btn-sm" style="margin-left:auto" download>Export CSV ↓</a>
    <% if (counts.unread > 0) { %>
      <form method="post" action="/admin/leads/mark-all-read" style="margin:0">
        <input type="hidden" name="_csrf" value="<%= csrfToken %>">
        <button type="submit" class="btn btn-ghost btn-sm">Mark all read</button>
      </form>
    <% } %>
  </div>

  <% if (leads.length === 0) { %>
    <p class="muted" style="margin-top:32px">
      <% if (filter === 'unread') { %>
        🎉 Inbox zero — every lead is marked read. <a href="/admin/leads">Show all</a>.
      <% } else { %>
        No leads yet. Make sure your <a href="/admin/profile">profile</a> is filled out — the more complete the listing, the more inbound.
      <% } %>
    </p>
  <% } else { %>
    <table style="width:100%;border-collapse:collapse;margin:24px 0;font-size:13px">
      <thead>
        <tr style="border-bottom:2px solid var(--fg);text-align:left">
          <th style="padding:10px 8px;font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:var(--fg-muted);font-weight:500;width:24px"></th>
          <th style="padding:10px 8px;font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:var(--fg-muted);font-weight:500">When</th>
          <th style="padding:10px 8px;font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:var(--fg-muted);font-weight:500">From</th>
          <th style="padding:10px 8px;font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:var(--fg-muted);font-weight:500">Message</th>
          <th style="padding:10px 8px;font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:var(--fg-muted);font-weight:500">Status</th>
          <th style="padding:10px 8px;font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:var(--fg-muted);font-weight:500"></th>
        </tr>
      </thead>
      <tbody>
        <% leads.forEach(function(l){
          var unread = !l.read_at;
        %>
          <tr style="border-bottom:1px solid var(--border);vertical-align:top<%= unread ? ';background:rgba(184,134,11,0.04)' : '' %>">
            <td style="padding:12px 4px;color:var(--brass);font-weight:bold;text-align:center"><% if (unread) { %>●<% } %></td>
            <td style="padding:12px 8px;color:var(--fg-muted);white-space:nowrap"><%= new Date(l.created_at).toLocaleString('en-US',{ month:'short', day:'numeric', hour:'numeric', minute:'2-digit' }) %></td>
            <td style="padding:12px 8px"><strong style="<%= unread ? 'color:var(--fg)' : 'color:var(--fg-muted)' %>"><%= l.consumer_name %></strong><br><a href="mailto:<%= l.consumer_email %>"><%= l.consumer_email %></a><% if (l.consumer_phone) { %><br><a href="tel:<%= l.consumer_phone %>"><%= l.consumer_phone %></a><% } %><% if (l.zip) { %><br><span style="color:var(--fg-muted)">ZIP <%= l.zip %></span><% } %></td>
            <td style="padding:12px 8px;max-width:380px;color:<%= unread ? 'var(--fg)' : 'var(--fg-muted)' %>"><%= l.message || '—' %></td>
            <td style="padding:12px 8px"><% if (l.delivered_at) { %><span style="color:#16a34a">Delivered</span><br><span style="color:var(--fg-muted);font-size:11px"><%= new Date(l.delivered_at).toLocaleString('en-US',{ month:'short', day:'numeric', hour:'numeric', minute:'2-digit' }) %></span><% } else { %><span style="color:var(--fg-muted)">Pending (≤5min)</span><% } %></td>
            <td style="padding:12px 8px;white-space:nowrap">
              <form method="post" action="/admin/leads/<%= l.id %>/<%= unread ? 'read' : 'unread' %>" style="margin:0">
                <input type="hidden" name="_csrf" value="<%= csrfToken %>">
                <input type="hidden" name="next" value="/admin/leads<%= filter === 'unread' ? '?filter=unread' : '' %>">
                <button type="submit" class="btn btn-ghost btn-sm" style="font-size:11px;padding:4px 8px"><%= unread ? 'Mark read' : 'Unread' %></button>
              </form>
            </td>
          </tr>
        <% }); %>
      </tbody>
    </table>

    <% if (hasPrev || hasNext) {
      function pageHref(p) {
        var pp = new URLSearchParams();
        if (filter === 'unread') pp.set('filter', 'unread');
        if (range !== 'all') pp.set('range', range);
        if (q) pp.set('q', q);
        if (p > 1) pp.set('page', p);
        var s = pp.toString();
        return '/admin/leads' + (s ? '?' + s : '');
      }
      var firstNum = (page - 1) * perPage + 1;
      var lastNum = firstNum + leads.length - 1;
    %>
      <div style="display:flex;align-items:center;justify-content:space-between;margin:24px 0;font-size:13px;color:var(--fg-muted)">
        <span>Showing <%= firstNum %>–<%= lastNum %><% if (counts.total > 0) { %> of <%= counts.total %><% } %></span>
        <div style="display:flex;gap:8px">
          <% if (hasPrev) { %><a href="<%= pageHref(page - 1) %>" class="btn btn-ghost btn-sm">← Prev</a><% } %>
          <% if (hasNext) { %><a href="<%= pageHref(page + 1) %>" class="btn btn-ghost btn-sm">Next →</a><% } %>
        </div>
      </div>
    <% } %>
  <% } %>
</section>

<%- include('../partials/footer') %>