Files
WooNooW/CUSTOMER_SPA_SETTINGS.md
Dwindi Ramadhana f397ef850f 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
2025-11-26 16:18:43 +07:00

548 lines
11 KiB
Markdown

# WooNooW Customer SPA Settings
## 📍 Settings Location
**Admin SPA > Settings > Customer SPA**
(NOT in wp-admin, but in our React admin interface)
---
## 📊 Settings Schema
### TypeScript Interface
```typescript
interface CustomerSPASettings {
// Mode
mode: 'disabled' | 'full' | 'checkout_only';
// Checkout-Only mode settings
checkoutPages?: {
checkout: boolean;
thankyou: boolean;
account: boolean;
cart: boolean;
};
// Layout (for full mode)
layout: 'classic' | 'modern' | 'boutique' | 'launch';
// Branding
branding: {
logo: string; // URL
favicon: string; // URL
siteName: string;
};
// Colors (Design Tokens)
colors: {
primary: string; // #3B82F6
secondary: string; // #8B5CF6
accent: string; // #10B981
background: string; // #FFFFFF
text: string; // #1F2937
};
// Typography
typography: {
preset: 'professional' | 'modern' | 'elegant' | 'tech' | 'custom';
customFonts?: {
heading: string;
body: string;
};
};
// Navigation
menus: {
primary: number; // WP menu ID
footer: number; // WP menu ID
};
// Homepage
homepage: {
sections: Array<{
id: string;
type: 'hero' | 'featured' | 'categories' | 'testimonials' | 'newsletter' | 'custom';
enabled: boolean;
order: number;
config: Record<string, any>;
}>;
};
// Product Page
product: {
layout: 'standard' | 'gallery' | 'minimal';
showRelatedProducts: boolean;
showReviews: boolean;
};
// Checkout
checkout: {
style: 'onepage' | 'multistep';
enableGuestCheckout: boolean;
showTrustBadges: boolean;
showOrderSummary: 'sidebar' | 'inline';
};
}
```
### Default Settings
```typescript
const DEFAULT_SETTINGS: CustomerSPASettings = {
mode: 'disabled',
checkoutPages: {
checkout: true,
thankyou: true,
account: true,
cart: false,
},
layout: 'modern',
branding: {
logo: '',
favicon: '',
siteName: get_bloginfo('name'),
},
colors: {
primary: '#3B82F6',
secondary: '#8B5CF6',
accent: '#10B981',
background: '#FFFFFF',
text: '#1F2937',
},
typography: {
preset: 'professional',
},
menus: {
primary: 0,
footer: 0,
},
homepage: {
sections: [
{ id: 'hero-1', type: 'hero', enabled: true, order: 0, config: {} },
{ id: 'featured-1', type: 'featured', enabled: true, order: 1, config: {} },
{ id: 'categories-1', type: 'categories', enabled: true, order: 2, config: {} },
],
},
product: {
layout: 'standard',
showRelatedProducts: true,
showReviews: true,
},
checkout: {
style: 'onepage',
enableGuestCheckout: true,
showTrustBadges: true,
showOrderSummary: 'sidebar',
},
};
```
---
## 🔌 REST API Endpoints
### Get Settings
```http
GET /wp-json/woonoow/v1/settings/customer-spa
```
**Response:**
```json
{
"enabled": true,
"layout": "modern",
"colors": {
"primary": "#3B82F6",
"secondary": "#8B5CF6",
"accent": "#10B981"
},
...
}
```
### Update Settings
```http
POST /wp-json/woonoow/v1/settings/customer-spa
Content-Type: application/json
{
"enabled": true,
"layout": "modern",
"colors": {
"primary": "#FF6B6B"
}
}
```
**Response:**
```json
{
"success": true,
"data": {
"enabled": true,
"layout": "modern",
"colors": {
"primary": "#FF6B6B",
"secondary": "#8B5CF6",
"accent": "#10B981"
},
...
}
}
```
---
## 🎨 Customization Options
### 1. Layout Options (4 Presets)
#### Classic Layout
- Traditional ecommerce design
- Header with logo + horizontal menu
- Sidebar filters on shop page
- Grid product listing
- Footer with widgets
- **Best for:** B2B, traditional retail
#### Modern Layout (Default)
- Minimalist, clean design
- Centered logo
- Top filters (no sidebar)
- Large product cards with hover effects
- Simplified footer
- **Best for:** Fashion, lifestyle brands
#### Boutique Layout
- Fashion/luxury focused
- Full-width hero sections
- Masonry grid layout
- Elegant typography
- Minimal UI elements
- **Best for:** High-end fashion, luxury goods
#### Launch Layout 🆕 (Single Product Funnel)
- **Landing page:** User's custom design (Elementor/Divi) - NOT controlled by WooNooW
- **WooNooW takes over:** From checkout onwards (after CTA click)
- **No traditional header/footer** on checkout/thank you/account pages
- **Streamlined checkout** (one-page, minimal fields, no cart)
- **Upsell/downsell** on thank you page
- **Direct product access** in My Account
- **Best for:**
- Digital products (courses, ebooks, software)
- SaaS trials → paid conversion
- Webinar funnels
- High-ticket consulting
- Limited-time offers
- Product launches
**Flow:** Landing Page (Custom) → [CTA to /checkout] → Checkout (SPA) → Thank You (SPA) → My Account (SPA)
**Note:** This is essentially Checkout-Only mode with funnel-optimized design.
### 2. Color Customization
**Primary Color:**
- Used for: Buttons, links, active states
- Default: `#3B82F6` (Blue)
**Secondary Color:**
- Used for: Badges, accents, secondary buttons
- Default: `#8B5CF6` (Purple)
**Accent Color:**
- Used for: Success states, CTAs, highlights
- Default: `#10B981` (Green)
**Background & Text:**
- Auto-calculated for proper contrast
- Supports light/dark mode
### 3. Typography Presets
#### Professional
- Heading: Inter
- Body: Lora
- Use case: Corporate, B2B
#### Modern
- Heading: Poppins
- Body: Roboto
- Use case: Tech, SaaS
#### Elegant
- Heading: Playfair Display
- Body: Source Sans Pro
- Use case: Fashion, Luxury
#### Tech
- Heading: Space Grotesk
- Body: IBM Plex Mono
- Use case: Electronics, Gadgets
#### Custom
- Upload custom fonts
- Specify font families
### 4. Homepage Sections
Available section types:
#### Hero Banner
```typescript
{
type: 'hero',
config: {
image: string; // Background image URL
heading: string; // Main heading
subheading: string; // Subheading
ctaText: string; // Button text
ctaLink: string; // Button URL
alignment: 'left' | 'center' | 'right';
}
}
```
#### Featured Products
```typescript
{
type: 'featured',
config: {
title: string;
productIds: number[]; // Manual selection
autoSelect: boolean; // Auto-select featured products
limit: number; // Number of products to show
columns: 2 | 3 | 4;
}
}
```
#### Category Grid
```typescript
{
type: 'categories',
config: {
title: string;
categoryIds: number[];
columns: 2 | 3 | 4;
showProductCount: boolean;
}
}
```
#### Testimonials
```typescript
{
type: 'testimonials',
config: {
title: string;
testimonials: Array<{
name: string;
avatar: string;
rating: number;
text: string;
}>;
}
}
```
#### Newsletter
```typescript
{
type: 'newsletter',
config: {
title: string;
description: string;
placeholder: string;
buttonText: string;
mailchimpListId?: string;
}
}
```
---
## 💾 Storage
### WordPress Options Table
Settings are stored in `wp_options`:
```php
// Option name: woonoow_customer_spa_enabled
// Value: boolean (true/false)
// Option name: woonoow_customer_spa_settings
// Value: JSON-encoded settings object
```
### PHP Implementation
```php
// Get settings
$settings = get_option('woonoow_customer_spa_settings', []);
// Update settings
update_option('woonoow_customer_spa_settings', $settings);
// Check if enabled
$enabled = get_option('woonoow_customer_spa_enabled', false);
```
---
## 🔒 Permissions
### Who Can Modify Settings?
- **Capability required:** `manage_woocommerce`
- **Roles:** Administrator, Shop Manager
### REST API Permission Check
```php
public function update_settings_permission_check() {
return current_user_can('manage_woocommerce');
}
```
---
## 🎯 Settings UI Components
### Admin SPA Components
1. **Enable/Disable Toggle**
- Component: `Switch`
- Shows warning when enabling
2. **Layout Selector**
- Component: `LayoutPreview`
- Visual preview of each layout
- Radio button selection
3. **Color Picker**
- Component: `ColorPicker`
- Supports hex, rgb, hsl
- Live preview
4. **Typography Selector**
- Component: `TypographyPreview`
- Shows font samples
- Dropdown selection
5. **Homepage Section Builder**
- Component: `SectionBuilder`
- Drag-and-drop reordering
- Add/remove/configure sections
6. **Menu Selector**
- Component: `MenuDropdown`
- Fetches WP menus via API
- Dropdown selection
---
## 📤 Data Flow
### Settings Update Flow
```
1. User changes setting in Admin SPA
2. React state updates (optimistic UI)
3. POST to /wp-json/woonoow/v1/settings/customer-spa
4. PHP validates & saves to wp_options
5. Response confirms save
6. React Query invalidates cache
7. Customer SPA receives new settings on next load
```
### Settings Load Flow (Customer SPA)
```
1. PHP renders spa-full-page.php
2. wp_head() outputs inline script:
window.woonoowCustomer = {
theme: <?php echo json_encode($settings); ?>
}
3. React app reads window.woonoowCustomer
4. ThemeProvider applies settings
5. CSS variables injected
6. Components render with theme
```
---
## 🧪 Testing
### Unit Tests
```typescript
describe('CustomerSPASettings', () => {
it('should load default settings', () => {
const settings = getDefaultSettings();
expect(settings.enabled).toBe(false);
expect(settings.layout).toBe('modern');
});
it('should validate color format', () => {
expect(isValidColor('#FF6B6B')).toBe(true);
expect(isValidColor('invalid')).toBe(false);
});
it('should merge partial updates', () => {
const current = getDefaultSettings();
const update = { colors: { primary: '#FF0000' } };
const merged = mergeSettings(current, update);
expect(merged.colors.primary).toBe('#FF0000');
expect(merged.colors.secondary).toBe('#8B5CF6'); // Unchanged
});
});
```
### Integration Tests
```php
class CustomerSPASettingsTest extends WP_UnitTestCase {
public function test_save_settings() {
$settings = ['enabled' => true, 'layout' => 'modern'];
update_option('woonoow_customer_spa_settings', $settings);
$saved = get_option('woonoow_customer_spa_settings');
$this->assertEquals('modern', $saved['layout']);
}
public function test_rest_api_requires_permission() {
wp_set_current_user(0); // Not logged in
$request = new WP_REST_Request('POST', '/woonoow/v1/settings/customer-spa');
$response = rest_do_request($request);
$this->assertEquals(401, $response->get_status());
}
}
```
---
## 📚 Related Documentation
- [Customer SPA Architecture](./CUSTOMER_SPA_ARCHITECTURE.md)
- [Customer SPA Theme System](./CUSTOMER_SPA_THEME_SYSTEM.md)
- [API Routes](./API_ROUTES.md)