11'use client' ;
22import React from 'react' ;
3- import '../styles/Footer.css' ;
4- import { Button , IconButton , useTheme } from '@mui/material' ;
3+ import { Box , IconButton , Typography , useTheme } from '@mui/material' ;
54import { GitHub , LinkedIn , OpenInNew } from '@mui/icons-material' ;
65import { MOBILITY_DATA_LINKS } from '../constants/Navigation' ;
76import { fontFamily } from '../Theme' ;
7+ import Image from 'next/image' ;
8+ import { useTranslations } from 'next-intl' ;
9+ import { FooterLink , FooterColumnTitle } from './FooterElements' ;
810
911const Footer : React . FC = ( ) => {
10- // TODO: revisit theming for SSR components
1112 const theme = useTheme ( ) ;
13+ const t = useTranslations ( 'footer' ) ;
14+ const FooterColumnWidth = '185px' ;
1215 const SlackSvg = (
1316 < svg
1417 xmlns = 'http://www.w3.org/2000/svg'
@@ -17,86 +20,235 @@ const Footer: React.FC = () => {
1720 viewBox = '0 0 24 24'
1821 >
1922 < path
20- fill = { theme . palette . primary . main }
23+ fill = 'currentColor'
2124 d = 'M6 15a2 2 0 0 1-2 2a2 2 0 0 1-2-2a2 2 0 0 1 2-2h2zm1 0a2 2 0 0 1 2-2a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2a2 2 0 0 1-2-2zm2-8a2 2 0 0 1-2-2a2 2 0 0 1 2-2a2 2 0 0 1 2 2v2zm0 1a2 2 0 0 1 2 2a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2a2 2 0 0 1 2-2zm8 2a2 2 0 0 1 2-2a2 2 0 0 1 2 2a2 2 0 0 1-2 2h-2zm-1 0a2 2 0 0 1-2 2a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2a2 2 0 0 1 2 2zm-2 8a2 2 0 0 1 2 2a2 2 0 0 1-2 2a2 2 0 0 1-2-2v-2zm0-1a2 2 0 0 1-2-2a2 2 0 0 1 2-2h5a2 2 0 0 1 2 2a2 2 0 0 1-2 2z'
2225 />
2326 </ svg >
2427 ) ;
2528
29+ const currentYear = new Date ( ) . getFullYear ( ) ;
30+
2631 return (
27- < footer className = 'footer' style = { { fontFamily : fontFamily . secondary } } >
28- < a
29- href = { 'https://share.mobilitydata.org/mobility-database-feedback' }
30- target = { '_blank' }
31- rel = 'noreferrer'
32- className = { 'btn-link' }
32+ < Box
33+ component = 'footer'
34+ sx = { {
35+ backgroundColor : theme . palette . background . paper ,
36+ width : '100%' ,
37+ boxSizing : 'border-box' ,
38+ mt : 6 ,
39+ } }
40+ >
41+ { /* Main footer content */ }
42+ < Box
43+ sx = { {
44+ display : 'flex' ,
45+ flexDirection : { xs : 'column' , md : 'row' } ,
46+ gap : { xs : 4 , md : 2 } ,
47+ px : { xs : 3 , md : 8 } ,
48+ py : 5 ,
49+ maxWidth : '1400px' ,
50+ mx : 'auto' ,
51+ flexWrap : 'wrap' ,
52+ } }
3353 >
34- < Button
54+ { /* Brand column */ }
55+ < Box sx = { { flex : 2 , minWidth : '200px' , pr : { md : 4 } } } >
56+ < Box sx = { { display : 'flex' , alignItems : 'center' , gap : 1 , mb : 2 } } >
57+ < Image
58+ src = {
59+ theme . palette . mode === 'light'
60+ ? '/assets/MOBILTYDATA_logo_light_blue_M.png'
61+ : '/assets/MOBILTYDATA_logo_purple_M.png'
62+ }
63+ alt = { t ( 'aria.logo' ) }
64+ width = { 32 }
65+ height = { 32 }
66+ />
67+ < Typography
68+ variant = 'h6'
69+ sx = { {
70+ fontWeight : 700 ,
71+ } }
72+ >
73+ MobilityDatabase
74+ </ Typography >
75+ </ Box >
76+
77+ < Typography
78+ sx = { {
79+ color : theme . palette . text . secondary ,
80+ fontSize : theme . typography . body2 . fontSize ,
81+ lineHeight : 1.6 ,
82+ mb : 3 ,
83+ fontFamily : fontFamily . primary ,
84+ } }
85+ >
86+ { t ( 'tagline' ) }
87+ </ Typography >
88+
89+ < Box sx = { { display : 'flex' , gap : 0.5 } } >
90+ < IconButton
91+ aria-label = { t ( 'aria.github' ) }
92+ component = 'a'
93+ href = { MOBILITY_DATA_LINKS . github }
94+ target = '_blank'
95+ rel = 'noreferrer'
96+ size = 'small'
97+ >
98+ < GitHub />
99+ </ IconButton >
100+ < IconButton
101+ aria-label = { t ( 'aria.slack' ) }
102+ component = 'a'
103+ href = { MOBILITY_DATA_LINKS . slack }
104+ target = '_blank'
105+ rel = 'noreferrer'
106+ size = 'small'
107+ >
108+ { SlackSvg }
109+ </ IconButton >
110+ < IconButton
111+ aria-label = { t ( 'aria.linkedin' ) }
112+ component = 'a'
113+ href = { MOBILITY_DATA_LINKS . linkedin }
114+ target = '_blank'
115+ rel = 'noreferrer'
116+ size = 'small'
117+ >
118+ < LinkedIn />
119+ </ IconButton >
120+ </ Box >
121+ </ Box >
122+
123+ < Box
35124 sx = { {
36- textTransform : 'none' ,
37- mb : 2 ,
38- fontFamily : fontFamily . secondary ,
125+ width : '100%' ,
126+ display : 'flex' ,
127+ gap : 1 ,
128+ flexWrap : 'wrap' ,
129+ maxWidth : '800px' ,
39130 } }
40- variant = { 'outlined' }
41- endIcon = { < OpenInNew /> }
42- >
43- Help Us by Sharing Feedback
44- </ Button >
45- </ a >
46- < div style = { { margin : 0 , display : 'flex' , justifyContent : 'center' } } >
47- < IconButton
48- aria-label = 'slack'
49- className = 'link-button'
50- color = 'primary'
51- component = 'a'
52- href = { MOBILITY_DATA_LINKS . slack }
53- target = '_blank'
54- rel = 'noreferrer'
55- >
56- { SlackSvg }
57- </ IconButton >
58- < IconButton
59- aria-label = 'linkedin'
60- className = 'link-button'
61- color = 'primary'
62- component = 'a'
63- href = { MOBILITY_DATA_LINKS . linkedin }
64- target = '_blank'
65- rel = 'noreferrer'
66- >
67- < LinkedIn />
68- </ IconButton >
69- < IconButton
70- aria-label = 'github'
71- className = 'link-button'
72- color = 'primary'
73- component = 'a'
74- href = { MOBILITY_DATA_LINKS . github }
75- target = '_blank'
76- rel = 'noreferrer'
77131 >
78- < GitHub />
79- </ IconButton >
80- </ div >
81- < p style = { { margin : 0 } } > Maintained with & #128156 ; by MobilityData . </ p >
82- < Button
83- variant = 'text'
84- href = { '/privacy-policy' }
85- target = { '_blank' }
86- rel = { 'noreferrer' }
87- >
88- Privacy Policy
89- </ Button >
90- |
91- < Button
92- variant = 'text'
93- href = { '/terms-and-conditions' }
94- target = { '_blank' }
95- rel = { 'noreferrer' }
132+ { /* Platform column */ }
133+ < Box sx = { { width : FooterColumnWidth } } >
134+ < FooterColumnTitle > { t ( 'columns.platform' ) } </ FooterColumnTitle >
135+ < FooterLink href = '/feeds' > { t ( 'links.feeds' ) } </ FooterLink >
136+ < FooterLink href = '/contribute' > { t ( 'links.addFeed' ) } </ FooterLink >
137+ < FooterLink
138+ href = 'https://mobilitydata.github.io/mobility-feed-api/SwaggerUI/index.html'
139+ external
140+ >
141+ { t ( 'links.apiDocs' ) }
142+ </ FooterLink >
143+ </ Box >
144+
145+ { /* Validators column */ }
146+ < Box sx = { { width : FooterColumnWidth } } >
147+ < FooterColumnTitle > { t ( 'columns.validators' ) } </ FooterColumnTitle >
148+ < FooterLink
149+ href = 'https://gtfs-validator.mobilitydata.org/'
150+ external
151+ >
152+ { t ( 'links.gtfsValidator' ) } { ' ' }
153+ < OpenInNew sx = { { fontSize : '1rem' , verticalAlign : 'middle' } } />
154+ </ FooterLink >
155+ < FooterLink
156+ href = 'https://github.com/MobilityData/gtfs-realtime-validator'
157+ external
158+ >
159+ { t ( 'links.gtfsRtValidator' ) } { ' ' }
160+ < OpenInNew sx = { { fontSize : '1rem' , verticalAlign : 'middle' } } />
161+ </ FooterLink >
162+ < FooterLink
163+ href = 'https://gbfs-validator.mobilitydata.org/'
164+ external
165+ >
166+ { t ( 'links.gbfsValidator' ) } { ' ' }
167+ < OpenInNew sx = { { fontSize : '1rem' , verticalAlign : 'middle' } } />
168+ </ FooterLink >
169+ </ Box >
170+
171+ { /* Company column */ }
172+ < Box sx = { { width : FooterColumnWidth } } >
173+ < FooterColumnTitle > { t ( 'columns.company' ) } </ FooterColumnTitle >
174+ < FooterLink href = '/about' > { t ( 'links.about' ) } </ FooterLink >
175+ < FooterLink href = '/faq' > { t ( 'links.faq' ) } </ FooterLink >
176+ < FooterLink href = '/contact-us' > { t ( 'links.contactUs' ) } </ FooterLink >
177+ < FooterLink
178+ href = 'https://share.mobilitydata.org/mobility-database-feedback'
179+ external
180+ >
181+ { t ( 'links.shareFeedback' ) }
182+ </ FooterLink >
183+ </ Box >
184+
185+ { /* Legal column */ }
186+ < Box sx = { { width : FooterColumnWidth } } >
187+ < FooterColumnTitle > { t ( 'columns.legal' ) } </ FooterColumnTitle >
188+ < FooterLink href = '/privacy-policy' >
189+ { t ( 'links.privacyPolicy' ) }
190+ </ FooterLink >
191+ < FooterLink href = '/terms-and-conditions' >
192+ { t ( 'links.termsAndConditions' ) }
193+ </ FooterLink >
194+ </ Box >
195+ </ Box >
196+ </ Box >
197+
198+ { /* Bottom bar */ }
199+ < Box
200+ sx = { {
201+ backgroundColor : theme . palette . background . paper ,
202+ borderTop : `1px solid ${ theme . palette . divider } ` ,
203+ px : { xs : 3 , md : 8 } ,
204+ py : 2 ,
205+ } }
96206 >
97- Terms and Conditions
98- </ Button >
99- </ footer >
207+ < Box
208+ sx = { {
209+ display : 'flex' ,
210+ justifyContent : 'space-between' ,
211+ alignItems : 'center' ,
212+ maxWidth : '1400px' ,
213+ mx : 'auto' ,
214+ flexDirection : { xs : 'column' , sm : 'row' } ,
215+ gap : 1 ,
216+ } }
217+ >
218+ < Box sx = { { display : 'flex' , alignItems : 'center' , gap : 1 } } >
219+ < Image
220+ src = {
221+ theme . palette . mode === 'light'
222+ ? '/assets/MOBILTYDATA_logo_light_blue_M.png'
223+ : '/assets/MOBILTYDATA_logo_purple_M.png'
224+ }
225+ alt = ''
226+ width = { 18 }
227+ height = { 18 }
228+ style = { { opacity : 0.8 } }
229+ />
230+ < Typography
231+ sx = { {
232+ color : theme . palette . text . secondary ,
233+ fontSize : '0.8rem' ,
234+ fontFamily : fontFamily . secondary ,
235+ } }
236+ >
237+ { t ( 'maintainedBy' ) }
238+ </ Typography >
239+ </ Box >
240+ < Typography
241+ sx = { {
242+ color : theme . palette . text . secondary ,
243+ fontSize : '0.8rem' ,
244+ fontFamily : fontFamily . secondary ,
245+ } }
246+ >
247+ { t ( 'copyright' , { year : currentYear } ) }
248+ </ Typography >
249+ </ Box >
250+ </ Box >
251+ </ Box >
100252 ) ;
101253} ;
102254
0 commit comments