From 495991449d72784c5cd8d3dd21bada8277197d5d Mon Sep 17 00:00:00 2001 From: aelassas Date: Wed, 11 Dec 2024 21:14:31 +0100 Subject: [PATCH] Add currencies setting to frontend --- frontend/.env.docker.example | 1 + frontend/.env.example | 1 + frontend/src/common/helper.ts | 8 + frontend/src/config/env.config.ts | 36 ++- frontend/src/services/StripeService.ts | 24 ++ packages/bookcars-helper/index.ts | 10 +- packages/currency-converter/index.ts | 316 ++++++++++++++++--------- 7 files changed, 283 insertions(+), 113 deletions(-) diff --git a/frontend/.env.docker.example b/frontend/.env.docker.example index 77d47d823..97b6fae46 100644 --- a/frontend/.env.docker.example +++ b/frontend/.env.docker.example @@ -3,6 +3,7 @@ VITE_BC_API_HOST=http://localhost:4002 VITE_BC_RECAPTCHA_ENABLED=false VITE_BC_RECAPTCHA_SITE_KEY=GOOGLE_RECAPTCHA_SITE_KEY VITE_BC_DEFAULT_LANGUAGE=en +VITE_BC_BASE_CURRENCY=USD VITE_BC_PAGE_SIZE=30 VITE_BC_CARS_PAGE_SIZE=15 VITE_BC_BOOKINGS_PAGE_SIZE=20 diff --git a/frontend/.env.example b/frontend/.env.example index 5a3ce16c3..67c8e02ca 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -4,6 +4,7 @@ VITE_BC_API_HOST=http://localhost:4002 VITE_BC_RECAPTCHA_ENABLED=false VITE_BC_RECAPTCHA_SITE_KEY=GOOGLE_RECAPTCHA_SITE_KEY VITE_BC_DEFAULT_LANGUAGE=en +VITE_BC_BASE_CURRENCY=USD VITE_BC_PAGE_SIZE=30 VITE_BC_CARS_PAGE_SIZE=15 VITE_BC_BOOKINGS_PAGE_SIZE=20 diff --git a/frontend/src/common/helper.ts b/frontend/src/common/helper.ts index 2e41d9dd6..86ce49f28 100644 --- a/frontend/src/common/helper.ts +++ b/frontend/src/common/helper.ts @@ -625,3 +625,11 @@ export const downloadURI = (uri: string, name: string = '') => { link.click() link.remove() } + +/** + * Return currency symbol. + * + * @param {string} code + * @returns {string|undefined} + */ +export const getCurrencySymbol = (code: string) => env._CURRENCIES.find((c) => c.code === code)?.symbol diff --git a/frontend/src/config/env.config.ts b/frontend/src/config/env.config.ts index e4c0f8802..3209a1999 100644 --- a/frontend/src/config/env.config.ts +++ b/frontend/src/config/env.config.ts @@ -1,11 +1,15 @@ import * as bookcarsTypes from ':bookcars-types' import Const from './const' -// -// ISO 639-1 language codes and their labels -// https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes -// -const LANGUAGES = [ +type Language = { code: string, label: string } + +/** + * ISO 639-1 language codes and their labels + * https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes + * + * @type {Language[]} + */ +const LANGUAGES: Language[] = [ { code: 'en', label: 'English', @@ -20,6 +24,25 @@ const LANGUAGES = [ }, ] +type Currency = { code: string, symbol: string } + +/** + * ISO 4217 currency codes and their symbols + * https://docs.stripe.com/currencies + * + * @type {Currency[]} + */ +const CURRENCIES: Currency[] = [ + { + code: 'USD', + symbol: '$', + }, + { + code: 'EUR', + symbol: '€', + } +] + const env = { isMobile: window.innerWidth <= 960, isProduction: import.meta.env.VITE_NODE_ENV === 'production', @@ -30,6 +53,9 @@ const env = { LANGUAGES: LANGUAGES.map((l) => l.code), _LANGUAGES: LANGUAGES, DEFAULT_LANGUAGE: String(import.meta.env.VITE_BC_DEFAULT_LANGUAGE || 'en'), + CURRENCIES: CURRENCIES.map((c) => c.code), + _CURRENCIES: CURRENCIES, + 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, BOOKINGS_PAGE_SIZE: Number.parseInt(String(import.meta.env.VITE_BC_BOOKINGS_PAGE_SIZE), 10) || 20, diff --git a/frontend/src/services/StripeService.ts b/frontend/src/services/StripeService.ts index fffee7eed..4ff43f2d4 100644 --- a/frontend/src/services/StripeService.ts +++ b/frontend/src/services/StripeService.ts @@ -1,5 +1,7 @@ import * as bookcarsTypes from ':bookcars-types' +import * as bookcarsHelper from ':bookcars-helper' import axiosInstance from './axiosInstance' +import env from '@/config/env.config' /** * Create Checkout Session. @@ -42,3 +44,25 @@ export const createPaymentIntent = (payload: bookcarsTypes.CreatePaymentPayload) payload ) .then((res) => res.data) + +/** +* Set currency. +* +* @param {string} currency +*/ +export const setCurrency = (currency: string) => { + localStorage.setItem('bc-fe-currency', currency) +} + +/** + * Get currency. + * + * @returns {string} + */ +export const getCurrency = () => { + const currency = localStorage.getItem('bc-fe-currency') + if (currency && bookcarsHelper.checkCurrency(currency)) { + return currency + } + return env.BASE_CURRENCY +} diff --git a/packages/bookcars-helper/index.ts b/packages/bookcars-helper/index.ts index 16a47ea60..0fcd99dec 100644 --- a/packages/bookcars-helper/index.ts +++ b/packages/bookcars-helper/index.ts @@ -1,5 +1,5 @@ import * as bookcarsTypes from ':bookcars-types' -import CurrencyConverter, { CurrencyCode } from ':currency-converter' +import CurrencyConverter, { CurrencyCode, currencies } from ':currency-converter' /** * Format a number. @@ -352,6 +352,14 @@ export const convertPrice = async (amount: number, from: CurrencyCode, to: Curre return res } +/** + * Check if currency is supported. + * + * @param {string} currency + * @returns {boolean} + */ +export const checkCurrency = (currency: string) => currencies.findIndex((c) => c === currency) > -1 + /** * Check whether language is french * diff --git a/packages/currency-converter/index.ts b/packages/currency-converter/index.ts index 2acdf6da4..7d70a3b6f 100644 --- a/packages/currency-converter/index.ts +++ b/packages/currency-converter/index.ts @@ -1,161 +1,279 @@ import { Convert } from 'easy-currencies' export type CurrencyCode = + | 'USD' + | 'AED' | 'AFN' | 'ALL' - | 'DZD' + | 'AMD' + | 'ANG' | 'AOA' | 'ARS' - | 'AMD' - | 'AWG' | 'AUD' + | 'AWG' | 'AZN' - | 'BSD' - | 'BHD' + | 'BAM' | 'BBD' | 'BDT' - | 'BYN' - | 'BZD' + | 'BGN' + | 'BIF' | 'BMD' - | 'BTN' - | 'XBT' + | 'BND' | 'BOB' - | 'BAM' - | 'BWP' | 'BRL' - | 'BND' - | 'BGN' - | 'BIF' - | 'XPF' - | 'KHR' + | 'BSD' + | 'BWP' + | 'BYN' + | 'BZD' | 'CAD' - | 'CVE' - | 'KYD' - | 'FCFA' + | 'CDF' + | 'CHF' | 'CLP' - | 'CLF' - | 'CNY' | 'CNY' | 'COP' - | 'KMF' - | 'CF' - | 'CDF' | 'CRC' - | 'HRK' - | 'CUC' + | 'CVE' | 'CZK' - | 'DKK' | 'DJF' + | 'DKK' | 'DOP' - | 'XCD' + | 'DZD' | 'EGP' | 'ETB' + | 'EUR' | 'FJD' - | 'GMD' + | 'FKP' | 'GBP' | 'GEL' - | 'GHS' - | 'GTQ' + | 'GIP' + | 'GMD' | 'GNF' + | 'GTQ' | 'GYD' - | 'HTG' - | 'HNL' | 'HKD' + | 'HNL' + | 'HTG' | 'HUF' - | 'ISK' - | 'INR' | 'IDR' - | 'IRR' - | 'IQD' | 'ILS' + | 'INR' + | 'ISK' | 'JMD' | 'JPY' - | 'JOD' - | 'KZT' | 'KES' - | 'KWD' | 'KGS' + | 'KHR' + | 'KMF' + | 'KRW' + | 'KYD' + | 'KZT' | 'LAK' | 'LBP' - | 'LSL' + | 'LKR' | 'LRD' - | 'LYD' - | 'MOP' - | 'MKD' + | 'LSL' + | 'MAD' + | 'MDL' | 'MGA' - | 'MWK' - | 'MYR' - | 'MVR' - | 'MRO' + | 'MKD' + | 'MMK' + | 'MNT' + | 'MOP' | 'MUR' + | 'MVR' + | 'MWK' | 'MXN' - | 'MDL' - | 'MAD' + | 'MYR' | 'MZN' - | 'MMK' | 'NAD' - | 'NPR' - | 'ANG' - | 'NZD' - | 'NIO' | 'NGN' + | 'NIO' | 'NOK' - | 'OMR' - | 'PKR' + | 'NPR' + | 'NZD' | 'PAB' + | 'PEN' | 'PGK' - | 'PYG' | 'PHP' + | 'PKR' | 'PLN' + | 'PYG' | 'QAR' | 'RON' + | 'RSD' | 'RUB' | 'RWF' - | 'SVC' | 'SAR' - | 'RSD' + | 'SBD' | 'SCR' - | 'SLL' + | 'SEK' | 'SGD' - | 'SBD' + | 'SHP' + | 'SLE' | 'SOS' - | 'ZAR' - | 'KRW' - | 'VES' - | 'LKR' - | 'SDG' | 'SRD' + | 'STD' | 'SZL' - | 'SEK' - | 'CHF' - | 'TJS' - | 'TZS' | 'THB' + | 'TJS' | 'TOP' - | 'TTD' - | 'TND' | 'TRY' - | 'TMT' - | 'UGX' + | 'TTD' + | 'TWD' + | 'TZS' | 'UAH' - | 'AED' - | 'USD' + | 'UGX' | 'UYU' | 'UZS' | 'VND' + | 'VUV' + | 'WST' | 'XAF' + | 'XCD' | 'XOF' + | 'XPF' | 'YER' + | 'ZAR' | 'ZMW' - | 'ETH' - | 'EUR' - | 'LTC' - | 'TWD' - | 'PEN' type CurrencyPair = { expiryDate: Date, rate: number } -export const currencies: CurrencyCode[] = ['AFN', 'ALL', 'DZD', 'AOA', 'ARS', 'AMD', 'AWG', 'AUD', 'AZN', 'BSD', 'BHD', 'BBD', 'BDT', 'BYN', 'BZD', 'BMD', 'BTN', 'XBT', 'BOB', 'BAM', 'BWP', 'BRL', 'BND', 'BGN', 'BIF', 'XPF', 'KHR', 'CAD', 'CVE', 'KYD', 'FCFA', 'CLP', 'CLF', 'CNY', 'CNY', 'COP', 'CF', 'CHF', 'CDF', 'CRC', 'HRK', 'CUC', 'CZK', 'DKK', 'DJF', 'DOP', 'XCD', 'EGP', 'ETB', 'FJD', 'GMD', 'GBP', 'GEL', 'GHS', 'GTQ', 'GNF', 'GYD', 'HTG', 'HNL', 'HKD', 'HUF', 'ISK', 'INR', 'IDR', 'IRR', 'IQD', 'ILS', 'JMD', 'JPY', 'JOD', 'KMF', 'KZT', 'KES', 'KWD', 'KGS', 'LAK', 'LBP', 'LSL', 'LRD', 'LYD', 'MOP', 'MKD', 'MGA', 'MWK', 'MYR', 'MVR', 'MRO', 'MUR', 'MXN', 'MDL', 'MAD', 'MZN', 'MMK', 'NAD', 'NPR', 'ANG', 'NZD', 'NIO', 'NGN', 'NOK', 'OMR', 'PKR', 'PAB', 'PGK', 'PYG', 'PHP', 'PLN', 'QAR', 'RON', 'RUB', 'RWF', 'SVC', 'SAR', 'RSD', 'SCR', 'SLL', 'SGD', 'SBD', 'SOS', 'ZAR', 'KRW', 'VES', 'LKR', 'SDG', 'SRD', 'SZL', 'SEK', 'CHF', 'TJS', 'TZS', 'THB', 'TOP', 'TTD', 'TND', 'TRY', 'TMT', 'UGX', 'UAH', 'AED', 'USD', 'UYU', 'UZS', 'VND', 'XAF', 'XOF', 'YER', 'ZMW', 'ETH', 'EUR', 'LTC', 'TWD', 'PEN'] +export const currencies: CurrencyCode[] = [ + 'USD', + 'AED', + 'AFN', + 'ALL', + 'AMD', + 'ANG', + 'AOA', + 'ARS', + 'AUD', + 'AWG', + 'AZN', + 'BAM', + 'BBD', + 'BDT', + 'BGN', + 'BIF', + 'BMD', + 'BND', + 'BOB', + 'BRL', + 'BSD', + 'BWP', + 'BYN', + 'BZD', + 'CAD', + 'CDF', + 'CHF', + 'CLP', + 'CNY', + 'COP', + 'CRC', + 'CVE', + 'CZK', + 'DJF', + 'DKK', + 'DOP', + 'DZD', + 'EGP', + 'ETB', + 'EUR', + 'FJD', + 'FKP', + 'GBP', + 'GEL', + 'GIP', + 'GMD', + 'GNF', + 'GTQ', + 'GYD', + 'HKD', + 'HNL', + 'HTG', + 'HUF', + 'IDR', + 'ILS', + 'INR', + 'ISK', + 'JMD', + 'JPY', + 'KES', + 'KGS', + 'KHR', + 'KMF', + 'KRW', + 'KYD', + 'KZT', + 'LAK', + 'LBP', + 'LKR', + 'LRD', + 'LSL', + 'MAD', + 'MDL', + 'MGA', + 'MKD', + 'MMK', + 'MNT', + 'MOP', + 'MUR', + 'MVR', + 'MWK', + 'MXN', + 'MYR', + 'MZN', + 'NAD', + 'NGN', + 'NIO', + 'NOK', + 'NPR', + 'NZD', + 'PAB', + 'PEN', + 'PGK', + 'PHP', + 'PKR', + 'PLN', + 'PYG', + 'QAR', + 'RON', + 'RSD', + 'RUB', + 'RWF', + 'SAR', + 'SBD', + 'SCR', + 'SEK', + 'SGD', + 'SHP', + 'SLE', + 'SOS', + 'SRD', + 'STD', + 'SZL', + 'THB', + 'TJS', + 'TOP', + 'TRY', + 'TTD', + 'TWD', + 'TZS', + 'UAH', + 'UGX', + 'UYU', + 'UZS', + 'VND', + 'VUV', + 'WST', + 'XAF', + 'XCD', + 'XOF', + 'XPF', + 'YER', + 'ZAR', + 'ZMW', +] class CurrencyConverter { currencyFrom: string @@ -177,13 +295,11 @@ class CurrencyConverter { 'AUD': 'Australian Dollar', 'AZN': 'Azerbaijani M anat', 'BSD': 'Bahamian Dollar', - 'BHD': 'Bahraini Dinar', 'BBD': 'Bajan Dollar', 'BDT': 'Bangladeshi Taka', 'BYN': 'Belarusian Ruble', 'BZD': 'Belize Dollar', 'BMD': 'Bermudan Dollar', - 'BTN': 'Bhutan currency', 'BOB': 'Bolivian Boliviano', 'BAM': 'Bosnia-Herzegovina Convertible Mark', 'BWP': 'Botswanan Pula', @@ -196,16 +312,12 @@ class CurrencyConverter { 'CAD': 'Canadian Dollar', 'CVE': 'Cape Verdean Escudo', 'KYD': 'Cayman Islands Dollar', - 'FCFA': 'Central African CFA Franc', 'CLP': 'Chilean Peso', - 'CLF': 'Chilean Unit of Account (UF)', 'CNY': 'Chinese Yuan', 'COP': 'Colombian Peso', 'KMF': 'Comorian Franc', 'CDF': 'Congolese Franc', 'CRC': 'Costa Rican Colón', - 'HRK': 'Croatian Kuna', - 'CUC': 'Cuban Peso', 'CZK': 'Czech Koruna', 'DKK': 'Danish Krone', 'DJF': 'Djiboutian Franc', @@ -216,45 +328,41 @@ class CurrencyConverter { 'FJD': 'Fijian Dollar', 'GMD': 'Gambian dalasi', 'GEL': 'Georgian Lari', - 'GHS': 'Ghanaian Cedi', + 'GIP': 'Gibraltar pound', 'GTQ': 'Guatemalan Quetzal', 'GNF': 'Guinean Franc', 'GYD': 'Guyanaese Dollar', 'HTG': 'Haitian Gourde', + 'FKP': 'Falkland Islands pound', 'HNL': 'Honduran Lempira', 'HKD': 'Hong Kong Dollar', 'HUF': 'Hungarian Forint', 'ISK': 'Icelandic Króna', 'INR': 'Indian Rupee', 'IDR': 'Indonesian Rupiah', - 'IRR': 'Iranian Rial', - 'IQD': 'Iraqi Dinar', 'ILS': 'Israeli New Shekel', 'JMD': 'Jamaican Dollar', 'JPY': 'Japanese Yen', - 'JOD': 'Jordanian Dinar', 'KZT': 'Kazakhstani Tenge', 'KES': 'Kenyan Shilling', - 'KWD': 'Kuwaiti Dinar', 'KGS': 'Kyrgystani Som', 'LAK': 'Laotian Kip', 'LBP': 'Lebanese pound', 'LSL': 'Lesotho Loti', 'LRD': 'Liberian Dollar', - 'LYD': 'Libyan Dinar', 'MOP': 'Macanese Pataca', 'MKD': 'Macedonian Denar', 'MGA': 'Malagasy Ariary', 'MWK': 'Malawian Kwacha', 'MYR': 'Malaysian Ringgit', 'MVR': 'Maldivian Rufiyaa', - 'MRO': 'Mauritanian Ouguiya', 'MUR': 'Mauritian Rupee', 'MXN': 'Mexican Peso', 'MDL': 'Moldovan Leu', 'MAD': 'Moroccan Dirham', 'MZN': 'Mozambican metical', 'MMK': 'Myanmar Kyat', + 'MNT': 'Mongolia', 'NAD': 'Namibian dol lar', 'NPR': 'Nepalese Rupee', 'ANG': 'Netherlands Antillean Guilder', @@ -262,7 +370,6 @@ class CurrencyConverter { 'NIO': 'Nicaraguan Córdoba', 'NGN': 'Nigerian Naira', 'NOK': 'Norwegian Krone', - 'OMR': 'Omani Rial', 'PKR': 'Pakistani Rupee', 'PAB': 'Panamanian Balboa', 'PGK': 'Papua New Guinean Kina', @@ -274,47 +381,42 @@ class CurrencyConverter { 'RON': 'Romania n Leu', 'RUB': 'Russian Ruble', 'RWF': 'Rwandan franc', - 'SVC': 'Salvadoran Colón', 'SAR': 'Saudi Riyal', 'RSD': 'Serbian Dinar', 'SCR': 'Seychellois Rupee', - 'SLL': 'Sierra Leonean Leone', 'SGD': 'Singapore Dollar', 'SBD': 'Solomon Islands Dollar', 'SOS': 'Somali Shilling', 'ZAR': 'South African Rand', 'KRW': 'South Korean won', - 'VES': 'Sovereign Bolivar', 'LKR': 'Sri Lankan Rupee', - 'SDG': 'Sudanese pound', + 'SHP': 'Saint Helena pound', + 'SLE': 'Sierra Leonean leone', 'SRD': 'Surinamese Dollar', + 'STD': 'São Tomé and Príncipe', 'SZL': 'Swazi Lilangeni', 'SEK': 'Swedish Krona', - 'CF': 'Swiss Franc', 'CHF': 'Swiss Franc', 'TJS': 'Tajikistani Somoni', 'TZS': 'Tanzanian Shilling', 'THB': 'Thai Baht', 'TOP': 'Tongan Pa\'anga', 'TTD': 'Trinidad and Tobago Dollar', - 'TND': 'Tunisian Dinar', 'TRY': 'Turkish lira', - 'TMT': 'Turkmenistan manat', 'UGX': 'Ugandan Shilling', 'UAH': 'Ukrainian hryvnia', 'AED': 'United Arab Emirates Dirham', 'USD': 'United States Dollar', 'UYU': 'Uruguayan Peso', 'UZS': 'Uzbekistani Som', + 'VUV': 'Vanuatu Vatu', 'VND': 'Vietnamese dong', + 'WST': 'Samoa', 'XAF': 'Central African CFA franc', 'XOF': 'West African CFA franc', 'YER': 'Yemeni Rial', 'ZMW': 'Zambian Kwacha', - 'XBT': 'Bitcoin', - 'ETH': 'Ether', 'EUR': 'Euro', - 'LTC': 'Litecoin', 'TWD': 'NT$', 'PEN': 'Peruvian Sol' }