Mobile layout fix for Job Details items; coat color on invoice line items

- Job Details: hide desktop item tables on mobile (d-none d-lg-block) so only
  the existing mobile-card layout shows on small screens — prevents 20-line rows
  on a narrow phone display
- Invoices Create (ForJob path): load job item coats and derive ColorName from
  coat colors when the item itself has no explicit color set; multiple coats join
  as 'Color1 / Color2' — lets customers distinguish repeated items (e.g. multiple
  caliper sets) on the invoice

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-19 19:34:54 -04:00
parent 4a7087cc0c
commit 551116d7e5
2 changed files with 26 additions and 1 deletions
@@ -355,6 +355,15 @@ public class InvoicesController : Controller
var job = await _unitOfWork.Jobs.GetByIdAsync(jobId.Value, false, j => j.Customer, j => j.JobItems);
if (job == null) return NotFound();
// Pre-load coats so we can derive color names for invoice line items
var activeItemIds = job.JobItems.Where(ji => !ji.IsDeleted).Select(ji => ji.Id).ToList();
var allCoats = activeItemIds.Any()
? (await _unitOfWork.JobItemCoats.FindAsync(c => activeItemIds.Contains(c.JobItemId) && !c.IsDeleted)).ToList()
: new List<JobItemCoat>();
var coatsByItem = allCoats
.GroupBy(c => c.JobItemId)
.ToDictionary(g => g.Key, g => g.OrderBy(c => c.Sequence).ToList());
// Validate no existing active invoice for this job (voided ones are kept as history)
var existing = await _unitOfWork.Invoices.GetForJobAsync(jobId.Value);
if (existing != null && existing.Status != InvoiceStatus.Voided)
@@ -404,6 +413,16 @@ public class InvoicesController : Controller
revenueAccountId = ci.RevenueAccountId;
revenueAccountId ??= defaultRevenueAccount?.Id;
// Derive color from coats when the item itself has no explicit color set
var derivedColor = item.ColorName;
if (string.IsNullOrEmpty(derivedColor) && coatsByItem.TryGetValue(item.Id, out var itemCoats))
{
var coatColors = itemCoats
.Where(c => !string.IsNullOrEmpty(c.ColorName))
.Select(c => c.ColorName!);
derivedColor = string.Join(" / ", coatColors);
}
dto.InvoiceItems.Add(new CreateInvoiceItemDto
{
SourceJobItemId = item.Id,
@@ -412,7 +431,7 @@ public class InvoicesController : Controller
Quantity = item.Quantity > 0 ? item.Quantity : 1,
UnitPrice = item.UnitPrice,
TotalPrice = item.TotalPrice,
ColorName = item.ColorName,
ColorName = derivedColor,
Notes = item.Notes,
DisplayOrder = order++,
RevenueAccountId = revenueAccountId
@@ -324,6 +324,7 @@
@* -- Catalog Products -- *@
@if (catalogItems.Any())
{
<div class="d-none d-lg-block">
<h6 class="text-primary mb-3"><i class="bi bi-bag-check me-2"></i>Catalog Products</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-sm">
@@ -412,11 +413,13 @@
</tbody>
</table>
</div>
</div>
}
@* -- Custom Work -- *@
@if (customItems.Any())
{
<div class="d-none d-lg-block">
<h6 class="text-success mb-3"><i class="bi bi-calculator me-2"></i>Custom Work</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-sm">
@@ -563,11 +566,13 @@
</tbody>
</table>
</div>
</div>
}
@* -- Labor -- *@
@if (laborItems.Any())
{
<div class="d-none d-lg-block">
<h6 class="text-warning mb-3"><i class="bi bi-person-gear me-2"></i>Labor</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-sm">
@@ -614,6 +619,7 @@
</tbody>
</table>
</div>
</div>
}
@* -- Mobile cards -- *@