import React from 'react';
import { HashRouter, BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { HelmetProvider } from 'react-helmet-async';
import { Toaster } from 'sonner';
// Theme
import { ThemeProvider } from './contexts/ThemeContext';
import { BaseLayout } from './layouts/BaseLayout';
// Pages
import Shop from './pages/Shop';
import Product from './pages/Product';
import Cart from './pages/Cart';
import Checkout from './pages/Checkout';
import ThankYou from './pages/ThankYou';
import Account from './pages/Account';
import Wishlist from './pages/Wishlist';
import Login from './pages/Login';
import ForgotPassword from './pages/ForgotPassword';
import ResetPassword from './pages/ResetPassword';
import OrderPay from './pages/OrderPay';
import { DynamicPageRenderer } from './pages/DynamicPage';
// Create QueryClient instance
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5, // 5 minutes
refetchOnWindowFocus: false,
retry: 1,
},
},
});
// Get theme config from window (injected by PHP)
const getThemeConfig = () => {
const config = (window as any).woonoowCustomer?.theme;
// Default config if not provided
return config || {
mode: 'full',
layout: 'modern',
colors: {
primary: '#3B82F6',
secondary: '#8B5CF6',
accent: '#10B981',
},
typography: {
preset: 'professional',
},
};
};
// Get appearance settings from window
const getAppearanceSettings = () => {
return (window as any).woonoowCustomer?.appearanceSettings || {};
};
// Get initial route from data attribute or derive from SPA mode
const getInitialRoute = () => {
const appEl = document.getElementById('woonoow-customer-app');
const initialRoute = appEl?.getAttribute('data-initial-route');
if (initialRoute) return initialRoute;
// Derive from SPA mode if no explicit route
const spaMode = (window as any).woonoowCustomer?.spaMode || 'full';
if (spaMode === 'checkout_only') return '/checkout';
return '/shop'; // Default for full mode
};
// Get front page slug from config
const getFrontPageSlug = () => {
return (window as any).woonoowCustomer?.frontPageSlug || null;
};
// Router wrapper component that uses hooks requiring Router context
function AppRoutes() {
const initialRoute = getInitialRoute();
const frontPageSlug = getFrontPageSlug();
return (
{/* License Connect - Standalone focused page without layout */}
} />
{/* All other routes wrapped in BaseLayout */}
{/* Root route: If frontPageSlug exists, render it. Else redirect to initialRoute (e.g. /shop) */}
) : (
)
}
/>
{/* Shop Routes */}
} />
} />
{/* Cart & Checkout */}
} />
} />
} />
} />
} />
{/* Wishlist - Public route accessible to guests */}
} />
{/* Login & Auth */}
} />
} />
} />
{/* My Account */}
} />
{/* Dynamic Pages - CPT content with path base (e.g., /blog/:slug) */}
} />
{/* Dynamic Pages - Structural pages (e.g., /about, /contact) */}
} />
}
/>
);
}
// Get router config from WordPress
const getRouterConfig = () => {
const config = (window as any).woonoowCustomer;
return {
useBrowserRouter: config?.useBrowserRouter ?? true,
basePath: config?.basePath ?? '/store',
};
};
// Router wrapper that conditionally uses BrowserRouter or HashRouter
function RouterProvider({ children }: { children: React.ReactNode }) {
const { useBrowserRouter, basePath } = getRouterConfig();
if (useBrowserRouter) {
return {children};
}
return {children};
}
function App() {
const themeConfig = getThemeConfig();
const appearanceSettings = getAppearanceSettings();
const toastPosition = (appearanceSettings?.general?.toast_position || 'top-right') as any;
// Inject gradient CSS variables
React.useEffect(() => {
// appearanceSettings is already the 'data' object from Assets.php injection
// Structure: { general: { colors: { primary, secondary, accent, text, background, gradientStart, gradientEnd } } }
const colors = appearanceSettings?.general?.colors;
if (colors) {
const root = document.documentElement;
// Inject all color settings as CSS variables
if (colors.primary) root.style.setProperty('--wn-primary', colors.primary);
if (colors.secondary) root.style.setProperty('--wn-secondary', colors.secondary);
if (colors.accent) root.style.setProperty('--wn-accent', colors.accent);
if (colors.text) root.style.setProperty('--wn-text', colors.text);
if (colors.background) root.style.setProperty('--wn-background', colors.background);
if (colors.gradientStart) root.style.setProperty('--wn-gradient-start', colors.gradientStart);
if (colors.gradientEnd) root.style.setProperty('--wn-gradient-end', colors.gradientEnd);
}
}, [appearanceSettings]);
return (
{/* Toast notifications - position from settings */}
);
}
export default App;