Skip to content

Commit 871a758

Browse files
committed
fix: navbar, pinned carousel, pin state
1 parent 703725c commit 871a758

File tree

7 files changed

+77
-53
lines changed

7 files changed

+77
-53
lines changed

src/components/FloatingNavbar.tsx

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
DropdownMenuContent,
1818
DropdownMenuItem,
1919
} from "@/components/ui/dropdown-menu";
20-
20+
import PinnedModal from "./ui/PinnedModal";
2121
interface Props {
2222
onNavigate: () => void;
2323
}
@@ -31,7 +31,7 @@ export default function FloatingNavbar({ onNavigate }: Props) {
3131
<DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>
3232
<DropdownMenuTrigger asChild>
3333
<button
34-
className="flex h-10 w-10 items-center justify-center rounded-full bg-[#4B22D1] text-white shadow-lg transition-transform duration-200 hover:scale-105 active:scale-95 pointer-events-auto"
34+
className="flex h-10 w-10 items-center justify-center rounded-full border border-[#3A3745] bg-[#e8e9ff] text-gray-700 hover:bg-slate-50 dark:bg-black dark:text-white dark:hover:bg-[#1A1823] shadow-lg transition-transform duration-200 hover:scale-105 active:scale-95 pointer-events-auto"
3535
aria-label="Toggle dropdown"
3636
>
3737
<ChevronDown
@@ -41,7 +41,10 @@ export default function FloatingNavbar({ onNavigate }: Props) {
4141
</DropdownMenuTrigger>
4242

4343
<DropdownMenuContent
44-
className="xl:hidden mt-2 py-2 w-72 space-y-1 rounded-3xl bg-[#4B22D1] text-white border border-[rgba(255,255,255,0.1)] shadow-2xl backdrop-blur-sm pointer-events-auto"
44+
className="xl:hidden mt-2 py-2 w-72 space-y-1 rounded-3xl
45+
border border-[#3A3745] shadow-lg backdrop-blur-sm transition-colors
46+
bg-[#e8e9ff] text-gray-700
47+
dark:bg-black dark:text-white dark:border-[#3A3745]"
4548
align="end"
4649
>
4750
<DropdownMenuItem asChild>
@@ -57,15 +60,10 @@ export default function FloatingNavbar({ onNavigate }: Props) {
5760
</Link>
5861
</DropdownMenuItem>
5962

60-
<DropdownMenuItem asChild>
61-
<Link
62-
href="/pinned"
63-
onClick={() => onNavigate()}
64-
className="flex w-full items-center gap-3 rounded-lg px-3 py-1 hover:bg-[#1A1823] transition"
65-
>
66-
<Pin className="h-4 w-4" />
67-
<span className="text-sm font-medium">Pinned Subjects</span>
68-
</Link>
63+
<DropdownMenuItem asChild onSelect={(e) => e.preventDefault()}>
64+
<div className="flex w-full items-center gap-3 rounded-lg px-3 py-1 hover:bg-[#1A1823] transition">
65+
<PinnedModal/>
66+
</div>
6967
</DropdownMenuItem>
7068

7169
<DropdownMenuItem asChild>

src/components/Navbar.tsx

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ function Navbar() {
4747
</Link> */}
4848

4949
<div className="flex h-8 items-center gap-1 rounded-full border border-[#3A3745] bg-[#e8e9ff] px-2.5 py-1 text-xs font-semibold text-gray-700 transition hover:bg-slate-50 dark:bg-black dark:text-white dark:hover:bg-[#1A1823] sm:h-9 sm:gap-2 sm:px-3.5 sm:py-1.5 sm:text-sm md:h-10 md:px-4 md:py-2 md:text-base">
50-
<Pin className="h-3.5 w-3.5 sm:h-4 sm:w-4" />
5150
<span className="truncate">
5251
<PinnedModal/>
5352
</span>
@@ -98,7 +97,7 @@ function Navbar() {
9897
<DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>
9998
<DropdownMenuTrigger asChild>
10099
<button
101-
className="flex h-10 w-10 items-center justify-center rounded-full bg-[#4B22D1] text-white shadow-lg transition-transform duration-200 hover:scale-105 active:scale-95"
100+
className="flex h-10 w-10 items-center justify-center rounded-full border border-[#3A3745] bg-[#e8e9ff] text-gray-700 hover:bg-slate-50 dark:bg-black dark:text-white dark:hover:bg-[#1A1823] shadow-lg transition-transform duration-200 hover:scale-105 active:scale-95"
102101
aria-label="Toggle dropdown"
103102
>
104103
<ChevronDown
@@ -108,10 +107,10 @@ function Navbar() {
108107
</DropdownMenuTrigger>
109108

110109
<DropdownMenuContent
111-
className="w-56 rounded-2xl border border-[rgba(255,255,255,0.1)] bg-[#4B22D1] text-white shadow-2xl backdrop-blur-sm"
110+
className="w-56 rounded-2xl border border-[rgba(255,255,255,0.1)] border-[#3A3745] bg-[#e8e9ff] text-gray-700 hover:bg-slate-50 dark:bg-black dark:text-white dark:hover:bg-[#1A1823] shadow-2xl backdrop-blur-sm"
112111
align="start"
113112
>
114-
<DropdownMenuItem asChild>
113+
<DropdownMenuItem asChild onSelect={(e) => e.preventDefault()}>
115114
<PinnedModal/>
116115
</DropdownMenuItem>
117116
<DropdownMenuItem asChild>
@@ -132,7 +131,7 @@ function Navbar() {
132131
>
133132
<DropdownMenuTrigger asChild>
134133
<button
135-
className="flex h-10 w-10 items-center justify-center rounded-full bg-[#4B22D1] text-white shadow-lg transition-transform duration-200 hover:scale-105 active:scale-95"
134+
className="flex h-10 w-10 items-center justify-center rounded-full border border-[#3A3745] bg-[#e8e9ff] text-gray-700 hover:bg-slate-50 dark:bg-black dark:text-white dark:hover:bg-[#1A1823] shadow-lg transition-transform duration-200 hover:scale-105 active:scale-95"
136135
aria-label="Toggle dropdown"
137136
>
138137
<ChevronDown
@@ -142,14 +141,14 @@ function Navbar() {
142141
</DropdownMenuTrigger>
143142

144143
<DropdownMenuContent
145-
className="w-56 rounded-2xl border border-[rgba(255,255,255,0.1)] bg-[#4B22D1] text-white shadow-2xl backdrop-blur-sm"
146-
align="start"
147-
>
148-
<DropdownMenuItem asChild>
149-
<Link href="/pinned" className="flex items-center gap-3">
150-
<Pin className="h-4 w-4" />
151-
<span className="font-medium">Pinned Subjects</span>
152-
</Link>
144+
className="xl:hidden mt-2 py-2 w-72 space-y-1 rounded-3xl
145+
border border-[#3A3745] shadow-lg backdrop-blur-sm transition-colors
146+
bg-[#e8e9ff] text-gray-700
147+
dark:bg-black dark:text-white dark:border-[#3A3745]"
148+
align="end"
149+
>
150+
<DropdownMenuItem asChild onSelect={(e) => e.preventDefault()}>
151+
<PinnedModal/>
153152
</DropdownMenuItem>
154153
<DropdownMenuItem asChild>
155154
<Link href="/request" className="flex items-center gap-3">

src/components/PapersCarousel.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,24 @@ function PapersCarousel() {
3939
}, []);
4040

4141
useEffect(() => {
42-
async function fetchPapers() {
42+
const fetchPapers = async () => {
4343
try {
4444
setIsLoading(true);
45-
const response = await axios.get<IUpcomingPaper[]>(
46-
"/api/upcoming-papers",
47-
);
45+
const response = await axios.get<IUpcomingPaper[]>("/api/upcoming-papers");
4846
setDisplayPapers(response.data);
4947
} catch (error) {
5048
console.error("Failed to fetch papers:", error);
5149
} finally {
5250
setIsLoading(false);
5351
}
54-
}
55-
52+
};
5653
void fetchPapers();
54+
const handleUpdate = () => void fetchPapers();
55+
window.addEventListener("updatePapers", handleUpdate);
56+
57+
return () => {
58+
window.removeEventListener("updatePapers", handleUpdate);
59+
};
5760
}, []);
5861

5962
const chunkedPapers = chunkArray(displayPapers, chunkSize);

src/components/PinnedPapersCarousel.tsx

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import PinnedModal from "./ui/PinnedModal";
2323
type PinnedPapersCarouselProps = {
2424
carouselType: "users" | "upcoming",
2525
}
26+
import { Plus } from "lucide-react";
2627

2728
function PinnedPapersCarousel({
2829
carouselType = "upcoming",
@@ -49,6 +50,18 @@ function PinnedPapersCarousel({
4950

5051
const chunkedPapers = chunkArray(displayPapers, chunkSize);
5152

53+
if (chunkedPapers.length > 0) {
54+
const lastChunkIndex = chunkedPapers.length - 1;
55+
if ((chunkedPapers[lastChunkIndex]?.length ?? 0) < chunkSize) {
56+
chunkedPapers[lastChunkIndex] = [
57+
...(chunkedPapers[lastChunkIndex] ?? []),
58+
{ subject: "add_subject_button", slots: [] } as IUpcomingPaper,
59+
];
60+
} else {
61+
chunkedPapers.push([{ subject: "add_subject_button", slots: [] } as IUpcomingPaper]);
62+
}
63+
}
64+
5265
const fetchPapers = async () => {
5366
try {
5467
setIsLoading(true);
@@ -138,7 +151,7 @@ function PinnedPapersCarousel({
138151
const plugins = [Autoplay({ delay: 8000, stopOnInteraction: true })];
139152

140153
return (
141-
<div className="px-4 mt-4">
154+
<div className="px-4 mt-8 md:mt-4">
142155
<div className="">
143156
{displayPapers.length > 0 ?
144157
<Carousel
@@ -149,7 +162,7 @@ function PinnedPapersCarousel({
149162
plugins={plugins}
150163
className="w-full"
151164
>
152-
{displayPapers.length > 8 &&
165+
{displayPapers.length >= 8 &&
153166
<div
154167
className={`relative mt-4 flex justify-end gap-4`}
155168
>
@@ -167,8 +180,7 @@ function PinnedPapersCarousel({
167180
</CarouselItem>
168181
) : (
169182
chunkedPapers.map((paperGroup, index) => {
170-
const isLastChunk = index === chunkedPapers.length - 1;
171-
183+
const placeholdersNeeded = (chunkSize - paperGroup.length) % chunkSize;
172184
return (
173185
<CarouselItem
174186
key={`carousel-item-${index}`}
@@ -177,6 +189,11 @@ function PinnedPapersCarousel({
177189
} gap-4 lg:auto-rows-fr`}
178190
>
179191
{paperGroup.map((paper, subIndex) => (
192+
paper.subject === "add_subject_button" ?
193+
<div key={subIndex} className="h-full border-dashed border border-[#734DFF] dark:border-[#36266D] rounded-sm font-bold hover:bg-[#EFEAFF] dark:bg-transparent dark:hover:bg-[#1A1823] bg-[#FFFFFF]">
194+
<PinnedModal triggerName={"Add Subjects"} page={"Carousel"}/>
195+
</div>
196+
:
180197
<div key={subIndex} className="h-full">
181198
<UpcomingPaper
182199
subject={paper.subject}
@@ -185,26 +202,24 @@ function PinnedPapersCarousel({
185202
</div>
186203
))}
187204

188-
{isLastChunk && displayPapers.length < 8 && (
205+
{Array.from({ length: placeholdersNeeded }).map(
206+
(_, placeholderIndex) => (
189207
<div
190-
className="h-full"
191-
onClick={() => {
192-
window.dispatchEvent(new Event("addButtonClicked"));
193-
}}
194-
>
195-
</div>
196-
)}
208+
key={`placeholder-${placeholderIndex}`}
209+
className="invisible h-full"
210+
></div>
211+
),
212+
)}
197213
</CarouselItem>
198214
);
199215
})
200216
)}
201217
</CarouselContent>
202218
</Carousel> :
203-
<div className={`relative flex flex-col justify-center gap-4 items-center h-max text-center my-48 font-bold`}
219+
<div className={`relative flex flex-col justify-center gap-4 items-center text-center font-bold`}
204220
>
205221
Start pinning subjects for quick and easy access.
206222
<div className="flex h-8 items-center gap-1 rounded-full border border-[#3A3745] bg-[#e8e9ff] px-2.5 py-1 text-xs font-semibold text-gray-700 transition hover:bg-slate-50 dark:bg-black dark:text-white dark:hover:bg-[#1A1823] sm:h-9 sm:gap-2 sm:px-3.5 sm:py-1.5 sm:text-sm md:h-10 md:px-4 md:py-2 md:text-base">
207-
<Pin className="h-3.5 w-3.5 sm:h-4 sm:w-4" />
208223
<span className="truncate">
209224
<PinnedModal/>
210225
</span>

src/components/UpcomingPaper.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ export default function PaperCard({ subject, slots }: PaperCardProps) {
3434

3535
localStorage.setItem("userSubjects", JSON.stringify(updated));
3636
window.dispatchEvent(new Event("userSubjectsChanged"));
37+
if(!current)
38+
window.dispatchEvent(new Event("updatePapers"));
3739
};
3840

3941
useEffect(() => {

src/components/screens/Hero.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@ const Hero = () => {
1515
<p className="my-8 hidden text-center font-play text-lg font-semibold md:block">
1616
Pinned Subjects
1717
</p>
18-
<div className="min-h-[40vh]">
19-
<PinnedPapersCarousel
20-
carouselType="users"
21-
/>
22-
</div>
18+
<PinnedPapersCarousel carouselType="users"/>
2319
<PapersCarousel />
2420
</div>
2521
);

src/components/ui/PinnedModal.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ import { type IUpcomingPaper } from "@/interface";
1414
import { StoredSubjects } from "@/interface";
1515
import { useState, useEffect } from "react";
1616
import { Pin, PinOff } from "lucide-react";
17+
import { Plus } from "lucide-react";
1718

18-
const PinnedModal = () => {
19+
const PinnedModal = ({triggerName = "Pin Subjects", page = "Navbar"} : {triggerName? : String, page? : String}) => {
1920
const [displayPapers, setDisplayPapers] = useState<IUpcomingPaper[]>([]);
2021
const [isLoading, setIsLoading] = useState(true);
2122
const [open, setOpen] = useState(false);
2223
const fetchPapers = async () => {
2324
try {
2425
setIsLoading(true);
25-
2626
const storedSubjects = JSON.parse(
2727
localStorage.getItem("userSubjects") ?? "[]",
2828
) as StoredSubjects;
@@ -65,6 +65,7 @@ const PinnedModal = () => {
6565
localStorage.setItem("userSubjects", JSON.stringify(updatedSubjects));
6666
setDisplayPapers((prev) => prev.filter((paper) => paper.subject !== subjectToRemove));
6767
window.dispatchEvent(new Event("userSubjectsChanged"));
68+
window.dispatchEvent(new Event("updatePapers"));
6869
};
6970

7071
useEffect(() => {
@@ -78,9 +79,19 @@ const PinnedModal = () => {
7879
void fetchPapers();
7980
}else{
8081
window.dispatchEvent(new Event("userSubjectsChanged"));
82+
window.dispatchEvent(new Event("updatePapers"));
8183
}
8284
}}>
83-
<DialogTrigger>Pin Subjects</DialogTrigger>
85+
{page === "Navbar" ?
86+
<DialogTrigger className="flex flex-row gap-2 items-center h-full w-full">
87+
<Pin size={16}/>
88+
{triggerName}
89+
</DialogTrigger> :
90+
<DialogTrigger className="flex flex-row gap-2 items-center h-full w-full justify-center">
91+
<Plus className="font-extrabold"/>
92+
{triggerName}
93+
</DialogTrigger>
94+
}
8495
<DialogContent className="bg-[#F3F5FF] dark:bg-[#070114] border-[#3A3745]">
8596
<DialogHeader>
8697
<DialogTitle>Quick Access to This Semester&apos;s Subjects</DialogTitle>

0 commit comments

Comments
 (0)