Skip to content

Commit

Permalink
Add currency menu to header
Browse files Browse the repository at this point in the history
  • Loading branch information
aelassas committed Dec 11, 2024
1 parent a377059 commit 2724b9f
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 49 deletions.
13 changes: 13 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"leaflet": "^1.9.4",
"leaflet-boundary-canvas": "^1.0.0",
"react": "^19.0.0",
"react-circle-flags": "^0.0.23",
"react-dom": "^19.0.0",
"react-ga4": "^2.1.0",
"react-google-recaptcha-v3": "^1.10.1",
Expand Down
12 changes: 12 additions & 0 deletions frontend/src/assets/css/header.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@
z-index: 1401 !important;
}

.menu div.language,
.btn div.language {
display: flex;
flex-direction: row;
align-items: center;
}

.menu div.language .flag {
width: 24px;
margin-right: 10px;
}

.header-action {
margin-right: 20px;
}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/assets/css/home.css
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ div.home-subtitle {

div.home div.search {
z-index: 2;
background-color: #F9F9F9;
background-color: #fff;
width: 100%;
display: flex;
flex-direction: column;
Expand All @@ -121,7 +121,7 @@ div.home div.search div.home-search {
}

div.home div.why {
background-color: #F9F9F9;
background-color: #fff;
width: 100%;
padding: 40px 0;
display: flex;
Expand Down
103 changes: 84 additions & 19 deletions frontend/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react'
import { toast } from 'react-toastify'
import { useNavigate } from 'react-router-dom'
import {
AppBar,
Toolbar,
Expand All @@ -21,7 +21,6 @@ import {
Mail as MailIcon,
Notifications as NotificationsIcon,
More as MoreIcon,
Language as LanguageIcon,
Settings as SettingsIcon,
Home as HomeIcon,
InfoTwoTone as AboutIcon,
Expand All @@ -34,7 +33,8 @@ import {
PrivacyTip as PrivacyIcon,
QuestionAnswer as FaqIcon,
} from '@mui/icons-material'
import { useNavigate } from 'react-router-dom'
import { toast } from 'react-toastify'
import { CircleFlag } from 'react-circle-flags'
import * as bookcarsTypes from ':bookcars-types'
import env from '@/config/env.config'
import { strings } from '@/lang/header'
Expand All @@ -45,9 +45,12 @@ import Avatar from './Avatar'
import * as langHelper from '@/common/langHelper'
import * as helper from '@/common/helper'
import { useGlobalContext, GlobalContextType } from '@/context/GlobalContext'
import * as StripeService from '@/services/StripeService'

import '@/assets/css/header.css'

const flagHeight = 28

interface HeaderProps {
user?: bookcarsTypes.User
hidden?: boolean
Expand All @@ -69,6 +72,7 @@ const Header = ({
const [lang, setLang] = useState(helper.getLanguage(env.DEFAULT_LANGUAGE))
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null)
const [langAnchorEl, setLangAnchorEl] = useState<HTMLElement | null>(null)
const [currencyAnchorEl, setCurrencyAnchorEl] = useState<HTMLElement | null>(null)
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = useState<HTMLElement | null>(null)
const [sideAnchorEl, setSideAnchorEl] = useState<HTMLElement | null>(null)
const [isSignedIn, setIsSignedIn] = useState(false)
Expand All @@ -78,6 +82,7 @@ const Header = ({
const isMenuOpen = Boolean(anchorEl)
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl)
const isLangMenuOpen = Boolean(langAnchorEl)
const isCurrencyMenuOpen = Boolean(currencyAnchorEl)
const isSideMenuOpen = Boolean(sideAnchorEl)

const classes = {
Expand Down Expand Up @@ -112,6 +117,10 @@ const Header = ({
setLangAnchorEl(event.currentTarget)
}

const handleCurrencyMenuOpen = (event: React.MouseEvent<HTMLElement>) => {
setCurrencyAnchorEl(event.currentTarget)
}

const refreshPage = () => {
const params = new URLSearchParams(window.location.search)

Expand Down Expand Up @@ -156,6 +165,21 @@ const Header = ({
}
}

const handleCurrencyMenuClose = async (event: React.MouseEvent<HTMLElement>) => {
setCurrencyAnchorEl(null)

const { code } = event.currentTarget.dataset
if (code) {
const currentCurrency = StripeService.getCurrency()

if (code && code !== currentCurrency) {
StripeService.setCurrency(code)
// Refresh page
refreshPage()
}
}
}

const handleMenuClose = () => {
setAnchorEl(null)
handleMobileMenuClose()
Expand Down Expand Up @@ -246,12 +270,12 @@ const Header = ({
<SettingsIcon className="header-action" />
<p>{strings.SETTINGS}</p>
</MenuItem>
<MenuItem onClick={handleLangMenuOpen}>
{/* <MenuItem onClick={handleLangMenuOpen}>
<IconButton aria-label="language of current user" aria-controls="primary-search-account-menu" aria-haspopup="true" color="inherit">
<LanguageIcon />
</IconButton>
<p>{strings.LANGUAGE}</p>
</MenuItem>
</MenuItem> */}
<MenuItem onClick={handleSignout}>
<IconButton color="inherit">
<SignoutIcon />
Expand All @@ -276,7 +300,32 @@ const Header = ({
{
env._LANGUAGES.map((language) => (
<MenuItem onClick={handleLangMenuClose} data-code={language.code} key={language.code}>
{language.label}
<div className="language">
<CircleFlag countryCode={language.countryCode as string} height={flagHeight} className="flag" title={language.label} />
<span>{language.label}</span>
</div>
</MenuItem>
))
}
</Menu>
)

const currencyMenuId = 'currency-menu'
const renderCurrencyMenu = (
<Menu
anchorEl={currencyAnchorEl}
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
id={currencyMenuId}
keepMounted
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
open={isCurrencyMenuOpen}
onClose={handleCurrencyMenuClose}
className="menu"
>
{
env._CURRENCIES.map((_currency) => (
<MenuItem onClick={handleCurrencyMenuClose} data-code={_currency.code} key={_currency.code}>
{_currency.code}
</MenuItem>
))
}
Expand Down Expand Up @@ -349,33 +398,48 @@ const Header = ({
</Drawer>
{(env.isMobile || !headerTitle) && <div style={classes.grow} />}
<div className="header-desktop">
{isSignedIn && (
<IconButton aria-label="" onClick={handleNotificationsClick} className="btn">
<Badge badgeContent={notificationCount > 0 ? notificationCount : null} color="error">
<NotificationsIcon />
</Badge>
</IconButton>
)}
{!hideSignin && !isSignedIn && isLoaded && !loading && (
<Button variant="contained" startIcon={<LoginIcon />} href="/sign-in" disableElevation fullWidth className="btn" style={{ minWidth: '180px' }}>
<Button variant="contained" startIcon={<LoginIcon />} href="/sign-in" disableElevation fullWidth className="btn" style={{ minWidth: '170px' }}>
{strings.SIGN_IN}
</Button>
)}
{isLoaded && !loading && (
<Button variant="contained" startIcon={<LanguageIcon />} onClick={handleLangMenuOpen} disableElevation fullWidth className="btn">
{lang?.label}
<Button variant="contained" onClick={handleCurrencyMenuOpen} disableElevation fullWidth className="btn">
{StripeService.getCurrency()}
</Button>
)}
{isLoaded && !loading && (
<Button variant="contained" onClick={handleLangMenuOpen} disableElevation fullWidth className="btn">
<div className="language">
<CircleFlag countryCode={lang?.countryCode as string} height={flagHeight} className="flag" title={lang?.label} />
</div>
</Button>
)}
{isSignedIn && (
<IconButton aria-label="" onClick={handleNotificationsClick} className="btn">
<Badge badgeContent={notificationCount > 0 ? notificationCount : null} color="error">
<NotificationsIcon />
</Badge>
</IconButton>
)}
{isSignedIn && (
<IconButton edge="end" aria-label="account" aria-controls={menuId} aria-haspopup="true" onClick={handleAccountMenuOpen} className="btn">
<Avatar loggedUser={user} user={user} size="small" readonly />
</IconButton>
)}
</div>
<div className="header-mobile">
{!isSignedIn && !loading && (
<Button variant="contained" startIcon={<LanguageIcon />} onClick={handleLangMenuOpen} disableElevation fullWidth className="btn">
{lang?.label}
{!loading && (
<Button variant="contained" onClick={handleCurrencyMenuOpen} disableElevation fullWidth className="btn">
{StripeService.getCurrency()}
</Button>
)}
{!loading && (
<Button variant="contained" onClick={handleLangMenuOpen} disableElevation fullWidth className="btn">
<div className="language">
<CircleFlag countryCode={lang?.countryCode as string} height={flagHeight} className="flag" title={lang?.label} />
{/* <span>{lang?.label}</span> */}
</div>
</Button>
)}
{isSignedIn && (
Expand All @@ -397,6 +461,7 @@ const Header = ({
{renderMobileMenu}
{renderMenu}
{renderLanguageMenu}
{renderCurrencyMenu}
</div>
)) || <></>
)
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/config/env.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as bookcarsTypes from ':bookcars-types'
import Const from './const'

type Language = { code: string, label: string }
type Language = { code: string, countryCode: string, label: string }

/**
* ISO 639-1 language codes and their labels
Expand All @@ -12,14 +12,17 @@ type Language = { code: string, label: string }
const LANGUAGES: Language[] = [
{
code: 'en',
countryCode: 'us',
label: 'English',
},
{
code: 'fr',
countryCode: 'fr',
label: 'Français',
},
{
code: 'es',
countryCode: 'es',
label: 'Español',
},
]
Expand Down
51 changes: 27 additions & 24 deletions frontend/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ import { strings as settingsStrings } from '@/lang/settings'
import { strings as signInStrings } from '@/lang/sign-in'
import { strings as signUpStrings } from '@/lang/sign-up'
import { strings as tosStrings } from '@/lang/tos'

// import 'github-fork-ribbon-css/gh-fork-ribbon.css'
import { strings as newsletterFormStrings } from '@/lang/newsletter-form'
import { strings as privacyStrings } from '@/lang/privacy'
import { strings as faqListStrings } from '@/lang/faq-list'
import { strings as checkoutStatusStrings } from '@/lang/checkout-status'

import 'react-toastify/dist/ReactToastify.min.css'
import '@/assets/css/common.css'
Expand Down Expand Up @@ -145,6 +147,10 @@ if (lang) {
signUpStrings.setLanguage(_lang)
tosStrings.setLanguage(_lang)
carSpecsStrings.setLanguage(_lang)
newsletterFormStrings.setLanguage(_lang)
privacyStrings.setLanguage(_lang)
faqListStrings.setLanguage(_lang)
checkoutStatusStrings.setLanguage(_lang)
}

if (env.SET_LANGUAGE_FROM_IP && !storedLang) {
Expand All @@ -166,25 +172,30 @@ const isEs = language === 'es'

const theme = createTheme(
{
// palette: {
// primary: {
// main: '#1976D2',
// contrastText: '#121212',
// dark: '#1976D2',
// },
// },
palette: {
primary: {
main: '#003B95',
// main: '#006CE4',

// contrastText: '#003B95',
// dark: '#003B95',
},
// text: {
// primary: '#003B95',
// }
},
typography: {
fontFamily: [
'-apple-system',
'BlinkMacSystemFont',
'"Segoe UI"',
'Roboto',
"'Helvetica Neue'",
'"Helvetica Neue"',
'Arial',
'sans-serif',
"'Apple Color Emoji'",
"'Segoe UI Emoji'",
"'Segoe UI Symbol'",
'-apple-system',
'BlinkMacSystemFont',
"'Segoe UI'",
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"',
].join(','),
},
components: {
Expand Down Expand Up @@ -264,14 +275,6 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
pauseOnHover
theme="dark"
/>
{/* <a
className="github-fork-ribbon fixed left-bottom"
href="https://github.com/aelassas/bookcars"
data-ribbon="Fork me on GitHub"
title="Fork me on GitHub"
>
Fork me on GitHub
</a> */}
</CssBaseline>
</ThemeProvider>,
)
Loading

0 comments on commit 2724b9f

Please sign in to comment.