|
3 | 3 | import { useState, useEffect } from 'react'; |
4 | 4 | import Link from 'next/link'; |
5 | 5 | import Image from 'next/image'; |
6 | | -import { Linkedin, Youtube, Instagram, Twitter } from 'lucide-react'; |
7 | | -import { FaBluesky, FaThreads } from 'react-icons/fa6'; |
| 6 | +import { |
| 7 | + FaInstagram, |
| 8 | + FaYoutube, |
| 9 | + FaXTwitter, |
| 10 | + FaThreads, |
| 11 | + FaBluesky, |
| 12 | + FaLinkedinIn, |
| 13 | +} from 'react-icons/fa6'; |
| 14 | +import { BiLogoTelegram } from 'react-icons/bi'; |
8 | 15 |
|
9 | 16 | const iconMap = { |
10 | | - linkedin: Linkedin, |
11 | | - youtube: Youtube, |
12 | | - instagram: Instagram, |
13 | | - x: Twitter, |
14 | | - threads: FaThreads, |
15 | | - bluesky: FaBluesky |
| 17 | + linkedin: FaLinkedinIn, |
| 18 | + youtube: FaYoutube, |
| 19 | + instagram: FaInstagram, |
| 20 | + x: FaXTwitter, |
| 21 | + telegram: BiLogoTelegram, |
| 22 | + threads: FaThreads, |
| 23 | + bluesky: FaBluesky, |
16 | 24 | }; |
17 | 25 |
|
18 | 26 | export default function Footer({ data, editions = [] }) { |
19 | | - const [currentYear, setCurrentYear] = useState(null); |
| 27 | + const [currentYear, setCurrentYear] = useState(new Date().getFullYear()); |
20 | 28 |
|
21 | | - useEffect(() => { |
22 | | - setCurrentYear(new Date().getFullYear()); |
23 | | - }, []); |
| 29 | + useEffect(() => { |
| 30 | + setCurrentYear(new Date().getFullYear()); |
| 31 | + }, []); |
24 | 32 |
|
25 | | - if (!data) return null; |
| 33 | + if (!data) return null; |
26 | 34 |
|
27 | | - const { footer, general } = data; |
28 | | - const currentEdition = data.general.edition.toString(); |
29 | | - const pastEditions = editions.filter(e => e !== currentEdition).sort((a, b) => b.localeCompare(a)); |
30 | | - const navLinks = data.navbar.links.header; |
| 35 | + const { footer, general } = data; |
| 36 | + const currentEdition = general.edition.toString(); |
| 37 | + const pastEditions = editions |
| 38 | + .filter((e) => e !== currentEdition) |
| 39 | + .sort((a, b) => b.localeCompare(a)); |
| 40 | + const navLinks = data.navbar.links.header; |
31 | 41 |
|
32 | | - return ( |
33 | | - <footer className="bg-gray-900 text-white"> |
34 | | - <div className="container mx-auto max-w-7xl px-4"> |
35 | | - <div className="h-px bg-gradient-to-r from-transparent via-blue-500/30 to-transparent"></div> |
| 42 | + return ( |
| 43 | + <footer className='bg-gray-900 text-white'> |
| 44 | + <div className='container mx-auto max-w-7xl px-4'> |
| 45 | + <div className='h-px bg-gradient-to-r from-transparent via-blue-500/30 to-transparent' /> |
36 | 46 |
|
37 | | - <div className="py-16"> |
38 | | - <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-12"> |
39 | | - <div className="lg:col-span-1"> |
40 | | - <Image src={footer.image} alt="Logo" width={150} height={40} /> |
41 | | - <p className="mt-4 text-gray-400 text-sm"> |
42 | | - {general.event.description} |
43 | | - </p> |
44 | | - </div> |
| 47 | + <div className='py-16'> |
| 48 | + <div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-12'> |
| 49 | + <div className='lg:col-span-1'> |
| 50 | + <Image src={footer.image} alt='Logo' width={225} height={60} /> |
| 51 | + <p className='mt-4 text-gray-400 text-sm'> |
| 52 | + {general.event.description} |
| 53 | + </p> |
| 54 | + </div> |
45 | 55 |
|
46 | | - <div className="md:col-start-2"> |
47 | | - <h3 className="text-sm font-semibold uppercase tracking-wider text-gray-300">Navigation</h3> |
48 | | - <ul className="mt-4 space-y-3"> |
49 | | - {navLinks.map((link) => ( |
50 | | - <li key={link.text}> |
51 | | - <Link href={link.to} className="text-gray-400 hover:text-white transition-colors"> |
52 | | - {link.text} |
53 | | - </Link> |
54 | | - </li> |
55 | | - ))} |
56 | | - </ul> |
57 | | - </div> |
| 56 | + <div className='md:col-start-2'> |
| 57 | + <h3 className='text-sm font-semibold uppercase tracking-wider text-gray-300'> |
| 58 | + Navigation |
| 59 | + </h3> |
| 60 | + <ul className='mt-4 space-y-3'> |
| 61 | + {navLinks.map((link) => ( |
| 62 | + <li key={link.text}> |
| 63 | + <Link |
| 64 | + href={link.to} |
| 65 | + className='text-gray-400 hover:text-white transition-colors' |
| 66 | + > |
| 67 | + {link.text} |
| 68 | + </Link> |
| 69 | + </li> |
| 70 | + ))} |
| 71 | + </ul> |
| 72 | + </div> |
58 | 73 |
|
59 | | - <div> |
60 | | - <h3 className="text-sm font-semibold uppercase tracking-wider text-gray-300">Past Editions</h3> |
61 | | - <ul className="mt-4 space-y-3"> |
62 | | - {pastEditions.map((year) => ( |
63 | | - <li key={year}> |
64 | | - <Link href={`/${year}`} className="text-gray-400 hover:text-white transition-colors"> |
65 | | - Edition {year} |
66 | | - </Link> |
67 | | - </li> |
68 | | - ))} |
69 | | - </ul> |
70 | | - </div> |
| 74 | + <div> |
| 75 | + <h3 className='text-sm font-semibold uppercase tracking-wider text-gray-300'> |
| 76 | + Past Editions |
| 77 | + </h3> |
| 78 | + <ul className='mt-4 space-y-3'> |
| 79 | + {pastEditions.map((year) => ( |
| 80 | + <li key={year}> |
| 81 | + <Link |
| 82 | + href={`/${year}`} |
| 83 | + className='text-gray-400 hover:text-white transition-colors' |
| 84 | + > |
| 85 | + Edition {year} |
| 86 | + </Link> |
| 87 | + </li> |
| 88 | + ))} |
| 89 | + </ul> |
| 90 | + </div> |
71 | 91 |
|
72 | | - <div> |
73 | | - <h3 className="text-sm font-semibold uppercase tracking-wider text-gray-300">Connect</h3> |
74 | | - <ul className="mt-4 space-y-3"> |
75 | | - <li><a href={`mailto:${general.contact.email}`} className="text-gray-400 hover:text-white transition-colors">Contact Us</a></li> |
76 | | - <li><Link href="/sponsors" className="text-gray-400 hover:text-white transition-colors">Sponsorship</Link></li> |
77 | | - <li><Link href="/code-of-conduct" className="text-gray-400 hover:text-white transition-colors">Code of Conduct</Link></li> |
78 | | - </ul> |
79 | | - </div> |
80 | | - </div> |
| 92 | + <div> |
| 93 | + <h3 className='text-sm font-semibold uppercase tracking-wider text-gray-300'> |
| 94 | + Connect |
| 95 | + </h3> |
| 96 | + <ul className='mt-4 space-y-3'> |
| 97 | + <li> |
| 98 | + <a |
| 99 | + href={`mailto:${general.contact.email}`} |
| 100 | + className='text-gray-400 hover:text-white transition-colors' |
| 101 | + > |
| 102 | + Contact Us |
| 103 | + </a> |
| 104 | + </li> |
| 105 | + <li> |
| 106 | + <Link |
| 107 | + href='/sponsors' |
| 108 | + className='text-gray-400 hover:text-white transition-colors' |
| 109 | + > |
| 110 | + Sponsorship |
| 111 | + </Link> |
| 112 | + </li> |
| 113 | + <li> |
| 114 | + <Link |
| 115 | + href='/code-of-conduct' |
| 116 | + className='text-gray-400 hover:text-white transition-colors' |
| 117 | + > |
| 118 | + Code of Conduct |
| 119 | + </Link> |
| 120 | + </li> |
| 121 | + </ul> |
| 122 | + </div> |
| 123 | + </div> |
81 | 124 |
|
82 | | - <div className="mt-12 border-t border-gray-800 pt-8 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"> |
83 | | - <p className="text-sm text-gray-500 text-center sm:text-left"> |
84 | | - © {currentYear} {general.event.name}. All rights reserved. |
85 | | - </p> |
86 | | - <div className="flex justify-center gap-4"> |
87 | | - {footer.icons.filter(i => i.active).map(({ iconName, url, alt }) => { |
88 | | - const Icon = iconMap[iconName]; |
89 | | - if (!Icon) return null; |
90 | | - return ( |
91 | | - <a |
92 | | - key={iconName} |
93 | | - href={url} |
94 | | - target="_blank" |
95 | | - rel="noopener noreferrer" |
96 | | - aria-label={alt} |
97 | | - className="text-gray-500 hover:text-white transition-colors" |
98 | | - > |
99 | | - <Icon className="w-6 h-6" /> |
100 | | - </a> |
101 | | - ); |
102 | | - })} |
103 | | - </div> |
104 | | - </div> |
105 | | - </div> |
| 125 | + <div className='mt-12 border-t border-gray-800 pt-8 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4'> |
| 126 | + <p className='text-sm text-gray-500 text-center sm:text-left'> |
| 127 | + © {currentYear} {general.event.name}. All rights reserved. |
| 128 | + </p> |
| 129 | + <div className='flex justify-center gap-4 flex-wrap'> |
| 130 | + {footer.icons |
| 131 | + .filter((i) => i.active) |
| 132 | + .map(({ iconName, url, alt }) => { |
| 133 | + const Icon = iconMap[iconName]; |
| 134 | + if (!Icon) return null; |
| 135 | + return ( |
| 136 | + <a |
| 137 | + key={iconName} |
| 138 | + href={url} |
| 139 | + target='_blank' |
| 140 | + rel='noopener noreferrer' |
| 141 | + aria-label={alt} |
| 142 | + className='text-gray-500 hover:text-white transition-colors' |
| 143 | + > |
| 144 | + <Icon className='w-6 h-6' /> |
| 145 | + </a> |
| 146 | + ); |
| 147 | + })} |
106 | 148 | </div> |
107 | | - </footer> |
108 | | - ); |
109 | | -}; |
| 149 | + </div> |
| 150 | + </div> |
| 151 | + </div> |
| 152 | + </footer> |
| 153 | + ); |
| 154 | +} |
0 commit comments