diff --git a/fusion_plating/fusion_plating_shopfloor/__manifest__.py b/fusion_plating/fusion_plating_shopfloor/__manifest__.py index 5a431f9b..248a3d0e 100644 --- a/fusion_plating/fusion_plating_shopfloor/__manifest__.py +++ b/fusion_plating/fusion_plating_shopfloor/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Fusion Plating — Shop Floor', - 'version': '19.0.13.0.0', + 'version': '19.0.14.0.0', 'category': 'Manufacturing/Plating', 'summary': 'Shop-floor tablet stations, QR scanning, bake window enforcer, ' 'first-piece inspection gates.', diff --git a/fusion_plating/fusion_plating_shopfloor/static/src/js/plant_overview.js b/fusion_plating/fusion_plating_shopfloor/static/src/js/plant_overview.js index 2618c375..17540dc7 100644 --- a/fusion_plating/fusion_plating_shopfloor/static/src/js/plant_overview.js +++ b/fusion_plating/fusion_plating_shopfloor/static/src/js/plant_overview.js @@ -74,18 +74,33 @@ export class PlantOverview extends Component { } // ----- Search ------------------------------------------------------------ + // + // Live search with a 200ms debounce. The user types, the cards update + // as they go — no "press Enter" leap of faith. Debounce keeps us off + // the network on every keystroke when someone types fast. onSearchInput(ev) { this.state.searchTerm = ev.target.value; + this._debouncedSearch(); + } + + _debouncedSearch() { + if (this._searchTimer) clearTimeout(this._searchTimer); + this._searchTimer = setTimeout(() => this.loadData(), 200); } onSearchKey(ev) { + // Enter still works — fires immediately, skipping the debounce. if (ev.key === "Enter") { + if (this._searchTimer) clearTimeout(this._searchTimer); this.loadData(); + } else if (ev.key === "Escape") { + this.onSearchClear(); } } onSearchClear() { + if (this._searchTimer) clearTimeout(this._searchTimer); this.state.searchTerm = ""; this.loadData(); } diff --git a/fusion_plating/fusion_plating_shopfloor/static/src/scss/plant_overview.scss b/fusion_plating/fusion_plating_shopfloor/static/src/scss/plant_overview.scss index e49c6b89..32e5e353 100644 --- a/fusion_plating/fusion_plating_shopfloor/static/src/scss/plant_overview.scss +++ b/fusion_plating/fusion_plating_shopfloor/static/src/scss/plant_overview.scss @@ -65,26 +65,36 @@ align-items: center; .o_fp_po_search_icon { - position: absolute; left: 14px; + position: absolute; left: 16px; color: $fp-ink-mute; pointer-events: none; + font-size: 1.05rem; } .o_fp_po_search_input { - padding: 0 $fp-space-4 0 $fp-space-7; - min-height: $fp-touch-min; + // Bumped from 260px → 380px and slightly taller padding so the + // search bar carries proper visual weight on the toolbar. Live + // search (200ms debounce) makes the input feel like the + // primary affordance on the page, not an afterthought. + padding: 0 $fp-space-5 0 $fp-space-8; + min-height: 52px; border: 1px solid #{$fp-border}; border-radius: $fp-radius-md; background-color: $fp-card; color: $fp-ink; box-shadow: $fp-elev-1; - width: 260px; - font-size: $fp-text-base; + width: 380px; + font-size: $fp-text-md; + font-weight: $fp-weight-medium; transition: box-shadow $fp-dur $fp-ease, border-color $fp-dur $fp-ease; + &::placeholder { color: $fp-ink-faint; font-weight: $fp-weight-medium; } &:focus { @include fp-focus-ring; border-color: $fp-accent; } - @media (max-width: 600px) { width: 100%; } + // Tablet — keep it generously sized but cap so the toolbar + // doesn't blow past the viewport. + @media (max-width: 1180px) { width: 320px; min-height: 48px; } + @media (max-width: 900px) { width: 100%; } } .o_fp_po_search_clear { position: absolute; right: 6px;