feat(search): conditionally hide SearchBar on non-searchable routes
All checks were successful
Deploy Flowstate to VPS / deploy (push) Successful in 47s
All checks were successful
Deploy Flowstate to VPS / deploy (push) Successful in 47s
This commit is contained in:
parent
07d80a2674
commit
c33fcb9f91
1 changed files with 30 additions and 4 deletions
|
|
@ -6,9 +6,11 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect, useTransition } from "react";
|
import { useState, useEffect, useTransition } from "react";
|
||||||
import { useRouter, useSearchParams } from "next/navigation";
|
import { useRouter, usePathname, useSearchParams } from "next/navigation";
|
||||||
import { Search, X } from "lucide-react";
|
import { Search, X } from "lucide-react";
|
||||||
|
|
||||||
|
const SEARCHABLE_ROUTES = ["/dashboard", "/trash"];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Properties for the SearchBar component.
|
* Properties for the SearchBar component.
|
||||||
*
|
*
|
||||||
|
|
@ -27,7 +29,7 @@ interface SearchBarProps {
|
||||||
* Renders a debounced search bar input that syncs its local state with the URL's "search" query parameter.
|
* Renders a debounced search bar input that syncs its local state with the URL's "search" query parameter.
|
||||||
*
|
*
|
||||||
* @param {SearchBarProps} props - The component props.
|
* @param {SearchBarProps} props - The component props.
|
||||||
* @returns {JSX.Element} The rendered search bar component.
|
* @returns {JSX.Element | null} The rendered search bar component or null if the current route is not searchable.
|
||||||
*/
|
*/
|
||||||
export default function SearchBar({
|
export default function SearchBar({
|
||||||
placeholder = "Search...",
|
placeholder = "Search...",
|
||||||
|
|
@ -35,14 +37,27 @@ export default function SearchBar({
|
||||||
autoFocus = false,
|
autoFocus = false,
|
||||||
}: SearchBarProps) {
|
}: SearchBarProps) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const pathname = usePathname();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const searchQuery = searchParams.get("search") || "";
|
|
||||||
|
|
||||||
|
// Check whether the current route supports the search
|
||||||
|
const isSearchableRoute = SEARCHABLE_ROUTES.some(
|
||||||
|
(route) => pathname === route || pathname.startsWith(`${route}/`),
|
||||||
|
);
|
||||||
|
|
||||||
|
const searchQuery = searchParams.get("search") || "";
|
||||||
const [localValue, setLocalValue] = useState(searchQuery);
|
const [localValue, setLocalValue] = useState(searchQuery);
|
||||||
const [isPending, startTransition] = useTransition();
|
const [isPending, startTransition] = useTransition();
|
||||||
|
|
||||||
|
// Synchronize state when the path or URL changes
|
||||||
|
useEffect(() => {
|
||||||
|
setLocalValue(searchQuery);
|
||||||
|
}, [searchQuery, pathname]);
|
||||||
|
|
||||||
// Debounced URL Update
|
// Debounced URL Update
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!isSearchableRoute) return;
|
||||||
|
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
if (localValue !== searchQuery) {
|
if (localValue !== searchQuery) {
|
||||||
const params = new URLSearchParams(searchParams.toString());
|
const params = new URLSearchParams(searchParams.toString());
|
||||||
|
|
@ -59,7 +74,18 @@ export default function SearchBar({
|
||||||
}, debounceMs);
|
}, debounceMs);
|
||||||
|
|
||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}, [localValue, searchQuery, searchParams, debounceMs, router]);
|
}, [
|
||||||
|
localValue,
|
||||||
|
searchQuery,
|
||||||
|
searchParams,
|
||||||
|
debounceMs,
|
||||||
|
router,
|
||||||
|
isSearchableRoute,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!isSearchableRoute) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the local search input value to an empty string.
|
* Resets the local search input value to an empty string.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue