From fe98e6233d0c04341fb5ec67abe3c737429185e7 Mon Sep 17 00:00:00 2001 From: Dwindi Ramadhana Date: Tue, 30 Dec 2025 20:33:15 +0700 Subject: [PATCH] refactor: Simplify to single SPA entry page architecture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User feedback: 'SPA means Single Page, why 4 pages?' Correct architecture: - 1 SPA entry page (e.g., /store) - SPA Mode determines initial route: * Full SPA → starts at shop page * Checkout Only → starts at cart page * Disabled → never loads - React Router handles rest via /#/ routing Changes: - Admin UI: Changed from 4 page selectors to 1 SPA entry page - Backend: spa_pages array → spa_page integer - Template: Initial route based on spa_mode setting - Simplified is_spa_page() checks (single ID comparison) Benefits: - User can set /store as homepage (Settings → Reading) - Landing page → CTA → direct to cart/checkout - Clean single entry point - Mode controls behavior, not multiple pages Example flow: - Visit https://site.com/store - Full SPA: loads shop, navigate via /#/product/123 - Checkout Only: loads cart, navigate via /#/checkout - Homepage: set /store as homepage, SPA loads on site root Next: Add direct-to-cart CTA with product parameter --- admin-spa/src/routes/Appearance/General.tsx | 104 ++++---------------- includes/Admin/AppearanceController.php | 14 +-- includes/Frontend/Assets.php | 16 ++- includes/Frontend/TemplateOverride.php | 16 ++- templates/spa-full-page.php | 26 +++-- 5 files changed, 45 insertions(+), 131 deletions(-) diff --git a/admin-spa/src/routes/Appearance/General.tsx b/admin-spa/src/routes/Appearance/General.tsx index 8752f26..110076d 100644 --- a/admin-spa/src/routes/Appearance/General.tsx +++ b/admin-spa/src/routes/Appearance/General.tsx @@ -21,12 +21,7 @@ interface WordPressPage { export default function AppearanceGeneral() { const [loading, setLoading] = useState(true); const [spaMode, setSpaMode] = useState<'disabled' | 'checkout_only' | 'full'>('full'); - const [spaPages, setSpaPages] = useState({ - shop: 0, - cart: 0, - checkout: 0, - account: 0, - }); + const [spaPage, setSpaPage] = useState(0); const [availablePages, setAvailablePages] = useState([]); const [toastPosition, setToastPosition] = useState('top-right'); const [typographyMode, setTypographyMode] = useState<'predefined' | 'custom_google'>('predefined'); @@ -59,14 +54,7 @@ export default function AppearanceGeneral() { if (general) { if (general.spa_mode) setSpaMode(general.spa_mode); - if (general.spa_pages) { - setSpaPages({ - shop: general.spa_pages.shop || 0, - cart: general.spa_pages.cart || 0, - checkout: general.spa_pages.checkout || 0, - account: general.spa_pages.account || 0, - }); - } + if (general.spa_page) setSpaPage(general.spa_page || 0); if (general.toast_position) setToastPosition(general.toast_position); if (general.typography) { setTypographyMode(general.typography.mode || 'predefined'); @@ -105,7 +93,7 @@ export default function AppearanceGeneral() { try { await api.post('/appearance/general', { spaMode, - spaPages, + spaPage, toastPosition, typography: { mode: typographyMode, @@ -142,7 +130,7 @@ export default function AppearanceGeneral() { Disabled

- Use WordPress default pages (no SPA functionality) + SPA never loads (use WordPress default pages)

