diff --git a/src/PowderCoating.Web/Controllers/JobsController.cs b/src/PowderCoating.Web/Controllers/JobsController.cs index b7f9840..896a931 100644 --- a/src/PowderCoating.Web/Controllers/JobsController.cs +++ b/src/PowderCoating.Web/Controllers/JobsController.cs @@ -503,9 +503,17 @@ public class JobsController : Controller .OrderBy(i => i.Name) .Select(i => new { i.Id, i.Name, i.Manufacturer, i.UnitOfMeasure, i.QuantityOnHand }) .ToList(); - ViewBag.InventoryItemsForModal = System.Text.Json.JsonSerializer.Serialize( - inventoryItemsForModal, - new System.Text.Json.JsonSerializerOptions { PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase }); + var jsonOpts = new System.Text.Json.JsonSerializerOptions { PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase }; + ViewBag.InventoryItemsForModal = System.Text.Json.JsonSerializer.Serialize(inventoryItemsForModal, jsonOpts); + + // IDs of powders already assigned to this job's coats — shown at top of log-material dropdown + var jobPowderIds = (jobDto.Items ?? new List()) + .SelectMany(i => i.Coats ?? new List()) + .Where(c => c.InventoryItemId.HasValue) + .Select(c => c.InventoryItemId!.Value) + .Distinct() + .ToList(); + ViewBag.JobPowderIds = System.Text.Json.JsonSerializer.Serialize(jobPowderIds, jsonOpts); // Pre-logged powder grouped by InventoryItemId (for Complete Job modal pre-fill) ViewBag.PreLoggedPowder = allJobTransactions diff --git a/src/PowderCoating.Web/Views/Jobs/Details.cshtml b/src/PowderCoating.Web/Views/Jobs/Details.cshtml index 87746fd..ff238ca 100644 --- a/src/PowderCoating.Web/Views/Jobs/Details.cshtml +++ b/src/PowderCoating.Web/Views/Jobs/Details.cshtml @@ -3162,10 +3162,11 @@ diff --git a/src/PowderCoating.Web/wwwroot/js/log-material.js b/src/PowderCoating.Web/wwwroot/js/log-material.js index e4c1b1c..286f551 100644 --- a/src/PowderCoating.Web/wwwroot/js/log-material.js +++ b/src/PowderCoating.Web/wwwroot/js/log-material.js @@ -4,6 +4,7 @@ */ (function () { let _items = []; + let _jobPowderIds = new Set(); let _modal = null; // ── Combobox state ──────────────────────────────────────────────────────── @@ -35,6 +36,23 @@ } } + function lmMakeRow(it) { + const label = it.name + (it.unitOfMeasure ? ' (' + it.unitOfMeasure + ')' : ''); + const mfr = it.manufacturer + ? `${escLm(it.manufacturer)}` + : ''; + return `
+ ${escLm(label)}${mfr} +
`; + } + function lmComboRender(query) { const dd = document.getElementById('lmItemDropdown'); if (!dd) return; @@ -47,20 +65,21 @@ dd.innerHTML = '
No items match.
'; return; } - dd.innerHTML = filtered.map(it => { - const label = it.name + (it.unitOfMeasure ? ' (' + it.unitOfMeasure + ')' : ''); - const mfr = it.manufacturer ? `${escLm(it.manufacturer)}` : ''; - return `
- ${escLm(label)}${mfr} -
`; - }).join(''); + + const jobItems = filtered.filter(it => _jobPowderIds.has(it.id)); + const otherItems = filtered.filter(it => !_jobPowderIds.has(it.id)); + + let html = ''; + if (jobItems.length > 0) { + html += '
This Job
'; + html += jobItems.map(lmMakeRow).join(''); + if (otherItems.length > 0) { + html += '
'; + html += '
All Inventory
'; + } + } + html += otherItems.map(lmMakeRow).join(''); + dd.innerHTML = html; } function lmComboShow() { @@ -245,6 +264,7 @@ if (!cfg) return; _items = cfg.inventoryItems || []; + _jobPowderIds = new Set(cfg.jobPowderIds || []); _modal = new bootstrap.Modal(document.getElementById('logMaterialModal')); document.getElementById('lmQuantity').addEventListener('input', lmOnQtyInput);