diff --git a/src/components/home/ResourcesTabs.tsx b/src/components/home/ResourcesTabs.tsx index 99f4476b..9d7363d6 100644 --- a/src/components/home/ResourcesTabs.tsx +++ b/src/components/home/ResourcesTabs.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef } from 'react'; import { useSearchParams } from 'next/navigation'; import { motion, AnimatePresence } from 'framer-motion'; import { FileText, Video, Code, Terminal, Book, Star, Calendar, Brain, Briefcase, Users, Building2, MessageSquare, Map, GraduationCap, Layout, Rocket, Database } from 'lucide-react'; @@ -330,6 +330,9 @@ export default function ResourcesTabs() { ]; const [activeMainTab, setActiveMainTab] = useState('roadmaps'); + useEffect(() => { + setVisibleCount(ITEMS_PER_PAGE); +}, [activeMainTab]); const [activeSubTab, setActiveSubTab] = useState(aiPromptsCategories[0]); const [isInternshipModalOpen, setIsInternshipModalOpen] = useState(false); const [isRoadmapModalOpen, setIsRoadmapModalOpen] = useState(false); @@ -338,9 +341,35 @@ export default function ResourcesTabs() { // Progress State mapping roadmap IDs to completion percentages const [progressData, setProgressData] = useState>({}); - + const ITEMS_PER_PAGE = 2; + const [visibleCount, setVisibleCount] = useState(ITEMS_PER_PAGE); + const [isLoading, setIsLoading] = useState(false); + const observerRef = useRef(null); const searchParams = useSearchParams(); + useEffect(() => { + if (activeMainTab !== 'roadmaps') return; + + const observer = new IntersectionObserver( + (entries) => { + if (entries[0].isIntersecting && !isLoading) { + const roadmaps = originalResources.roadmaps; + if (visibleCount < roadmaps.length) { + setIsLoading(true); + setTimeout(() => { + setVisibleCount(prev => Math.min(prev + ITEMS_PER_PAGE, roadmaps.length)); + setIsLoading(false); + }, 800); + } + } + }, + { threshold: 1.0 } + ); + + if (observerRef.current) observer.observe(observerRef.current); + return () => observer.disconnect(); +}, [visibleCount, isLoading, activeMainTab]); + useEffect(() => { const openParam = searchParams.get('open'); if (openParam === 'internship-calendar') { @@ -525,7 +554,10 @@ export default function ResourcesTabs() { // --- Other Sections (Standard Cards & Roadmaps) ---
- {originalResources[activeMainTab as keyof typeof originalResources]?.map((resource, index) => { + {(activeMainTab === 'roadmaps' + ? originalResources.roadmaps.slice(0, visibleCount) + : originalResources[activeMainTab as keyof typeof originalResources] + )?.map((resource, index) => { // Calculate Progress for Roadmaps const roadmapId = resource.details?.id || resource.title.toLowerCase().replace(/\s+/g, '-'); const progress = progressData[roadmapId] || 0; @@ -597,6 +629,18 @@ export default function ResourcesTabs() { ); })} + + {/* Infinite Scroll Observer */} + {activeMainTab === 'roadmaps' && ( +
+ {isLoading && ( +
+
+ Loading more... +
+ )} +
+ )}
)}
diff --git a/src/components/layout/Footer.tsx b/src/components/layout/Footer.tsx index 8afc9458..7543d1b8 100644 --- a/src/components/layout/Footer.tsx +++ b/src/components/layout/Footer.tsx @@ -1,7 +1,7 @@ import Link from 'next/link'; import Image from 'next/image'; import { Github, Book, Flag, Users, RefreshCw, Code, MessageSquare } from 'lucide-react'; -import logo from '@/assets/logo.webp'; +import logo from '@/assets/logo.png'; import styles from './Footer.module.css'; import { MagneticText } from '../ui/magnetic-text'; import { siteConfig } from '@/config/siteConfig'; diff --git a/src/components/layout/Navbar.tsx b/src/components/layout/Navbar.tsx index 5e13fae6..8db959fa 100644 --- a/src/components/layout/Navbar.tsx +++ b/src/components/layout/Navbar.tsx @@ -6,7 +6,7 @@ import { usePathname } from 'next/navigation'; import Image from 'next/image'; import { motion, AnimatePresence } from 'framer-motion'; import { Flame, Github, LogIn, Menu, X, LogOut, Lock } from 'lucide-react'; -import logo from '@/assets/logo.webp'; +import logo from '@/assets/logo.png'; import { useAuth } from '@/context/AuthContext'; import { NotificationDropdown } from '@/components/NotificationDropdown'; import { ThemeToggle } from '@/components/ui/theme-toggle';