chore: setup project for production
This commit is contained in:
150
app/contexts/currencyContext.js
Normal file
150
app/contexts/currencyContext.js
Normal file
@@ -0,0 +1,150 @@
|
||||
"use client";
|
||||
import React, { createContext, useContext, useState, useEffect } from "react";
|
||||
|
||||
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");
|
||||
const [exchangeRates, setExchangeRates] = useState(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const currencies = Object.keys(SUPPORTED_CURRENCIES)
|
||||
.filter((key) => key !== "INR")
|
||||
.join(",");
|
||||
|
||||
const response = await fetch(
|
||||
`https://apilayer.net/api/live?access_key=9bcb30907dee1cda9866f7b49f0f8def¤cies=${currencies}&source=INR&format=1`
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch exchange rates");
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
if (!data.success) {
|
||||
throw new Error(data.error?.info || "API request failed");
|
||||
}
|
||||
|
||||
const rates = Object.keys(SUPPORTED_CURRENCIES).reduce(
|
||||
(acc, currency) => {
|
||||
if (currency === "INR") {
|
||||
acc[currency] = 1;
|
||||
} else {
|
||||
const rate = data.quotes?.[`INR${currency}`];
|
||||
acc[currency] = rate || null;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
const ratesData = {
|
||||
rates,
|
||||
timestamp: data.timestamp * 1000,
|
||||
};
|
||||
|
||||
localStorage.setItem("exchangeRates", JSON.stringify(ratesData));
|
||||
setExchangeRates(rates);
|
||||
} catch (err) {
|
||||
setError("Error fetching exchange rates");
|
||||
console.error("Exchange rate fetch error:", err);
|
||||
} finally {
|
||||
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",
|
||||
MYR: "ms-MY",
|
||||
NPR: "ne-NP",
|
||||
};
|
||||
return localeMap[currency] || "en-US";
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchExchangeRates();
|
||||
const interval = setInterval(fetchExchangeRates, 24 * 60 * 60 * 1000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const value = {
|
||||
selectedCurrency,
|
||||
setSelectedCurrency,
|
||||
convertPrice,
|
||||
formatPrice,
|
||||
isLoading,
|
||||
error,
|
||||
SUPPORTED_CURRENCIES,
|
||||
refreshRates: fetchExchangeRates,
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
92
app/contexts/mainContext.js
Normal file
92
app/contexts/mainContext.js
Normal file
@@ -0,0 +1,92 @@
|
||||
'use client'
|
||||
import axios from "axios";
|
||||
import { createContext, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
|
||||
|
||||
|
||||
const MainContext = createContext()
|
||||
|
||||
export const ContextProvider = ({ children }) => {
|
||||
const router = useRouter()
|
||||
const [token, setToken] = useState(() => {
|
||||
if (typeof window !== 'undefined' && localStorage.getItem('token')) {
|
||||
return localStorage.getItem('token');
|
||||
}
|
||||
return null;
|
||||
});
|
||||
const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL;
|
||||
|
||||
|
||||
const loginUser = async (credentials) => {
|
||||
try {
|
||||
const response = await axios.post(`${backendUrl}/account/login/`, credentials);
|
||||
console.log("Login Successful:", response.data);
|
||||
setToken(response.data.token)
|
||||
localStorage.setItem('token',response.data.token)
|
||||
toast.success('Login Successful');
|
||||
router.push('/')
|
||||
|
||||
return response.data
|
||||
} catch (error) {
|
||||
if (error.response) {
|
||||
|
||||
console.error("Error during login:", error.response.data);
|
||||
const message = error.response.data.message || "Login failed. Please try again.";
|
||||
toast.error(message);
|
||||
} else if (error.request) {
|
||||
|
||||
console.error("No response during login:", error.request);
|
||||
toast.error("Unable to connect to the server. Please try again later.");
|
||||
} else {
|
||||
|
||||
console.error("Unexpected error during login:", error.message);
|
||||
toast.error("An unexpected error occurred. Please try again.");
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const registerUser = async (credentials) => {
|
||||
try {
|
||||
const response = await axios.post(`${backendUrl}/account/register/`, credentials);
|
||||
console.log("Register Successful:", response.data);
|
||||
setToken(response.data.token)
|
||||
localStorage.setItem('token',response.data.token)
|
||||
toast.success('Registration Successful');
|
||||
router.push('/')
|
||||
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
if (error.response) {
|
||||
console.error("Error during registration:", error.response.data);
|
||||
const message = error.response.data.message || "Registration failed. Please try again.";
|
||||
toast.error(message);
|
||||
} else if (error.request) {
|
||||
|
||||
console.error("No response during registration:", error.request);
|
||||
toast.error("Unable to connect to the server. Please try again later.");
|
||||
} else {
|
||||
|
||||
console.error("Unexpected error during registration:", error.message);
|
||||
toast.error("An unexpected error occurred. Please try again.");
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<MainContext.Provider value={{
|
||||
loginUser,
|
||||
registerUser,
|
||||
token,
|
||||
setToken
|
||||
}}>
|
||||
{children}
|
||||
</MainContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export default MainContext
|
||||
61
app/contexts/productContext.js
Normal file
61
app/contexts/productContext.js
Normal file
@@ -0,0 +1,61 @@
|
||||
"use client";
|
||||
|
||||
import authAxios, { backendUrl } from "@/utils/axios";
|
||||
import axios from "axios";
|
||||
import { createContext, useEffect, useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
const ProductContext = createContext();
|
||||
|
||||
export const ProductContextProvider = ({ children }) => {
|
||||
const [products, setProducts] = useState(null);
|
||||
const [category, setCategory] = useState(null);
|
||||
|
||||
|
||||
const fetchData = async () => {
|
||||
const response = await axios.get(`${backendUrl}/products/variants/`);
|
||||
setProducts(response.data)
|
||||
};
|
||||
|
||||
const fetchCategory = async () => {
|
||||
const response = await axios.get(`${backendUrl}/products/category/`);
|
||||
setCategory(response.data);
|
||||
|
||||
};
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
fetchCategory();
|
||||
}, []);
|
||||
|
||||
const cartFn = async (variantId, designId, quantity) => {
|
||||
|
||||
try{
|
||||
const response = await authAxios.post('/orders/cart/manage_item/',{
|
||||
variant: variantId,
|
||||
design: designId,
|
||||
quantity: quantity
|
||||
})
|
||||
toast.success('Modified Cart Successfully!')
|
||||
return response
|
||||
}
|
||||
catch(error){
|
||||
if (error?.response.data?.detail) {
|
||||
toast.error('Please login First!')
|
||||
}
|
||||
else {
|
||||
toast.error(error?.response.data?.error || 'Failed To Modify Cart')
|
||||
}
|
||||
return error
|
||||
}
|
||||
}
|
||||
return (
|
||||
<ProductContext.Provider value={{
|
||||
products,
|
||||
cartFn,
|
||||
category,
|
||||
|
||||
}}>{children}</ProductContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductContext;
|
||||
Reference in New Issue
Block a user