Skip to content

Created new component to display users starred papers #217

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/app/api/papers/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export async function GET(req: NextRequest) {
if (papers.length === 0) {
return NextResponse.json(
{ message: "No papers found for the specified subject" },
{ status: 404 },
{ status: 200 },
);
}

Expand Down
9 changes: 7 additions & 2 deletions src/app/api/upcoming-papers/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ export async function GET() {
{ status: 404 },
);
}
const nextSlot = String.fromCharCode(slot.charCodeAt(0) + 1)
const correspondingSlots = [slot + "1", slot + "2", nextSlot + "1", nextSlot + "2"];
const nextSlot = String.fromCharCode(slot.charCodeAt(0) + 1);
const correspondingSlots = [
slot + "1",
slot + "2",
nextSlot + "1",
nextSlot + "2",
];
const selectedSubjects = await UpcomingSubject.find({
slots: { $in: correspondingSlots },
});
Expand Down
50 changes: 50 additions & 0 deletions src/app/api/user-papers/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { NextResponse } from "next/server";
import { connectToDatabase } from "@/lib/mongoose";
import Paper from "@/db/papers";

export const dynamic = "force-dynamic";

export async function POST(req: Request) {
try {
await connectToDatabase();
const body = await req.json();

const subjects: string[] = body;

const usersPapers = await Paper.find({
subject: { $in: subjects },
});

const transformedPapers = usersPapers.reduce((acc, paper) => {
const existing = acc.find((item) => item.subject === paper.subject);

if (existing) {
existing.slots.push(paper.slot);
} else {
acc.push({ subject: paper.subject, slots: [paper.slot] });
}

return acc;
}, []);

// check duplicates
const seenSubjects = new Set();
const uniquePapers = transformedPapers.filter((paper) => {
if (seenSubjects.has(paper.subject)) return false;
seenSubjects.add(paper.subject);
return true;
});

return NextResponse.json(uniquePapers, {
status: 200,
});
} catch (error) {
console.error("Error fetching papers:", error);
return NextResponse.json(
{
error: "Failed to fetch papers.",
},
{ status: 500 },
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ import {
import Autoplay from "embla-carousel-autoplay";
import { chunkArray } from "@/util/utils";

function StoredPapers() {
function PapersCarousel({
carouselType,
}: {
carouselType: "users" | "default";
}) {
const [displayPapers, setDisplayPapers] = useState<IUpcomingPaper[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [chunkSize, setChunkSize] = useState<number>(4);
Expand All @@ -29,6 +33,17 @@ function StoredPapers() {
}
};

localStorage.setItem(
"userSubjects",
JSON.stringify([
"Information Security [CBS3002]",
"Foundations of Data Analytics [BCSE351E]",
"Design and Analysis of Algorithms [MCSE502L]",
"Complex Variables and Linear Algebra [BMAT201L]",
"Differential Equations and Transforms [BMAT102L]",
]),
);

handleResize();
window.addEventListener("resize", handleResize);

Expand All @@ -43,10 +58,18 @@ function StoredPapers() {
async function fetchPapers() {
try {
setIsLoading(true);
const response = await axios.get<IUpcomingPaper[]>(
"/api/upcoming-papers",
);
setDisplayPapers(response.data);
if (carouselType === "users") {
const storedSubjects = JSON.parse(
localStorage.getItem("userSubjects"),
);
const response = await axios.post("/api/user-papers", storedSubjects);
setDisplayPapers(response.data);
} else {
const response = await axios.get<IUpcomingPaper[]>(
"/api/upcoming-papers",
);
setDisplayPapers(response.data);
}
} catch (error) {
console.error("Failed to fetch papers:", error);
} finally {
Expand All @@ -66,7 +89,7 @@ function StoredPapers() {
return (
<div className="px-4">
<p className="my-8 text-center font-play text-lg font-semibold">
Upcoming Papers
{carouselType === "users" ? "Your Papers" : "Upcoming Papers"}
</p>

<div className="">
Expand Down Expand Up @@ -107,4 +130,4 @@ function StoredPapers() {
);
}

export default StoredPapers;
export default PapersCarousel;
37 changes: 33 additions & 4 deletions src/components/Searchbar/searchbar-child.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Search } from "lucide-react";
import { useRouter } from "next/navigation";
import { Input } from "@/components/ui/input";
import Fuse from "fuse.js";
import axios from "axios";

function SearchBarChild({
initialSubjects,
Expand All @@ -19,7 +20,26 @@ function SearchBarChild({
const suggestionsRef = useRef<HTMLUListElement | null>(null);
const fuzzy = new Fuse(initialSubjects);

const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const fetchPaperQuantityByName = async (subjectName: string) => {
try {
const response = await axios.get("/api/papers", {
params: { subject: subjectName },
});

if (
response.data.message === "No papers found for the specified subject"
) {
return 0;
}

return response.data.papers.length;
} catch (error) {
console.error("Error fetching paper quantity:", error);
return "request-error";
}
};

const handleSearchChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
const text = e.target.value;
setSearchText(text);

Expand All @@ -32,7 +52,16 @@ function SearchBarChild({
.map((item) => item.item)
.slice(0, 10);

setSuggestions(filteredSuggestions);
const suggestionsWithCount = await Promise.all(
filteredSuggestions.map(async (suggestion) => {
const count = await fetchPaperQuantityByName(suggestion);
return count !== "request-error"
? `${suggestion} (${count})`
: suggestion;
}),
);

setSuggestions(suggestionsWithCount);
} else {
setSuggestions([]);
}
Expand Down Expand Up @@ -62,7 +91,7 @@ function SearchBarChild({
}, []);

return (
<div className="font-play mx-auto w-full max-w-xl">
<div className="mx-auto w-full max-w-xl font-play">
<form
onSubmit={(e) => {
e.preventDefault();
Expand All @@ -78,7 +107,7 @@ function SearchBarChild({
value={searchText}
onChange={handleSearchChange}
placeholder="Search by subject..."
className={`text-md font-play rounded-lg bg-[#B2B8FF] px-4 py-6 pr-10 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" : ""}`}
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" : ""}`}
/>
<button
type="submit"
Expand Down
7 changes: 4 additions & 3 deletions src/components/screens/Hero.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import React from "react";
import SearchBar from "../Searchbar/searchbar";
import StoredPapers from "../StoredPapers";
import PapersCarousel from "../PapersCarousel";

const Hero = () => {
return (
<div id="hero" className="flex flex-col justify-between">
<h1 className="font-vipnabd mx-auto my-8 text-center text-3xl font-extrabold">
<h1 className="mx-auto my-8 text-center font-vipnabd text-3xl font-extrabold">
Built by Students for Students
</h1>
<div className="px-6">
<SearchBar />
</div>
<StoredPapers />
<PapersCarousel carouselType="users" />
<PapersCarousel carouselType="default" />
{/* <div className="hidden lg:flex flex-col items-center whitespace-nowrap text-center">
<h1 className="font-play text-md">Learn More</h1>
<Link
Expand Down