diff --git a/admin-spa/src/routes/Appearance/General.tsx b/admin-spa/src/routes/Appearance/General.tsx index 110076d..956890c 100644 --- a/admin-spa/src/routes/Appearance/General.tsx +++ b/admin-spa/src/routes/Appearance/General.tsx @@ -76,11 +76,16 @@ export default function AppearanceGeneral() { // Load available pages const pagesResponse = await api.get('/pages/list'); - if (pagesResponse.data?.data) { - setAvailablePages(pagesResponse.data.data); + console.log('Pages API response:', pagesResponse); + if (pagesResponse.data) { + console.log('Pages loaded:', pagesResponse.data); + setAvailablePages(pagesResponse.data); + } else { + console.warn('No pages data in response:', pagesResponse); } } catch (error) { console.error('Failed to load settings:', error); + console.error('Error details:', error); } finally { setLoading(false); } diff --git a/customer-spa/src/App.tsx b/customer-spa/src/App.tsx index 097d35f..b01b26e 100644 --- a/customer-spa/src/App.tsx +++ b/customer-spa/src/App.tsx @@ -6,6 +6,7 @@ import { Toaster } from 'sonner'; // Theme import { ThemeProvider } from './contexts/ThemeContext'; import { BaseLayout } from './layouts/BaseLayout'; +import { useAddToCartFromUrl } from './hooks/useAddToCartFromUrl'; // Pages import Shop from './pages/Shop'; @@ -56,14 +57,21 @@ function App() { const appearanceSettings = getAppearanceSettings(); const toastPosition = (appearanceSettings?.general?.toast_position || 'top-right') as any; + // Handle add-to-cart from URL parameters + useAddToCartFromUrl(); + // Get initial route from data attribute (set by PHP based on SPA mode) const getInitialRoute = () => { const appEl = document.getElementById('woonoow-customer-app'); const initialRoute = appEl?.getAttribute('data-initial-route'); + console.log('[WooNooW Customer] Initial route from data attribute:', initialRoute); + console.log('[WooNooW Customer] App element:', appEl); + console.log('[WooNooW Customer] All data attributes:', appEl?.dataset); return initialRoute || '/shop'; // Default to shop if not specified }; const initialRoute = getInitialRoute(); + console.log('[WooNooW Customer] Using initial route:', initialRoute); return ( diff --git a/customer-spa/src/hooks/useAddToCartFromUrl.ts b/customer-spa/src/hooks/useAddToCartFromUrl.ts new file mode 100644 index 0000000..59adb22 --- /dev/null +++ b/customer-spa/src/hooks/useAddToCartFromUrl.ts @@ -0,0 +1,95 @@ +import { useEffect } from 'react'; +import { useNavigate, useLocation } from 'react-router-dom'; +import { toast } from 'sonner'; + +/** + * Hook to handle add-to-cart from URL parameters + * Supports both simple and variable products + * + * URL formats: + * - Simple product: ?add-to-cart=123 + * - Variable product: ?add-to-cart=123&variation_id=456 + * - With quantity: ?add-to-cart=123&quantity=2 + */ +export function useAddToCartFromUrl() { + const navigate = useNavigate(); + const location = useLocation(); + + useEffect(() => { + const params = new URLSearchParams(window.location.search); + const productId = params.get('add-to-cart'); + + if (!productId) return; + + const variationId = params.get('variation_id'); + const quantity = parseInt(params.get('quantity') || '1', 10); + + console.log('[WooNooW] Add to cart from URL:', { + productId, + variationId, + quantity, + fullUrl: window.location.href, + }); + + // Add product to cart + addToCart(productId, variationId, quantity) + .then(() => { + // Remove URL parameters after adding to cart + const cleanUrl = window.location.pathname + window.location.hash; + window.history.replaceState({}, '', cleanUrl); + + // Navigate to cart if not already there + if (!location.pathname.includes('/cart')) { + navigate('/cart'); + } + }) + .catch((error) => { + console.error('[WooNooW] Failed to add product to cart:', error); + toast.error('Failed to add product to cart'); + }); + }, []); // Run once on mount +} + +async function addToCart( + productId: string, + variationId: string | null, + quantity: number +): Promise { + const apiRoot = (window as any).woonoowCustomer?.apiRoot || '/wp-json/woonoow/v1'; + const nonce = (window as any).woonoowCustomer?.nonce || ''; + + const body: any = { + product_id: parseInt(productId, 10), + quantity, + }; + + if (variationId) { + body.variation_id = parseInt(variationId, 10); + } + + console.log('[WooNooW] Adding to cart:', body); + + const response = await fetch(`${apiRoot}/cart/add`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-WP-Nonce': nonce, + }, + credentials: 'include', + body: JSON.stringify(body), + }); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(errorData.message || 'Failed to add to cart'); + } + + const data = await response.json(); + + if (!data.success) { + throw new Error(data.message || 'Failed to add to cart'); + } + + console.log('[WooNooW] Product added to cart:', data); + toast.success('Product added to cart'); +} diff --git a/templates/spa-full-page.php b/templates/spa-full-page.php index cfad91e..b061218 100644 --- a/templates/spa-full-page.php +++ b/templates/spa-full-page.php @@ -12,15 +12,21 @@ $appearance_settings = get_option('woonoow_appearance_settings', []); $spa_mode = isset($appearance_settings['general']['spa_mode']) ? $appearance_settings['general']['spa_mode'] : 'full'; + // Debug logging + error_log('[WooNooW SPA Template] Settings: ' . print_r($appearance_settings, true)); + error_log('[WooNooW SPA Template] SPA Mode: ' . $spa_mode); + // Set initial page based on mode if ($spa_mode === 'checkout_only') { // Checkout Only mode starts at cart $page_type = 'cart'; $data_attrs = 'data-page="cart" data-initial-route="/cart"'; + error_log('[WooNooW SPA Template] Using CART initial route'); } else { // Full SPA mode starts at shop $page_type = 'shop'; $data_attrs = 'data-page="shop" data-initial-route="/shop"'; + error_log('[WooNooW SPA Template] Using SHOP initial route'); } ?>