Files
rudarksh-frontend/app/contexts/currencyContext.js

282 lines
8.5 KiB
JavaScript

"use client";
import React, { createContext, useContext, useState, useEffect } from "react";
import axios from 'axios';
const CurrencyContext = createContext();
export const SUPPORTED_CURRENCIES = {
INR: { symbol: "₹", name: "Indian Rupee", country: "India" },
MYR: { symbol: "RM", name: "Malaysian Ringgit", country: "Malaysia" },
NPR: { symbol: "रू", name: "Nepalese Rupee", country: "Nepal" },
};
export const CurrencyProvider = ({ children }) => {
const [selectedCurrency, setSelectedCurrency] = useState("INR");
useEffect(() => {
const fetchCurrencyForCountry = async () => {
try {
const userCountry = localStorage.getItem('userCountry');
if (!userCountry) {
return;
}
const response = await axios.get(`https://restcountries.com/v3.1/name/${userCountry}`);
if (response.data && response.data.length > 0) {
const countryData = response.data[0];
if (countryData.currencies) {
const currencyCode = Object.keys(countryData.currencies)[0];
if (currencyCode) {
setSelectedCurrency(currencyCode);
}
}
}
} catch (error) {
console.error("Error fetching currency for country:", error);
setSelectedCurrency("INR")
}
};
fetchCurrencyForCountry();
}, []);
const [exchangeRates, setExchangeRates] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const [userCountry, setUserCountry] = useState(null);
const [allCountries, setAllCountries] = useState([]);
const [countryCurrencyMap, setCountryCurrencyMap] = useState({});
// Fetch all countries and their currencies
const fetchCountriesAndCurrencies = async () => {
try {
// First, get the list of countries
const countriesResponse = await fetch('https://countriesnow.space/api/v0.1/countries/');
const countriesData = await countriesResponse.json();
if (!countriesData.error) {
setAllCountries(countriesData.data);
const currencyResponse = await fetch('https://restcountries.com/v3.1/all?fields=name,currencies');
const currencyData = await currencyResponse.json();
const currencyMap = {};
const currencyDetails = {};
currencyData.forEach(country => {
const countryName = country.name.common;
if (country.currencies) {
const currencyCode = Object.keys(country.currencies)[0];
if (currencyCode) {
currencyMap[countryName] = currencyCode;
if (!currencyDetails[currencyCode]) {
const currencyInfo = country.currencies[currencyCode];
currencyDetails[currencyCode] = {
symbol: currencyInfo.symbol || currencyCode,
name: currencyInfo.name || `${currencyCode} Currency`,
country: countryName
};
}
}
}
});
Object.keys(currencyDetails).forEach(code => {
if (!SUPPORTED_CURRENCIES[code]) {
SUPPORTED_CURRENCIES[code] = currencyDetails[code];
}
});
setCountryCurrencyMap(currencyMap);
// Check if we have a stored country and set the currency accordingly
const storedCountry = localStorage.getItem('userCountry');
if (storedCountry && currencyMap[storedCountry]) {
const currencyCode = currencyMap[storedCountry];
if (currencyCode) {
setSelectedCurrency(currencyCode);
localStorage.setItem('selectedCurrency', currencyCode);
}
}
}
} catch (error) {
console.error("Error fetching countries and currencies:", error);
}
};
const fetchExchangeRates = async () => {
try {
setIsLoading(true);
setError(null);
const cachedData = localStorage.getItem("exchangeRates");
const cached = cachedData ? JSON.parse(cachedData) : null;
if (cached && new Date().getTime() - cached.timestamp < 24 * 60 * 60 * 1000) {
setExchangeRates(cached.rates);
setIsLoading(false);
return;
}
try {
const response = await axios.get(`https://open.er-api.com/v6/latest/${selectedCurrency}`);
const data = response.data;
if (!data.rates) {
throw new Error("API request failed - no rates returned");
}
const rates = {};
rates["INR"] = 1; // Base currency
Object.keys(SUPPORTED_CURRENCIES).forEach(currencyCode => {
if (currencyCode !== "INR" && data.rates[currencyCode]) {
rates[currencyCode] = data.rates[currencyCode];
}
});
localStorage.setItem(
"exchangeRates",
JSON.stringify({ rates, timestamp: new Date().getTime() })
);
setExchangeRates(rates);
} catch (error) {
console.error("Error fetching exchange rates:", error);
setError("Failed to load currency conversion rates. Please try again later.");
if (cached) {
console.log("Using older cached rates as fallback");
setExchangeRates(cached.rates);
} else {
setExchangeRates(null);
}
}
setIsLoading(false);
} catch (error) {
console.error("Error in exchange rate handling:", error);
setError("Failed to load currency conversion rates");
setIsLoading(false);
}
};
const convertPrice = (price) => {
if (!price || typeof price !== "number") return price;
if (!exchangeRates || !exchangeRates[selectedCurrency]) return price;
if (selectedCurrency === "INR") return price;
try {
const rate = exchangeRates[selectedCurrency];
return rate ? Number((price * rate).toFixed(2)) : price;
} catch (err) {
console.error("Price conversion error:", err);
return price;
}
};
const formatPrice = (price) => {
const convertedPrice = convertPrice(price);
if (typeof convertedPrice !== "number")
return `${SUPPORTED_CURRENCIES[selectedCurrency]?.symbol || "$"}0.00`;
try {
return new Intl.NumberFormat(getLocaleFromCurrency(selectedCurrency), {
style: "currency",
currency: selectedCurrency,
}).format(convertedPrice);
} catch (err) {
return `${
SUPPORTED_CURRENCIES[selectedCurrency]?.symbol || "$"
}${convertedPrice.toFixed(2)}`;
}
};
const getLocaleFromCurrency = (currency) => {
const localeMap = {
INR: "en-IN",
USD: "en-US",
GBP: "en-GB",
EUR: "de-DE",
JPY: "ja-JP",
AUD: "en-AU",
CAD: "en-CA",
SGD: "en-SG",
MYR: "ms-MY",
NPR: "ne-NP",
IDR: "id-ID",
THB: "th-TH",
PHP: "fil-PH",
VND: "vi-VN",
KRW: "ko-KR",
};
return localeMap[currency] || "en-US";
};
const setUserCurrencyFromCountry = (country) => {
if (country && countryCurrencyMap[country]) {
const currencyCode = countryCurrencyMap[country];
if (currencyCode && SUPPORTED_CURRENCIES[currencyCode]) {
setSelectedCurrency(currencyCode);
localStorage.setItem('selectedCurrency', currencyCode);
}
}
};
useEffect(() => {
const storedCountry = localStorage.getItem('userCountry');
if (storedCountry) {
setUserCountry(storedCountry);
}
fetchCountriesAndCurrencies();
fetchExchangeRates();
const savedCurrency = localStorage.getItem('selectedCurrency');
if (savedCurrency && SUPPORTED_CURRENCIES[savedCurrency]) {
setSelectedCurrency(savedCurrency);
}
const interval = setInterval(fetchExchangeRates, 24 * 60 * 60 * 1000);
return () => clearInterval(interval);
}, []);
useEffect(() => {
if (userCountry && countryCurrencyMap[userCountry]) {
setUserCurrencyFromCountry(userCountry);
}
}, [userCountry, countryCurrencyMap]);
const value = {
selectedCurrency,
setSelectedCurrency,
convertPrice,
formatPrice,
isLoading,
error,
SUPPORTED_CURRENCIES,
refreshRates: fetchExchangeRates,
allCountries,
setUserCountry,
userCountry
};
return (
<CurrencyContext.Provider value={value}>
{children}
</CurrencyContext.Provider>
);
};
export const useCurrency = () => {
const context = useContext(CurrencyContext);
if (!context) {
throw new Error('useCurrency must be used within a CurrencyProvider');
}
return context;
};