← back to NationalPaperHangers

views/admin/dashboard.ejs

178 lines

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

<section class="admin-main">
  <%
    /* Onboarding completion signals derived from available render data */
    var _profileComplete = !!installer.profile_complete;
    var _availabilitySet = (typeof hasAvailability !== 'undefined') ? !!hasAvailability : false;
    var _proActive = installer.subscription_status === 'active';
    var _payoutsActive = !!installer.stripe_account_id && !!installer.stripe_account_charges_enabled;
    var _allDone = _profileComplete && _availabilitySet && _proActive && _payoutsActive;
  %>

  <% if (typeof connectFlash !== 'undefined' && connectFlash === 'ok') { %>
    <div class="callout callout-ok"><strong>Payouts ready.</strong> Stripe Connect onboarding complete — booking deposits will route to your bank account, net of NPH's <%= ((installer.tier === 'enterprise') ? '15' : '25') %>% lead-coordination fee.</div>
  <% } else if (typeof connectFlash !== 'undefined' && connectFlash === 'mock') { %>
    <div class="callout">Stripe is in test mode — Connect onboarding ran in mock. Save real <code>STRIPE_SECRET_KEY</code> via the secrets manager to enable live payouts.</div>
  <% } %>

  <% if (flash && flash.connect_prompt && !installer.stripe_account_id) { %>
    <aside class="callout callout-prompt" role="region" aria-label="Set up payouts">
      <p style="margin:0 0 6px"><strong>Welcome — your studio is claimed. One last setup step.</strong></p>
      <p style="margin:0 0 12px;font-size:0.92rem">Connect your bank account so booking deposits flow to you automatically. Takes 3 minutes — Stripe-hosted, no NPH access to your bank info.</p>
      <form method="post" action="/admin/connect/onboard" class="inline-form" style="margin:0">
        <input type="hidden" name="_csrf" value="<%= csrfToken %>">
        <button type="submit" class="btn btn-primary">Set up payouts now →</button>
      </form>
      <p style="margin:8px 0 0;font-size:0.82rem;color:var(--fg-muted)">You can skip and do this later from /admin/billing.</p>
    </aside>
  <% } %>

  <% if (welcome || !_allDone) { %>
    <div class="onboarding-checklist" aria-label="Account setup checklist">
      <h2 class="onboarding-title">Get your studio live</h2>
      <ol class="onboarding-steps" role="list">
        <li class="onboarding-step <%= _profileComplete ? 'step-done' : 'step-todo' %>">
          <span class="step-icon" aria-hidden="true"><%= _profileComplete ? '✓' : '○' %></span>
          <span class="step-label">Profile complete</span>
          <% if (!_profileComplete) { %>
            <a href="/admin/profile" class="step-action">Complete profile →</a>
          <% } else { %>
            <span class="step-done-label">Done</span>
          <% } %>
        </li>
        <li class="onboarding-step <%= _availabilitySet ? 'step-done' : 'step-todo' %>">
          <span class="step-icon" aria-hidden="true"><%= _availabilitySet ? '✓' : '○' %></span>
          <span class="step-label">Availability set</span>
          <% if (!_availabilitySet) { %>
            <a href="/admin/calendar" class="step-action">Set availability →</a>
          <% } else { %>
            <span class="step-done-label">Done</span>
          <% } %>
        </li>
        <li class="onboarding-step <%= _proActive ? 'step-done' : 'step-todo' %>">
          <span class="step-icon" aria-hidden="true"><%= _proActive ? '✓' : '○' %></span>
          <span class="step-label">Pro tier active</span>
          <% if (!_proActive) { %>
            <a href="/admin/billing" class="step-action btn btn-primary btn-sm">Upgrade to Pro →</a>
          <% } else { %>
            <span class="step-done-label">Active</span>
          <% } %>
        </li>
        <li class="onboarding-step <%= _payoutsActive ? 'step-done' : 'step-todo' %>">
          <span class="step-icon" aria-hidden="true"><%= _payoutsActive ? '✓' : '○' %></span>
          <span class="step-label">Payouts set up</span>
          <% if (!_payoutsActive) { %>
            <form method="post" action="/admin/connect/onboard" class="inline-form" style="margin:0">
              <input type="hidden" name="_csrf" value="<%= csrfToken %>">
              <button type="submit" class="step-action btn btn-primary btn-sm">Set up payouts →</button>
            </form>
          <% } else { %>
            <span class="step-done-label">Active</span>
          <% } %>
        </li>
      </ol>
      <% if (!_payoutsActive) { %>
        <p class="muted" style="margin: 12px 0 0; font-size: 0.85rem;">
          Customers pay their booking deposit through NPH. Once your Stripe payouts are set up, your share lands in your bank in 1–2 business days, net of NPH's <%= Math.round((installer.tier === 'enterprise' ? 1500 : 2500) / 100) %>% lead-coordination fee.
        </p>
      <% } %>
    </div>
  <% } %>

  <header class="admin-page-head">
    <h1>Dashboard</h1>
    <p class="muted"><%= installer.business_name %> · <%= installer.city %>, <%= installer.state %> · <%= installer.tier %> tier</p>
  </header>

  <div class="stat-grid">
    <div class="stat">
      <span class="stat-label">Pending</span>
      <span class="stat-value"><%= stats.pending_count %></span>
    </div>
    <div class="stat">
      <span class="stat-label">Upcoming</span>
      <span class="stat-value"><%= stats.upcoming_count %></span>
    </div>
    <div class="stat">
      <span class="stat-label">Completed</span>
      <span class="stat-value"><%= stats.completed_count %></span>
    </div>
    <div class="stat">
      <span class="stat-label">Portfolio items</span>
      <span class="stat-value"><%= portfolioCount %></span>
    </div>
    <% if (typeof market !== 'undefined' && market) { %>
      <div class="stat">
        <span class="stat-label">Deposits paid</span>
        <span class="stat-value">$<%= (market.deposits_paid_cents/100).toFixed(0) %></span>
        <span class="stat-sub muted"><%= market.count_paid %> bookings</span>
      </div>
      <% if (!market.on_connect && market.deposits_paid_cents > 0) { %>
        <div class="stat stat-warn">
          <span class="stat-label">Pending payout</span>
          <span class="stat-value">$<%= (market.payouts_pending_cents/100).toFixed(0) %></span>
          <span class="stat-sub muted">held — set up payouts</span>
        </div>
      <% } %>
    <% } %>
  </div>

  <% if (installer.subscription_status !== 'active') { %>
    <div class="callout callout-warn">
      <strong>Calendar bookings are off.</strong>
      Upgrade to Pro to let customers self-book directly into your calendar.
      <a href="/admin/billing" class="btn btn-primary btn-sm">Upgrade</a>
    </div>
  <% } %>

  <section class="admin-section">
    <div class="section-head">
      <h2>Upcoming bookings</h2>
      <a href="/admin/bookings" class="section-link">All bookings →</a>
    </div>
    <% if (upcoming.length === 0) { %>
      <div class="empty-state">No upcoming bookings yet.</div>
    <% } else { %>
      <table class="data-table">
        <thead><tr><th>When</th><th>Customer</th><th>Type</th><th>Status</th></tr></thead>
        <tbody>
          <% upcoming.forEach(function(b){ %>
            <tr>
              <td><%= new Date(b.scheduled_start).toLocaleString() %></td>
              <td><%= b.customer_name %><br><span class="muted"><%= b.customer_email %></span></td>
              <td><%= (b.project_type || 'consultation').replace(/_/g,' ') %></td>
              <td><span class="status-badge status-<%= b.status %>"><%= b.status %></span></td>
            </tr>
          <% }); %>
        </tbody>
      </table>
    <% } %>
  </section>

  <section class="admin-section">
    <div class="section-head"><h2>Quick actions</h2></div>
    <div class="action-grid">
      <a class="action-card" href="/admin/calendar">
        <h3>Calendar</h3>
        <p>Set weekly availability and block time off.</p>
      </a>
      <a class="action-card" href="/admin/profile">
        <h3>Profile</h3>
        <p>Edit your studio bio, materials, brands, and accreditations.</p>
      </a>
      <a class="action-card" href="/admin/bookings">
        <h3>Bookings</h3>
        <p>Review, confirm, decline, or complete jobs.</p>
      </a>
      <a class="action-card" href="/admin/billing">
        <h3>Billing</h3>
        <p>Manage your subscription and invoices.</p>
      </a>
    </div>
  </section>
</section>

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