-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from RicardoGEsteves/search-bar
feat: ✨ Type: Enhancement | Title: Adding Search Bar Functionality
- Loading branch information
Showing
11 changed files
with
778 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { db } from "@/lib/db"; | ||
|
||
export async function GET(req: Request) { | ||
const url = new URL(req.url); | ||
const q = url.searchParams.get("q"); | ||
|
||
if (!q) return new Response("Invalid query", { status: 400 }); | ||
|
||
const results = await db.subSpreadIt.findMany({ | ||
where: { | ||
name: { | ||
startsWith: q, | ||
}, | ||
}, | ||
include: { | ||
_count: true, | ||
}, | ||
take: 5, | ||
}); | ||
|
||
return new Response(JSON.stringify(results)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
"use client"; | ||
|
||
import { useCallback, useEffect, useRef, useState } from "react"; | ||
import { usePathname, useRouter } from "next/navigation"; | ||
import debounce from "lodash.debounce"; | ||
import { useQuery } from "@tanstack/react-query"; | ||
import axios from "axios"; | ||
import { Prisma, SubSpreadIt } from "@prisma/client"; | ||
import { Users } from "lucide-react"; | ||
|
||
import { useOnClickOutside } from "@/hooks/use-on-click-outside"; | ||
import { | ||
Command, | ||
CommandEmpty, | ||
CommandGroup, | ||
CommandInput, | ||
CommandItem, | ||
CommandList, | ||
} from "../ui/command"; | ||
|
||
const SearchBar = () => { | ||
const [input, setInput] = useState<string>(""); | ||
const pathname = usePathname(); | ||
const commandRef = useRef<HTMLDivElement>(null); | ||
const router = useRouter(); | ||
|
||
useOnClickOutside(commandRef, () => { | ||
setInput(""); | ||
}); | ||
|
||
const request = debounce(async () => { | ||
refetch(); | ||
}, 300); | ||
|
||
const debounceRequest = useCallback(() => { | ||
request(); | ||
|
||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, []); | ||
|
||
const { | ||
isFetching, | ||
data: queryResults, | ||
refetch, | ||
isFetched, | ||
} = useQuery({ | ||
queryFn: async () => { | ||
if (!input) return []; | ||
const { data } = await axios.get(`/api/search?q=${input}`); | ||
return data as (SubSpreadIt & { | ||
_count: Prisma.SubSpreadItCountOutputType; | ||
})[]; | ||
}, | ||
queryKey: ["search-query"], | ||
enabled: false, | ||
}); | ||
|
||
useEffect(() => { | ||
setInput(""); | ||
}, [pathname]); | ||
|
||
return ( | ||
<Command | ||
ref={commandRef} | ||
className="relative rounded-lg border max-w-lg z-50 overflow-visible" | ||
> | ||
<CommandInput | ||
// isLoading={isFetching} | ||
onValueChange={(text) => { | ||
setInput(text); | ||
debounceRequest(); | ||
}} | ||
value={input} | ||
className="outline-none border-none focus:border-none focus:outline-none ring-0" | ||
placeholder="Search communities & SpreadIt..." | ||
/> | ||
|
||
{input.length > 0 && ( | ||
<CommandList className="absolute bg-background top-full inset-x-0 shadow rounded-b-md"> | ||
{isFetched && ( | ||
<CommandEmpty> | ||
<span className="text-muted-foreground">No results found.</span> | ||
</CommandEmpty> | ||
)} | ||
{(queryResults?.length ?? 0) > 0 ? ( | ||
<CommandGroup heading="Communities"> | ||
{queryResults?.map((subSpreadIt) => ( | ||
<CommandItem | ||
onSelect={(e) => { | ||
router.push(`/r/${e}`); | ||
router.refresh(); | ||
}} | ||
key={subSpreadIt.id} | ||
value={subSpreadIt.name} | ||
className="text-muted-foreground aria-selected:text-emerald-500" | ||
> | ||
<Users className="mr-2 h-4 w-4" /> | ||
<a href={`/r/${subSpreadIt.name}`}>r/{subSpreadIt.name}</a> | ||
</CommandItem> | ||
))} | ||
</CommandGroup> | ||
) : null} | ||
</CommandList> | ||
)} | ||
</Command> | ||
); | ||
}; | ||
|
||
export default SearchBar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
"use client"; | ||
|
||
import { ChevronLeft } from "lucide-react"; | ||
import { usePathname } from "next/navigation"; | ||
|
||
import { buttonVariants } from "./ui/button"; | ||
import { cn } from "@/lib/utils"; | ||
|
||
const ToFeedButton = () => { | ||
const pathname = usePathname(); | ||
|
||
// if path is /r/mycom, turn into / | ||
// if path is /r/mycom/post/cligad6jf0003uhest4qqkeco, turn into /r/mycom | ||
|
||
const subSpreadItPath = getSubSpreadItPath(pathname); | ||
|
||
return ( | ||
<a | ||
href={subSpreadItPath} | ||
className={cn( | ||
buttonVariants({ variant: "ghost" }), | ||
"text-emerald-500 hover:text-emerald-600" | ||
)} | ||
> | ||
<ChevronLeft className="h-4 w-4 mr-1" /> | ||
{subSpreadItPath === "/" ? "Back home" : "Back to community"} | ||
</a> | ||
); | ||
}; | ||
|
||
const getSubSpreadItPath = (pathname: string) => { | ||
const splitPath = pathname.split("/"); | ||
|
||
if (splitPath.length === 3) return "/"; | ||
else if (splitPath.length > 3) return `/${splitPath[1]}/${splitPath[2]}`; | ||
// default path, in case pathname does not match expected format | ||
else return "/"; | ||
}; | ||
|
||
export default ToFeedButton; |
Oops, something went wrong.