awaketurbulence commited on
Commit
004b4f0
1 Parent(s): 900e2e7

add search functionality

Browse files

- adds a search bar to the Spaces component, allowing users to filter spaces by title or author name.
- search is case-insensitive and updates in real-time as the user types.
- switched from useUpdateEffect to useEffect for managing router updates based on sort changes.

Files changed (1) hide show
  1. components/spaces/index.tsx +23 -7
components/spaces/index.tsx CHANGED
@@ -1,13 +1,11 @@
1
  "use client";
2
  import { useEffect, useState } from "react";
3
- import { useLocalStorage, useUpdateEffect } from "react-use";
4
  import { useRouter } from "next/navigation";
5
  import { useTheme } from "next-themes";
6
  import { MdDarkMode, MdLightMode } from "react-icons/md";
7
 
8
  import { SpaceProps } from "@/utils/type";
9
  import { SpaceIcon } from "@/components/space_icon";
10
-
11
  import { Space } from "@/components/spaces/space";
12
  import { Sort } from "@/components/sort";
13
 
@@ -18,10 +16,12 @@ export const Spaces: React.FC<{ spaces: SpaceProps[] }> = ({ spaces }) => {
18
  const [selectedGpu, setSelectedGpu] = useState<string | undefined>(undefined);
19
  const router = useRouter();
20
  const [sort, setSort] = useState<"likes" | "createdAt">("likes");
 
21
 
22
- useUpdateEffect(() => {
23
  router.push("/?sort=" + sort);
24
- }, [sort]);
 
25
 
26
  const handleSelectGpu = (gpu: string) => {
27
  if (selectedGpu === gpu) {
@@ -31,6 +31,13 @@ export const Spaces: React.FC<{ spaces: SpaceProps[] }> = ({ spaces }) => {
31
  setSelectedGpu(gpu);
32
  };
33
 
 
 
 
 
 
 
 
34
  return (
35
  <section className="flex h-screen overflow-auto">
36
  <div className="w-full container px-6 py-10 lg:py-20 mx-auto space-y-10 lg:space-y-14">
@@ -51,7 +58,7 @@ export const Spaces: React.FC<{ spaces: SpaceProps[] }> = ({ spaces }) => {
51
  </button>
52
  <div className="font-regular text-xs text-center max-w-max rounded-full border-gray-200 bg-gray-50 border text-gray-700 dark:text-slate-400 dark:bg-slate-900 dark:border-slate-800 px-3 py-2 transition-all duration-300">
53
  <SpaceIcon className="inline-block w-4 h-4 mr-2 drop-shadow-lg" />
54
- Browse {spaces.length} spaces
55
  </div>
56
  </div>
57
  <h1 className="font-extrabold text-3xl text-black dark:text-slate-100">
@@ -63,8 +70,17 @@ export const Spaces: React.FC<{ spaces: SpaceProps[] }> = ({ spaces }) => {
63
  </div>
64
  <Sort value={sort} onChange={setSort} />
65
  </header>
 
 
 
 
 
 
 
 
 
66
  <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4 pb-10">
67
- {spaces?.map((space: SpaceProps) => (
68
  <Space
69
  key={space.id}
70
  space={space}
@@ -76,4 +92,4 @@ export const Spaces: React.FC<{ spaces: SpaceProps[] }> = ({ spaces }) => {
76
  </div>
77
  </section>
78
  );
79
- };
 
1
  "use client";
2
  import { useEffect, useState } from "react";
 
3
  import { useRouter } from "next/navigation";
4
  import { useTheme } from "next-themes";
5
  import { MdDarkMode, MdLightMode } from "react-icons/md";
6
 
7
  import { SpaceProps } from "@/utils/type";
8
  import { SpaceIcon } from "@/components/space_icon";
 
9
  import { Space } from "@/components/spaces/space";
10
  import { Sort } from "@/components/sort";
11
 
 
16
  const [selectedGpu, setSelectedGpu] = useState<string | undefined>(undefined);
17
  const router = useRouter();
18
  const [sort, setSort] = useState<"likes" | "createdAt">("likes");
19
+ const [searchQuery, setSearchQuery] = useState<string>("");
20
 
21
+ useEffect(() => {
22
  router.push("/?sort=" + sort);
23
+ }, [sort, router]);
24
+
25
 
26
  const handleSelectGpu = (gpu: string) => {
27
  if (selectedGpu === gpu) {
 
31
  setSelectedGpu(gpu);
32
  };
33
 
34
+ const filteredSpaces = searchQuery
35
+ ? spaces.filter(space =>
36
+ space.title?.toLowerCase().includes(searchQuery.trim().toLowerCase()) ||
37
+ space.authorData?.name?.toLowerCase().includes(searchQuery.trim().toLowerCase())
38
+ )
39
+ : spaces;
40
+
41
  return (
42
  <section className="flex h-screen overflow-auto">
43
  <div className="w-full container px-6 py-10 lg:py-20 mx-auto space-y-10 lg:space-y-14">
 
58
  </button>
59
  <div className="font-regular text-xs text-center max-w-max rounded-full border-gray-200 bg-gray-50 border text-gray-700 dark:text-slate-400 dark:bg-slate-900 dark:border-slate-800 px-3 py-2 transition-all duration-300">
60
  <SpaceIcon className="inline-block w-4 h-4 mr-2 drop-shadow-lg" />
61
+ Browse {filteredSpaces.length} spaces
62
  </div>
63
  </div>
64
  <h1 className="font-extrabold text-3xl text-black dark:text-slate-100">
 
70
  </div>
71
  <Sort value={sort} onChange={setSort} />
72
  </header>
73
+ <div className="flex items-center justify-between mb-4">
74
+ <input
75
+ type="text"
76
+ placeholder="Search spaces..."
77
+ className="w-full rounded-md border border-gray-300 dark:border-slate-700 bg-white dark:bg-slate-800 text-gray-700 dark:text-slate-200 px-4 py-2 focus:outline-none focus:ring-2 focus:ring-purple-600 dark:focus:ring-purple-400"
78
+ value={searchQuery}
79
+ onChange={(e) => setSearchQuery(e.target.value)}
80
+ />
81
+ </div>
82
  <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4 pb-10">
83
+ {filteredSpaces?.map((space: SpaceProps) => (
84
  <Space
85
  key={space.id}
86
  space={space}
 
92
  </div>
93
  </section>
94
  );
95
+ };