Skip to content

Commit 0c3db74

Browse files
committed
feat:reverse sorting years in drop-down
1 parent 0dc9c34 commit 0c3db74

File tree

1 file changed

+152
-104
lines changed

1 file changed

+152
-104
lines changed

src/components/screens/PapersPage.tsx

Lines changed: 152 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -7,116 +7,164 @@ import { exams, slots, years } from "@/components/select_options"
77
import { Input } from "@/components/ui/input"
88
import axios from "axios"
99
import Fuse from "fuse.js"
10+
import { ArrowRight } from "lucide-react"
11+
import Image from "next/image"
1012

1113
export default function PapersPage() {
12-
const [subjects, setSubjects] = useState<string[]>([])
13-
const [searchText, setSearchText] = useState("")
14-
const [suggestions, setSuggestions] = useState<string[]>([])
15-
const [selectedSubject, setSelectedSubject] = useState<string | null>(null)
16-
const [selectedExam, setSelectedExam] = useState<string | null>(null)
17-
const [selectedSlot, setSelectedSlot] = useState<string | null>(null)
18-
const [selectedYear, setSelectedYear] = useState<string | null>(null)
19-
const suggestionsRef = useRef<HTMLUListElement | null>(null)
20-
21-
useEffect(() => {
22-
async function fetchSubjects() {
23-
try {
24-
const response = await axios.get(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/course-list`)
25-
console.log("API subjects:", response.data)
26-
const names = response.data.map((course: any) => course.name || course.courseName || course.title)
27-
setSubjects(names)
28-
} catch (err) {
29-
console.error("Error fetching subjects:", err)
30-
}
31-
}
32-
fetchSubjects()
33-
}, [])
14+
const [subjects, setSubjects] = useState<string[]>([])
15+
const [searchText, setSearchText] = useState("")
16+
const [suggestions, setSuggestions] = useState<string[]>([])
17+
const [selectedSubject, setSelectedSubject] = useState<string | null>(null)
18+
const [selectedExam, setSelectedExam] = useState<string | null>(null)
19+
const [selectedSlot, setSelectedSlot] = useState<string | null>(null)
20+
const [selectedYear, setSelectedYear] = useState<string | null>(null)
21+
const suggestionsRef = useRef<HTMLUListElement | null>(null)
3422

35-
const fuse = useMemo(() => new Fuse(subjects, { includeScore: true, threshold: 0.3 }), [subjects])
23+
useEffect(() => {
24+
async function fetchSubjects() {
25+
try {
26+
const response = await axios.get(`${process.env.NEXT_PUBLIC_SERVER_URL}/api/course-list`)
27+
const names = response.data.map((course: any) => course.name || course.courseName || course.title)
28+
setSubjects(names)
29+
} catch (err) {
30+
console.error("Error fetching subjects:", err)
31+
}
32+
}
33+
fetchSubjects()
34+
}, [])
3635

37-
useEffect(() => {
38-
if (!searchText.trim()) {
39-
setSuggestions([])
40-
return
41-
}
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])
47-
48-
const handleSelectSubject = (subject: string) => {
49-
setSelectedSubject(subject)
50-
setSearchText(subject)
51-
setSuggestions([])
52-
setSelectedExam(null)
53-
setSelectedSlot(null)
54-
setSelectedYear(null)
55-
}
56-
57-
useEffect(() => {
58-
function handleClickOutside(event: MouseEvent) {
59-
if (suggestionsRef.current && !suggestionsRef.current.contains(event.target as Node)) {
36+
const fuse = useMemo(() => new Fuse(subjects, { includeScore: true, threshold: 0.3 }), [subjects])
37+
38+
useEffect(() => {
39+
if (!searchText.trim()) {
40+
setSuggestions([])
41+
return
42+
}
43+
const results = fuse.search(searchText)
44+
setSuggestions(results.map(r => r.item).slice(0, 10))
45+
}, [searchText, fuse])
46+
47+
const handleSelectSubject = (subject: string) => {
48+
setSelectedSubject(subject)
49+
setSearchText(subject)
6050
setSuggestions([])
61-
}
51+
setSelectedExam(null)
52+
setSelectedSlot(null)
53+
setSelectedYear(null)
6254
}
63-
document.addEventListener("mousedown", handleClickOutside)
64-
return () => document.removeEventListener("mousedown", handleClickOutside)
65-
}, [])
66-
67-
const handleSubmit = () => {
68-
if (!selectedSubject || !selectedExam || !selectedSlot || !selectedYear) {
69-
alert("Please fill all fields before submitting")
70-
return
55+
56+
useEffect(() => {
57+
function handleClickOutside(event: MouseEvent) {
58+
if (suggestionsRef.current && !suggestionsRef.current.contains(event.target as Node)) {
59+
setSuggestions([])
60+
}
61+
}
62+
document.addEventListener("mousedown", handleClickOutside)
63+
return () => document.removeEventListener("mousedown", handleClickOutside)
64+
}, [])
65+
66+
const handleSubmit = () => {
67+
if (!selectedSubject || !selectedExam || !selectedSlot || !selectedYear) {
68+
alert("Please fill all fields before submitting")
69+
return
70+
}
71+
console.log({ subject: selectedSubject, exam: selectedExam, slot: selectedSlot, year: selectedYear })
7172
}
72-
console.log({ subject: selectedSubject, exam: selectedExam, slot: selectedSlot, year: selectedYear })
73-
}
74-
75-
return (
76-
<div className="min-h-screen bg-[#F3F5FF] dark:bg-[#070114] text-black dark:text-white px-6 py-12">
77-
<main>
78-
<div className="max-w-4xl mx-auto text-center mb-16">
79-
<h2 className="font-vipnabd text-3xl md:text-4xl font-extrabold mb-12">Specific Paper Request</h2>
80-
<div className="relative max-w-xl mx-auto mb-8 font-play">
81-
<Input
82-
type="text"
83-
value={searchText}
84-
onChange={(e) => setSearchText(e.target.value)}
85-
placeholder="Search by subject..."
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" : ""}`}
87-
/>
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"/>
91-
</svg>
92-
</button>
93-
{suggestions.length > 0 && (
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]">
95-
{suggestions.map((s, idx) => (
96-
<li key={idx} onClick={() => handleSelectSubject(s)} className="cursor-pointer truncate p-2 hover:bg-gray-100 dark:hover:bg-gray-800">
97-
{s}
98-
</li>
99-
))}
100-
</ul>
101-
)}
102-
</div>
103-
<div className="flex justify-center gap-4 mb-8">
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>
107-
</Select>
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>
111-
</Select>
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>
115-
</Select>
116-
</div>
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>
73+
74+
return (
75+
<div className="min-h-screen bg-[#F3F5FF] dark:bg-[#070114] text-black dark:text-white px-6 py-12">
76+
<main>
77+
<div className="max-w-4xl mx-auto text-center mb-16">
78+
<h2 className="font-vipnabd text-3xl md:text-4xl font-extrabold mb-12">Specific Paper Request</h2>
79+
80+
<div className="relative max-w-xl mx-auto mb-8 font-play">
81+
<Input
82+
type="text"
83+
value={searchText}
84+
onChange={(e) => setSearchText(e.target.value)}
85+
placeholder="Search by subject..."
86+
className={`text-md rounded-lg bg-[#B2B8FF] px-4 py-6 pr-10 font-play tracking-wider
87+
text-black shadow-sm ring-0 placeholder:text-black focus:outline-none focus:ring-0
88+
dark:bg-[#7480FF66] dark:text-white placeholder:dark:text-white
89+
${suggestions.length > 0 ? "rounded-b-none" : ""}`}
90+
/>
91+
<button type="button" className="absolute inset-y-0 right-0 flex items-center pr-3">
92+
<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">
93+
<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" />
94+
</svg>
95+
</button>
96+
{suggestions.length > 0 && (
97+
<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]">
98+
{suggestions.map((s, idx) => (
99+
<li key={idx} onClick={() => handleSelectSubject(s)} className="cursor-pointer truncate p-2 hover:bg-gray-100 dark:hover:bg-gray-800">
100+
{s}
101+
</li>
102+
))}
103+
</ul>
104+
)}
105+
</div>
106+
107+
<div className="flex justify-center gap-4 mb-8">
108+
<Select onValueChange={setSelectedExam} disabled={!selectedSubject}>
109+
<SelectTrigger className="w-32"><SelectValue placeholder="Exam" /></SelectTrigger>
110+
<SelectContent>{exams.map((exam) => <SelectItem key={exam} value={exam}>{exam}</SelectItem>)}</SelectContent>
111+
</Select>
112+
<Select onValueChange={setSelectedSlot} disabled={!selectedSubject}>
113+
<SelectTrigger className="w-32"><SelectValue placeholder="Slot" /></SelectTrigger>
114+
<SelectContent>{slots.map((slot) => <SelectItem key={slot} value={slot}>{slot}</SelectItem>)}</SelectContent>
115+
</Select>
116+
<Select onValueChange={setSelectedYear} disabled={!selectedSubject}>
117+
<SelectTrigger className="w-32"><SelectValue placeholder="Year" /></SelectTrigger>
118+
<SelectContent>
119+
{[...years].sort((a, b) => Number(b) - Number(a)).map((year) => (
120+
<SelectItem key={year} value={year}>{year}</SelectItem>
121+
))}
122+
</SelectContent>
123+
124+
</Select>
125+
</div>
126+
127+
<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>
128+
</div>
129+
130+
{ }
131+
<div className="max-w-6xl mx-auto mt-16 text-center">
132+
<div className="relative mb-8 text-center">
133+
<h3 className="font-vipnabd text-2xl font-bold">Explore More</h3>
134+
<div className="absolute right-0 top-1/2 -translate-y-1/2">
135+
<Button variant="outline" className="border-gray-300 dark:border-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800">
136+
View All
137+
<ArrowRight className="w-4 h-4 ml-2" />
138+
</Button>
139+
</div>
140+
</div>
141+
142+
143+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 justify-center">
144+
{[1, 2, 3, 4].map((index) => (
145+
<div key={index} className="bg-white dark:bg-[#303771] rounded-lg overflow-hidden shadow-md">
146+
<div className="aspect-[4/3] bg-gray-200 dark:bg-gray-700 relative">
147+
<Image
148+
src="/placeholder.svg?height=200&width=300&text=Paper"
149+
alt={`Paper ${index}`}
150+
width={300}
151+
height={200}
152+
className="w-full h-full object-cover opacity-60"
153+
/>
154+
</div>
155+
<div className="p-4">
156+
<div className="flex flex-wrap gap-2">
157+
<span className="bg-[#4A55FF]/20 dark:bg-[#9EA8FF]/20 text-[#4A55FF] dark:text-[#9EA8FF] px-2 py-1 rounded text-xs">C1</span>
158+
<span className="bg-[#4A55FF]/20 dark:bg-[#9EA8FF]/20 text-[#4A55FF] dark:text-[#9EA8FF] px-2 py-1 rounded text-xs">CAT-1</span>
159+
<span className="bg-[#4A55FF]/20 dark:bg-[#9EA8FF]/20 text-[#4A55FF] dark:text-[#9EA8FF] px-2 py-1 rounded text-xs">2024</span>
160+
<span className="bg-[#4A55FF]/20 dark:bg-[#9EA8FF]/20 text-[#4A55FF] dark:text-[#9EA8FF] px-2 py-1 rounded text-xs">Fall</span>
161+
</div>
162+
</div>
163+
</div>
164+
))}
165+
</div>
166+
</div>
167+
</main>
118168
</div>
119-
</main>
120-
</div>
121-
)
169+
)
122170
}

0 commit comments

Comments
 (0)