← back to Ventura Claw Leads

views/admin/dashboard.ejs

124 lines

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

<section class="long-form" style="max-width:1100px">
  <% if (welcome) { %>
    <div class="callout" style="background:#dcfce7;border-left:3px solid #16a34a;color:#166534;padding:14px 18px;margin:0 0 24px;border-radius:4px">
      <strong>Welcome to Ventura Claw.</strong> Your listing is now claimed. Edit your profile and pick a tier to unlock featured placement.
    </div>
  <% } %>

  <p class="kicker">Dashboard</p>
  <h1 class="display-sm"><%= currentBusiness.business_name %></h1>
  <p class="lede">Tier: <strong><%= currentBusiness.tier === 'free' ? 'Free' : (currentBusiness.tier.charAt(0).toUpperCase() + currentBusiness.tier.slice(1)) %></strong> · Subscription: <strong><%= currentBusiness.subscription_status || 'inactive' %></strong></p>

  <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:14px;margin:32px 0">
    <div class="side-card" style="text-align:center">
      <h3>Total leads</h3>
      <p style="font-family:var(--serif);font-size:36px;color:var(--brass);margin:0"><%= stats.total_leads %></p>
    </div>
    <div class="side-card" style="text-align:center">
      <h3>Last 30 days</h3>
      <p style="font-family:var(--serif);font-size:36px;color:var(--brass);margin:0"><%= stats.last_30d %></p>
    </div>
    <div class="side-card" style="text-align:center">
      <h3>Delivered</h3>
      <p style="font-family:var(--serif);font-size:36px;color:var(--brass);margin:0"><%= stats.delivered %></p>
    </div>
    <div class="side-card" style="text-align:center">
      <h3>Pending</h3>
      <p style="font-family:var(--serif);font-size:36px;color:var(--brass);margin:0"><%= stats.pending %></p>
    </div>
    <div class="side-card" style="text-align:center<%= stats.unread > 0 ? ';border-color:var(--brass)' : '' %>">
      <h3>Unread<% if (stats.unread > 0) { %> <span style="color:#dc2626">●</span><% } %></h3>
      <p style="font-family:var(--serif);font-size:36px;color:<%= stats.unread > 0 ? '#dc2626' : 'var(--fg-muted)' %>;margin:0"><%= stats.unread %></p>
      <% if (stats.unread > 0) { %><a href="/admin/leads?filter=unread" style="font-size:11px;color:var(--brass);border:none">Triage →</a><% } %>
    </div>
    <div class="side-card" style="text-align:center">
      <h3>Profile views</h3>
      <p style="font-family:var(--serif);font-size:36px;color:var(--brass);margin:0"><%= stats.views_30d %></p>
      <p style="font-size:11px;color:var(--fg-muted);margin:4px 0 0;letter-spacing:0.06em;text-transform:uppercase">last 30 days · <%= stats.views_today %> today</p>
    </div>
    <div class="side-card" style="text-align:center">
      <h3>Shares</h3>
      <p style="font-family:var(--serif);font-size:36px;color:var(--brass);margin:0"><%= stats.shares_total %></p>
      <p style="font-size:11px;color:var(--fg-muted);margin:4px 0 0;letter-spacing:0.06em;text-transform:uppercase">all-time</p>
    </div>
  </div>

  <%
    // Sparkline: 30 day-bins. Width fluid; height fixed at 60px.
    var sparkW = 480; var sparkH = 60; var pad = 2;
    var binW = (sparkW - pad * 2) / Math.max(1, trend.length);
    var maxV = Math.max(1, trendPeak); // avoid /0 — flat zero shows as flat baseline
  %>
  <div class="side-card" style="margin-bottom:24px">
    <div style="display:flex;align-items:baseline;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:8px">
      <h3 style="margin:0">30-day lead trend</h3>
      <p class="muted" style="margin:0;font-size:12px">peak <%= trendPeak %> · total <%= trend.reduce(function(s,p){return s+p.n;},0) %></p>
    </div>
    <svg viewBox="0 0 <%= sparkW %> <%= sparkH %>" style="width:100%;height:80px;display:block" preserveAspectRatio="none" aria-label="30-day lead trend">
      <% trend.forEach(function(p, i){
        var h = p.n > 0 ? Math.max(2, (p.n / maxV) * (sparkH - pad * 2)) : 0;
        var x = pad + i * binW;
        var y = sparkH - pad - h;
        var w = Math.max(1, binW - 2);
        var isPeak = trendPeak > 0 && p.n === trendPeak;
        var dayLabel = new Date(p.day).toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
      %>
        <% if (h > 0) { %>
          <rect x="<%= x.toFixed(2) %>" y="<%= y.toFixed(2) %>" width="<%= w.toFixed(2) %>" height="<%= h.toFixed(2) %>"
                fill="<%= isPeak ? 'var(--brass)' : 'var(--fg-muted)' %>"
                opacity="<%= isPeak ? '1' : '0.55' %>">
            <title><%= dayLabel %>: <%= p.n %> lead<%= p.n === 1 ? '' : 's' %></title>
          </rect>
        <% } else { %>
          <rect x="<%= x.toFixed(2) %>" y="<%= (sparkH - pad - 1).toFixed(2) %>" width="<%= w.toFixed(2) %>" height="1"
                fill="var(--border)" opacity="0.6">
            <title><%= dayLabel %>: 0 leads</title>
          </rect>
        <% } %>
      <% }); %>
    </svg>
    <div style="display:flex;justify-content:space-between;font-size:11px;color:var(--fg-muted);margin-top:4px">
      <span><%= new Date(trend[0].day).toLocaleDateString('en-US',{ month:'short', day:'numeric' }) %></span>
      <span>today</span>
    </div>
  </div>

  <h2>Recent leads</h2>
  <% if (recent.length === 0) { %>
    <p class="muted">No leads yet — your listing is live; consumers will start finding you. Make sure your <a href="/admin/profile">profile</a> is filled out.</p>
  <% } else { %>
    <table style="width:100%;border-collapse:collapse;margin:16px 0">
      <thead>
        <tr style="border-bottom:1px solid var(--border);text-align:left">
          <th style="padding:8px 0;font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:var(--fg-muted);font-weight:500">When</th>
          <th style="padding:8px 0;font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:var(--fg-muted);font-weight:500">From</th>
          <th style="padding:8px 0;font-size:11px;letter-spacing:0.08em;text-transform:uppercase;color:var(--fg-muted);font-weight:500">Status</th>
        </tr>
      </thead>
      <tbody>
        <% recent.forEach(function(l){ %>
          <tr style="border-bottom:1px solid var(--border)">
            <td style="padding:10px 0;font-size:13px;color:var(--fg-muted)"><%= new Date(l.created_at).toLocaleString('en-US',{ dateStyle:'medium', timeStyle:'short' }) %></td>
            <td style="padding:10px 0;font-size:13px"><strong><%= l.consumer_name %></strong> · <%= l.consumer_email %></td>
            <td style="padding:10px 0;font-size:13px"><%= l.delivered_at ? '<span style="color:#16a34a">Delivered</span>' : '<span style="color:var(--fg-muted)">Pending</span>' %></td>
          </tr>
        <% }); %>
      </tbody>
    </table>
    <p style="margin-top:16px"><a href="/admin/leads" class="btn btn-ghost btn-sm">See all leads →</a></p>
  <% } %>

  <h2 style="margin-top:48px">Next steps</h2>
  <ul>
    <li><a href="/admin/profile">Edit your public profile</a> — make sure description, hours, contact, and Instagram are current.</li>
    <li><a href="/admin/billing">Pick a tier</a> — Free is fine; paid tiers unlock featured placement and category-sidebar feature.</li>
    <li><a href="/admin/team">Invite a teammate</a> — let multiple people respond to leads.</li>
    <li><a href="/business/<%= currentBusiness.slug %>" target="_blank" rel="noopener noreferrer">View your live profile ↗</a></li>
  </ul>
</section>

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