From 1ff3870ae9a3a0508473cf22d0659c39140b9b3c Mon Sep 17 00:00:00 2001 From: Jason <17367223+jsoltys@users.noreply.github.com> Date: Thu, 30 Apr 2026 14:49:03 -0500 Subject: [PATCH] Merged search buttons into a sinfgle button --- app/static/css/styles.css | 19 ++-- app/static/js/script.js | 138 +++++++++++++++++++----------- app/templates/product_finder.html | 6 +- 3 files changed, 100 insertions(+), 63 deletions(-) diff --git a/app/static/css/styles.css b/app/static/css/styles.css index 7048405..9fba4f9 100644 --- a/app/static/css/styles.css +++ b/app/static/css/styles.css @@ -747,11 +747,13 @@ body { .search-input-wrapper { position: relative; - margin-bottom: 15px; + display: flex; + gap: 10px; + align-items: flex-start; } .search-input { - width: 100%; + flex: 1; padding: 12px 16px; font-size: 16px; border: 2px solid #333; @@ -770,7 +772,7 @@ body { position: absolute; top: 100%; left: 0; - right: 0; + right: 120px; background-color: white; border: 2px solid #333; border-top: none; @@ -813,14 +815,9 @@ body { color: #666; } -.search-buttons { - display: flex; - gap: 10px; - justify-content: center; -} - .search-btn { - padding: 10px 20px; + flex-shrink: 0; + padding: 12px 24px; font-size: 14px; font-weight: bold; border: 2px solid #333; @@ -829,6 +826,8 @@ body { transition: all 0.3s ease; background-color: white; color: #333; + height: 48px; + white-space: nowrap; } .search-btn:hover:not(:disabled) { diff --git a/app/static/js/script.js b/app/static/js/script.js index 5ddf309..0296302 100644 --- a/app/static/js/script.js +++ b/app/static/js/script.js @@ -1470,53 +1470,84 @@ function toggleSearchBar() { function clearSearch() { const searchInput = document.getElementById('searchInput'); const searchDropdown = document.getElementById('searchDropdown'); - const viewBtn = document.getElementById('viewBtn'); if (searchInput) searchInput.value = ''; if (searchDropdown) { searchDropdown.style.display = 'none'; searchDropdown.innerHTML = ''; } - if (viewBtn) viewBtn.disabled = true; searchMatches = []; selectedSearchIndex = -1; } +// Helper function to normalize text for searching +function normalizeText(text) { + if (!text) return ''; + return text.toString().toLowerCase() + .replace(/[-\s_]/g, '') // Remove hyphens, spaces, underscores + .replace(/[^a-z0-9]/g, ''); // Remove other special characters +} + +// Helper function to check if a value matches a search term +function matchesTerm(value, term) { + if (!value) return false; + + // For arrays (like colors, materials) + if (Array.isArray(value)) { + return value.some(item => normalizeText(item).includes(term)); + } + + // For objects (like subType) + if (typeof value === 'object' && value !== null) { + return Object.values(value).some(v => + v && normalizeText(v).includes(term) + ); + } + + // For strings and numbers + return normalizeText(value).includes(term); +} + // Filter products by search term function filterProductsBySearch(searchTerm) { if (!searchTerm || searchTerm.trim().length < 2) { return []; } - const term = searchTerm.toLowerCase().trim(); + // Split search query into individual terms + const searchTerms = searchTerm.toLowerCase() + .split(/\s+/) + .filter(term => term.length > 0) + .map(term => normalizeText(term)); + // Filter products that match ALL search terms return productData.filter(product => { - const description = (product.description || '').toLowerCase(); - const productCode = (product.productCode || '').toLowerCase(); - const category = (product.category || '').toLowerCase(); - const baseType = (product.baseType || '').toLowerCase(); - const subTypeWindow = (product.subType?.window || '').toLowerCase(); - const subTypeDoor = (product.subType?.door || '').toLowerCase(); - - return description.includes(term) || - productCode.includes(term) || - category.includes(term) || - baseType.includes(term) || - subTypeWindow.includes(term) || - subTypeDoor.includes(term); + // Each product must match ALL search terms + return searchTerms.every(term => { + // Check if the term matches any of these fields + return ( + matchesTerm(product.productCode, term) || + matchesTerm(product.id, term) || + matchesTerm(product.description, term) || + matchesTerm(product.category, term) || + matchesTerm(product.baseType, term) || + matchesTerm(product.subType, term) || + matchesTerm(product.materials, term) || + matchesTerm(product.colors, term) || + matchesTerm(product.location, term) + ); + }); }); } // Update search dropdown with matches function updateSearchDropdown(matches) { const dropdown = document.getElementById('searchDropdown'); - const viewBtn = document.getElementById('viewBtn'); if (!matches || matches.length === 0) { dropdown.style.display = 'none'; dropdown.innerHTML = ''; - viewBtn.disabled = true; selectedSearchIndex = -1; return; } @@ -1555,12 +1586,9 @@ function updateSearchDropdown(matches) { // Select a search item function selectSearchItem(index, closeDropdown = true) { selectedSearchIndex = index; - const viewBtn = document.getElementById('viewBtn'); const searchInput = document.getElementById('searchInput'); const searchDropdown = document.getElementById('searchDropdown'); - viewBtn.disabled = false; - // Update search input with selected product description if (searchMatches[index]) { const selectedProduct = searchMatches[index]; @@ -1584,7 +1612,7 @@ function selectSearchItem(index, closeDropdown = true) { }); } -// Handle View button click +// Handle View button click (kept for backward compatibility) function handleViewProduct() { if (selectedSearchIndex >= 0 && selectedSearchIndex < searchMatches.length) { const product = searchMatches[selectedSearchIndex]; @@ -1598,34 +1626,55 @@ function handleViewProduct() { } } -// Handle Search button click (show results grid) +// Handle Search/Go button click with smart behavior +function handleSearchGo() { + const searchInput = document.getElementById('searchInput'); + const searchTerm = searchInput.value.trim(); + + // If an item is selected from dropdown, go directly to that product + if (selectedSearchIndex >= 0 && selectedSearchIndex < searchMatches.length) { + handleViewProduct(); + return; + } + + // If search term is empty or too short, go to advanced search + if (!searchTerm || searchTerm.length < 2) { + handleAdvancedSearch(); + return; + } + + // Get matches for the search term + const matches = filterProductsBySearch(searchTerm); + + // If exactly one match, go directly to that product + if (matches.length === 1) { + const product = matches[0]; + const prodCode = product.productCode || product.id; + clearSearch(); + showProductByCode(prodCode); + return; + } + + // Otherwise, go to advanced search with the search term + handleAdvancedSearch(); +} + +// Handle Search button click (show results grid) - kept for "+ more" functionality function handleSearchResults() { const searchInput = document.getElementById('searchInput'); const searchTerm = searchInput.value.trim(); + // If no search term, go to advanced search if (!searchTerm || searchTerm.length < 2) { - alert('Please enter at least 2 characters to search.'); + handleAdvancedSearch(); return; } - const matches = filterProductsBySearch(searchTerm); - - if (matches.length === 0) { - alert('No products found matching "' + searchTerm + '".'); - return; - } - - // Store search results temporarily - searchMatches = matches; - - // Clear search UI - clearSearch(); - - // Display results in grid format (similar to showFilteredProducts) - showSearchResultsGrid(matches, searchTerm); + // Navigate to advanced search with search term + handleAdvancedSearch(); } -// Show search results in a grid +// Show search results in a grid (kept for potential future use) function showSearchResultsGrid(matches, searchTerm) { const contentDiv = document.getElementById('content'); @@ -1711,7 +1760,6 @@ function initSearchBar() { // Reset selection selectedSearchIndex = -1; - document.getElementById('viewBtn').disabled = true; }); // Keyboard navigation (arrow keys and enter) @@ -1729,16 +1777,10 @@ function initSearchBar() { if (selectedSearchIndex >= 0) { updateSearchDropdown(searchMatches); selectSearchItem(selectedSearchIndex, false); // Keep dropdown open - } else { - document.getElementById('viewBtn').disabled = true; } } else if (e.key === 'Enter') { e.preventDefault(); - if (selectedSearchIndex >= 0) { - handleViewProduct(); - } else { - handleSearchResults(); - } + handleSearchGo(); } else if (e.key === 'Escape') { clearSearch(); } diff --git a/app/templates/product_finder.html b/app/templates/product_finder.html index 9a24599..29bab7d 100644 --- a/app/templates/product_finder.html +++ b/app/templates/product_finder.html @@ -35,13 +35,9 @@ class="search-input" placeholder="Search for products... (e.g., Storm Window)" autocomplete="off"> +
-
- - - -