Skip to content

feat: add global search and dedicated search page#119

Open
it-education-md wants to merge 1 commit intoentrius:testfrom
it-education-md:feat/search-ui
Open

feat: add global search and dedicated search page#119
it-education-md wants to merge 1 commit intoentrius:testfrom
it-education-md:feat/search-ui

Conversation

@it-education-md
Copy link
Copy Markdown

Summary

This PR adds a unified search experience across the website.

It primarily focuses on functional improvement while also keeping the search UI visually aligned with the rest of the website.

  • a global search bar for quick lookup from the main website layout
  • a dedicated /search page for full-result exploration
  • grouped search results across miners, repositories, pull requests, and issues
  • direct navigation from search results into the correct detail pages
  • URL-backed search state for query, tab, page, and rows

The main value here is simple: users should be able to find the item they want directly, without first knowing where it lives.

Type of Change

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • Other (describe below)

Checklist

  • New components are modularized/separated where sensible
  • Uses predefined theme (e.g. no hardcoded colors)
  • Responsive/mobile checked
  • Tested against the test API
  • npm run format and npm run lint:fix have been run
  • npm run build passes
  • Screenshots included for any UI/visual changes

Why This Matters

Today, discovery is fragmented across multiple sections of the website. That makes navigation slower than it should be, especially for users who already know the miner, repository, PR, or issue they want.

New search removes that friction by introducing a single, reliable entry point for finding known entities and moving directly to the right destination.

This matters even more in a data-heavy website. As the volume of miners, repositories, pull requests, and issues grows over time, navigation by browsing alone becomes less efficient.

This makes the website feel:

  • faster to navigate
  • easier to understand
  • more complete
  • more aligned with real user workflows

Approach

1. Search Data Flow

The current search implementation is frontend-driven and intentionally lightweight.

  • search reads from the existing React Query cache first and only fetches datasets when cached data is missing
  • data fetching starts on search interaction for quick search and on page load for the full search page
  • a minimum query length avoids noisy matches and unnecessary filtering work
  • quick search limits visible results per entity type, while full search paginates rendered rows for larger result sets
  • search table data is derived into UI-friendly shapes before rendering
  • results rank exact matches first, then prefix matches, then substring matches; ties are resolved by entity-specific signals such as score, recency, or weight

This keeps the current implementation simple and consistent. If search scope or data volume grows materially, the next step would likely be a backend search endpoint rather than more frontend complexity.

2. Search UI/UX

The search experience is intentionally scoped around fast navigation and lightweight comparison.

  • the global search bar is currently enabled on the home, dashboard, and issues pages, where it adds value without duplicating more focused page-specific search UI
  • global quick search uses a grouped dropdown with limited results per entity type
  • the dedicated search page uses tabs so each result type stays easy to scan
  • long values stay truncated in-table and expand through tooltips when needed
  • search state stays in the URL so users can revisit or share the same search context
  • each search table shows only the minimum metadata needed before opening a detail page

The table fields:

  • miners: rank, miner, tier, credibility, token score, PRs, score
  • repositories: rank, repository, weight, total score, PRs, contributors
  • pull requests: PR number, title, repository, +/-, score, date or status
  • issues: issue number, repository, issue, status

This keeps search useful as a discovery layer without turning it into a heavier analysis surface.

3. Implementation

The implementation is intentionally split into a few clear responsibilities.

  • src/pages/search/searchData.ts owns shared search data loading, normalization, matching, ranking, and table-derived data
  • src/components/layout/GlobalSearchBar.tsx owns the quick-search dropdown experience and direct result navigation
  • src/pages/search/SearchPage.tsx owns full-search state, URL synchronization, tab selection, and pagination
  • the tab components under src/pages/search/ own entity-specific table rendering for miners, repositories, pull requests, and issues
  • src/pages/search/styles.ts centralizes the shared search-table styling so the tab UIs stay aligned without duplicating presentation logic

This keeps the feature easier to reason about by separating shared search behavior from surface-specific rendering.

Notes

  • quick search and full search share the same core ranking behavior
  • quick vs full modes differ in searchable fields and result volume, not in the overall search model
  • search data is normalized before rendering so backend naming differences do not leak into the UI
  • the shared back button is intentionally simplified to always show Back to avoid extra UI friction as search adds more navigation paths, while navigation state still preserves return paths when history is unavailable

Screenshots

image image image image image image image image image

Copy link
Copy Markdown
Collaborator

@anderdc anderdc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the outcome of this PR, however there is fair amount of cleanup/abstraction that can be done

case 'registered':
return {
color: STATUS_COLORS.warning,
bgColor: 'rgba(245, 158, 11, 0.15)',
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want any hardcoded colors introduced. Please use the theme or perhaps add new colors to the theme (if absolutely necessary)

@@ -0,0 +1,60 @@
import { type Theme } from '@mui/material/styles';

export const headerCellSx = (theme: Theme) => ({
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I like the organization, this file doesn't follow our current pattern of styling. Please leverage the theme or add in-line sx props to components. Then remove this file

Copy link
Copy Markdown
Author

@it-education-md it-education-md Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file contains shared sx props used for tables in multiple tabs component so it removes code duplication.

rowsPerPage,
rowsPerPageOptions,
}) => (
<Card elevation={0} sx={tableCardSx}>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these __Tab components follow the same pattern. I believe we can abstract out the core and other reused code to a 'base' component. Then all the tab components can just be child classes of the base component. You should be thinking in terms of OOP/component composition when there is a lot of reused code.

There is no way I'll accept the PR if this is not solved/cleaned up

@anderdc
Copy link
Copy Markdown
Collaborator

anderdc commented Mar 30, 2026

Also there is a fair portion of searchData.ts that should just have been added somewhere in the api/ folder

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants