Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search bar not working #44

Open
luukee opened this issue Oct 16, 2024 · 1 comment
Open

Search bar not working #44

luukee opened this issue Oct 16, 2024 · 1 comment
Assignees
Labels
bug Something isn't working

Comments

@luukee
Copy link
Contributor

luukee commented Oct 16, 2024

For Admin & Agency user login.

Test on the dev site: https://dev-truthsleuthlocal.netlify.app. The search bar should do a dynamic (as you type) search of the reports content.

Screen.Recording.2024-10-16.at.8.49.36.AM.mp4
@Tominium Tominium self-assigned this Oct 16, 2024
@luukee
Copy link
Contributor Author

luukee commented Oct 16, 2024

1. Set up Firestore Search Functionality

Firestore does not have a full-text search capability by default. However, you can implement a basic search with queries that filter data by field values. For more advanced full-text search, you can integrate services like Algolia or ElasticSearch. In this example, I'll show how to implement a basic search based on field matching within the Firestore reports collection.

Assume your reports collection has fields like title, description, and tags.

2. Create a Firestore Query Function

First, create a function that searches the Firestore reports collection based on a search term (e.g., searching by title or description):

import { useState } from 'react'
import { db } from '../firebase' // Adjust to your Firebase config path
import { collection, query, where, getDocs } from 'firebase/firestore'

const searchReports = async (searchTerm) => {
  const q = query(
    collection(db, 'reports'),
    where('title', '>=', searchTerm), // Start searching by title
    where('title', '<=', searchTerm + '\uf8ff') // End range for search term
  )

  const querySnapshot = await getDocs(q)
  let results = []
  querySnapshot.forEach((doc) => {
    results.push({ id: doc.id, ...doc.data() })
  })
  return results
}

This function queries the reports collection, filtering by the title field using Firestore's range queries. The \uf8ff ensures it matches titles starting with the search term.

3. Create a Search Component

Now, create a SearchBar component that will allow users to type in a search query and show the results.

import { useState } from 'react'

const SearchBar = () => {
  const [searchTerm, setSearchTerm] = useState('')
  const [searchResults, setSearchResults] = useState([])

  const handleSearch = async (e) => {
    e.preventDefault()
    if (!searchTerm.trim()) return // Ignore empty searches

    const results = await searchReports(searchTerm)
    setSearchResults(results)
  }

  return (
    <div>
      <form onSubmit={handleSearch}>
        <input
          type="text"
          value={searchTerm}
          onChange={(e) => setSearchTerm(e.target.value)}
          placeholder="Search reports..."
        />
        <button type="submit">Search</button>
      </form>

      {/* Display search results */}
      <ul>
        {searchResults.map((result) => (
          <li key={result.id}>{result.title}</li>
        ))}
      </ul>
    </div>
  )
}

export default SearchBar

4. Usage in a Page Component

You can now import and use this SearchBar component in any Next.js page where you'd like to offer search functionality:

import SearchBar from '../components/SearchBar'

const ReportsPage = () => {
  return (
    <div>
      <h1>Search Reports</h1>
      <SearchBar />
    </div>
  )
}

export default ReportsPage

5. Optimizing for Larger Search

For larger datasets or if you want to search multiple fields (e.g., title, description, tags), you may want to consider using Firestore's array-contains for tags or combining multiple queries, but this can get limited with Firestore's querying capabilities.

For more advanced searching (e.g., partial matching, fuzzy search), integrating with Algolia would be ideal, as it offers robust full-text search capabilities and can index your Firestore collection.

Optional: Debouncing Search Queries

To avoid too many Firestore queries, you can implement debouncing so the query runs only after the user has stopped typing for a short period:

import { useState, useEffect } from 'react'

const SearchBar = () => {
  const [searchTerm, setSearchTerm] = useState('')
  const [debouncedSearchTerm, setDebouncedSearchTerm] = useState(searchTerm)
  const [searchResults, setSearchResults] = useState([])

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedSearchTerm(searchTerm)
    }, 300)

    return () => {
      clearTimeout(handler)
    }
  }, [searchTerm])

  useEffect(() => {
    if (debouncedSearchTerm) {
      searchReports(debouncedSearchTerm).then(setSearchResults)
    }
  }, [debouncedSearchTerm])

  return (
    <div>
      <input
        type="text"
        value={searchTerm}
        onChange={(e) => setSearchTerm(e.target.value)}
        placeholder="Search reports..."
      />
      <ul>
        {searchResults.map((result) => (
          <li key={result.id}>{result.title}</li>
        ))}
      </ul>
    </div>
  )
}

This ensures that Firestore queries are sent only after the user has paused typing for 300ms.

@luukee luukee added the bug Something isn't working label Oct 18, 2024
@luukee luukee pinned this issue Oct 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants