diff --git a/assets/controllers/global_search_controller.js b/assets/controllers/global_search_controller.js index ecbfaad..1f3720d 100644 --- a/assets/controllers/global_search_controller.js +++ b/assets/controllers/global_search_controller.js @@ -1,7 +1,7 @@ import { Controller } from "@hotwired/stimulus"; export default class extends Controller { - static targets = ["searchBar", "searchResults"]; + static targets = ["searchInput"]; connect() { this.ignoreNextClick = false; // Prevents conflict on initial click @@ -9,7 +9,7 @@ export default class extends Controller { } toggleSearchBar(event) { - event.preventDefault(); // Prevent default link behavior + event.preventDefault(); // Prevent default anchor behavior if (this.isSearchBarOpen()) { this.closeSearchBar(); @@ -19,23 +19,19 @@ export default class extends Controller { } openSearchBar() { - // Add "search-overlay" class to - document.body.classList.add("search-overlay"); - // Remove "not-shown" class from the search bar - this.searchBarTarget.classList.remove("not-shown"); - // Ignore the next click to avoid immediate close - this.ignoreNextClick = true; - // Add event listener to detect clicks outside the search bar - document.addEventListener("click", this.handleOutsideClick); + document.body.classList.add("global-search-shown"); // Add class to + this.searchInputTarget.focus(); // Focus the input field + this.ignoreNextClick = true; // Prevent immediate close + document.addEventListener("click", this.handleOutsideClick); // Add outside click listener } - closeSearchBar() { - // Remove "search-overlay" class from - document.body.classList.remove("search-overlay"); - // Add "not-shown" class to the search bar - this.searchBarTarget.classList.add("not-shown"); - // Remove event listener for outside clicks - document.removeEventListener("click", this.handleOutsideClick); + closeSearchBar(event) { + if (event) { + event.preventDefault(); // Prevent default behavior + } + + document.body.classList.remove("global-search-shown"); // Remove class from + document.removeEventListener("click", this.handleOutsideClick); // Remove outside click listener } handleOutsideClick(event) { @@ -44,16 +40,15 @@ export default class extends Controller { return; } - const isClickInsideSearch = - this.searchBarTarget.contains(event.target) || - this.searchResultsTargets.some((target) => target.contains(event.target)); + const clickedOverlay = event.target.classList.contains("global-search-overlay"); - if (!isClickInsideSearch) { + // Close if the click is on the overlay or outside the search elements + if (clickedOverlay || !event.target.closest(".global-search")) { this.closeSearchBar(); } } isSearchBarOpen() { - return !this.searchBarTarget.classList.contains("not-shown"); + return document.body.classList.contains("global-search-shown"); } } diff --git a/assets/styles/app.scss b/assets/styles/app.scss index b997000..a90d46b 100755 --- a/assets/styles/app.scss +++ b/assets/styles/app.scss @@ -313,6 +313,7 @@ td.rank { .navbar-brand { padding: 4px 0; + margin-right: 0 !important; } @include media-breakpoint-up(lg) { @@ -602,21 +603,32 @@ canvas { border-radius: 0 !important; } -body::before { - content: ''; - opacity: 0; -} - -body.search-overlay::before { +.global-search-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; - background: rgba(0, 0, 0, 0.6); - z-index: 5; + background-color: rgba(0, 0, 0, 0.6); + z-index: 10; + opacity: 0; + pointer-events: none; transition: opacity 0.3s ease-in-out; - opacity: 1; +} + +.global-search-shown { + overflow: hidden; + + .global-search-overlay { + opacity: 1; + pointer-events: all; + } + + .global-search { + opacity: 1; + transform: translateX(-50%) translateY(0); + pointer-events: all; + } } .global-search { @@ -631,37 +643,23 @@ body.search-overlay::before { opacity: 0; margin: 0 auto; transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out; + pointer-events: none; .input-group { box-shadow: 0 4px 6px rgba(0, 0, 0, 0.4); + border-radius: 5px; } - - &.not-shown { - display: block; /* Keep block but hidden with opacity and transform */ - opacity: 0; - transform: translateX(-50%) translateY(-20px); /* Hide by moving up */ - } -} - -body.search-overlay .global-search { - opacity: 1; - transform: translateX(-50%) translateY(0); /* Slide to original position */ } .global-search-results { z-index: 20; width: 100%; margin: 15px 0 0; - background: #f9f9f9; + background: #fff; padding: 15px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.4); border-radius: 8px; - opacity: 0; - transform: translateY(-10px); - transition: transform 0.2s ease-in-out, opacity 0.2s ease-in-out; - - body.search-overlay & { - opacity: 1; - transform: translateY(0); - } + max-height: calc(100vh - 210px); + overflow-y: auto; /* Enable vertical scrolling */ + overflow-x: hidden; /* Disable horizontal scrolling (optional) */ } diff --git a/src/Query/SearchPlayers.php b/src/Query/SearchPlayers.php index 39a3497..40358b4 100644 --- a/src/Query/SearchPlayers.php +++ b/src/Query/SearchPlayers.php @@ -26,20 +26,19 @@ public function fulltext(string $search, null|int $limit = null): array country AS player_country, code AS player_code, CASE - WHEN LOWER(name) = LOWER(:searchQuery) OR LOWER(code) = LOWER(:searchQuery) THEN 5 -- Exact match with diacritics - WHEN LOWER(unaccent(name)) = LOWER(unaccent(:searchQuery)) OR LOWER(unaccent(code)) = LOWER(unaccent(:searchQuery)) THEN 4 -- Exact match without diacritics - WHEN LOWER(name) LIKE LOWER(:searchEndLikeQuery) OR LOWER(name) LIKE LOWER(:searchStartLikeQuery) OR LOWER(code) LIKE LOWER(:searchEndLikeQuery) OR LOWER(code) LIKE LOWER(:searchStartLikeQuery) THEN 3 -- Starts or ends with the query with diacritics - WHEN LOWER(unaccent(name)) LIKE LOWER(unaccent(:searchEndLikeQuery)) OR LOWER(unaccent(name)) LIKE LOWER(unaccent(:searchStartLikeQuery)) OR LOWER(unaccent(code)) LIKE LOWER(unaccent(:searchEndLikeQuery)) OR LOWER(unaccent(code)) LIKE LOWER(unaccent(:searchStartLikeQuery)) THEN 2 -- Starts or ends with the query without diacritics - WHEN LOWER(name) LIKE LOWER(:searchFullLikeQuery) OR LOWER(code) LIKE LOWER(:searchFullLikeQuery) THEN 1 -- Partial match with diacritics - ELSE 0 -- Partial match without diacritics or any other case + WHEN LOWER(code) = LOWER(:searchQuery) THEN 6 -- Exact match on code with diacritics + WHEN LOWER(name) = LOWER(:searchQuery) THEN 5 -- Exact match on name with diacritics + WHEN LOWER(unaccent(code)) = LOWER(unaccent(:searchQuery)) THEN 4 -- Exact match on code without diacritics + WHEN LOWER(unaccent(name)) = LOWER(unaccent(:searchQuery)) THEN 3 -- Exact match on name without diacritics + WHEN LOWER(code) LIKE LOWER(:searchFullLikeQuery) THEN 3 -- Partial match on code with diacritics + WHEN LOWER(name) LIKE LOWER(:searchFullLikeQuery) THEN 2 -- Partial match on name with diacritics + WHEN LOWER(unaccent(code)) LIKE LOWER(unaccent(:searchFullLikeQuery)) THEN 2 -- Partial match on code without diacritics + WHEN LOWER(unaccent(name)) LIKE LOWER(unaccent(:searchFullLikeQuery)) THEN 1 -- Partial match on name without diacritics + ELSE 0 -- Other cases END as match_score FROM player WHERE LOWER(name) LIKE LOWER(:searchFullLikeQuery) OR LOWER(code) LIKE LOWER(:searchFullLikeQuery) OR LOWER(unaccent(name)) LIKE LOWER(unaccent(:searchFullLikeQuery)) OR LOWER(unaccent(code)) LIKE LOWER(unaccent(:searchFullLikeQuery)) - OR LOWER(name) = LOWER(:searchQuery) OR LOWER(code) = LOWER(:searchQuery) - OR LOWER(unaccent(name)) = LOWER(unaccent(:searchQuery)) OR LOWER(unaccent(code)) = LOWER(unaccent(:searchQuery)) - OR LOWER(name) LIKE LOWER(:searchEndLikeQuery) OR LOWER(name) LIKE LOWER(:searchStartLikeQuery) OR LOWER(code) LIKE LOWER(:searchEndLikeQuery) OR LOWER(code) LIKE LOWER(:searchStartLikeQuery) - OR LOWER(unaccent(name)) LIKE LOWER(unaccent(:searchEndLikeQuery)) OR LOWER(unaccent(name)) LIKE LOWER(unaccent(:searchStartLikeQuery)) OR LOWER(unaccent(code)) LIKE LOWER(unaccent(:searchEndLikeQuery)) OR LOWER(unaccent(code)) LIKE LOWER(unaccent(:searchStartLikeQuery)) ORDER BY match_score DESC SQL; diff --git a/src/Query/SearchPuzzle.php b/src/Query/SearchPuzzle.php index e539fdd..a3dea90 100644 --- a/src/Query/SearchPuzzle.php +++ b/src/Query/SearchPuzzle.php @@ -54,9 +54,6 @@ public function countByUserInput( $count = $this->database ->executeQuery($query, [ - 'searchQuery' => $search, - 'searchStartLikeQuery' => "%$search", - 'searchEndLikeQuery' => "$search%", 'searchFullLikeQuery' => "%$search%", 'brandId' => $brandId, 'minPieces' => $pieces->minPieces(), diff --git a/templates/base.html.twig b/templates/base.html.twig index 5d2a19a..6513720 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -101,10 +101,11 @@ @@ -187,7 +188,7 @@
{% if logged_user.profile and logged_user.profile.isAdmin %} -