Skip to content

Instantly share code, notes, and snippets.

@thedivtagguy
Last active Jun 22, 2021
Embed
What would you like to do?
import algoliasearch from "algoliasearch/lite"
import {
InstantSearch,
Hits,
Highlight,
connectStateResults,
SearchBox,
RefinementList,
PoweredBy,
ClearRefinements,
MenuSelect,
} from "react-instantsearch-dom"
import React, { useState } from "react"
import PropTypes from "prop-types"
import { graphql, Link } from "gatsby"
import qs from "qs"
const DEBOUNCE_TIME = 400
const searchClient = algoliasearch(
process.env.GATSBY_ALGOLIA_APP_ID,
process.env.GATSBY_ALGOLIA_SEARCH_KEY
)
const createURL = state => `?${qs.stringify(state)}`
const searchStateToUrl = ({ location }, searchState) =>
searchState ? `${location.pathname}${createURL(searchState)}` : ""
const urlToSearchState = ({ search }) => qs.parse(search.slice(1))
//Search Grid
const SearchGrid = ({ location, history }) => {
const [searchState, setSearchState] = useState(urlToSearchState(location))
const [debouncedSetState, setDebouncedSetState] = useState(null)
const onSearchStateChange = updatedSearchState => {
clearTimeout(debouncedSetState)
setDebouncedSetState(
setTimeout(() => {
history.pushState(
updatedSearchState,
null,
searchStateToUrl(updatedSearchState)
)
}, DEBOUNCE_TIME)
)
setSearchState(updatedSearchState)
}
return (
<div className="bg-gray-900 pattern ">
<div class="sticky top-0 ">
<InstantSearch
searchClient={searchClient}
indexName="archives"
searchState={searchState}
onSearchStateChange={onSearchStateChange}
createURL={createURL}
>
<div class="flex sticky top-0 pt-4">
<div class="bg-gray-800 border-r-4 border-saffron sticky top-0 pl-4 w-64 pb-6 hidden md:block">
<div class="sticky top-0 pt-8">
<div class="py-2 mt-4 w-1/2 flex justify-start items-center mx-4">
<ClearRefinements />
</div>
<div class="text-mint-cream mb-2 mt-3 px-4 flex justify-between">
<div class="flex-auto">
<h1 class="font-semibold text-lime text-sm leading-tight mb-1 truncate">
Major
</h1>
</div>
</div>
<div class="mb-2">
<div class="px-4 mb-2 text-black text-sm font-semibold flex justify-between items-center">
<MenuSelect attribute="major"></MenuSelect>
</div>
<div class="px-4 pt-2">
<h1 class="font-semibold text-lime text-sm leading-tight mb-1 truncate">
Year
</h1>
</div>
<div class="bg-teal-dark py-1 px-4 text-white">
<RefinementList attribute="year" className="yearlist" />
</div>
</div>
<div class="px-4 pt-2">
<h1 class="font-semibold text-lime text-sm leading-tight mb-1 truncate">
Tools
</h1>
</div>
<div>
<div class="mb-2 text-white flex justify-between items-center">
<div class="bg-teal-dark py-1 px-4 overflow-auto text-white">
<RefinementList
placeholder="Tools"
limit={5}
showMore
attribute="tools"
className="yearlist"
/>
</div>
</div>
</div>
</div>
</div>
<div class="w-full">
<div class="h-full ">
<div className="container">
<div class="flex-row flex py-2 sticky top-0 mt-3">
<div class="flex-1 ">
<SearchBox
className="search"
translations={{
placeholder: "Start Typing...",
}}
/>
</div>
<div
id="power"
class="px-4 flex-grow-0 lg:block md:block hidden bg-mint-cream shadow-orange"
>
<PoweredBy />
</div>
</div>
<div>
<Results>
<div class="py-8">
<Hits hitComponent={Hit} />
<div
id="mobile-alg"
class="lg:hidden md:hidden mx-auto flex justify-center items-center"
>
<PoweredBy />
</div>
</div>
</Results>
</div>
</div>
</div>
</div>
</div>
</InstantSearch>
</div>
</div>
)
}
function Hit(props) {
const items = props.hit.tools.slice(0, 2)
return (
<div class="h">
<Link to={`/${props.hit.slug}`}>
<div className="bg-gray-800 border-b-2 border-high-yellow h-full rounded-xl overflow-hidden group">
<div className="group-hover:opacity-75 transition duration-150 ease-in-out"></div>
<div className="p-4 h-54 sm:p-5">
<p class="uppercase px-4 tracking-wide text-sm font-bold text-lime">
{" "}
<Highlight attribute="major" hit={props.hit} />
</p>
<h1 className="text-xl px-4 text-mint-cream font-bold">
{" "}
<Highlight attribute="name" hit={props.hit} />
</h1>
<p className="text-mint-cream px-4 h-28 line-clamp-4 pt-2 text-sm hidden">
{
<Highlight
attribute="description.description"
hit={props.hit}
/>
}
</p>
</div>
<div class="flex p-4 border-t border-gray-900 text-gray-600">
<div class="flex-1 pl-4 inline-flex items-center">
<p class="text-xs text-lime font-semibold pr-1">
<Highlight attribute="year" hit={props.hit} />
</p>
</div>
<div class="flex-1 pr-4 inline-flex items-center">
{items.map((tag, i) => [
<p class="text-xs whitespace-normal pl-1" key={i}>
<span class="text-lime font-semibold">{tag}</span>
{i < items.length - 1 ? ", " : ""}
</p>,
])}
</div>
</div>
<div class="px-4 pt-3 pb-4 border-t border-gray-900 bg-gray-700">
<div class="flex items-center">
<div>
<p class="font-bold px-4 text-md text-gray-300">
{" "}
<Highlight attribute="author" hit={props.hit} />
</p>
</div>
</div>
</div>
</div>
</Link>
</div>
)
}
Hit.propTypes = {
hit: PropTypes.object.isRequired,
}
//Error Handling
const Results = connectStateResults(
({ searchState, searchResults, children }) =>
searchResults && searchResults.nbHits !== 0 ? (
children
) : (
<div class="mx-auto flex justify-center items-center flex-col">
{" "}
<h1 class="text-4xl py-8 font-bold uppercase w-1/2 text-lime text-center">
I literally don't know what you mean by {searchState.query}. <br></br>{" "}
<span class="text-xs">you good my dude?</span>
</h1>
<img
src="https://media.giphy.com/media/ghuvaCOI6GOoTX0RmH/giphy.gif"
alt="Not Found"
></img>
</div>
)
)
export default SearchGrid
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment