diff --git a/public/app.mjs b/public/app.mjs index 1be1422..14433ee 100644 --- a/public/app.mjs +++ b/public/app.mjs @@ -1625,8 +1625,9 @@ function open_inventory_dialog(entry = null, default_component_id = null, defaul const new_comp_btn = qs(dlg, '#i-new-component'); const grid_row_div = qs(dlg, '#i-grid-row'); const grid_sel = qs(dlg, '#i-grid-select'); - const row_num_input = qs(dlg, '#i-grid-row-num'); - const col_num_input = qs(dlg, '#i-grid-col-num'); + const grid_visual = qs(dlg, '#i-grid-visual'); + let picker_row = null; + let picker_col = null; title.textContent = entry ? 'Edit inventory entry' : 'Add inventory entry'; @@ -1659,8 +1660,44 @@ function open_inventory_dialog(entry = null, default_component_id = null, defaul })) ); if (effective_grid_cell?.grid_id) { grid_sel.value = effective_grid_cell.grid_id; } - row_num_input.value = effective_grid_cell?.grid_row != null ? effective_grid_cell.grid_row + 1 : 1; - col_num_input.value = effective_grid_cell?.grid_col != null ? effective_grid_cell.grid_col + 1 : 1; + picker_row = effective_grid_cell?.grid_row ?? null; + picker_col = effective_grid_cell?.grid_col ?? null; + + function rebuild_grid_visual() { + const grid = all_grids.find(g => g.id === grid_sel.value); + if (!grid) { grid_visual.replaceChildren(); return; } + grid_visual.style.gridTemplateColumns = `repeat(${grid.cols}, 1fr)`; + const cells = []; + for (let r = 0; r < grid.rows; r++) { + for (let c = 0; c < grid.cols; c++) { + const cell = document.createElement('div'); + cell.className = 'igv-cell'; + if (r === picker_row && c === picker_col) cell.classList.add('igv-selected'); + const filename = grid.cells?.[r]?.[c]; + if (filename) { + const img = document.createElement('img'); + img.src = `/img/${filename}`; + img.className = 'igv-img'; + cell.appendChild(img); + } + cell.addEventListener('click', () => { + picker_row = r; + picker_col = c; + grid_visual.querySelectorAll('.igv-cell').forEach(el => el.classList.remove('igv-selected')); + cell.classList.add('igv-selected'); + }); + cells.push(cell); + } + } + grid_visual.replaceChildren(...cells); + } + + rebuild_grid_visual(); + + const old_grid_handler = grid_sel._change_handler; + if (old_grid_handler) grid_sel.removeEventListener('change', old_grid_handler); + grid_sel._change_handler = () => { picker_row = null; picker_col = null; rebuild_grid_visual(); }; + grid_sel.addEventListener('change', grid_sel._change_handler); function update_ref_label() { ref_label.textContent = ref_label_for_type(type_sel.value); @@ -1700,8 +1737,8 @@ function open_inventory_dialog(entry = null, default_component_id = null, defaul quantity: qty_input.value.trim(), notes: notes_input.value.trim(), grid_id: is_grid ? (grid_sel.value || null) : null, - grid_row: is_grid ? parseInt(row_num_input.value) - 1 : null, - grid_col: is_grid ? parseInt(col_num_input.value) - 1 : null, + grid_row: is_grid ? picker_row : null, + grid_col: is_grid ? picker_col : null, }; if (entry) { const result = await api.update_inventory(entry.id, body); diff --git a/public/style.css b/public/style.css index d89b5bd..3178ee6 100644 --- a/public/style.css +++ b/public/style.css @@ -1504,15 +1504,38 @@ nav { gap: 0.4rem; } -.i-grid-coords { - display: flex; - align-items: center; - gap: 0.4rem; - font-size: 0.9rem; +.i-grid-visual { + display: grid; + gap: 2px; + max-height: 320px; + overflow-y: auto; } -.input-narrow { - width: 4rem; +.igv-cell { + position: relative; + aspect-ratio: 1; + background: var(--surface-raised); + border: 2px solid transparent; + border-radius: 2px; + cursor: pointer; + overflow: hidden; +} + +.igv-cell:hover { + border-color: var(--accent); +} + +.igv-cell.igv-selected { + border-color: var(--accent); + box-shadow: inset 0 0 0 1px var(--accent); +} + +.igv-img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + pointer-events: none; } /* ===== CELL INVENTORY OVERLAY ===== */ diff --git a/public/templates.html b/public/templates.html index b1a8232..fda93b6 100644 --- a/public/templates.html +++ b/public/templates.html @@ -444,12 +444,7 @@
-
- - - - -
+