feat: Add product images support with WP Media Library integration
- Add WP Media Library integration for product and variation images - Support images array (URLs) conversion to attachment IDs - Add images array to API responses (Admin & Customer SPA) - Implement drag-and-drop sortable images in Admin product form - Add image gallery thumbnails in Customer SPA product page - Initialize WooCommerce session for guest cart operations - Fix product variations and attributes display in Customer SPA - Add variation image field in Admin SPA Changes: - includes/Api/ProductsController.php: Handle images array, add to responses - includes/Frontend/ShopController.php: Add images array for customer SPA - includes/Frontend/CartController.php: Initialize WC session for guests - admin-spa/src/lib/wp-media.ts: Add openWPMediaGallery function - admin-spa/src/routes/Products/partials/tabs/GeneralTab.tsx: WP Media + sortable images - admin-spa/src/routes/Products/partials/tabs/VariationsTab.tsx: Add variation image field - customer-spa/src/pages/Product/index.tsx: Add gallery thumbnails display
This commit is contained in:
341
CUSTOMER_SPA_ARCHITECTURE.md
Normal file
341
CUSTOMER_SPA_ARCHITECTURE.md
Normal file
@@ -0,0 +1,341 @@
|
||||
# WooNooW Customer SPA Architecture
|
||||
|
||||
## 🎯 Core Decision: Full SPA Takeover (No Hybrid)
|
||||
|
||||
### ❌ What We're NOT Doing (Lessons Learned)
|
||||
|
||||
**REJECTED: Hybrid SSR + SPA approach**
|
||||
- WordPress renders HTML (SSR)
|
||||
- React hydrates on top (SPA)
|
||||
- WooCommerce hooks inject content
|
||||
- Theme controls layout
|
||||
|
||||
**PROBLEMS EXPERIENCED:**
|
||||
- ✗ Script loading hell (spent 3+ hours debugging)
|
||||
- ✗ React Refresh preamble errors
|
||||
- ✗ Cache conflicts
|
||||
- ✗ Theme conflicts
|
||||
- ✗ Hook compatibility nightmare
|
||||
- ✗ Inconsistent UX (some pages SSR, some SPA)
|
||||
- ✗ Not truly "single-page" - full page reloads
|
||||
|
||||
### ✅ What We're Doing Instead
|
||||
|
||||
**APPROVED: Full SPA Takeover**
|
||||
- React controls ENTIRE page (including `<html>`, `<body>`)
|
||||
- Zero WordPress theme involvement
|
||||
- Zero WooCommerce template rendering
|
||||
- Pure client-side routing
|
||||
- All data via REST API
|
||||
|
||||
**BENEFITS:**
|
||||
- ✓ Clean separation of concerns
|
||||
- ✓ True SPA performance
|
||||
- ✓ No script loading issues
|
||||
- ✓ No theme conflicts
|
||||
- ✓ Predictable behavior
|
||||
- ✓ Easy to debug
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Architecture Overview
|
||||
|
||||
### System Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ WooNooW Plugin │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────────┐ ┌──────────────────┐ │
|
||||
│ │ Admin SPA │ │ Customer SPA │ │
|
||||
│ │ (React) │ │ (React) │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ - Products │ │ - Shop │ │
|
||||
│ │ - Orders │ │ - Product Detail │ │
|
||||
│ │ - Customers │ │ - Cart │ │
|
||||
│ │ - Analytics │ │ - Checkout │ │
|
||||
│ │ - Settings │◄─────┤ - My Account │ │
|
||||
│ │ └─ Customer │ │ │ │
|
||||
│ │ SPA Config │ │ Uses settings │ │
|
||||
│ └────────┬─────────┘ └────────┬─────────┘ │
|
||||
│ │ │ │
|
||||
│ └────────┬────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────▼──────────┐ │
|
||||
│ │ REST API Layer │ │
|
||||
│ │ (PHP Controllers) │ │
|
||||
│ └──────────┬──────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────▼──────────┐ │
|
||||
│ │ WordPress Core │ │
|
||||
│ │ + WooCommerce │ │
|
||||
│ │ (Data Layer Only) │ │
|
||||
│ └─────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Three-Mode System
|
||||
|
||||
### Mode 1: Admin Only (Default)
|
||||
```
|
||||
✅ Admin SPA: Active (product management, orders, etc.)
|
||||
❌ Customer SPA: Inactive
|
||||
→ User uses their own theme/page builder for frontend
|
||||
```
|
||||
|
||||
### Mode 2: Full SPA (Complete takeover)
|
||||
```
|
||||
✅ Admin SPA: Active
|
||||
✅ Customer SPA: Full Mode (takes over entire site)
|
||||
→ WooNooW controls everything
|
||||
→ Choose from 4 layouts: Classic, Modern, Boutique, Launch
|
||||
```
|
||||
|
||||
### Mode 3: Checkout-Only SPA 🆕 (Hybrid approach)
|
||||
```
|
||||
✅ Admin SPA: Active
|
||||
✅ Customer SPA: Checkout Mode (partial takeover)
|
||||
→ Only overrides: Checkout → Thank You → My Account
|
||||
→ User keeps theme/page builder for landing pages
|
||||
→ Perfect for single product sellers with custom landing pages
|
||||
```
|
||||
|
||||
**Settings UI:**
|
||||
```
|
||||
Admin SPA > Settings > Customer SPA
|
||||
|
||||
Customer SPA Mode:
|
||||
○ Disabled (Use your own theme)
|
||||
○ Full SPA (Take over entire storefront)
|
||||
● Checkout Only (Override checkout pages only)
|
||||
|
||||
If Checkout Only selected:
|
||||
Pages to override:
|
||||
[✓] Checkout
|
||||
[✓] Thank You (Order Received)
|
||||
[✓] My Account
|
||||
[ ] Cart (optional)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔌 Technical Implementation
|
||||
|
||||
### 1. Customer SPA Activation Flow
|
||||
|
||||
```php
|
||||
// When user enables Customer SPA in Admin SPA:
|
||||
|
||||
1. Admin SPA sends: POST /wp-json/woonoow/v1/settings/customer-spa
|
||||
{
|
||||
"enabled": true,
|
||||
"layout": "modern",
|
||||
"colors": {...},
|
||||
...
|
||||
}
|
||||
|
||||
2. PHP saves to wp_options:
|
||||
update_option('woonoow_customer_spa_enabled', true);
|
||||
update_option('woonoow_customer_spa_settings', $settings);
|
||||
|
||||
3. PHP activates template override:
|
||||
- template_include filter returns spa-full-page.php
|
||||
- Dequeues all theme scripts/styles
|
||||
- Outputs minimal HTML with React mount point
|
||||
|
||||
4. React SPA loads and takes over entire page
|
||||
```
|
||||
|
||||
### 2. Template Override (PHP)
|
||||
|
||||
**File:** `includes/Frontend/TemplateOverride.php`
|
||||
|
||||
```php
|
||||
public static function use_spa_template($template) {
|
||||
$mode = get_option('woonoow_customer_spa_mode', 'disabled');
|
||||
|
||||
// Mode 1: Disabled
|
||||
if ($mode === 'disabled') {
|
||||
return $template; // Use normal theme
|
||||
}
|
||||
|
||||
// Mode 3: Checkout-Only (partial SPA)
|
||||
if ($mode === 'checkout_only') {
|
||||
$checkout_pages = get_option('woonoow_customer_spa_checkout_pages', [
|
||||
'checkout' => true,
|
||||
'thankyou' => true,
|
||||
'account' => true,
|
||||
'cart' => false,
|
||||
]);
|
||||
|
||||
if (($checkout_pages['checkout'] && is_checkout()) ||
|
||||
($checkout_pages['thankyou'] && is_order_received_page()) ||
|
||||
($checkout_pages['account'] && is_account_page()) ||
|
||||
($checkout_pages['cart'] && is_cart())) {
|
||||
return plugin_dir_path(__DIR__) . '../templates/spa-full-page.php';
|
||||
}
|
||||
|
||||
return $template; // Use theme for other pages
|
||||
}
|
||||
|
||||
// Mode 2: Full SPA
|
||||
if ($mode === 'full') {
|
||||
// Override all WooCommerce pages
|
||||
if (is_woocommerce() || is_cart() || is_checkout() || is_account_page()) {
|
||||
return plugin_dir_path(__DIR__) . '../templates/spa-full-page.php';
|
||||
}
|
||||
}
|
||||
|
||||
return $template;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. SPA Template (Minimal HTML)
|
||||
|
||||
**File:** `templates/spa-full-page.php`
|
||||
|
||||
```php
|
||||
<!DOCTYPE html>
|
||||
<html <?php language_attributes(); ?>>
|
||||
<head>
|
||||
<meta charset="<?php bloginfo('charset'); ?>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?php wp_title('|', true, 'right'); ?><?php bloginfo('name'); ?></title>
|
||||
<?php wp_head(); // Loads WooNooW scripts only ?>
|
||||
</head>
|
||||
<body <?php body_class('woonoow-spa'); ?>>
|
||||
<!-- React mount point -->
|
||||
<div id="woonoow-customer-app"></div>
|
||||
|
||||
<?php wp_footer(); ?>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
**That's it!** No WordPress theme markup, no WooCommerce templates.
|
||||
|
||||
### 4. React SPA Entry Point
|
||||
|
||||
**File:** `customer-spa/src/main.tsx`
|
||||
|
||||
```typescript
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import App from './App';
|
||||
import './index.css';
|
||||
|
||||
// Get config from PHP
|
||||
const config = window.woonoowCustomer;
|
||||
|
||||
// Mount React app
|
||||
const root = document.getElementById('woonoow-customer-app');
|
||||
if (root) {
|
||||
createRoot(root).render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<App config={config} />
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 5. React Router (Client-Side Only)
|
||||
|
||||
**File:** `customer-spa/src/App.tsx`
|
||||
|
||||
```typescript
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
import { ThemeProvider } from './contexts/ThemeContext';
|
||||
import Layout from './components/Layout';
|
||||
import Shop from './pages/Shop';
|
||||
import Product from './pages/Product';
|
||||
import Cart from './pages/Cart';
|
||||
import Checkout from './pages/Checkout';
|
||||
import Account from './pages/Account';
|
||||
|
||||
export default function App({ config }) {
|
||||
return (
|
||||
<ThemeProvider config={config.theme}>
|
||||
<Layout>
|
||||
<Routes>
|
||||
<Route path="/shop" element={<Shop />} />
|
||||
<Route path="/product/:slug" element={<Product />} />
|
||||
<Route path="/cart" element={<Cart />} />
|
||||
<Route path="/checkout" element={<Checkout />} />
|
||||
<Route path="/my-account/*" element={<Account />} />
|
||||
</Routes>
|
||||
</Layout>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**Key Point:** React Router handles ALL navigation. No page reloads!
|
||||
|
||||
---
|
||||
|
||||
## 📋 Implementation Roadmap
|
||||
|
||||
### Phase 1: Core Infrastructure ✅ (DONE)
|
||||
- [x] Full-page SPA template
|
||||
- [x] Script loading (Vite dev server)
|
||||
- [x] React Refresh preamble fix
|
||||
- [x] Template override system
|
||||
- [x] Dequeue conflicting scripts
|
||||
|
||||
### Phase 2: Settings System (NEXT)
|
||||
- [ ] Create Settings REST API endpoint
|
||||
- [ ] Build Settings UI in Admin SPA
|
||||
- [ ] Implement color picker component
|
||||
- [ ] Implement layout selector
|
||||
- [ ] Save/load settings from wp_options
|
||||
|
||||
### Phase 3: Theme System
|
||||
- [ ] Create 3 master layouts (Classic, Modern, Boutique)
|
||||
- [ ] Implement design token system
|
||||
- [ ] Build ThemeProvider
|
||||
- [ ] Apply theme to all components
|
||||
|
||||
### Phase 4: Homepage Builder
|
||||
- [ ] Create section components (Hero, Featured, etc.)
|
||||
- [ ] Build drag-drop section manager
|
||||
- [ ] Section configuration modals
|
||||
- [ ] Dynamic section rendering
|
||||
|
||||
### Phase 5: Navigation
|
||||
- [ ] Fetch WP menus via REST API
|
||||
- [ ] Render menus in SPA
|
||||
- [ ] Mobile menu component
|
||||
- [ ] Mega menu support
|
||||
|
||||
### Phase 6: Pages
|
||||
- [ ] Shop page (product grid)
|
||||
- [ ] Product detail page
|
||||
- [ ] Cart page
|
||||
- [ ] Checkout page
|
||||
- [ ] My Account pages
|
||||
|
||||
---
|
||||
|
||||
## ✅ Decision Log
|
||||
|
||||
| Decision | Rationale | Date |
|
||||
|----------|-----------|------|
|
||||
| **Full SPA takeover (no hybrid)** | Hybrid SSR+SPA caused script loading hell, cache issues, theme conflicts | Nov 22, 2024 |
|
||||
| **Settings in Admin SPA (not wp-admin)** | Consistent UX, better UI components, easier to maintain | Nov 22, 2024 |
|
||||
| **3 master layouts (not infinite)** | SaaS approach: curated options > infinite flexibility | Nov 22, 2024 |
|
||||
| **Design tokens (not custom CSS)** | Maintainable, predictable, accessible | Nov 22, 2024 |
|
||||
| **Client-side routing only** | True SPA performance, no page reloads | Nov 22, 2024 |
|
||||
|
||||
---
|
||||
|
||||
## 📚 Related Documentation
|
||||
|
||||
- [Customer SPA Settings](./CUSTOMER_SPA_SETTINGS.md) - Settings schema & API
|
||||
- [Customer SPA Theme System](./CUSTOMER_SPA_THEME_SYSTEM.md) - Design tokens & layouts
|
||||
- [Customer SPA Development](./CUSTOMER_SPA_DEVELOPMENT.md) - Dev guide for contributors
|
||||
Reference in New Issue
Block a user