Skip to content

Commit ddb825d

Browse files
authored
Merge pull request #80 from abhitrueprogrammer/staging
Feat: Added 2 campus, answerKey and sem tag
2 parents eb398fb + 7ed7fe2 commit ddb825d

File tree

15 files changed

+228
-66
lines changed

15 files changed

+228
-66
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
- Tailwind CSS : Utility-first CSS framework for rapid UI development.
1616
- MongoDB & Mongoose : Database and object data modeling (ODM) for Node.js.
1717
- Cloudinary : Media storage and optimization service.
18-
- Nodemailer : Node.js library for sending emails.
1918
- Shadcn : Collection of pre-built components using Radix UI and Tailwind CSS.
2019

2120
## 💡 Features:

ongoing-papers.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { type Paper } from "@/interface";
1+
import { type IPaper } from "@/interface";
22

3-
const papers: Paper[] = [
3+
const papers: IPaper[] = [
44
{
55
_id: "6708fd8002a75017a4f08759",
66
finalUrl:
@@ -11,6 +11,8 @@ const papers: Paper[] = [
1111
slot: "A2",
1212
year: "2023",
1313
exam: "CAT-2",
14+
semester: "Fall",
15+
campus: "Vellore",
1416
},
1517
{
1618
_id: "670980523ec3fdad83b2d211",
@@ -22,6 +24,8 @@ const papers: Paper[] = [
2224
slot: "A2",
2325
year: "2024",
2426
exam: "CAT-2",
27+
semester: "Fall",
28+
campus: "Vellore",
2529
},
2630
{
2731
_id: "670a105e6272bcf9da4e2362",
@@ -34,6 +38,8 @@ const papers: Paper[] = [
3438
slot: "A1",
3539
year: "2023",
3640
exam: "CAT-2",
41+
semester: "Fall",
42+
campus: "Vellore",
3743
},
3844
{
3945
_id: "67097e7b3ec3fdad83b2d205",
@@ -45,6 +51,8 @@ const papers: Paper[] = [
4551
slot: "C2",
4652
year: "2023",
4753
exam: "CAT-2",
54+
semester: "Fall",
55+
campus: "Vellore",
4856
},
4957
];
5058

src/app/api/getTags/route.ts

Whitespace-only changes.

src/app/api/papers/route.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { NextResponse, NextRequest } from "next/server";
22
import { connectToDatabase } from "@/lib/mongoose";
33
import Paper from "@/db/papers";
4-
import { type IPaper } from "@/interface";
4+
import { IPaper, type IAdminPaper } from "@/interface";
55

66
export const dynamic = "force-dynamic";
77

@@ -21,11 +21,11 @@ export async function GET(req: NextRequest) {
2121
{ status: 400 },
2222
);
2323
}
24-
24+
console.log((await Paper.find()).map((paper)=>{paper.campus}))
2525
const papers: IPaper[] = await Paper.find({
2626
subject: { $regex: new RegExp(`${escapedSubject}`, "i") },
2727
});
28-
28+
console.log(papers[0]?.campus)
2929
if (papers.length === 0) {
3030
return NextResponse.json(
3131
{ message: "No papers found for the specified subject" },
@@ -36,9 +36,11 @@ export async function GET(req: NextRequest) {
3636
const uniqueYears = Array.from(new Set(papers.map((paper) => paper.year)));
3737
const uniqueSlots = Array.from(new Set(papers.map((paper) => paper.slot)));
3838
const uniqueExams = Array.from(new Set(papers.map((paper) => paper.exam)));
39+
const uniqueCampuses = Array.from(new Set(papers.map((paper) => paper.campus)));
40+
const uniqueSemesters = Array.from(new Set(papers.map((paper) => paper.semester)));
3941

4042
return NextResponse.json(
41-
{ papers, uniqueYears, uniqueSlots, uniqueExams },
43+
{ papers, uniqueYears, uniqueSlots, uniqueExams, uniqueCampuses, uniqueSemesters },
4244
{ status: 200 }
4345
);
4446
} catch (error) {

src/app/api/upload/route.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { NextResponse } from "next/server";
22
import { PDFDocument } from "pdf-lib";
3-
import { slots, years } from "@/components/select_options";
3+
import { campuses, exams, semesters, slots, years } from "@/components/select_options";
44
import { connectToDatabase } from "@/lib/mongoose";
55
import cloudinary from "cloudinary";
66
import { type ICourses, type CloudinaryUploadResult } from "@/interface";
@@ -26,6 +26,9 @@ export async function POST(req: Request) {
2626
const slot = formData.get("slot") as string;
2727
const year = formData.get("year") as string;
2828
const exam = formData.get("exam") as string;
29+
const campus = formData.get("campus") as string;
30+
const semester = formData.get("semester") as string;
31+
2932
const isPdf = formData.get("isPdf") === "true"; // Convert string to boolean
3033

3134
const { data } = await axios.get<ICourses[]>(`${process.env.SERVER_URL}/api/course-list`);
@@ -34,7 +37,10 @@ export async function POST(req: Request) {
3437
!(
3538
courses.includes(subject) &&
3639
slots.includes(slot) &&
37-
years.includes(year)
40+
years.includes(year) &&
41+
exams.includes(exam) &&
42+
campuses.includes(campus) &&
43+
semesters.includes(semester)
3844
)
3945
) {
4046
return NextResponse.json({ message: "Bad Request" }, { status: 400 });
@@ -90,6 +96,8 @@ export async function POST(req: Request) {
9096
slot,
9197
year,
9298
exam,
99+
campus,
100+
semester
93101
});
94102
await paper.save();
95103
return NextResponse.json(

src/app/upload/page.tsx

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Button } from "@/components/ui/button";
88
import Navbar from "@/components/Navbar";
99
import Footer from "@/components/Footer";
1010
import { type PostPDFToCloudinary } from "@/interface";
11-
import { slots, years } from "@/components/select_options";
11+
import { slots, years, campuses, semesters, exams } from "@/components/select_options";
1212
import SearchBar from "@/components/searchbarSubjectList";
1313
import Dropzone from "react-dropzone";
1414
import {
@@ -26,6 +26,9 @@ const Page = () => {
2626
const [subject, setSubject] = useState("");
2727
const [exam, setExam] = useState("");
2828
const [year, setYear] = useState("");
29+
const [campus, setCampus] = useState("");
30+
const [semester, setSemester] = useState("");
31+
2932
const [files, setFiles] = useState<File[]>([]);
3033
const [isUploading, setIsUploading] = useState(false);
3134
const [resetSearch, setResetSearch] = useState(false);
@@ -55,7 +58,14 @@ const Page = () => {
5558
toast.error("Year is required");
5659
return;
5760
}
58-
61+
if (!campus) {
62+
toast.error("Campus is required");
63+
return;
64+
}
65+
if (!semester) {
66+
toast.error("Semester is required");
67+
return;
68+
}
5969
if (!files || files.length === 0) {
6070
toast.error("No files selected");
6171
return;
@@ -94,6 +104,9 @@ const Page = () => {
94104
formData.append("slot", slot);
95105
formData.append("year", year);
96106
formData.append("exam", exam);
107+
formData.append("semester", semester);
108+
formData.append("campus", campus);
109+
97110
formData.append("isPdf", String(isPdf));
98111

99112
setIsUploading(true);
@@ -162,9 +175,11 @@ const Page = () => {
162175
<SelectContent>
163176
<SelectGroup>
164177
<SelectLabel>Exams</SelectLabel>
165-
<SelectItem value="CAT-1">CAT-1</SelectItem>
166-
<SelectItem value="CAT-2">CAT-2</SelectItem>
167-
<SelectItem value="FAT">FAT</SelectItem>
178+
{exams.map((exam) => (
179+
<SelectItem key={exam} value={String(exam)}>
180+
{exam}
181+
</SelectItem>
182+
))}{" "}
168183
</SelectGroup>
169184
</SelectContent>
170185
</Select>
@@ -196,6 +211,44 @@ const Page = () => {
196211
</Select>
197212
</div>
198213

214+
{/* Year Selection */}
215+
<div>
216+
<label>Campus Selection:</label>
217+
<Select value={campus} onValueChange={setCampus}>
218+
<SelectTrigger className="m-2 rounded-md border p-2">
219+
<SelectValue placeholder="Select campus" />
220+
</SelectTrigger>
221+
<SelectContent>
222+
<SelectGroup>
223+
<SelectLabel>Years</SelectLabel>
224+
{campuses.map((campus) => (
225+
<SelectItem key={campus} value={String(campus)}>
226+
{campus}
227+
</SelectItem>
228+
))}
229+
</SelectGroup>
230+
</SelectContent>
231+
</Select>
232+
</div>
233+
<div>
234+
<label>Semester Selection:</label>
235+
<Select value={semester} onValueChange={setSemester}>
236+
<SelectTrigger className="m-2 rounded-md border p-2">
237+
<SelectValue placeholder="Select semester" />
238+
</SelectTrigger>
239+
<SelectContent>
240+
<SelectGroup>
241+
<SelectLabel>Semester</SelectLabel>
242+
{semesters.map((semester) => (
243+
<SelectItem key={semester} value={String(semester)}>
244+
{semester}
245+
</SelectItem>
246+
))}
247+
</SelectGroup>
248+
</SelectContent>
249+
</Select>
250+
</div>
251+
199252
{/* File Dropzone */}
200253
<div>
201254
<Dropzone

src/components/Card.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { useEffect, useState } from "react";
2-
import { type Paper } from "@/interface";
2+
import { type IPaper } from "@/interface";
33
import Image from "next/image";
44
import { Eye, Download } from "lucide-react";
55
import {
6+
capsuleGreen,
67
extractBracketContent,
78
extractWithoutBracketContent,
89
} from "@/util/utils";
@@ -16,8 +17,8 @@ const Card = ({
1617
onSelect,
1718
isSelected,
1819
}: {
19-
paper: Paper;
20-
onSelect: (paper: Paper, isSelected: boolean) => void;
20+
paper: IPaper;
21+
onSelect: (paper: IPaper, isSelected: boolean) => void;
2122
isSelected: boolean;
2223
}) => {
2324
const router = useRouter();
@@ -27,7 +28,7 @@ const Card = ({
2728
setChecked(isSelected);
2829
}, [isSelected]);
2930

30-
const handleDownload = async (paper: Paper) => {
31+
const handleDownload = async (paper: IPaper) => {
3132
const extension = paper.finalUrl.split(".").pop();
3233
const fileName = `${extractBracketContent(paper.subject)}-${paper.exam}-${paper.slot}-${paper.year}.${extension}`;
3334
await downloadFile(paper.finalUrl, fileName);
@@ -68,17 +69,20 @@ const Card = ({
6869
/>
6970
</Link>
7071

71-
<div className="justify-center space-y-2 h-28">
72+
<div className="justify-center space-y-2 h-30">
7273
<div className="text-sm font-sans font-medium">
7374
{extractBracketContent(paper.subject)}
7475
</div>
7576
<div className="text-base font-sans font-semibold">
7677
{extractWithoutBracketContent(paper.subject)}
7778
</div>
78-
<div className="flex gap-2 py-2">
79+
<div className="flex flex-wrap gap-2 py-2">
7980
{capsule(paper.exam)}
8081
{capsule(paper.slot)}
8182
{capsule(paper.year)}
83+
{capsule(paper.campus)}
84+
{capsule(paper.semester)}
85+
{paper.answerKeyIncluded && capsuleGreen("Answer key included")}
8286
</div>
8387
</div>
8488

src/components/CatalogueContent.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ import { useSearchParams } from "next/navigation";
22
import { useEffect, useState } from "react";
33
import axios, { type AxiosError } from "axios";
44
import { Button } from "@/components/ui/button";
5-
import { type Paper, type Filters } from "@/interface";
5+
import { type IPaper, type Filters } from "@/interface";
66
import { FilterDialog } from "@/components/FilterDialog";
77
import Card from "./Card";
88
import { extractBracketContent } from "@/util/utils";
99
import { useRouter } from "next/navigation";
1010
import SearchBar from "./searchbar";
1111
import Loader from "./ui/loader";
12+
import { campuses, semesters } from "./select_options";
1213

1314
const CatalogueContent = () => {
1415
const searchParams = useSearchParams();
@@ -17,6 +18,9 @@ const CatalogueContent = () => {
1718
const exams = searchParams.get("exams")?.split(",");
1819
const slots = searchParams.get("slots")?.split(",");
1920
const years = searchParams.get("years")?.split(",");
21+
const semesters = searchParams.get("semesters")?.split(",");
22+
const campuses = searchParams.get("campuses")?.split(",");
23+
2024
const [selectedExams, setSelectedExams] = useState<string[] | undefined>(
2125
exams,
2226
);
@@ -34,8 +38,8 @@ const CatalogueContent = () => {
3438
router.push(`/catalogue?subject=${encodeURIComponent(subject!)}`);
3539
};
3640

37-
const [papers, setPapers] = useState<Paper[]>([]);
38-
const [selectedPapers, setSelectedPapers] = useState<Paper[]>([]);
41+
const [papers, setPapers] = useState<IPaper[]>([]);
42+
const [selectedPapers, setSelectedPapers] = useState<IPaper[]>([]);
3943
const [error, setError] = useState<string | null>(null);
4044
const [loading, setLoading] = useState<boolean>(false);
4145
const [filterOptions, setFilterOptions] = useState<Filters>();
@@ -63,7 +67,7 @@ const CatalogueContent = () => {
6367
} catch (error) {}
6468
}
6569

66-
const handleSelectPaper = (paper: Paper, isSelected: boolean) => {
70+
const handleSelectPaper = (paper: IPaper, isSelected: boolean) => {
6771
if (isSelected) {
6872
setSelectedPapers((prev) => [...prev, paper]);
6973
} else {
@@ -171,6 +175,8 @@ const CatalogueContent = () => {
171175
initialExams={exams}
172176
initialSlots={slots}
173177
initialYears={years}
178+
initialCampuses={campuses}
179+
initialSemesters={semesters}
174180
onReset={handleResetFilters}
175181
onApplyFilters={handleApplyFilters}
176182
/>

0 commit comments

Comments
 (0)