Skip to content

Commit a57db0f

Browse files
made subject selection on upload page to be similar in function to one on homepage
1 parent a16895f commit a57db0f

File tree

3 files changed

+142
-5
lines changed

3 files changed

+142
-5
lines changed

src/app/upload/page.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"use client";
22
import React, { useRef, useState } from "react";
33
import axios from "axios";
4-
import { slots, courses } from "./select_options";
54
import toast, { Toaster } from "react-hot-toast";
65
import { handleAPIError } from "../../util/error";
76
import { useRouter } from "next/navigation";
@@ -29,6 +28,8 @@ import {
2928
import Navbar from "@/components/Navbar";
3029
import Footer from "@/components/Footer";
3130
import {PostPDFToCloudinary} from "@/interface"
31+
import { courses, slots } from "@/components/select_options";
32+
import SearchBar from "@/components/searchbarSubjectList";
3233
const Page = () => {
3334
const router = useRouter();
3435
const fileInputRef = useRef<HTMLInputElement>(null);
@@ -197,15 +198,17 @@ const Page = () => {
197198
{/* Subject Selection */}
198199
<div>
199200
<label>Subject:</label>
200-
<Command className="rounded-lg border shadow-md md:min-w-[450px]">
201+
{/* setSubject */}
202+
<SearchBar setSubject={setSubject}></SearchBar>
203+
{/* <Command className="rounded-lg border shadow-md md:min-w-[450px]">
201204
<CommandInput
202205
value={inputValue}
203206
onChangeCapture={(e) =>
204207
setInputValue((e.target as HTMLInputElement).value)
205208
}
206209
placeholder="Type a subject or search..."
207-
/>
208-
<CommandList className="h-[100px]">
210+
/> */}
211+
{/* <CommandList className="h-[100px]">
209212
<CommandEmpty>No results found.</CommandEmpty>
210213
211214
<CommandGroup heading="Subjects">
@@ -219,7 +222,7 @@ const Page = () => {
219222
))}
220223
</CommandGroup>
221224
</CommandList>
222-
</Command>
225+
</Command> */}
223226
</div>
224227

225228
{/* Year Selection */}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
"use client";
2+
3+
import { useState, useCallback, useRef, useEffect } from "react";
4+
import { Search } from "lucide-react";
5+
import debounce from "debounce";
6+
import { Input } from "@/components/ui/input";
7+
import { courses } from "./select_options";
8+
9+
function searchbarSubjectList({
10+
setSubject,
11+
}: {
12+
setSubject: React.Dispatch<React.SetStateAction<string>>;
13+
}) {
14+
const [searchText, setSearchText] = useState("");
15+
const [suggestions, setSuggestions] = useState<string[]>([]);
16+
const [error, setError] = useState<string | null>(null);
17+
const [loading, setLoading] = useState(false);
18+
const suggestionsRef = useRef<HTMLUListElement | null>(null);
19+
20+
const debouncedSearch = useCallback(
21+
debounce(async (text: string) => {
22+
if (text.length > 0) {
23+
setLoading(true);
24+
const escapedSearchText = text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
25+
26+
const regex = new RegExp(escapedSearchText, "i");
27+
const filteredSubjects = courses
28+
.filter((subject) => subject.search(regex) !== -1)
29+
.slice(0, 10);
30+
31+
if (filteredSubjects.length === 0) {
32+
setError("Subject not found");
33+
return;
34+
}
35+
setSuggestions(filteredSubjects);
36+
setError(null);
37+
38+
setLoading(false);
39+
} else {
40+
setSuggestions([]);
41+
}
42+
}, 500),
43+
[],
44+
);
45+
46+
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
47+
const text = e.target.value;
48+
setSearchText(text);
49+
if (text.length <= 0) {
50+
setSuggestions([]);
51+
}
52+
void debouncedSearch(text);
53+
};
54+
55+
const handleSelectSuggestion = async (suggestion: string) => {
56+
setSearchText(suggestion);
57+
setSuggestions([]);
58+
setSubject(suggestion);
59+
// router.push(`/catalogue?subject=${encodeURIComponent(suggestion)}`);
60+
};
61+
62+
const handleClickOutside = (event: MouseEvent) => {
63+
if (
64+
suggestionsRef.current &&
65+
!suggestionsRef.current.contains(event.target as Node)
66+
) {
67+
setSuggestions([]);
68+
}
69+
};
70+
71+
useEffect(() => {
72+
document.addEventListener("mousedown", handleClickOutside);
73+
return () => {
74+
document.removeEventListener("mousedown", handleClickOutside);
75+
};
76+
}, []);
77+
78+
return (
79+
<div className="mx-4 md:mx-0">
80+
<form className=" my-2 ml-2 w-full max-w-xl">
81+
<div className="relative">
82+
<Input
83+
type="text"
84+
value={searchText}
85+
onChange={handleSearchChange}
86+
placeholder="Search for subject..."
87+
// className={`text-md w-fuyll rounded-full border bg-[#434dba] px-4 py-6 pr-10 font-sans tracking-wider text-white shadow-sm placeholder:text-white focus:outline-none focus:ring-2 ${loading ? "opacity-70" : ""}`}
88+
/>
89+
<button
90+
type="submit"
91+
className="absolute inset-y-0 right-0 flex items-center pr-3"
92+
disabled
93+
>
94+
{" "}
95+
<Search className="h-5 w-5 text-white " />
96+
</button>
97+
{loading && (
98+
<div className="text-md absolute z-20 mt-2 w-full max-w-xl rounded-md border border-[#434dba] bg-white p-2 text-center font-sans font-semibold tracking-wider dark:bg-[#030712]">
99+
Loading suggestions...
100+
</div>
101+
)}
102+
{(suggestions.length > 0 || error) && !loading && (
103+
<ul
104+
ref={suggestionsRef}
105+
className="absolute z-20 mx-0.5 mt-2 w-full max-w-xl rounded-md border border-[#434dba] bg-white text-center dark:bg-[#030712] md:mx-0"
106+
>
107+
{error ? (
108+
<li className="text-red p-2">{error}</li>
109+
) : (
110+
suggestions.map((suggestion, index) => (
111+
<li
112+
key={index}
113+
onClick={() => handleSelectSuggestion(suggestion)}
114+
className="cursor-pointer truncate p-2 hover:opacity-50"
115+
style={{
116+
width: "100%",
117+
overflow: "hidden",
118+
whiteSpace: "nowrap",
119+
textOverflow: "ellipsis",
120+
}}
121+
>
122+
{suggestion}
123+
</li>
124+
))
125+
)}
126+
</ul>
127+
)}
128+
</div>
129+
</form>
130+
</div>
131+
);
132+
}
133+
134+
export default searchbarSubjectList;
File renamed without changes.

0 commit comments

Comments
 (0)