283 lines
15 KiB
Plaintext
283 lines
15 KiB
Plaintext
@model VerificationDashboardViewModel
|
||
@{
|
||
ViewData["Title"] = "Carton Shipment Verification";
|
||
}
|
||
|
||
<header class="topbar">
|
||
<div class="topbar-brand">
|
||
<span class="brand-icon">◈</span>
|
||
<span>SHIPPING MARK</span>
|
||
</div>
|
||
<div class="topbar-siren" id="siren-indicator">
|
||
<span>🔊</span>
|
||
<span>SIREN: ON</span>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="dashboard-main">
|
||
<section class="top-grid">
|
||
<section class="panel panel-scan">
|
||
<h2 class="section-title"><span class="section-icon">🖶</span> SCAN QR CODE</h2>
|
||
<form id="scan-form" autocomplete="off" novalidate onsubmit="return false;">
|
||
@Html.AntiForgeryToken()
|
||
<div class="scan-input-wrap">
|
||
<span class="scan-icon">⚙</span>
|
||
<input id="qr-input"
|
||
name="qrValue"
|
||
class="scan-input"
|
||
type="text"
|
||
placeholder="Use scanner or paste (typing is not allowed)…"
|
||
autofocus
|
||
spellcheck="false" />
|
||
</div>
|
||
<div class="form-hint">Format: modelnumber;uniquenumber — scans submit automatically.</div>
|
||
</form>
|
||
</section>
|
||
|
||
<section class="panel panel-scanned-details">
|
||
<h2 class="section-title"><span class="section-icon">ⓘ</span> SCANNED DETAILS</h2>
|
||
<div class="info-grid">
|
||
<span>Model Number</span><strong id="detail-model">-</strong>
|
||
<span>Unique Number</span><strong id="detail-unique">-</strong>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
|
||
<section class="kpi-grid">
|
||
<section id="status-card" class="panel panel-status status-neutral" aria-live="polite">
|
||
<h2 class="section-title"><span class="section-icon">∿</span> VERIFICATION STATUS</h2>
|
||
<div class="status-mini-icon" id="status-mini-icon">-</div>
|
||
<div class="status-mini-headline" id="status-mini-headline">AWAITING SCAN</div>
|
||
<div id="status-mini-message" class="status-mini-message">Waiting for QR input.</div>
|
||
<div class="last-updated">
|
||
<span>◴ Last Updated:</span>
|
||
<strong id="last-updated-time">-</strong>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="panel panel-available-cartons" aria-live="polite">
|
||
<h2 class="section-title section-title-center"><span class="section-icon">📦</span> AVAILABLE CARTONS</h2>
|
||
<div id="available-cartons-count" class="available-cartons-value">@(Model.AvailableCartonsCount.HasValue ? Model.AvailableCartonsCount.Value.ToString("N0") : "—")</div>
|
||
<div class="available-cartons-subtitle">Not moved to warehouse</div>
|
||
</section>
|
||
|
||
<section class="panel panel-verification-result">
|
||
<h2 class="section-title"><span class="section-icon">🛡</span> VERIFICATION RESULT</h2>
|
||
<div class="info-grid">
|
||
<span>Exists in Carton Logs</span><strong id="detail-exists">-</strong>
|
||
<span>Shipment Marked</span><strong id="detail-marked">-</strong>
|
||
<span>Marked At</span><strong id="detail-time">-</strong>
|
||
<span>Marked By</span><strong id="detail-marked-by">System</strong>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
|
||
<section class="panel panel-history">
|
||
<div class="panel-history-head">
|
||
<h2 class="section-title section-title-tight"><span class="section-icon">🗎</span> RECENT SCANS</h2>
|
||
<button type="button" class="btn-scan-history" id="btn-open-scan-history">History</button>
|
||
</div>
|
||
<div class="history-split">
|
||
<div class="history-column">
|
||
<h3 class="history-subtitle">Successful Scans</h3>
|
||
<div class="table-responsive history-wrap">
|
||
<table class="table table-sm align-middle" id="history-success-table">
|
||
<thead>
|
||
<tr>
|
||
<th>#</th>
|
||
<th>MODEL NUMBER</th>
|
||
<th>UNIQUE NUMBER</th>
|
||
<th>STATUS</th>
|
||
<th>MARKED AT</th>
|
||
<th>MARKED BY</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="history-success-body">
|
||
@{
|
||
var rowNumber = 1;
|
||
}
|
||
@foreach (var item in Model.RecentSuccessfulScans)
|
||
{
|
||
<tr>
|
||
<td>@rowNumber</td>
|
||
<td>@item.ModelNumber</td>
|
||
<td>@item.UniqueNumber</td>
|
||
<td>
|
||
<span class="status-pill status-true">TRUE</span>
|
||
</td>
|
||
<td>@DateTime.SpecifyKind(item.ProcessedAtUtc, DateTimeKind.Utc).ToLocalTime().ToString("dd MMM yyyy h:mm tt")</td>
|
||
<td>System</td>
|
||
</tr>
|
||
rowNumber++;
|
||
}
|
||
</tbody>
|
||
</table>
|
||
<div class="history-empty @(Model.RecentSuccessfulScans.Count > 0 ? "is-hidden" : string.Empty)" id="history-success-empty">
|
||
<div class="empty-icon">📦</div>
|
||
<div class="empty-title">No successful scans yet</div>
|
||
<div class="empty-text">Verified cartons will appear here.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="history-column">
|
||
<h3 class="history-subtitle">Rejected Scans</h3>
|
||
<div class="table-responsive history-wrap">
|
||
<table class="table table-sm align-middle" id="history-rejected-table">
|
||
<thead>
|
||
<tr>
|
||
<th>TIME</th>
|
||
<th>SCANNED / INPUT</th>
|
||
<th>MODEL</th>
|
||
<th>UNIQUE</th>
|
||
<th>REASON</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="history-rejected-body">
|
||
@foreach (var item in Model.RecentRejectedScans)
|
||
{
|
||
<tr>
|
||
<td>@DateTime.SpecifyKind(item.ProcessedAtUtc, DateTimeKind.Utc).ToLocalTime().ToString("dd MMM yyyy h:mm tt")</td>
|
||
<td>@item.RawInputValue</td>
|
||
<td>@(string.IsNullOrEmpty(item.ModelNumber) ? "—" : item.ModelNumber)</td>
|
||
<td>@(string.IsNullOrEmpty(item.UniqueNumber) ? "—" : item.UniqueNumber)</td>
|
||
<td>@item.RejectionReason</td>
|
||
</tr>
|
||
}
|
||
</tbody>
|
||
</table>
|
||
<div class="history-empty @(Model.RecentRejectedScans.Count > 0 ? "is-hidden" : string.Empty)" id="history-rejected-empty">
|
||
<div class="empty-icon">⚠</div>
|
||
<div class="empty-title">No rejected scans</div>
|
||
<div class="empty-text">Rejections will appear here with a reason.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<dialog id="scan-history-dialog" class="scan-history-dialog scan-history-dialog--wide" aria-labelledby="scan-history-dialog-title">
|
||
<div class="scan-history-dialog-content">
|
||
<header class="scan-history-dialog-header">
|
||
<h2 id="scan-history-dialog-title" class="scan-history-dialog-title">Scan History & Analytics</h2>
|
||
<button type="button" class="scan-history-dialog-close" id="scan-history-dialog-close" aria-label="Close">×</button>
|
||
</header>
|
||
|
||
<div class="scan-history-dialog-toolbar scan-history-mode-toolbar">
|
||
<label class="scan-history-filter-label" for="scan-history-filter">Show</label>
|
||
<select id="scan-history-filter" class="scan-history-filter" aria-label="Record type">
|
||
<option value="successful">Successful Records</option>
|
||
<option value="rejected">Rejected Records</option>
|
||
</select>
|
||
<button type="button" class="btn-history-mode" id="btn-movement-analytics">Movement Analytics</button>
|
||
</div>
|
||
|
||
<div id="scan-history-records-view">
|
||
<div class="scan-history-dialog-body table-responsive">
|
||
<table class="table table-sm align-middle" id="scan-history-modal-table">
|
||
<thead id="scan-history-modal-thead"></thead>
|
||
<tbody id="scan-history-modal-tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="scan-history-analytics-view" class="scan-history-analytics-view is-hidden" hidden>
|
||
<div class="scan-history-dialog-toolbar analytics-toolbar">
|
||
<div class="analytics-toolbar-filters">
|
||
<label class="scan-history-filter-label" for="analytics-date-from">Date Range</label>
|
||
<input type="date" id="analytics-date-from" class="analytics-date-input" aria-label="From date" />
|
||
<span class="analytics-date-sep">–</span>
|
||
<input type="date" id="analytics-date-to" class="analytics-date-input" aria-label="To date" />
|
||
<label class="scan-history-filter-label" for="analytics-group-by">Show</label>
|
||
<select id="analytics-group-by" class="scan-history-filter" aria-label="Grouping">
|
||
<option value="day" selected>Day-wise</option>
|
||
</select>
|
||
</div>
|
||
<button type="button" class="btn-analytics-export" id="btn-analytics-export">Export</button>
|
||
</div>
|
||
|
||
<div class="analytics-summary-grid">
|
||
<article class="analytics-summary-card">
|
||
<span class="analytics-summary-icon analytics-icon-box" aria-hidden="true">📦</span>
|
||
<div>
|
||
<div class="analytics-summary-value" id="summary-moved-today">0</div>
|
||
<div class="analytics-summary-label">Moved Today</div>
|
||
</div>
|
||
</article>
|
||
<article class="analytics-summary-card">
|
||
<span class="analytics-summary-icon analytics-icon-week" aria-hidden="true">📅</span>
|
||
<div>
|
||
<div class="analytics-summary-value" id="summary-moved-week">0</div>
|
||
<div class="analytics-summary-label">Moved This Week</div>
|
||
</div>
|
||
</article>
|
||
<article class="analytics-summary-card">
|
||
<span class="analytics-summary-icon analytics-icon-month" aria-hidden="true">📅</span>
|
||
<div>
|
||
<div class="analytics-summary-value" id="summary-moved-month">0</div>
|
||
<div class="analytics-summary-label">Moved This Month</div>
|
||
</div>
|
||
</article>
|
||
<article class="analytics-summary-card">
|
||
<span class="analytics-summary-icon analytics-icon-total" aria-hidden="true">📦</span>
|
||
<div>
|
||
<div class="analytics-summary-value" id="summary-total-moved">0</div>
|
||
<div class="analytics-summary-label">Total Moved</div>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
|
||
<div class="analytics-charts-row">
|
||
<section class="analytics-chart-panel">
|
||
<h3 class="analytics-panel-title">Cartons Moved to Warehouse by Day</h3>
|
||
<div class="analytics-bar-chart-wrap">
|
||
<canvas id="analytics-bar-chart" aria-label="Cartons moved by day"></canvas>
|
||
</div>
|
||
</section>
|
||
<section class="analytics-chart-panel analytics-donut-panel">
|
||
<h3 class="analytics-panel-title">Status Share</h3>
|
||
<div class="analytics-donut-wrap">
|
||
<canvas id="analytics-donut-chart" aria-label="Moved versus pending share"></canvas>
|
||
</div>
|
||
<ul class="analytics-legend" id="analytics-status-legend"></ul>
|
||
</section>
|
||
</div>
|
||
|
||
<section class="analytics-table-section">
|
||
<h3 class="analytics-panel-title">Day-wise Movement Details</h3>
|
||
<div class="table-responsive analytics-table-wrap">
|
||
<table class="table table-sm align-middle" id="analytics-day-table">
|
||
<thead>
|
||
<tr>
|
||
<th>DATE</th>
|
||
<th>MOVED CARTONS</th>
|
||
<th>SUCCESSFUL SCANS</th>
|
||
<th>DUPLICATE REJECTIONS</th>
|
||
<th>MANUAL ENTRY REJECTIONS</th>
|
||
<th>LAST MOVED AT</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="analytics-day-tbody"></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
|
||
<div class="scan-history-dialog-footer">
|
||
<button type="button" class="btn-scan-history-dialog-close" id="btn-scan-history-dialog-close">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</dialog>
|
||
</main>
|
||
|
||
<footer class="page-footer">
|
||
<span>SHIPPING MARK BY TECHNOLOGY</span>
|
||
<span>|</span>
|
||
<span>SHIPPING MARK</span>
|
||
</footer>
|
||
|
||
@section Scripts {
|
||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js" crossorigin="anonymous"></script>
|
||
<script src="~/js/movement-analytics.js" asp-append-version="true"></script>
|
||
<script src="~/js/verification-dashboard.js" asp-append-version="true"></script>
|
||
}
|