From 1c8666f451fa3519c6422cde72943696858f6e78 Mon Sep 17 00:00:00 2001 From: Ashwani Senapati Date: Sat, 29 Nov 2025 18:55:35 +0530 Subject: [PATCH] minor fixes --- src/app/achievements/page.tsx | 271 +++++++++--------- src/app/components/Navbar.jsx | 517 +++++++++++++--------------------- src/app/favicon.ico | Bin 25931 -> 10218 bytes src/app/layout.tsx | 4 +- 4 files changed, 347 insertions(+), 445 deletions(-) diff --git a/src/app/achievements/page.tsx b/src/app/achievements/page.tsx index e2287ee..2c4b58d 100644 --- a/src/app/achievements/page.tsx +++ b/src/app/achievements/page.tsx @@ -1,5 +1,5 @@ "use client"; - +import Image from "next/image"; import { useEffect, useState, useRef } from "react"; import { FaGithub, FaLinkedin, FaExternalLinkAlt, FaStar, FaRocket, FaAward } from "react-icons/fa"; import NeuralBackground from "../components/NeuralBackground"; @@ -130,9 +130,40 @@ function InfiniteCarousel() { ); } +function LoadingScreen() { + return ( +
+
+
+
+
+
+ ML4E +
+
+
+

+ Loading Achievements +

+

+ Fetching the latest achievements… +

+
+
+
+ ); +} + export default function AchievementsPage() { const [achievements, setAchievements] = useState([]); - const [loading, setLoading] = useState(false); + const [loading, setLoading] = useState(true); useEffect(() => { async function fetchAchievements() { @@ -143,6 +174,8 @@ export default function AchievementsPage() { setAchievements(data); } catch (error) { console.error("Error fetching achievements:", error); + // Fallback to local achievements on error + setAchievements([]); } finally { setLoading(false); } @@ -152,6 +185,11 @@ export default function AchievementsPage() { const combinedAchievements = [...achievements]; + // Show loading screen until data is fetched + if (loading) { + return ; + } + return ( <> @@ -167,12 +205,13 @@ export default function AchievementsPage() { -
- {loading ? ( -

Loading achievements...

+ {combinedAchievements.length === 0 ? ( +
+

No achievements found.

+
) : ( combinedAchievements.map((achievement, idx) => { const isImageLeft = idx % 2 === 0; @@ -234,16 +273,6 @@ function AchievementCard({ achievement, isImageLeft, index }: { achievement: Ach showContent ? 'opacity-100 translate-x-0' : 'opacity-0 translate-x-20' }`} > - {/* Styled Speech Bubble Tail - Pointing Left */} - {/*
-
- {/* Main triangular tail with same background as card */} - {/*
*/} - {/* Gradient overlay to match card gradient */} - {/*
*/} - {/*
*/} - {/*
*/} - {/* Modern Card Design with enhanced glassmorphism */}
{/* Enhanced Glow Effect */} @@ -329,121 +358,111 @@ function AchievementCard({ achievement, isImageLeft, index }: { achievement: Ach
) : ( - <> - {/* Content Box Left - Overlapping with higher z-index */} -
- {/* Styled Speech Bubble Tail - Pointing Right */} - {/*
-
- {/* Main triangular tail with same background as card */} - {/*
*/} - {/* Gradient overlay to match card gradient */} - {/*
*/} - {/*
*/} - {/*
*/} - - {/* Modern Card Design with enhanced glassmorphism */} -
- {/* Enhanced Glow Effect */} -
- - {/* Header with Icon */} -
-
- -
-
-

- {startTyping && } -

-
- {[1, 2, 3].map((star) => ( - - ))} -
-
-
- - {/* Content */} -

- {startTyping && } -

- -

- {startTyping && } -

- - {/* Technologies */} - {achievement.technologies && showContent && ( -
- {achievement.technologies.map((tech, i) => ( - + {/* Content Box Left - Overlapping with higher z-index */} +
- {tech} - - ))} -
- )} + {/* Modern Card Design with enhanced glassmorphism */} +
+ {/* Enhanced Glow Effect */} +
+ + {/* Header with Icon */} +
+
+ +
+
+

+ {startTyping && } +

+
+ {[1, 2, 3].map((star) => ( + + ))} +
+
+
- {/* Footer */} - - - {/* Corner Accents */} -
-
-
-
- - {/* Image Right - Larger with LOWER z-index so card overlaps it */} -
- {achievement.title} -
-
- + + {/* Image Right - Larger with LOWER z-index so card overlaps it */} +
+ {achievement.title} +
+
+ )}
diff --git a/src/app/components/Navbar.jsx b/src/app/components/Navbar.jsx index 9c105bf..8dd7127 100644 --- a/src/app/components/Navbar.jsx +++ b/src/app/components/Navbar.jsx @@ -2,7 +2,6 @@ import { useState, useEffect } from "react"; import { motion, AnimatePresence } from "framer-motion"; -import { div } from "framer-motion/client"; const ANIMATIONS = { overlay: { @@ -10,7 +9,7 @@ const ANIMATIONS = { visible: { opacity: 1, transition: { duration: 0.3 } }, exit: { opacity: 0, transition: { duration: 0.3 } }, }, - menuContainer: { + menuContainer: { hidden: { opacity: 0 }, visible: { opacity: 1, @@ -28,16 +27,42 @@ const ANIMATIONS = { }, }; +// ✅ Define dropdown configurations +const DROPDOWN_CONFIG = { + Team: { + title: "Meet Our Team", + items: [ + { label: "Executive Body", href: "/team" }, + { label: "Team Members", href: "/teams" }, + ], + }, + Resources: { + title: "Resources", + items: [ + { label: "Online Resources", href: "/onlineresources" }, + // { label: "Books", href: "/books" }, + ], + }, +}; + +// ✅ Direct link configurations +const DIRECT_LINKS = { + Home: "/", + Projects: "/projects", + Achievements: "/achievements", + Events: "/events", +}; + export default function Navbar() { const [isOpen, setIsOpen] = useState(false); - const [showDropdownResources, setShowDropdownResources] = useState(false); - const [showDropDownTeams, setshowDropDownTeams] = useState(false); + const [activeDropdown, setActiveDropdown] = useState(null); // ✅ Fixed keyboard listener for JSX useEffect(() => { const handleKeyDown = (event) => { if (event.key === "Escape") { setIsOpen(false); + setActiveDropdown(null); } }; @@ -69,48 +94,175 @@ export default function Navbar() { "Contact", ]; + // ✅ Get href for any menu item + const getHref = (item) => { + if (DIRECT_LINKS[item]) return DIRECT_LINKS[item]; + return `#${item.toLowerCase()}`; + }; + + // ✅ Render mobile dropdown + const renderMobileDropdown = (item) => { + const config = DROPDOWN_CONFIG[item]; + if (!config) return null; + + return ( + + + {config.title} + + + + {config.items.map((dropdownItem) => ( + setIsOpen(false)} + > + {dropdownItem.label} + + ))} + + + ); + }; + + // ✅ Render desktop dropdown + // ✅ Render desktop dropdown +const renderDesktopDropdown = (item) => { + const config = DROPDOWN_CONFIG[item]; + if (!config) return null; + + const isActive = activeDropdown === item; + + return ( +
setActiveDropdown(item)} + onMouseLeave={() => setActiveDropdown(null)} + > + + {item} ▾ + + + + {isActive && ( + + {config.items.map((dropdownItem) => ( + setIsOpen(false)} + > + {dropdownItem.label} + + ))} + + )} + +
+ ); +}; + + // ✅ Render regular menu item + const renderMenuItem = (item, isMobile = false) => { + // Check if it's a dropdown item + if (DROPDOWN_CONFIG[item]) { + return isMobile ? renderMobileDropdown(item) : renderDesktopDropdown(item); + } + + // Regular menu item + return ( + setIsOpen(false)} + > + {item} + + ); + }; + + // Logo component to avoid repetition + const Logo = () => ( +
+ + + + + + +
+ ); + + // Hamburger button component + const HamburgerButton = ({ onClick, isOpen, className = "" }) => ( + + ); + return ( <> {/* ---------------- MOBILE NAV ---------------- */}