Skip to content

Commit

Permalink
Add currency conversion to homepage
Browse files Browse the repository at this point in the history
  • Loading branch information
aelassas committed Dec 11, 2024
1 parent 2724b9f commit a919c38
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 26 deletions.
1 change: 0 additions & 1 deletion frontend/.env.docker.example
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ VITE_BC_MINIMUM_AGE=21
VITE_BC_PAGINATION_MODE=classic
VITE_BC_STRIPE_PUBLISHABLE_KEY=STRIPE_PUBLISHABLE_KEY
VITE_BC_STRIPE_CURRENCY_CODE=USD
VITE_BC_CURRENCY=$
VITE_BC_SET_LANGUAGE_FROM_IP=false
VITE_BC_GOOGLE_ANALYTICS_ENABLED=false
VITE_BC_GOOGLE_ANALYTICS_ID=G-XXXXXXXXXX
Expand Down
1 change: 0 additions & 1 deletion frontend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ VITE_BC_MINIMUM_AGE=21
VITE_BC_PAGINATION_MODE=classic
VITE_BC_STRIPE_PUBLISHABLE_KEY=STRIPE_PUBLISHABLE_KEY
VITE_BC_STRIPE_CURRENCY_CODE=USD
VITE_BC_CURRENCY=$
VITE_BC_SET_LANGUAGE_FROM_IP=false
VITE_BC_GOOGLE_ANALYTICS_ENABLED=false
VITE_BC_GOOGLE_ANALYTICS_ID=G-XXXXXXXXXX
Expand Down
20 changes: 16 additions & 4 deletions frontend/src/common/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as bookcarsHelper from ':bookcars-helper'
import { strings } from '@/lang/cars'
import { strings as commonStrings } from '@/lang/common'
import env from '@/config/env.config'
import * as StripeService from '@/services/StripeService'

/**
* Get language.
Expand Down Expand Up @@ -627,9 +628,20 @@ export const downloadURI = (uri: string, name: string = '') => {
}

/**
* Return currency symbol.
* Convert a price to a given currency.
*
* @param {string} code
* @returns {string|undefined}
* @async
* @param {number} amount
* @param {string} to
* @returns {Promise<number>}
*/
export const getCurrencySymbol = (code: string) => env._CURRENCIES.find((c) => c.code === code)?.symbol
export const convertPrice = async (amount: number) => {
const to = StripeService.getCurrency()

if (to !== env.BASE_CURRENCY) {
const res = await bookcarsHelper.convertPrice(amount, env.BASE_CURRENCY, to)
return res
}

return amount
}
15 changes: 9 additions & 6 deletions frontend/src/config/env.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ const CURRENCIES: Currency[] = [
{
code: 'EUR',
symbol: '€',
},
{
code: 'IQD',
symbol: 'IQD',
}
]

