Skip to content

Commit 0dc9c34

Browse files
committed
feat:fixed search capability and drop-down menus
1 parent 8ca9991 commit 0dc9c34

File tree

1 file changed

+40
-99
lines changed

1 file changed

+40
-99
lines changed

src/components/screens/PapersPage.tsx

Lines changed: 40 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
"use client"
22

3-
import { useEffect, useState } from "react"
3+
import { useEffect, useState, useRef, useMemo } from "react"
44
import { Button } from "@/components/ui/button"
55
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
66
import { exams, slots, years } from "@/components/select_options"
77
import { Input } from "@/components/ui/input"
88
import axios from "axios"
9+
import Fuse from "fuse.js"
910

1011
export default function PapersPage() {
1112
const [subjects, setSubjects] = useState<string[]>([])
@@ -15,31 +16,34 @@ export default function PapersPage() {
1516
const [selectedExam, setSelectedExam] = useState<string | null>(null)
1617
const [selectedSlot, setSelectedSlot] = useState<string | null>(null)
1718
const [selectedYear, setSelectedYear] = useState<string | null>(null)
19+
const suggestionsRef = useRef<HTMLUListElement | null>(null)
1820

1921
useEffect(() => {
2022
async function fetchSubjects() {
2123
try {
2224
const response = await axios.get(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/course-list`)
23-
setSubjects(response.data.map((course: { name: string }) => course.name))
25+
console.log("API subjects:", response.data)
26+
const names = response.data.map((course: any) => course.name || course.courseName || course.title)
27+
setSubjects(names)
2428
} catch (err) {
2529
console.error("Error fetching subjects:", err)
2630
}
2731
}
2832
fetchSubjects()
2933
}, [])
3034

35+
const fuse = useMemo(() => new Fuse(subjects, { includeScore: true, threshold: 0.3 }), [subjects])
3136

3237
useEffect(() => {
3338
if (!searchText.trim()) {
3439
setSuggestions([])
3540
return
3641
}
37-
const lower = searchText.toLowerCase()
38-
const filtered = subjects.filter((subj) =>
39-
subj.toLowerCase().includes(lower)
40-
)
41-
setSuggestions(filtered.slice(0, 10))
42-
}, [searchText, subjects])
42+
const results = fuse.search(searchText)
43+
const mapped = results.map(r => r.item).slice(0, 10)
44+
console.log("Filtered suggestions:", mapped)
45+
setSuggestions(mapped)
46+
}, [searchText, fuse])
4347

4448
const handleSelectSubject = (subject: string) => {
4549
setSelectedSubject(subject)
@@ -50,130 +54,67 @@ export default function PapersPage() {
5054
setSelectedYear(null)
5155
}
5256

57+
useEffect(() => {
58+
function handleClickOutside(event: MouseEvent) {
59+
if (suggestionsRef.current && !suggestionsRef.current.contains(event.target as Node)) {
60+
setSuggestions([])
61+
}
62+
}
63+
document.addEventListener("mousedown", handleClickOutside)
64+
return () => document.removeEventListener("mousedown", handleClickOutside)
65+
}, [])
66+
5367
const handleSubmit = () => {
5468
if (!selectedSubject || !selectedExam || !selectedSlot || !selectedYear) {
5569
alert("Please fill all fields before submitting")
5670
return
5771
}
58-
console.log({
59-
subject: selectedSubject,
60-
exam: selectedExam,
61-
slot: selectedSlot,
62-
year: selectedYear,
63-
})
64-
72+
console.log({ subject: selectedSubject, exam: selectedExam, slot: selectedSlot, year: selectedYear })
6573
}
6674

6775
return (
6876
<div className="min-h-screen bg-[#F3F5FF] dark:bg-[#070114] text-black dark:text-white px-6 py-12">
6977
<main>
7078
<div className="max-w-4xl mx-auto text-center mb-16">
71-
<h2 className="font-vipnabd text-3xl md:text-4xl font-extrabold mb-12">
72-
Specific Paper Request
73-
</h2>
74-
75-
{}
79+
<h2 className="font-vipnabd text-3xl md:text-4xl font-extrabold mb-12">Specific Paper Request</h2>
7680
<div className="relative max-w-xl mx-auto mb-8 font-play">
7781
<Input
7882
type="text"
7983
value={searchText}
8084
onChange={(e) => setSearchText(e.target.value)}
8185
placeholder="Search by subject..."
82-
className={`text-md rounded-lg bg-[#B2B8FF] px-4 py-6 pr-10 font-play tracking-wider
83-
text-black shadow-sm ring-0 placeholder:text-black focus:outline-none focus:ring-0
84-
dark:bg-[#7480FF66] dark:text-white placeholder:dark:text-white
85-
${suggestions.length > 0 ? "rounded-b-none" : ""}`}
86+
className={`text-md rounded-lg bg-[#B2B8FF] px-4 py-6 pr-10 font-play tracking-wider text-black shadow-sm ring-0 placeholder:text-black focus:outline-none focus:ring-0 dark:bg-[#7480FF66] dark:text-white placeholder:dark:text-white ${suggestions.length > 0 ? "rounded-b-none" : ""}`}
8687
/>
87-
<button
88-
type="button"
89-
className="absolute inset-y-0 right-0 flex items-center pr-3"
90-
>
91-
<svg xmlns="http://www.w3.org/2000/svg"
92-
className="h-5 w-5 text-black dark:text-white"
93-
fill="none" viewBox="0 0 24 24" stroke="currentColor">
94-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2"
95-
d="M21 21l-4.35-4.35M17 11a6 6 0 11-12 0 6 6 0 0112 0z"/>
88+
<button type="button" className="absolute inset-y-0 right-0 flex items-center pr-3">
89+
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 text-black dark:text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
90+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M21 21l-4.35-4.35M17 11a6 6 0 11-12 0 6 6 0 0112 0z"/>
9691
</svg>
9792
</button>
98-
9993
{suggestions.length > 0 && (
100-
<ul
101-
className={`absolute z-20 h-[250px] w-full max-w-xl overflow-y-scroll rounded-md
102-
rounded-t-none border border-t-0 bg-white text-center shadow-lg dark:bg-[#303771]
103-
${suggestions.length > 6 ? "h-[250px]" : "h-auto"}
104-
${suggestions.length > 10 ? "md:h-[400px]" : "md:h-auto"}`}
105-
>
94+
<ul ref={suggestionsRef} className="absolute z-20 max-h-[250px] w-full max-w-xl overflow-y-auto rounded-md rounded-t-none border border-t-0 bg-white text-center shadow-lg dark:bg-[#303771]">
10695
{suggestions.map((s, idx) => (
107-
<li
108-
key={idx}
109-
onClick={() => handleSelectSubject(s)}
110-
className="cursor-pointer truncate p-2 hover:bg-gray-100 dark:hover:bg-gray-800"
111-
>
96+
<li key={idx} onClick={() => handleSelectSubject(s)} className="cursor-pointer truncate p-2 hover:bg-gray-100 dark:hover:bg-gray-800">
11297
{s}
11398
</li>
11499
))}
115100
</ul>
116101
)}
117102
</div>
118-
119-
{}
120103
<div className="flex justify-center gap-4 mb-8">
121-
<Select
122-
onValueChange={setSelectedExam}
123-
disabled={!selectedSubject}
124-
>
125-
<SelectTrigger className="w-32">
126-
<SelectValue placeholder="Exam" />
127-
</SelectTrigger>
128-
<SelectContent>
129-
{exams.map((exam) => (
130-
<SelectItem key={exam} value={exam}>
131-
{exam}
132-
</SelectItem>
133-
))}
134-
</SelectContent>
104+
<Select onValueChange={setSelectedExam} disabled={!selectedSubject}>
105+
<SelectTrigger className="w-32"><SelectValue placeholder="Exam" /></SelectTrigger>
106+
<SelectContent>{exams.map((exam) => <SelectItem key={exam} value={exam}>{exam}</SelectItem>)}</SelectContent>
135107
</Select>
136-
137-
<Select
138-
onValueChange={setSelectedSlot}
139-
disabled={!selectedSubject}
140-
>
141-
<SelectTrigger className="w-32">
142-
<SelectValue placeholder="Slot" />
143-
</SelectTrigger>
144-
<SelectContent>
145-
{slots.map((slot) => (
146-
<SelectItem key={slot} value={slot}>
147-
{slot}
148-
</SelectItem>
149-
))}
150-
</SelectContent>
108+
<Select onValueChange={setSelectedSlot} disabled={!selectedSubject}>
109+
<SelectTrigger className="w-32"><SelectValue placeholder="Slot" /></SelectTrigger>
110+
<SelectContent>{slots.map((slot) => <SelectItem key={slot} value={slot}>{slot}</SelectItem>)}</SelectContent>
151111
</Select>
152-
153-
<Select
154-
onValueChange={setSelectedYear}
155-
disabled={!selectedSubject}
156-
>
157-
<SelectTrigger className="w-32">
158-
<SelectValue placeholder="Year" />
159-
</SelectTrigger>
160-
<SelectContent>
161-
{years.map((year) => (
162-
<SelectItem key={year} value={year}>
163-
{year}
164-
</SelectItem>
165-
))}
166-
</SelectContent>
112+
<Select onValueChange={setSelectedYear} disabled={!selectedSubject}>
113+
<SelectTrigger className="w-32"><SelectValue placeholder="Year" /></SelectTrigger>
114+
<SelectContent>{years.map((year) => <SelectItem key={year} value={year}>{year}</SelectItem>)}</SelectContent>
167115
</Select>
168116
</div>
169-
170-
{}
171-
<Button
172-
className="px-8 py-3 rounded-lg text-base bg-[#4A55FF] hover:bg-[#3A44CC] text-white dark:bg-[#9EA8FF] dark:hover:bg-[#7D86E5] dark:text-black"
173-
onClick={handleSubmit}
174-
>
175-
Submit
176-
</Button>
117+
<Button className="px-8 py-3 rounded-lg text-base bg-[#4A55FF] hover:bg-[#3A44CC] text-white dark:bg-[#9EA8FF] dark:hover:bg-[#7D86E5] dark:text-black" onClick={handleSubmit}>Submit</Button>
177118
</div>
178119
</main>
179120
</div>

0 commit comments

Comments
 (0)