159 lines
6.4 KiB
HTML
159 lines
6.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>NEWT Customer Dashboard</title>
|
|
<link rel="stylesheet" href="/styles.css" />
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js"></script>
|
|
</head>
|
|
<body>
|
|
|
|
<!-- ---------- LOGIN SCREEN ---------- -->
|
|
<div id="login-screen" class="login-screen">
|
|
<form id="login-form" class="login-card">
|
|
<h1>NEWT Customer Dashboard</h1>
|
|
<p class="subtitle">Enter the password to continue</p>
|
|
<input type="password" id="login-password" placeholder="Password" autocomplete="current-password" required />
|
|
<button type="submit">Sign in</button>
|
|
<p id="login-error" class="error-text"></p>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- ---------- APP SHELL ---------- -->
|
|
<div id="app-shell" class="app-shell hidden">
|
|
<nav class="sidebar">
|
|
<div class="brand">NEWT<span>Dashboard</span></div>
|
|
<button class="nav-item active" data-tab="overview">Overview</button>
|
|
<button class="nav-item" data-tab="products">Product Summary</button>
|
|
<button class="nav-item" data-tab="newpkg">New Package Adoption</button>
|
|
<button class="nav-item" data-tab="search">Search & Drill-down</button>
|
|
<button id="logout-btn" class="nav-item logout">Log out</button>
|
|
</nav>
|
|
|
|
<main class="content">
|
|
|
|
<!-- OVERVIEW TAB -->
|
|
<section id="tab-overview" class="tab">
|
|
<h2>Overview</h2>
|
|
<div class="stat-grid" id="overview-stats"></div>
|
|
<div class="panel">
|
|
<h3>Top Products by Revenue</h3>
|
|
<canvas id="overview-chart" height="90"></canvas>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- PRODUCT SUMMARY TAB -->
|
|
<section id="tab-products" class="tab hidden">
|
|
<h2>Product Summary</h2>
|
|
<div class="panel">
|
|
<h3>Monthly Trend — Top Products</h3>
|
|
<canvas id="trend-chart" height="90"></canvas>
|
|
</div>
|
|
<div class="panel">
|
|
<div class="panel-header">
|
|
<h3>Sum of $ Amount by Product</h3>
|
|
<span class="hint">Click a row to drill into that product's transactions</span>
|
|
</div>
|
|
<table class="data-table" id="products-table">
|
|
<thead>
|
|
<tr>
|
|
<th data-sort="product">Product</th>
|
|
<th data-sort="total_amount" class="num">Total $</th>
|
|
<th data-sort="txn_count" class="num"># Transactions</th>
|
|
<th data-sort="customer_count" class="num"># Customers</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- NEW PACKAGE ADOPTION TAB -->
|
|
<section id="tab-newpkg" class="tab hidden">
|
|
<h2>New Package Adoption</h2>
|
|
<p class="tab-desc">For every customer + package combination, the first month it appeared in billing. "New customer" means it was their very first billed month; "Upsell" means the customer already existed and added this package later.</p>
|
|
<div class="panel">
|
|
<div class="filter-row">
|
|
<select id="np-mode">
|
|
<option value="all">All</option>
|
|
<option value="new">New customers only</option>
|
|
<option value="upsell">Upsells only (existing customer, new package)</option>
|
|
</select>
|
|
<select id="np-package"><option value="">All packages</option></select>
|
|
<input type="text" id="np-search" placeholder="Search customer name/number..." />
|
|
<select id="np-sort">
|
|
<option value="first_seen_desc">Most recent first</option>
|
|
<option value="first_seen_asc">Oldest first</option>
|
|
<option value="amount_desc">Largest first-month $</option>
|
|
<option value="customer_asc">Customer name A-Z</option>
|
|
</select>
|
|
<button id="np-search-btn">Apply</button>
|
|
</div>
|
|
<table class="data-table" id="newpkg-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Customer</th>
|
|
<th>Package</th>
|
|
<th>First Month</th>
|
|
<th>Type</th>
|
|
<th class="num">First-Month $</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
<div class="pagination" id="newpkg-pagination"></div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- SEARCH / DRILLDOWN TAB -->
|
|
<section id="tab-search" class="tab hidden">
|
|
<h2>Search & Drill-down</h2>
|
|
<div class="panel">
|
|
<div class="filter-grid">
|
|
<input type="text" id="s-customer" placeholder="Customer name or number" />
|
|
<select id="s-product"><option value="">All products</option></select>
|
|
<select id="s-package"><option value="">All packages</option></select>
|
|
<select id="s-customertype"><option value="">All customer types</option></select>
|
|
<select id="s-brand"><option value="">All brands</option></select>
|
|
<input type="text" id="s-text" placeholder="Search item description / SOP / item #" />
|
|
<select id="s-year"><option value="">Any year</option></select>
|
|
<select id="s-month"><option value="">Any month</option></select>
|
|
</div>
|
|
<div class="filter-row date-range-row">
|
|
<label class="date-field"><span>GL date from</span><input type="date" id="s-date-from" /></label>
|
|
<label class="date-field"><span>to</span><input type="date" id="s-date-to" /></label>
|
|
<span class="hint">Filters on the actual GL posting date; leave either side blank for an open-ended range.</span>
|
|
</div>
|
|
<div class="filter-row">
|
|
<label class="level-toggle">
|
|
<span>Results level:</span>
|
|
<select id="s-level">
|
|
<option value="customer">Customer subtotals</option>
|
|
<option value="detail">Individual invoice lines</option>
|
|
</select>
|
|
</label>
|
|
<label class="checkbox-inline"><input type="checkbox" id="s-voided" /> Include voided transactions</label>
|
|
<button id="s-search-btn">Search</button>
|
|
<button id="s-clear-btn" class="secondary">Clear filters</button>
|
|
</div>
|
|
<div id="s-summary" class="search-summary"></div>
|
|
<div class="table-scroll">
|
|
<table class="data-table" id="search-table">
|
|
<thead></thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
<div class="pagination" id="search-pagination"></div>
|
|
</div>
|
|
</section>
|
|
|
|
</main>
|
|
</div>
|
|
|
|
<script src="/app.js"></script>
|
|
</body>
|
|
</html>
|