Files
PowderCoatingLogix/src/PowderCoating.Web/Views/Inventory/SamplePanels.cshtml
T
2026-04-23 21:38:24 -04:00

342 lines
18 KiB
Plaintext

@{
ViewData["Title"] = "Sample Panels";
ViewData["PageIcon"] = "bi-palette";
var manufacturers = ViewBag.Manufacturers as List<string> ?? new List<string>();
var selectedMfr = ViewBag.SelectedManufacturer as string;
var activeTab = ViewBag.ActiveTab as string ?? "need";
var onHand = ViewBag.OnHandItems as List<PowderCoating.Core.Entities.InventoryItem> ?? new();
var needOrder = ViewBag.NeedToOrderItems as List<PowderCoating.Core.Entities.InventoryItem> ?? new();
var totalCoatings = (int)(ViewBag.TotalCoatings ?? 0);
var totalOnHand = (int)(ViewBag.TotalOnHand ?? 0);
var totalNeedOrder = (int)(ViewBag.TotalNeedOrder ?? 0);
string? lastMfr = null;
}
@section Styles {
<style>
.panel-row { cursor: pointer; transition: background .12s; }
.panel-row:hover { background: var(--bs-tertiary-bg); }
.panel-row td { vertical-align: middle; }
.panel-badge-on { color: #198754; }
.panel-badge-need { color: #6c757d; }
.color-swatch {
width: 24px; height: 24px;
border-radius: 4px;
border: 1px solid var(--bs-border-color);
display: inline-block;
flex-shrink: 0;
}
</style>
}
<div class="d-flex justify-content-end align-items-center gap-2 mb-4">
<a asp-action="Index" class="btn btn-outline-secondary">
<i class="bi bi-box-seam me-1"></i>Back to Inventory
</a>
<button class="btn btn-outline-primary" id="btnPrintList">
<i class="bi bi-printer me-1"></i>Print Need-to-Order
</button>
</div>
<!-- Stats -->
<div class="row g-3 mb-4">
<div class="col-sm-4">
<div class="card border-0 shadow-sm text-center py-3">
<div class="fs-2 fw-bold text-primary">@totalCoatings</div>
<div class="text-muted small">Total Coating Colors</div>
</div>
</div>
<div class="col-sm-4">
<div class="card border-0 shadow-sm text-center py-3">
<div class="fs-2 fw-bold text-success">@totalOnHand</div>
<div class="text-muted small">Panels on Wall</div>
</div>
</div>
<div class="col-sm-4">
<div class="card border-0 shadow-sm text-center py-3">
<div class="fs-2 fw-bold text-secondary">@totalNeedOrder</div>
<div class="text-muted small">Need to Order</div>
</div>
</div>
</div>
<!-- Manufacturer Filter -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-body py-3">
<form method="get" class="d-flex gap-2 align-items-center flex-wrap">
<input type="hidden" name="tab" value="@activeTab" id="filterTabInput" />
<label class="form-label mb-0 fw-semibold me-1">Filter by Manufacturer:</label>
<select name="manufacturer" class="form-select form-select-sm w-auto" onchange="this.form.submit()">
<option value="">— All Manufacturers —</option>
@foreach (var mfr in manufacturers)
{
<option value="@mfr" selected="@(selectedMfr == mfr ? "selected" : null)">@mfr</option>
}
</select>
@if (!string.IsNullOrWhiteSpace(selectedMfr))
{
<a asp-action="SamplePanels" asp-route-tab="@activeTab" class="btn btn-sm btn-outline-secondary">
<i class="bi bi-x me-1"></i>Clear Filter
</a>
}
</form>
</div>
</div>
<!-- Tabs -->
<ul class="nav nav-tabs mb-0" id="samplePanelTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link @(activeTab == "need" ? "active" : "")" id="tab-need"
data-bs-toggle="tab" data-bs-target="#pane-need" type="button" role="tab"
onclick="document.getElementById('filterTabInput').value='need'">
<i class="bi bi-bag me-1 text-secondary"></i>
Need to Order
<span class="badge bg-secondary rounded-pill ms-1">@needOrder.Count</span>
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link @(activeTab == "onhand" ? "active" : "")" id="tab-onhand"
data-bs-toggle="tab" data-bs-target="#pane-onhand" type="button" role="tab"
onclick="document.getElementById('filterTabInput').value='onhand'">
<i class="bi bi-check-circle me-1 text-success"></i>
On Wall
<span class="badge bg-success rounded-pill ms-1">@onHand.Count</span>
</button>
</li>
</ul>
<div class="tab-content">
<!-- Need to Order Tab -->
<div class="tab-pane fade @(activeTab == "need" ? "show active" : "")" id="pane-need" role="tabpanel">
<div class="card border-0 shadow-sm border-top-0" style="border-radius: 0 0 .5rem .5rem;">
<div class="card-body p-0">
@if (!needOrder.Any())
{
<div class="text-center py-5 text-muted">
<i class="bi bi-check2-all display-4 text-success d-block mb-2"></i>
@if (string.IsNullOrWhiteSpace(selectedMfr))
{
<p>All coating colors have a sample panel on the wall!</p>
}
else
{
<p>All <strong>@selectedMfr</strong> colors have a sample panel on the wall.</p>
}
</div>
}
else
{
<div class="table-responsive">
<table class="table table-hover mb-0" id="needTable">
<thead class="table-group-divider">
<tr>
<th style="width:36px;"></th>
<th>Color / Item</th>
<th>Manufacturer</th>
<th>Part #</th>
<th>Finish</th>
<th>In Stock</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody id="needTableBody">
@{ lastMfr = null; }
@foreach (var item in needOrder)
{
if (string.IsNullOrWhiteSpace(selectedMfr) && item.Manufacturer != lastMfr)
{
lastMfr = item.Manufacturer;
<tr class="table-secondary">
<td colspan="6" class="py-1 px-3">
<small class="fw-semibold text-uppercase text-muted">
@(string.IsNullOrWhiteSpace(item.Manufacturer) ? "No Manufacturer" : item.Manufacturer)
</small>
</td>
</tr>
}
<tr class="panel-row" data-id="@item.Id">
<td class="ps-3">
@if (!string.IsNullOrWhiteSpace(item.ColorCode))
{
<span class="color-swatch" style="background: @(item.ColorCode.StartsWith("#") ? item.ColorCode : "#" + item.ColorCode);"
title="@item.ColorCode"></span>
}
else
{
<span class="color-swatch bg-body-secondary"></span>
}
</td>
<td>
<div class="fw-semibold">@(item.ColorName ?? item.Name)</div>
@if (!string.IsNullOrWhiteSpace(item.ColorName) && item.ColorName != item.Name)
{
<div class="text-muted small">@item.Name</div>
}
</td>
<td>@(item.Manufacturer ?? "—")</td>
<td class="text-muted small">@(item.ManufacturerPartNumber ?? "—")</td>
<td>@(item.Finish ?? "—")</td>
<td>
@if (item.QuantityOnHand > 0)
{
<span class="badge bg-success bg-opacity-10 text-success">@item.QuantityOnHand.ToString("N2") @item.UnitOfMeasure</span>
}
else
{
<span class="text-muted small">None</span>
}
</td>
<td class="text-end pe-3">
<button class="btn btn-sm btn-outline-success me-1 btn-toggle-panel"
data-item-id="@item.Id" data-has-panel="true"
title="Mark as received — panel is on wall">
<i class="bi bi-check-lg me-1"></i>Got It
</button>
<a asp-action="Details" asp-route-id="@item.Id"
class="btn btn-sm btn-outline-secondary" title="View item">
<i class="bi bi-eye"></i>
</a>
</td>
</tr>
}
</tbody>
</table>
</div>
}
</div>
</div>
</div>
<!-- On Wall Tab -->
<div class="tab-pane fade @(activeTab == "onhand" ? "show active" : "")" id="pane-onhand" role="tabpanel">
<div class="card border-0 shadow-sm border-top-0" style="border-radius: 0 0 .5rem .5rem;">
<div class="card-body p-0">
@if (!onHand.Any())
{
<div class="text-center py-5 text-muted">
<i class="bi bi-palette display-4 d-block mb-2"></i>
<p>No sample panels recorded yet. Use the <strong>Need to Order</strong> tab to mark colors as received.</p>
</div>
}
else
{
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-group-divider">
<tr>
<th style="width:36px;"></th>
<th>Color / Item</th>
<th>Manufacturer</th>
<th>Part #</th>
<th>Finish</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
@{ lastMfr = null; }
@foreach (var item in onHand)
{
if (string.IsNullOrWhiteSpace(selectedMfr) && item.Manufacturer != lastMfr)
{
lastMfr = item.Manufacturer;
<tr class="table-secondary">
<td colspan="6" class="py-1 px-3">
<small class="fw-semibold text-uppercase text-muted">
@(string.IsNullOrWhiteSpace(item.Manufacturer) ? "No Manufacturer" : item.Manufacturer)
</small>
</td>
</tr>
}
<tr class="panel-row" data-id="@item.Id">
<td class="ps-3">
@if (!string.IsNullOrWhiteSpace(item.ColorCode))
{
<span class="color-swatch" style="background: @(item.ColorCode.StartsWith("#") ? item.ColorCode : "#" + item.ColorCode);"
title="@item.ColorCode"></span>
}
else
{
<span class="color-swatch bg-body-secondary"></span>
}
</td>
<td>
<div class="fw-semibold">@(item.ColorName ?? item.Name)</div>
@if (!string.IsNullOrWhiteSpace(item.ColorName) && item.ColorName != item.Name)
{
<div class="text-muted small">@item.Name</div>
}
</td>
<td>@(item.Manufacturer ?? "—")</td>
<td class="text-muted small">@(item.ManufacturerPartNumber ?? "—")</td>
<td>@(item.Finish ?? "—")</td>
<td class="text-end pe-3">
<button class="btn btn-sm btn-outline-danger me-1 btn-toggle-panel"
data-item-id="@item.Id" data-has-panel="false"
title="Remove — panel no longer on wall">
<i class="bi bi-x-lg me-1"></i>Remove
</button>
<a asp-action="Details" asp-route-id="@item.Id"
class="btn btn-sm btn-outline-secondary" title="View item">
<i class="bi bi-eye"></i>
</a>
</td>
</tr>
}
</tbody>
</table>
</div>
}
</div>
</div>
</div>
</div>
<!-- Print-only need-to-order output -->
<div id="printArea" style="display:none;">
<h3 style="font-family:sans-serif;">Sample Panels — Need to Order</h3>
@if (!string.IsNullOrWhiteSpace(selectedMfr))
{
<p style="font-family:sans-serif;font-size:.9rem;color:#666;">Manufacturer: @selectedMfr</p>
}
<p style="font-family:sans-serif;font-size:.85rem;color:#666;">Printed @DateTime.Now.ToString("MMMM dd, yyyy")</p>
<table style="width:100%;border-collapse:collapse;font-family:sans-serif;font-size:.85rem;">
<thead>
<tr style="background:#f0f0f0;">
<th style="border:1px solid #ccc;padding:6px 10px;text-align:left;">Color</th>
<th style="border:1px solid #ccc;padding:6px 10px;text-align:left;">Manufacturer</th>
<th style="border:1px solid #ccc;padding:6px 10px;text-align:left;">Part #</th>
<th style="border:1px solid #ccc;padding:6px 10px;text-align:left;">Finish</th>
<th style="border:1px solid #ccc;padding:6px 10px;text-align:left;">In Stock</th>
<th style="border:1px solid #ccc;padding:6px 10px;text-align:left;">Ordered ✓</th>
</tr>
</thead>
<tbody>
@{ lastMfr = null; }
@foreach (var item in needOrder)
{
if (string.IsNullOrWhiteSpace(selectedMfr) && item.Manufacturer != lastMfr)
{
lastMfr = item.Manufacturer;
<tr>
<td colspan="6" style="border:1px solid #ccc;padding:4px 10px;background:#f7f7f7;">
<strong>@(string.IsNullOrWhiteSpace(item.Manufacturer) ? "No Manufacturer" : item.Manufacturer)</strong>
</td>
</tr>
}
<tr>
<td style="border:1px solid #ccc;padding:6px 10px;">@(item.ColorName ?? item.Name)</td>
<td style="border:1px solid #ccc;padding:6px 10px;">@(item.Manufacturer ?? "")</td>
<td style="border:1px solid #ccc;padding:6px 10px;">@(item.ManufacturerPartNumber ?? "")</td>
<td style="border:1px solid #ccc;padding:6px 10px;">@(item.Finish ?? "")</td>
<td style="border:1px solid #ccc;padding:6px 10px;">@(item.QuantityOnHand > 0 ? item.QuantityOnHand.ToString("N2") + " " + item.UnitOfMeasure : "—")</td>
<td style="border:1px solid #ccc;padding:6px 10px;">&nbsp;</td>
</tr>
}
</tbody>
</table>
</div>
@section Scripts {
<script src="~/js/sample-panels.js" asp-append-version="true"></script>
}