11import { useState , useEffect } from 'react' ;
2- import { MapPin , Phone , MailOpen , Linkedin , Github , ExternalLink as Link , Code , Send , CheckCircle , AlertCircle , Award , Briefcase , Zap , Rocket , Stethoscope , Camera , Download , X , Menu , Users } from 'lucide-react' ;
2+ import { MapPin , Phone , MailOpen , Linkedin , Github , ExternalLink as Link , Code , Send , CheckCircle , AlertCircle , Award , Briefcase , Zap , Rocket , Stethoscope , Camera , Download , X , Menu , Users , BookOpen , ChevronLeft , ChevronRight , Calendar , ArrowRight } from 'lucide-react' ;
3+ import { contributions } from './contributionsData' ;
4+ import type { ContributionItem } from './contributionsData' ;
35
46// Custom Cursor Component
57const CustomCursor = ( ) => {
@@ -84,7 +86,7 @@ const StatCard = ({ icon: Icon, number, label }: { icon: any, number: string, la
8486
8587// Navigation
8688const Navigation = ( { currentPage, setCurrentPage, mobileMenuOpen, setMobileMenuOpen } : { currentPage : string , setCurrentPage : ( p : string ) => void , mobileMenuOpen : boolean , setMobileMenuOpen : ( b : boolean ) => void } ) => {
87- const pages = [ 'home' , 'about' , 'experience' , 'projects' , 'contact' ] ;
89+ const pages = [ 'home' , 'about' , 'experience' , 'projects' , 'contributions' , ' contact'] ;
8890
8991 return (
9092 < nav className = "navbar" >
@@ -775,6 +777,95 @@ const ContactPage = () => {
775777 ) ;
776778} ;
777779
780+ // Contributions Page
781+ const ITEMS_PER_PAGE = 10 ;
782+
783+ const ContributionsPage = ( ) => {
784+ const [ currentPage , setCurrentPage ] = useState ( 1 ) ;
785+ const totalPages = Math . ceil ( contributions . length / ITEMS_PER_PAGE ) ;
786+ const startIdx = ( currentPage - 1 ) * ITEMS_PER_PAGE ;
787+ const currentItems = contributions . slice ( startIdx , startIdx + ITEMS_PER_PAGE ) ;
788+
789+ const goToPage = ( page : number ) => {
790+ if ( page >= 1 && page <= totalPages ) {
791+ setCurrentPage ( page ) ;
792+ window . scrollTo ( { top : 0 , behavior : 'smooth' } ) ;
793+ }
794+ } ;
795+
796+ return (
797+ < div className = "page contributions-page" >
798+ < div className = "contributions-header" >
799+ < div className = "contributions-header-content" >
800+ < BookOpen size = { 40 } className = "contributions-header-icon" />
801+ < div >
802+ < h1 className = "page-title" style = { { marginBottom : '0.25rem' } } > Contribute to Learn as Much as You CAN</ h1 >
803+ < p className = "contributions-subtitle" > Curated resources, guides, and insights for continuous learning</ p >
804+ </ div >
805+ </ div >
806+ </ div >
807+
808+ < div className = "contributions-list" >
809+ { currentItems . map ( ( item : ContributionItem ) => (
810+ < a
811+ key = { item . id }
812+ href = { item . redirectionLink }
813+ target = "_blank"
814+ rel = "noopener noreferrer"
815+ className = "contribution-card-link"
816+ >
817+ < GlassCard hover className = "contribution-card" >
818+ < div className = "contribution-image-wrapper" >
819+ < img src = { `/${ item . imageUrl } ` } alt = { item . title } className = "contribution-image" />
820+ </ div >
821+ < div className = "contribution-content" >
822+ < div className = "contribution-meta" >
823+ < span className = "contribution-date" >
824+ < Calendar size = { 14 } />
825+ { item . date }
826+ </ span >
827+ </ div >
828+ < h3 className = "contribution-title" > { item . title } </ h3 >
829+ < p className = "contribution-card-subtitle" > { item . subtitle } </ p >
830+ < p className = "contribution-description" > { item . description } </ p >
831+ < span className = "contribution-read-more" >
832+ Read More < ArrowRight size = { 16 } />
833+ </ span >
834+ </ div >
835+ </ GlassCard >
836+ </ a >
837+ ) ) }
838+ </ div >
839+
840+ { totalPages > 1 && (
841+ < div className = "pagination-controls" >
842+ < button
843+ className = "pagination-btn"
844+ onClick = { ( ) => goToPage ( currentPage - 1 ) }
845+ disabled = { currentPage === 1 }
846+ >
847+ < ChevronLeft size = { 20 } /> Previous
848+ </ button >
849+ < span className = "pagination-info" > Page { currentPage } of { totalPages } </ span >
850+ < button
851+ className = "pagination-btn"
852+ onClick = { ( ) => goToPage ( currentPage + 1 ) }
853+ disabled = { currentPage === totalPages }
854+ >
855+ Next < ChevronRight size = { 20 } />
856+ </ button >
857+ </ div >
858+ ) }
859+
860+ { totalPages <= 1 && contributions . length > 0 && (
861+ < div className = "pagination-controls" >
862+ < span className = "pagination-info" > Page 1 of 1</ span >
863+ </ div >
864+ ) }
865+ </ div >
866+ ) ;
867+ } ;
868+
778869// Main App
779870const App = ( ) => {
780871 const [ currentPage , setCurrentPage ] = useState ( 'home' ) ;
@@ -790,6 +881,7 @@ const App = () => {
790881 case 'about' : return < AboutPage /> ;
791882 case 'experience' : return < ExperiencePage /> ;
792883 case 'projects' : return < ProjectsPage /> ;
884+ case 'contributions' : return < ContributionsPage /> ;
793885 case 'contact' : return < ContactPage /> ;
794886 default : return < HomePage setCurrentPage = { setCurrentPage } /> ;
795887 }
@@ -1986,6 +2078,194 @@ const App = () => {
19862078 color: #475569;
19872079 }
19882080
2081+ /* ========== Contributions Page Styles ========== */
2082+ .contributions-page {
2083+ max-width: 900px;
2084+ margin: 0 auto;
2085+ }
2086+
2087+ .contributions-header {
2088+ margin-bottom: 2.5rem;
2089+ }
2090+
2091+ .contributions-header-content {
2092+ display: flex;
2093+ align-items: center;
2094+ gap: 1.25rem;
2095+ }
2096+
2097+ .contributions-header-icon {
2098+ color: #06b6d4;
2099+ flex-shrink: 0;
2100+ }
2101+
2102+ .contributions-subtitle {
2103+ color: #94a3b8;
2104+ font-size: 1rem;
2105+ margin-top: 0.25rem;
2106+ }
2107+
2108+ .contributions-list {
2109+ display: flex;
2110+ flex-direction: column;
2111+ gap: 1.5rem;
2112+ }
2113+
2114+ .contribution-card-link {
2115+ text-decoration: none;
2116+ color: inherit;
2117+ display: block;
2118+ }
2119+
2120+ .contribution-card {
2121+ display: flex;
2122+ flex-direction: row;
2123+ overflow: hidden;
2124+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
2125+ }
2126+
2127+ .contribution-card:hover {
2128+ transform: translateY(-4px);
2129+ box-shadow: 0 20px 40px rgba(6, 182, 212, 0.15);
2130+ border-color: rgba(6, 182, 212, 0.4);
2131+ }
2132+
2133+ .contribution-image-wrapper {
2134+ width: 220px;
2135+ min-width: 220px;
2136+ max-width: 220px;
2137+ display: flex;
2138+ align-items: center;
2139+ justify-content: center;
2140+ background: linear-gradient(135deg, rgba(6, 182, 212, 0.08), rgba(37, 99, 235, 0.08));
2141+ padding: 1.5rem;
2142+ flex-shrink: 0;
2143+ }
2144+
2145+ .contribution-image {
2146+ width: 100%;
2147+ max-width: 140px;
2148+ height: auto;
2149+ object-fit: contain;
2150+ border-radius: 16px;
2151+ filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.3));
2152+ transition: transform 0.3s ease;
2153+ }
2154+
2155+ .contribution-card:hover .contribution-image {
2156+ transform: scale(1.08);
2157+ }
2158+
2159+ .contribution-content {
2160+ flex: 1;
2161+ padding: 1.5rem 1.75rem;
2162+ display: flex;
2163+ flex-direction: column;
2164+ gap: 0.5rem;
2165+ }
2166+
2167+ .contribution-meta {
2168+ display: flex;
2169+ align-items: center;
2170+ gap: 0.75rem;
2171+ }
2172+
2173+ .contribution-date {
2174+ display: flex;
2175+ align-items: center;
2176+ gap: 0.4rem;
2177+ color: #06b6d4;
2178+ font-size: 0.85rem;
2179+ font-weight: 500;
2180+ }
2181+
2182+ .contribution-title {
2183+ font-size: 1.35rem;
2184+ font-weight: 700;
2185+ background: linear-gradient(135deg, #e2e8f0, #06b6d4);
2186+ -webkit-background-clip: text;
2187+ -webkit-text-fill-color: transparent;
2188+ background-clip: text;
2189+ margin: 0;
2190+ }
2191+
2192+ .contribution-card-subtitle {
2193+ font-size: 0.95rem;
2194+ color: #94a3b8;
2195+ font-weight: 500;
2196+ margin: 0;
2197+ }
2198+
2199+ .contribution-description {
2200+ font-size: 0.9rem;
2201+ color: #cbd5e1;
2202+ line-height: 1.6;
2203+ margin: 0.25rem 0 0;
2204+ display: -webkit-box;
2205+ -webkit-line-clamp: 3;
2206+ -webkit-box-orient: vertical;
2207+ overflow: hidden;
2208+ }
2209+
2210+ .contribution-read-more {
2211+ display: inline-flex;
2212+ align-items: center;
2213+ gap: 0.4rem;
2214+ color: #06b6d4;
2215+ font-size: 0.9rem;
2216+ font-weight: 600;
2217+ margin-top: auto;
2218+ padding-top: 0.5rem;
2219+ transition: gap 0.3s ease, color 0.3s ease;
2220+ }
2221+
2222+ .contribution-card:hover .contribution-read-more {
2223+ gap: 0.75rem;
2224+ color: #22d3ee;
2225+ }
2226+
2227+ /* Pagination */
2228+ .pagination-controls {
2229+ display: flex;
2230+ align-items: center;
2231+ justify-content: center;
2232+ gap: 1.5rem;
2233+ margin-top: 2.5rem;
2234+ padding: 1rem;
2235+ }
2236+
2237+ .pagination-btn {
2238+ display: flex;
2239+ align-items: center;
2240+ gap: 0.4rem;
2241+ padding: 0.6rem 1.25rem;
2242+ border-radius: 12px;
2243+ border: 1px solid rgba(6, 182, 212, 0.3);
2244+ background: rgba(6, 182, 212, 0.08);
2245+ color: #06b6d4;
2246+ font-size: 0.9rem;
2247+ font-weight: 600;
2248+ cursor: pointer;
2249+ transition: all 0.3s ease;
2250+ }
2251+
2252+ .pagination-btn:hover:not(:disabled) {
2253+ background: rgba(6, 182, 212, 0.2);
2254+ border-color: rgba(6, 182, 212, 0.5);
2255+ box-shadow: 0 4px 15px rgba(6, 182, 212, 0.15);
2256+ }
2257+
2258+ .pagination-btn:disabled {
2259+ opacity: 0.35;
2260+ cursor: not-allowed;
2261+ }
2262+
2263+ .pagination-info {
2264+ color: #94a3b8;
2265+ font-size: 0.9rem;
2266+ font-weight: 500;
2267+ }
2268+
19892269 @media (max-width: 768px) {
19902270 .custom-cursor {
19912271 display: none;
@@ -2098,6 +2378,26 @@ const App = () => {
20982378 .experience-company {
20992379 font-size: 1.1rem;
21002380 }
2381+
2382+ .contribution-card {
2383+ flex-direction: column !important;
2384+ }
2385+
2386+ .contribution-image-wrapper {
2387+ width: 100% !important;
2388+ min-width: unset !important;
2389+ max-width: unset !important;
2390+ height: 200px !important;
2391+ }
2392+
2393+ .contribution-content {
2394+ padding: 1.25rem !important;
2395+ }
2396+
2397+ .pagination-controls {
2398+ flex-direction: row;
2399+ gap: 0.75rem;
2400+ }
21012401 }
21022402 ` } </ style >
21032403 </ div >
0 commit comments