Skip to content

Moved searchbar from sidebar to navbar #223

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
25 changes: 23 additions & 2 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,24 @@ import ModeToggle from "@/components/toggle-theme";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { ArrowDownLeftIcon } from "lucide-react";
import SearchbarChild from "./Searchbar/searchbar-child";
import { fetchSubjects } from "./Searchbar/searchbar";
import { useEffect, useState } from "react";

function Navbar() {
const pathname = usePathname();
const [subjects, setSubjects] = useState<string[]>([]);

useEffect(() => {
const getSubjects = async () => {
const subs = await fetchSubjects();
setSubjects(subs);
};
getSubjects();
}, []);

return (
<div className="sticky top-0 z-10 flex h-[85px] w-full items-center justify-between gap-x-3 overflow-hidden bg-[#B2B8FF] px-2 py-6 dark:bg-[#130E1F] md:px-12">
<div className="sticky top-0 z-10 flex h-[85px] w-full items-center justify-between gap-x-3 bg-[#B2B8FF] px-2 py-6 dark:bg-[#130E1F] md:px-12">
<div className="flex items-center gap-x-2 md:w-auto">
<a
href="https://www.codechefvit.com/"
Expand All @@ -32,6 +44,15 @@ function Navbar() {
Papers
</Link>
</div>

{pathname === "/catalogue" && (
<div className="hidden flex-1 justify-center md:flex">
<div className="w-[60%] max-w-[500px]">
<SearchbarChild initialSubjects={subjects} />
</div>
</div>
)}

<div className="md:w/[20%] flex items-center justify-end gap-x-2">
<div className="scale-75 sm:scale-100">
<ModeToggle />
Expand All @@ -52,4 +73,4 @@ function Navbar() {
);
}

export default Navbar;
export default Navbar;
133 changes: 69 additions & 64 deletions src/components/PapersCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import { useEffect, useState } from "react";
import axios from "axios";
import { type IUpcomingPaper } from "@/interface";
import Loader from "./ui/loader";
import UpcomingPaper from "./UpcomingPaper";
import {
Carousel,
Expand All @@ -14,15 +13,12 @@ import {
} from "@/components/ui/carousel";
import Autoplay from "embla-carousel-autoplay";
import { chunkArray } from "@/util/utils";
import { Skeleton } from "@/components/ui/skeleton";

function PapersCarousel({
carouselType,
}: {
carouselType: "users" | "default";
}) {
function PapersCarousel() {
const [displayPapers, setDisplayPapers] = useState<IUpcomingPaper[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [chunkSize, setChunkSize] = useState<number>(4);
const [chunkSize, setChunkSize] = useState<number>(4); // dynamic chunk size

useEffect(() => {
const handleResize = () => {
Expand All @@ -33,6 +29,7 @@ function PapersCarousel({
}
};

// preload sample subjects
localStorage.setItem(
"userSubjects",
JSON.stringify([
Expand All @@ -41,35 +38,20 @@ function PapersCarousel({
"Design and Analysis of Algorithms [MCSE502L]",
"Complex Variables and Linear Algebra [BMAT201L]",
"Differential Equations and Transforms [BMAT102L]",
]),
])
);

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

return () => {
window.removeEventListener("resize", handleResize);
};
return () => window.removeEventListener("resize", handleResize);
}, []);

const chunkedPapers = chunkArray(displayPapers, chunkSize);

useEffect(() => {
async function fetchPapers() {
try {
setIsLoading(true);
if (carouselType === "users") {
const storedSubjects = JSON.parse(
localStorage.getItem("userSubjects") ?? "[]"
) as string[];
const response = await axios.post<IUpcomingPaper []>("/api/user-papers", storedSubjects);
setDisplayPapers(response.data);
} else {
const response = await axios.get<IUpcomingPaper[]>(
"/api/upcoming-papers",
);
setDisplayPapers(response.data);
}
const response = await axios.get<IUpcomingPaper[]>("/api/upcoming-papers");
setDisplayPapers(response.data);
} catch (error) {
console.error("Failed to fetch papers:", error);
} finally {
Expand All @@ -80,52 +62,75 @@ function PapersCarousel({
void fetchPapers();
}, []);

if (isLoading) {
return <Loader prop="m-10" />;
}

const chunkedPapers = chunkArray(displayPapers, chunkSize);
const plugins = [Autoplay({ delay: 8000, stopOnInteraction: true })];

return (
<div className="px-4">
<p className="my-8 text-center font-play text-lg font-semibold">
{carouselType === "users" ? "Your Papers" : "Upcoming Papers"}
Upcoming Papers
</p>

<div className="">
<Carousel
opts={{
align: "start",
loop: true,
}}
plugins={plugins}
className="w-full"
>
<div className="relative mt-4 flex justify-end gap-4">
<CarouselPrevious className="relative" />
<CarouselNext className="relative" />
</div>
<CarouselContent>
{chunkedPapers.map((paperGroup, index) => {
return (
<CarouselItem
key={`carousel-item-${index}`}
className="grid grid-cols-2 grid-rows-2 gap-4 md:grid-cols-4 lg:auto-rows-fr"
<Carousel
opts={{ align: "start", loop: true }}
plugins={plugins}
className="w-full"
>
<div className="relative mt-4 flex justify-end gap-4">
<CarouselPrevious className="relative" />
<CarouselNext className="relative" />
</div>

<CarouselContent>
{isLoading ? (
<CarouselItem
className={`grid ${
chunkSize === 4
? "grid-cols-2 grid-rows-2"
: "grid-cols-4"
} gap-4 lg:auto-rows-fr`}
>
{Array.from({ length: chunkSize }).map((_, idx) => (
<div
key={idx}
className="cursor-pointer rounded-sm border-2 border-[#734DFF] bg-[#FFFFFF] text-black shadow-lg transition duration-150 ease-in-out hover:bg-[#EFEAFF] dark:border-[#36266D] dark:bg-[#171720] dark:text-white hover:dark:bg-[#262635]"
>
{paperGroup.map((paper, subIndex) => (
<div key={subIndex} className="h-full">
<UpcomingPaper
subject={paper.subject}
slots={paper.slots}
/>
<div className="border-b-2 border-[#453D60] p-2">
<Skeleton className="h-6 w-24 rounded-md" />
</div>
<div className="flex flex-col justify-between p-4">
<Skeleton className="mb-4 h-6 w-32 rounded-md" />
<div className="flex gap-2">
<Skeleton className="h-7 w-16 rounded-full" />
<Skeleton className="h-7 w-16 rounded-full" />
</div>
))}
</CarouselItem>
);
})}
</CarouselContent>
</Carousel>
</div>
</div>
</div>
))}
</CarouselItem>
) : (
chunkedPapers.map((paperGroup, index) => (
<CarouselItem
key={`carousel-item-${index}`}
className={`grid ${
chunkSize === 4
? "grid-cols-2 grid-rows-2"
: "grid-cols-4"
} gap-4 lg:auto-rows-fr`}
>
{paperGroup.map((paper, subIndex) => (
<div key={subIndex} className="h-full">
<UpcomingPaper
subject={paper.subject}
slots={paper.slots}
/>
</div>
))}
</CarouselItem>
))
)}
</CarouselContent>
</Carousel>
</div>
);
}
Expand Down
Loading