Skip to content

Commit

Permalink
feat: implement super basic prototype of autocomplete with Server Act…
Browse files Browse the repository at this point in the history
…ions
  • Loading branch information
bmstefanski committed Feb 20, 2024
1 parent 193f9da commit c4e95fb
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 6 deletions.
45 changes: 45 additions & 0 deletions apps/web/components/ui/Autocomplete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use client"

import Link from "next/link"
import { useRouter } from "next/navigation"
import { useState } from "react"

export default function Autocomplete({ searchProducts }: any) {
const [results, setResults] = useState<any>(null)
const [query, setQuery] = useState("")
const router = useRouter()

return (
<div className="relative flex flex-col">
<input
type="text"
className="bg-red-400"
placeholder="Search your products..."
onChange={async (e) => {
const query = e.target.value
setQuery(query)
setResults(await searchProducts(query))
}}
onKeyDown={(e) => {
if (e.key === "Enter") {
router.push(`/search?q=${query}`)
}
}}
/>

{results?.hits ? (
<div id="dropdownNavbar" className="absolute top-10 z-50 w-[300px] divide-y divide-gray-100 rounded-lg bg-white font-normal shadow">
<ul className="py-2 text-sm text-gray-700">
{results?.hits?.map((singleResult) => (
<li key={singleResult.id}>
<Link href={`/products/${singleResult.handle}`} className="block px-4 py-2 hover:bg-gray-100">
{singleResult?.title}
</Link>
</li>
))}
</ul>
</div>
) : null}
</div>
)
}
14 changes: 9 additions & 5 deletions apps/web/components/ui/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import { meilisearch } from "client/meilisearch"
import { storefrontClient } from "client/storefrontClient"
import { env } from "env.mjs"
import { unstable_cache } from "next/cache"
import Link from "next/link"
import { Input } from "./Input"
import Autocomplete from "./Autocomplete"

export async function Header() {
const items = await getCachedMenuItems()

async function searchProducts(query: string) {
"use server"

return (await meilisearch?.getIndex("products"))?.search(query, { limit: 5 })
}

return (
<header className="container mx-auto flex h-14 items-center justify-center px-4 lg:px-6">
<Link className="flex items-center justify-center" href="/">
<MountainIcon className="size-6" />
<span className="sr-only">Acme Inc</span>
</Link>
<nav className="ml-auto flex items-center gap-4 sm:gap-6">
<div className="relative ml-4 w-64">
<SearchIcon className="absolute left-2.5 top-2.5 size-4 text-gray-500" />
<Input className="w-full appearance-none bg-white pl-8 shadow-none" placeholder="Search products..." type="search" />
</div>
<Autocomplete searchProducts={searchProducts} />
{items.map((singleItem) => (
<Link key={singleItem.url} className="text-sm font-medium underline-offset-4 hover:underline" href={singleItem.url}>
{singleItem.title}
Expand Down
1 change: 0 additions & 1 deletion apps/web/views/Search/SearchView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export async function SearchView({ searchParams }: { searchParams: Record<string
page: parsedSearchParams.page,
})

console.log(meilisearchResults)
const hits = meilisearchResults.hits

const totalPages = meilisearchResults.totalPages
Expand Down

0 comments on commit c4e95fb

Please sign in to comment.