From 893218b3357ec742447a430342b0b46a4fcbfe54 Mon Sep 17 00:00:00 2001 From: Chew Date: Sun, 16 Aug 2026 18:15:01 -0500 Subject: [PATCH 1/2] feat: sort search page based on modal --- .../SearchResults/SearchResults.tsx | 44 +-- .../SearchResultsContainer.tsx | 292 +++++++++++------- 2 files changed, 207 insertions(+), 129 deletions(-) diff --git a/resources/js/common/components/GlobalSearch/components/SearchResults/SearchResults.tsx b/resources/js/common/components/GlobalSearch/components/SearchResults/SearchResults.tsx index 5bffd013a4..ca3289383c 100644 --- a/resources/js/common/components/GlobalSearch/components/SearchResults/SearchResults.tsx +++ b/resources/js/common/components/GlobalSearch/components/SearchResults/SearchResults.tsx @@ -24,9 +24,11 @@ type SearchResult = | App.Platform.Data.Game | App.Platform.Data.Achievement | App.Platform.Data.GameSet - | App.Platform.Data.Event; + | App.Platform.Data.Event + | App.Data.ForumTopicComment + | App.Community.Data.Comment; -interface SearchSection { +export interface SearchSection { key: string; heading: string; results: SearchResult[]; @@ -42,6 +44,25 @@ interface SearchResultsProps { onClose: () => void; } +export function sortSections(a: SearchSection, b: SearchSection) { + // If one section has significantly higher relevance (>0.3 difference), prioritize it. + const relevanceDiff = b.relevance - a.relevance; + if (Math.abs(relevanceDiff) > 0.3) { + return relevanceDiff > 0 ? 1 : -1; + } + + // Otherwise, use logical default ordering. + const defaultOrder: Record = { + games: 1, + hubs: 2, + users: 3, + events: 4, + achievements: 5, + }; + + return (defaultOrder[a.key] as number) - (defaultOrder[b.key] as number); +} + export const SearchResults: FC = ({ currentSearchMode, searchResults, @@ -216,24 +237,7 @@ export const SearchResults: FC = ({ const sectionsWithResults = sections.filter((section) => section.results.length > 0); // Use smart section ordering with fallback to logical defaults. - sectionsWithResults.sort((a, b) => { - // If one section has significantly higher relevance (>0.3 difference), prioritize it. - const relevanceDiff = b.relevance - a.relevance; - if (Math.abs(relevanceDiff) > 0.3) { - return relevanceDiff > 0 ? 1 : -1; - } - - // Otherwise, use logical default ordering. - const defaultOrder: Record = { - games: 1, - hubs: 2, - users: 3, - events: 4, - achievements: 5, - }; - - return (defaultOrder[a.key] as number) - (defaultOrder[b.key] as number); - }); + sectionsWithResults.sort(sortSections); const maxResultsSize = 10; diff --git a/resources/js/features/search/components/SearchResultsContainer/SearchResultsContainer.tsx b/resources/js/features/search/components/SearchResultsContainer/SearchResultsContainer.tsx index ee6fef71b6..c2b730a321 100644 --- a/resources/js/features/search/components/SearchResultsContainer/SearchResultsContainer.tsx +++ b/resources/js/features/search/components/SearchResultsContainer/SearchResultsContainer.tsx @@ -5,6 +5,7 @@ import { ImTrophy } from 'react-icons/im'; import { LuCalendar, LuMessageSquare, LuNetwork, LuUsers } from 'react-icons/lu'; import { route } from 'ziggy-js'; +import { SearchSection, sortSections } from '@/common/components/GlobalSearch/components/SearchResults'; import { AchievementResultDisplay } from '@/common/components/GlobalSearch/components/SearchResults/AchievementResultDisplay'; import { EventResultDisplay } from '@/common/components/GlobalSearch/components/SearchResults/EventResultDisplay'; import { GameResultDisplay } from '@/common/components/GlobalSearch/components/SearchResults/GameResultDisplay'; @@ -91,6 +92,179 @@ export const SearchResultsContainer: FC = ({ return null; } + const sections: SearchSection[] = [ + { + key: 'users', + heading: t('Users'), + results: searchResults.results.users || [], + relevance: searchResults.scopeRelevance.users || 0, + limit: 3, + icon: LuUsers, + + render: (user) => { + const safeUser = user as App.Data.User; + + return ( + + + + ); + }, + }, + + { + key: 'games', + heading: t('Games'), + results: searchResults.results.games || [], + relevance: searchResults.scopeRelevance.games || 0, + limit: 6, + icon: FaGamepad, + + render: (game) => { + const safeGame = game as App.Platform.Data.Game; + + return ( + + + + ); + }, + }, + + { + key: 'hubs', + heading: t('Hubs'), + results: searchResults.results.hubs || [], + relevance: searchResults.scopeRelevance.hubs || 0, + limit: 4, + icon: LuNetwork, + + render: (hub) => { + const safeHub = hub as App.Platform.Data.GameSet + + return ( + + + + ); + }, + }, + + { + key: 'achievements', + heading: t('Achievements'), + results: searchResults.results.achievements || [], + relevance: searchResults.scopeRelevance.achievements || 0, + limit: 3, + icon: ImTrophy, + + render: (achievement) => { + const safeAchievement = achievement as App.Platform.Data.Achievement + + return ( + + + + ); + }, + }, + + { + key: 'events', + heading: t('Events'), + results: searchResults.results.events || [], + relevance: searchResults.scopeRelevance.events || 0, + limit: 4, + icon: LuCalendar, + + render: (event) => { + const safeEvent = event as App.Platform.Data.Event + + return ( + + + + ); + }, + }, + + { + key: 'forum-comments', + heading: t('Forum Posts'), + results: searchResults.results.forum_comments || [], + relevance: searchResults.scopeRelevance.forum_comments || 0, + limit: 4, + icon: LuMessageSquare, + + render: (forumComment) => { + const safeComment = forumComment as App.Data.ForumTopicComment + + return ( + + + + ) + } + }, + + { + key: 'comments', + heading: t('Comments'), + results: searchResults.results.comments || [], + relevance: searchResults.scopeRelevance.comments || 0, + limit: 4, + icon: LuMessageSquare, + + render: (comment) => { + const safeComment = comment as App.Community.Data.Comment + + return ( + + + + ) + } + } + ]; + + const sectionsWithResults = sections.filter((section) => section.results.length > 0); + + // Use smart section ordering with fallback to logical defaults. + sectionsWithResults.sort(sortSections); + return (
= ({ 'light:border-neutral-200 light:bg-white', )} > - {/* Users */} - {searchResults.results.users?.length ? ( - }> - {searchResults.results.users.map((user) => ( - - - - ))} - - ) : null} - - {/* Games */} - {searchResults.results.games?.length ? ( - }> - {searchResults.results.games.map((game) => ( - - - - ))} - - ) : null} - - {/* Hubs */} - {searchResults.results.hubs?.length ? ( - }> - {searchResults.results.hubs.map((hub) => ( - - - - ))} - - ) : null} - - {/* Achievements */} - {searchResults.results.achievements?.length ? ( - }> - {searchResults.results.achievements.map((achievement) => ( - - - - ))} - - ) : null} - - {/* Events */} - {searchResults.results.events?.length ? ( - }> - {searchResults.results.events.map((event) => ( - - - - ))} - - ) : null} - - {/* Forum Comments */} - {searchResults.results.forum_comments?.length ? ( - }> - {searchResults.results.forum_comments.map((comment) => ( - - - - ))} - - ) : null} - - {/* Comments */} - {searchResults.results.comments?.length ? ( - }> - {searchResults.results.comments.map((comment) => ( - - - - ))} - - ) : null} + {sectionsWithResults.map((section) => { + return ( + }> + {section.results.map((item) => + section.render(item) + )} + + ) + })}
); }; From afa6cbc9b192a4375ecd8b52ad042f3c61bf20cc Mon Sep 17 00:00:00 2001 From: Chew Date: Mon, 17 Aug 2026 15:18:37 -0500 Subject: [PATCH 2/2] fallback for missing orders, rank them last These could have technically always been an issue, but now falls back to being last. --- .../GlobalSearch/components/SearchResults/SearchResults.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/js/common/components/GlobalSearch/components/SearchResults/SearchResults.tsx b/resources/js/common/components/GlobalSearch/components/SearchResults/SearchResults.tsx index ca3289383c..0a0404c1e0 100644 --- a/resources/js/common/components/GlobalSearch/components/SearchResults/SearchResults.tsx +++ b/resources/js/common/components/GlobalSearch/components/SearchResults/SearchResults.tsx @@ -60,7 +60,7 @@ export function sortSections(a: SearchSection, b: SearchSection) { achievements: 5, }; - return (defaultOrder[a.key] as number) - (defaultOrder[b.key] as number); + return (defaultOrder[a.key] ?? 10) - (defaultOrder[b.key] ?? 10); } export const SearchResults: FC = ({