Expand All @@ -58,6 +62,11 @@ const env = {
DEFAULT_LANGUAGE: String(import.meta.env.VITE_BC_DEFAULT_LANGUAGE || 'en'),
CURRENCIES: CURRENCIES.map((c) => c.code),
_CURRENCIES: CURRENCIES,
/**
* The three-letter ISO 4217 alphabetic currency code, e.g. "USD" or "EUR". Required for Stripe payments. Default is "USD".
* Must be a supported currency: https://docs.stripe.com/currencies
* */
STRIPE_CURRENCY_CODE: String(import.meta.env.VITE_BC_STRIPE_CURRENCY_CODE || 'USD'),
BASE_CURRENCY: String(import.meta.env.VITE_BC_BASE_CURRENCY || 'USD'),
PAGE_SIZE: Number.parseInt(String(import.meta.env.VITE_BC_PAGE_SIZE), 10) || 30,
CARS_PAGE_SIZE: Number.parseInt(String(import.meta.env.VITE_BC_CARS_PAGE_SIZE), 10) || 15,
Expand Down Expand Up @@ -90,12 +99,6 @@ const env = {
? Const.PAGINATION_MODE.INFINITE_SCROLL
: Const.PAGINATION_MODE.CLASSIC,
STRIPE_PUBLISHABLE_KEY: String(import.meta.env.VITE_BC_STRIPE_PUBLISHABLE_KEY),
/**
* The three-letter ISO 4217 alphabetic currency code, e.g. "USD" or "EUR". Required for Stripe payments. Default is "USD".
* Must be a supported currency: https://docs.stripe.com/currencies
* */
STRIPE_CURRENCY_CODE: String(import.meta.env.VITE_BC_STRIPE_CURRENCY_CODE || 'USD'),
CURRENCY: import.meta.env.VITE_BC_CURRENCY || '$',
SET_LANGUAGE_FROM_IP: (import.meta.env.VITE_BC_SET_LANGUAGE_FROM_IP && import.meta.env.VITE_BC_SET_LANGUAGE_FROM_IP.toLowerCase()) === 'true',
GOOGLE_ANALYTICS_ENABLED: (import.meta.env.VITE_BC_GOOGLE_ANALYTICS_ENABLED && import.meta.env.VITE_BC_GOOGLE_ANALYTICS_ENABLED.toLowerCase()) === 'true',
GOOGLE_ANALYTICS_ID: String(import.meta.env.VITE_BC_GOOGLE_ANALYTICS_ID),
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/lang/common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import LocalizedStrings from 'react-localization'
import env from '@/config/env.config'
import * as langHelper from '@/common/langHelper'
import * as StripeService from '@/services/StripeService'

const strings = new LocalizedStrings({
fr: {
Expand Down Expand Up @@ -31,7 +32,7 @@ const strings = new LocalizedStrings({
SAVE: 'Sauvegarder',
CANCEL: 'Annuler',
RESET_PASSWORD: 'Changer le mot de passe',
CURRENCY: env.CURRENCY,
CURRENCY: StripeService.getCurrencySymbol(),
DAILY: '/jour',
DELETE_AVATAR_CONFIRM: 'Êtes-vous sûr de vouloir supprimer la photo ?',
DELETE_IMAGE: "Supprimer l'image",
Expand Down Expand Up @@ -117,7 +118,7 @@ const strings = new LocalizedStrings({
SAVE: 'Save',
CANCEL: 'Cancel',
RESET_PASSWORD: 'Change Password',
CURRENCY: env.CURRENCY,
CURRENCY: StripeService.getCurrencySymbol(),
DAILY: '/day',
DELETE_AVATAR_CONFIRM: 'Are you sure you want to delete the picture?',
UPLOAD_IMAGE: 'Upload image',
Expand Down Expand Up @@ -203,7 +204,7 @@ const strings = new LocalizedStrings({
SAVE: 'Guardar',
CANCEL: 'Cancelar',
RESET_PASSWORD: 'Cambiar contraseña',
CURRENCY: env.CURRENCY,
CURRENCY: StripeService.getCurrencySymbol(),
DAILY: '/día',
DELETE_AVATAR_CONFIRM: '¿Está seguro de que desea eliminar la foto?',
DELETE_IMAGE: 'Eliminar imagen',
Expand Down
41 changes: 34 additions & 7 deletions frontend/src/pages/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react'
import React, { useEffect, useState } from 'react'
import {
Button,
Checkbox,
Expand Down Expand Up @@ -37,6 +37,7 @@ import SearchForm from '@/components/SearchForm'
import Map from '@/components/Map'
import Footer from '@/components/Footer'
import FaqList from '@/components/FaqList'
import * as helper from '@/common/helper'

import Mini from '@/assets/img/mini.png'
import Midi from '@/assets/img/midi.png'
Expand All @@ -56,6 +57,32 @@ const Home = () => {
const [ranges, setRanges] = useState([bookcarsTypes.CarRange.Mini, bookcarsTypes.CarRange.Midi])
const [openRangeSearchFormDialog, setOpenRangeSearchFormDialog] = useState(false)
const [videoLoaded, setVideoLoaded] = useState(false)
const [miniPricePhr, setMiniPricePhr] = useState(2.5)
const [miniPricePday, setMiniPricePday] = useState(40)
const [midiPricePhr, setMidiPricePhr] = useState(3.5)
const [midiPricePday, setMidiPricePday] = useState(50)
const [maxiPricePhr, setMaxiPricePhr] = useState(3.5)
const [maxiPricePday, setMaxiPricePday] = useState(50)

useEffect(() => {
const init = async () => {
const _miniPricePhr = await helper.convertPrice(miniPricePhr)
setMiniPricePhr(_miniPricePhr)
const _miniPricePday = await helper.convertPrice(miniPricePday)
setMiniPricePday(_miniPricePday)
const _midiPricePhr = await helper.convertPrice(midiPricePhr)
setMidiPricePhr(_midiPricePhr)
const _midiPricePday = await helper.convertPrice(midiPricePday)
setMidiPricePday(_midiPricePday)
const _maxiPricePhr = await helper.convertPrice(maxiPricePhr)
setMaxiPricePhr(_maxiPricePhr)
const _maxiPricePday = await helper.convertPrice(maxiPricePday)
setMaxiPricePday(_maxiPricePday)
}

init()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

const handleTabChange = (_event: React.SyntheticEvent, newValue: number) => {
setTabValue(newValue)
Expand Down Expand Up @@ -315,11 +342,11 @@ const Home = () => {
/>
<ul>
<li>
<span className="price">{bookcarsHelper.formatPrice(2.5, commonStrings.CURRENCY, language)}</span>
<span className="price">{bookcarsHelper.formatPrice(miniPricePhr, commonStrings.CURRENCY, language)}</span>
<span className="unit"> · phr</span>
</li>
<li>
<span className="price">{bookcarsHelper.formatPrice(40, commonStrings.CURRENCY, language)}</span>
<span className="price">{bookcarsHelper.formatPrice(miniPricePday, commonStrings.CURRENCY, language)}</span>
<span className="unit"> · pday</span>
</li>
</ul>
Expand Down Expand Up @@ -347,11 +374,11 @@ const Home = () => {
/>
<ul>
<li>
<span className="price">{bookcarsHelper.formatPrice(3.5, commonStrings.CURRENCY, language)}</span>
<span className="price">{bookcarsHelper.formatPrice(midiPricePhr, commonStrings.CURRENCY, language)}</span>
<span className="unit"> · phr</span>
</li>
<li>
<span className="price">{bookcarsHelper.formatPrice(50, commonStrings.CURRENCY, language)}</span>
<span className="price">{bookcarsHelper.formatPrice(midiPricePday, commonStrings.CURRENCY, language)}</span>
<span className="unit"> · pday</span>
</li>
</ul>
Expand All @@ -378,11 +405,11 @@ const Home = () => {
/>
<ul>
<li>
<span className="price">{bookcarsHelper.formatPrice(4.5, commonStrings.CURRENCY, language)}</span>
<span className="price">{bookcarsHelper.formatPrice(maxiPricePhr, commonStrings.CURRENCY, language)}</span>
<span className="unit"> · phr</span>
</li>
<li>
<span className="price">{bookcarsHelper.formatPrice(70, commonStrings.CURRENCY, language)}</span>
<span className="price">{bookcarsHelper.formatPrice(maxiPricePday, commonStrings.CURRENCY, language)}</span>
<span className="unit"> · pday</span>
</li>
</ul>
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/services/StripeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,11 @@ export const getCurrency = () => {
}
return env.BASE_CURRENCY
}

/**
* Return currency symbol.
*
* @param {string} code
* @returns {string|undefined}
*/
export const getCurrencySymbol = () => env._CURRENCIES.find((c) => c.code === getCurrency())?.symbol || '$'
14 changes: 10 additions & 4 deletions packages/bookcars-helper/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as bookcarsTypes from ':bookcars-types'
import CurrencyConverter, { CurrencyCode, currencies } from ':currency-converter'
import CurrencyConverter, { currencies } from ':currency-converter'

/**
* Format a number.
Expand Down Expand Up @@ -342,11 +342,17 @@ export const calculateTotalPrice = (car: bookcarsTypes.Car, from: Date, to: Date
*
* @async
* @param {number} amount
* @param {CurrencyCode} from
* @param {CurrencyCode} to
* @param {string} from
* @param {string} to
* @returns {Promise<number>}
*/
export const convertPrice = async (amount: number, from: CurrencyCode, to: CurrencyCode): Promise<number> => {
export const convertPrice = async (amount: number, from: string, to: string): Promise<number> => {
if (!checkCurrency(from)) {
throw new Error(`Currency ${from} not supported`)
}
if (!checkCurrency(to)) {
throw new Error(`Currency ${to} not supported`)
}
const cc = new CurrencyConverter({ from, to, amount })
const res = await cc.convert()
return res
Expand Down

0 comments on commit a919c38

Please sign in to comment.