@@ -154,7 +142,7 @@ export default function AppearanceGeneral() { Checkout Only

- SPA for checkout flow only (cart, checkout, thank you) + SPA starts at cart page (cart → checkout → thank you → account)

@@ -166,90 +154,33 @@ export default function AppearanceGeneral() { Full SPA

- Entire customer-facing site uses SPA (recommended) + SPA starts at shop page (shop → product → cart → checkout → account)

- {/* SPA Pages */} + {/* SPA Page */}
- These pages will render directly to the body element with no theme interference. - This is the recommended approach for a clean SPA experience. + This page will render the full SPA to the body element with no theme interference. + The SPA Mode above determines the initial route (shop or cart). React Router handles navigation via /#/ routing. - + - - - - - - - - - - - - +

+ Full SPA: Loads shop page initially
+ Checkout Only: Loads cart page initially
+ Tip: You can set this page as your homepage in Settings → Reading +

diff --git a/includes/Admin/AppearanceController.php b/includes/Admin/AppearanceController.php index ba2f970..9265b47 100644 --- a/includes/Admin/AppearanceController.php +++ b/includes/Admin/AppearanceController.php @@ -89,12 +89,7 @@ class AppearanceController { $general_data = [ 'spa_mode' => sanitize_text_field($request->get_param('spaMode')), - 'spa_pages' => [ - 'shop' => absint($request->get_param('spaPages')['shop'] ?? 0), - 'cart' => absint($request->get_param('spaPages')['cart'] ?? 0), - 'checkout' => absint($request->get_param('spaPages')['checkout'] ?? 0), - 'account' => absint($request->get_param('spaPages')['account'] ?? 0), - ], + 'spa_page' => absint($request->get_param('spaPage') ?? 0), 'toast_position' => sanitize_text_field($request->get_param('toastPosition') ?? 'top-right'), 'typography' => [ 'mode' => sanitize_text_field($request->get_param('typography')['mode'] ?? 'predefined'), @@ -415,12 +410,7 @@ class AppearanceController { return [ 'general' => [ 'spa_mode' => 'full', - 'spa_pages' => [ - 'shop' => 0, - 'cart' => 0, - 'checkout' => 0, - 'account' => 0, - ], + 'spa_page' => 0, 'toast_position' => 'top-right', 'typography' => [ 'mode' => 'predefined', diff --git a/includes/Frontend/Assets.php b/includes/Frontend/Assets.php index 73cadaa..b4bf902 100644 --- a/includes/Frontend/Assets.php +++ b/includes/Frontend/Assets.php @@ -363,7 +363,7 @@ class Assets { } /** - * Check if current page is a designated SPA page + * Check if current page is the designated SPA page */ private static function is_spa_page() { global $post; @@ -371,17 +371,13 @@ class Assets { return false; } - // Get SPA page IDs from appearance settings + // Get SPA page ID from appearance settings $appearance_settings = get_option('woonoow_appearance_settings', []); - $spa_pages = isset($appearance_settings['general']['spa_pages']) ? $appearance_settings['general']['spa_pages'] : []; + $spa_page_id = isset($appearance_settings['general']['spa_page']) ? $appearance_settings['general']['spa_page'] : 0; - // Check if current page matches any SPA page - $current_page_id = $post->ID; - - foreach ($spa_pages as $page_type => $page_id) { - if ($page_id && $current_page_id == $page_id) { - return true; - } + // Check if current page matches the SPA page + if ($spa_page_id && $post->ID == $spa_page_id) { + return true; } return false; diff --git a/includes/Frontend/TemplateOverride.php b/includes/Frontend/TemplateOverride.php index 2733302..b2d0092 100644 --- a/includes/Frontend/TemplateOverride.php +++ b/includes/Frontend/TemplateOverride.php @@ -271,7 +271,7 @@ class TemplateOverride { } /** - * Check if current page is a designated SPA page + * Check if current page is the designated SPA page */ private static function is_spa_page() { global $post; @@ -279,17 +279,13 @@ class TemplateOverride { return false; } - // Get SPA page IDs from appearance settings + // Get SPA page ID from appearance settings $appearance_settings = get_option('woonoow_appearance_settings', []); - $spa_pages = isset($appearance_settings['general']['spa_pages']) ? $appearance_settings['general']['spa_pages'] : []; + $spa_page_id = isset($appearance_settings['general']['spa_page']) ? $appearance_settings['general']['spa_page'] : 0; - // Check if current page matches any SPA page - $current_page_id = $post->ID; - - foreach ($spa_pages as $page_type => $page_id) { - if ($page_id && $current_page_id == $page_id) { - return true; - } + // Check if current page matches the SPA page + if ($spa_page_id && $post->ID == $spa_page_id) { + return true; } return false; diff --git a/templates/spa-full-page.php b/templates/spa-full-page.php index 2974b09..cfad91e 100644 --- a/templates/spa-full-page.php +++ b/templates/spa-full-page.php @@ -8,23 +8,19 @@ > ID) . '"'; - } elseif (is_cart()) { + // 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"'; - } elseif (is_checkout()) { - $page_type = 'checkout'; - $data_attrs = 'data-page="checkout"'; - } elseif (is_account_page()) { - $page_type = 'account'; - $data_attrs = 'data-page="account"'; + $data_attrs = 'data-page="cart" data-initial-route="/cart"'; + } else { + // Full SPA mode starts at shop + $page_type = 'shop'; + $data_attrs = 'data-page="shop" data-initial-route="/shop"'; } ?>