E-Commerce-Module/frontend/src/App.jsx

199 lines
No EOL
8.6 KiB
JavaScript

import { Routes, Route } from 'react-router-dom';
import { Suspense, lazy, useEffect } from 'react';
import { CircularProgress, Box } from '@mui/material';
import Notifications from '@components/Notifications';
import ProtectedRoute from '@components/ProtectedRoute';
import { StripeProvider } from './context/StripeContext';
import useBrandingSettings from '@hooks/brandingHooks';
import imageUtils from '@utils/imageUtils';
import Clarity from '@microsoft/clarity';
// Import layouts
import MainLayout from './layouts/MainLayout';
import AuthLayout from './layouts/AuthLayout';
import AdminLayout from './layouts/AdminLayout';
// Pages - lazy loaded to reduce initial bundle size
const HomePage = lazy(() => import('@pages/HomePage'));
const ProductsPage = lazy(() => import('@pages/ProductsPage'));
const ProductDetailPage = lazy(() => import('@pages/ProductDetailPage'));
const CartPage = lazy(() => import('@pages/CartPage'));
const CheckoutPage = lazy(() => import('@pages/CheckoutPage'));
const PaymentSuccessPage = lazy(() => import('@pages/PaymentSuccessPage'));
const PaymentCancelPage = lazy(() => import('@pages/PaymentCancelPage'));
const LoginPage = lazy(() => import('@pages/LoginPage'));
const RegisterPage = lazy(() => import('@pages/RegisterPage'));
const VerifyPage = lazy(() => import('@pages/VerifyPage'));
const AdminDashboardPage = lazy(() => import('@pages/Admin/DashboardPage'));
const AdminProductsPage = lazy(() => import('@pages/Admin/ProductsPage'));
const AdminProductEditPage = lazy(() => import('@pages/Admin/ProductEditPage'));
const AdminCategoriesPage = lazy(() => import('@pages/Admin/CategoriesPage'));
const AdminCustomersPage = lazy(() => import('@pages/Admin/CustomersPage'));
const AdminOrdersPage = lazy(() => import('@pages/Admin/OrdersPage'));
const AdminSettingsPage = lazy(() => import('@pages/Admin/SettingsPage'));
const AdminReportsPage = lazy(() => import('@pages/Admin/ReportsPage'));
const UserOrdersPage = lazy(() => import('@pages/UserOrdersPage'));
const NotFoundPage = lazy(() => import('@pages/NotFoundPage'));
const CouponsPage = lazy(() => import('@pages/Admin/CouponsPage'));
const CouponEditPage = lazy(() => import('@pages/CouponEditPage'));
const CouponRedemptionsPage = lazy(() => import('@pages/CouponRedemptionsPage'));
const BlogPage = lazy(() => import('@pages/BlogPage'));
const BlogDetailPage = lazy(() => import('@pages/BlogDetailPage'));
const AdminBlogPage = lazy(() => import('@pages/Admin/BlogPage'));
const BlogEditPage = lazy(() => import('@pages/Admin/BlogEditPage'));
const AdminBlogCommentsPage = lazy(() => import('@pages/Admin/BlogCommentsPage'));
const AdminProductReviewsPage = lazy(() => import('@pages/Admin/ProductReviewsPage'));
const EmailTemplatesPage = lazy(() => import('@pages/Admin/EmailTemplatesPage'));
const BrandingPage = lazy(() => import('@pages/Admin/BrandingPage'));
const projectId = "rcjhrd0t72"
Clarity.init(projectId);
// Loading component for suspense fallback
const LoadingComponent = () => (
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
<CircularProgress />
</Box>
);
function App() {
// Use the centralized hook to fetch branding settings
const { data: brandingSettings, isLoading } = useBrandingSettings();
// Update the document head with branding settings
useEffect(() => {
if (brandingSettings) {
// Update document title
if (brandingSettings?.site_name) {
document.title = brandingSettings?.site_name;
}
// Update favicon if available
if (brandingSettings?.favicon_url) {
// Remove any existing favicon links
const existingLinks = document.querySelectorAll("link[rel*='icon']");
existingLinks.forEach(link => link.parentNode.removeChild(link));
// Create and add new favicon link
const link = document.createElement('link');
link.type = 'image/x-icon';
link.rel = 'shortcut icon';
link.href = imageUtils.getImageUrl(brandingSettings?.favicon_url); //brandingSettings?.favicon_url;
document.head.appendChild(link);
// Also add Apple touch icon for iOS devices
const touchIcon = document.createElement('link');
touchIcon.rel = 'apple-touch-icon';
touchIcon.href = imageUtils.getImageUrl(brandingSettings?.favicon_url);
document.head.appendChild(touchIcon);
console.log(link);
}
// Add meta description if available
if (brandingSettings?.site_description) {
// Remove any existing description meta tags
const existingMeta = document.querySelector("meta[name='description']");
if (existingMeta) {
existingMeta.parentNode.removeChild(existingMeta);
}
// Create and add new meta description
const meta = document.createElement('meta');
meta.name = 'description';
meta.content = brandingSettings?.site_description;
document.head.appendChild(meta);
}
}
}, [brandingSettings]);
return (
<StripeProvider>
<Suspense fallback={<LoadingComponent />}>
<Notifications />
<Routes>
{/* Main routes with MainLayout */}
<Route path="/" element={<MainLayout />}>
<Route path="account/orders" element={
<ProtectedRoute>
<UserOrdersPage />
</ProtectedRoute>
} />
<Route index element={<HomePage />} />
<Route path="products" element={<ProductsPage />} />
<Route path="products/:id" element={<ProductDetailPage />} />
<Route path="cart" element={
<ProtectedRoute>
<CartPage />
</ProtectedRoute>
} />
<Route path="checkout" element={
<ProtectedRoute>
<CheckoutPage />
</ProtectedRoute>
} />
{/* Payment success and cancel routes */}
<Route path="checkout/success" element={
<ProtectedRoute>
<PaymentSuccessPage />
</ProtectedRoute>
} />
<Route path="checkout/cancel" element={
<ProtectedRoute>
<PaymentCancelPage />
</ProtectedRoute>
} />
{/* Blog routes */}
<Route path="blog" element={<BlogPage />} />
<Route path="blog/:slug" element={<BlogDetailPage />} />
</Route>
{/* Auth routes with AuthLayout */}
<Route path="/auth" element={<AuthLayout />}>
<Route path="login" element={<LoginPage />} />
<Route path="register" element={<RegisterPage />} />
</Route>
{/* Verification route - standalone page */}
<Route path="/verify" element={<VerifyPage />} />
{/* Admin routes with AdminLayout - protected for admins only */}
<Route path="/admin" element={
<ProtectedRoute requireAdmin={true} redirectTo="/">
<AdminLayout />
</ProtectedRoute>
}>
<Route index element={<AdminDashboardPage />} />
<Route path="products" element={<AdminProductsPage />} />
<Route path="products/:id" element={<AdminProductEditPage />} />
<Route path="products/new" element={<AdminProductEditPage />} />
<Route path="categories" element={<AdminCategoriesPage />} />
<Route path="customers" element={<AdminCustomersPage />} />
<Route path="settings" element={<AdminSettingsPage />} />
<Route path="orders" element={<AdminOrdersPage />} />
<Route path="reports" element={<AdminReportsPage />} />
<Route path="coupons" element={<CouponsPage />} />
<Route path="coupons/new" element={<CouponEditPage />} />
<Route path="coupons/:id" element={<CouponEditPage />} />
<Route path="coupons/:id/redemptions" element={<CouponRedemptionsPage />} />
<Route path="blog" element={<AdminBlogPage />} />
<Route path="blog/new" element={<BlogEditPage />} />
<Route path="blog/:id" element={<BlogEditPage />} />
<Route path="blog-comments" element={<AdminBlogCommentsPage />} />
<Route path="product-reviews" element={<AdminProductReviewsPage />} />
<Route path="email-templates" element={<EmailTemplatesPage />} />
<Route path="branding" element={<BrandingPage />} /> {/* New Branding Route */}
</Route>
{/* Catch-all route for 404s */}
<Route path="*" element={<NotFoundPage />} />
</Routes>
</Suspense>
</StripeProvider>
);
}
export default App;