feat: Improve settings layout and add addon integration design

🎨 Layout Changes:
- Changed settings from boxed (max-w-5xl) to full-width
- Consistent with Orders/Dashboard pages
- Better use of space for complex forms

📝 Payments Page Reorder:
- Manual payment methods first (Bank Transfer, COD)
- Payment providers second (Stripe, PayPal)
- Payment settings third (test mode, capture)
- Test mode banner moved inside Payment Settings card

📚 Documentation:
- Created SETUP_WIZARD_DESIGN.md
- 5-step wizard flow (Store, Payments, Shipping, Taxes, Product)
- Smart defaults and skip logic
- Complete addon integration architecture

🔌 Addon Integration Design:
- PaymentProviderRegistry with filter hooks
- ShippingMethodRegistry with filter hooks
- REST API endpoints for dynamic loading
- Example addon implementations
- Support for custom React components

 Key Features:
- woonoow_payment_providers filter hook
- woonoow_shipping_zones filter hook
- Dynamic component loading from addons
- OAuth flow support for payment gateways
- Backward compatible with WooCommerce
This commit is contained in:
dwindown
2025-11-05 19:47:25 +07:00
parent 2898849263
commit 3bd2c07308
3 changed files with 675 additions and 62 deletions

614
SETUP_WIZARD_DESIGN.md Normal file
View File

@@ -0,0 +1,614 @@
# Setup Wizard Design Document
## Overview
A guided onboarding experience for new WooNooW stores, helping merchants configure essential settings in 5-10 minutes.
## Goals
1. **Fast Setup** - Get store operational in < 10 minutes
2. **Smart Defaults** - Pre-configure based on location/industry
3. **Progressive** - Can skip and complete later
4. **Educational** - Teach key concepts without overwhelming
---
## Wizard Flow (5 Steps)
### Step 1: Store Basics (2 min)
**Purpose:** Essential store identity
**Fields:**
- Store name (required)
- Store email (required)
- Country (required) Auto-detects currency, timezone
- Industry (optional) Suggests products/categories
**Smart Defaults:**
- Currency from country
- Timezone from country
- Language from browser
**Skip:** Cannot skip (required for operation)
---
### Step 2: Payments (2 min)
**Purpose:** Enable at least one payment method
**Options:**
1. **Quick Start (Recommended)**
- Enable manual methods (Bank Transfer, COD)
- "Set up Stripe later" button
2. **Connect Payment Provider**
- Stripe (OAuth flow)
- PayPal (OAuth flow)
- Other providers
**Smart Defaults:**
- Bank Transfer: Enabled
- Cash on Delivery: Enabled if physical products
**Skip:** Warning: "Customers won't be able to checkout"
---
### Step 3: Shipping (2 min)
**Purpose:** Configure basic shipping
**Options:**
1. **Simple Shipping**
- Flat rate for domestic
- Flat rate for international
- Free shipping threshold (optional)
2. **Advanced Setup**
- Multiple zones
- Calculated rates
- Carrier integrations
**Smart Defaults:**
- Domestic zone: Country from Step 1
- Flat rate: $10 (or currency equivalent)
**Skip:** Warning: "Only for digital products"
---
### Step 4: Taxes (1 min)
**Purpose:** Basic tax compliance
**Options:**
1. **Auto-calculate** (Recommended)
- Based on customer location
- Standard rates from database
2. **Manual rates**
- Set fixed percentage
- Per-country rates
3. **No taxes**
- For tax-exempt stores
**Smart Defaults:**
- Auto-calculate: ON
- Tax rate from country (e.g., 10% for Indonesia VAT)
**Skip:** Can skip (configure later)
---
### Step 5: First Product (3 min)
**Purpose:** Create sample product to test checkout
**Options:**
1. **Create Sample Product** (Recommended)
- Pre-filled with dummy data
- Can edit or delete later
- Helps test checkout flow
2. **Import Products**
- CSV upload
- WooCommerce import
3. **Skip for now**
- Add products later
**Smart Defaults:**
- Sample product based on industry from Step 1
**Skip:** Can skip
---
## Technical Architecture
### Frontend Components
```
/routes/Setup/
├── index.tsx # Wizard container
├── StepProgress.tsx # Progress indicator (1/5, 2/5, etc)
├── steps/
│ ├── StoreBasics.tsx
│ ├── Payments.tsx
│ ├── Shipping.tsx
│ ├── Taxes.tsx
│ └── FirstProduct.tsx
└── Complete.tsx # Success screen
```
### Backend API
```php
// REST API Endpoints
POST /woonoow/v1/setup/store-basics
POST /woonoow/v1/setup/payments
POST /woonoow/v1/setup/shipping
POST /woonoow/v1/setup/taxes
POST /woonoow/v1/setup/first-product
POST /woonoow/v1/setup/complete
// Option to track wizard state
update_option('wnw_setup_completed', true);
update_option('wnw_setup_step', 3); // Current step
```
### State Management
```typescript
// Zustand store for wizard state
interface SetupState {
currentStep: number;
completed: boolean;
data: {
storeBasics: StoreBasicsData;
payments: PaymentsData;
shipping: ShippingData;
taxes: TaxesData;
firstProduct: ProductData;
};
goToStep: (step: number) => void;
saveStep: (step: string, data: any) => Promise<void>;
completeSetup: () => Promise<void>;
}
```
---
## Payment Provider Integration
### Architecture
**Problem:** How to support payment addons (Stripe, PayPal, Xendit, Midtrans, etc)?
**Solution:** WordPress filter hooks + React components
### Backend: Payment Provider Registry
```php
<?php
// includes/Compat/PaymentProviderRegistry.php
class PaymentProviderRegistry {
/**
* Get all registered payment providers
* Allows addons to register their providers
*/
public static function get_providers(): array {
$providers = [
// Built-in manual methods
[
'id' => 'bacs',
'name' => 'Bank Transfer (BACS)',
'type' => 'manual',
'enabled' => true,
'icon' => 'banknote',
],
[
'id' => 'cod',
'name' => 'Cash on Delivery',
'type' => 'manual',
'enabled' => true,
'icon' => 'banknote',
],
];
/**
* Filter: Allow addons to register payment providers
*
* @param array $providers List of payment providers
*
* Example addon usage:
* add_filter('woonoow_payment_providers', function($providers) {
* $providers[] = [
* 'id' => 'stripe',
* 'name' => 'Stripe Payments',
* 'type' => 'gateway',
* 'description' => 'Accept Visa, Mastercard, Amex',
* 'icon' => 'credit-card',
* 'enabled' => false,
* 'connected' => false,
* 'setup_url' => admin_url('admin.php?page=wc-settings&tab=checkout&section=stripe'),
* 'component_url' => plugins_url('build/stripe-settings.js', __FILE__),
* 'fees' => '2.9% + $0.30 per transaction',
* ];
* return $providers;
* });
*/
return apply_filters('woonoow_payment_providers', $providers);
}
/**
* Get provider configuration
*/
public static function get_provider_config(string $provider_id): array {
$providers = self::get_providers();
foreach ($providers as $provider) {
if ($provider['id'] === $provider_id) {
return $provider;
}
}
return [];
}
/**
* Save provider settings
*/
public static function save_provider_settings(string $provider_id, array $settings): bool {
// Save to WooCommerce payment gateway settings
$gateway = WC()->payment_gateways()->payment_gateways()[$provider_id] ?? null;
if ($gateway) {
foreach ($settings as $key => $value) {
$gateway->update_option($key, $value);
}
return true;
}
return false;
}
}
```
### REST API Endpoint
```php
<?php
// includes/API/PaymentsController.php
class PaymentsController {
public static function register_routes() {
register_rest_route('woonoow/v1', '/payments/providers', [
'methods' => 'GET',
'callback' => [self::class, 'get_providers'],
'permission_callback' => [self::class, 'check_permission'],
]);
register_rest_route('woonoow/v1', '/payments/providers/(?P<id>[a-zA-Z0-9_-]+)', [
'methods' => 'POST',
'callback' => [self::class, 'save_provider'],
'permission_callback' => [self::class, 'check_permission'],
]);
}
public static function get_providers(WP_REST_Request $request) {
$providers = PaymentProviderRegistry::get_providers();
return rest_ensure_response($providers);
}
public static function save_provider(WP_REST_Request $request) {
$provider_id = $request->get_param('id');
$settings = $request->get_json_params();
$success = PaymentProviderRegistry::save_provider_settings($provider_id, $settings);
if ($success) {
return rest_ensure_response(['success' => true]);
}
return new WP_Error('save_failed', 'Failed to save provider settings', ['status' => 500]);
}
}
```
### Frontend: Dynamic Provider Loading
```typescript
// src/routes/Settings/Payments.tsx
import { useQuery } from '@tanstack/react-query';
import { api } from '@/lib/api';
export default function PaymentsPage() {
// Fetch providers from API (includes addon providers)
const { data: providers = [], isLoading } = useQuery({
queryKey: ['payment-providers'],
queryFn: () => api.get('/payments/providers'),
});
return (
<SettingsLayout title="Payments">
{/* Manual Methods */}
<SettingsCard title="Manual Payment Methods">
{providers
.filter(p => p.type === 'manual')
.map(provider => (
<PaymentMethodCard key={provider.id} provider={provider} />
))}
</SettingsCard>
{/* Payment Gateways */}
<SettingsCard title="Payment Providers">
{providers
.filter(p => p.type === 'gateway')
.map(provider => (
<PaymentProviderCard key={provider.id} provider={provider} />
))}
</SettingsCard>
</SettingsLayout>
);
}
```
### Addon Example: Stripe Integration
```php
<?php
/**
* Plugin Name: WooNooW Stripe Addon
* Description: Stripe payment gateway for WooNooW
*/
// Register Stripe provider
add_filter('woonoow_payment_providers', function($providers) {
$stripe_settings = get_option('woocommerce_stripe_settings', []);
$providers[] = [
'id' => 'stripe',
'name' => 'Stripe Payments',
'type' => 'gateway',
'description' => 'Accept Visa, Mastercard, Amex, and more',
'icon' => 'credit-card',
'enabled' => $stripe_settings['enabled'] === 'yes',
'connected' => !empty($stripe_settings['publishable_key']),
'setup_url' => admin_url('admin.php?page=wc-settings&tab=checkout&section=stripe'),
'component_url' => plugins_url('build/stripe-settings.js', __FILE__),
'fees' => '2.9% + $0.30 per transaction',
'test_mode' => $stripe_settings['testmode'] === 'yes',
];
return $providers;
});
```
---
## Shipping Methods Integration
### Backend: Shipping Method Registry
```php
<?php
// includes/Compat/ShippingMethodRegistry.php
class ShippingMethodRegistry {
/**
* Get all shipping zones with methods
* Allows addons to register custom shipping methods
*/
public static function get_zones(): array {
$zones_data = [];
$zones = WC_Shipping_Zones::get_zones();
foreach ($zones as $zone) {
$zone_obj = new WC_Shipping_Zone($zone['id']);
$methods = $zone_obj->get_shipping_methods();
$zone_methods = [];
foreach ($methods as $method) {
$zone_methods[] = [
'id' => $method->id,
'instance_id' => $method->instance_id,
'title' => $method->title,
'enabled' => $method->enabled === 'yes',
'method_id' => $method->id,
'settings' => $method->instance_settings,
];
}
$zones_data[] = [
'id' => $zone['id'],
'name' => $zone['zone_name'],
'regions' => $zone['formatted_zone_location'],
'methods' => $zone_methods,
];
}
/**
* Filter: Allow addons to modify shipping zones
*
* @param array $zones_data List of shipping zones with methods
*
* Example addon usage:
* add_filter('woonoow_shipping_zones', function($zones) {
* // Add custom shipping method to each zone
* foreach ($zones as &$zone) {
* $zone['methods'][] = [
* 'id' => 'custom_shipping',
* 'title' => 'Custom Shipping',
* 'enabled' => true,
* 'component_url' => plugins_url('build/custom-shipping.js', __FILE__),
* ];
* }
* return $zones;
* });
*/
return apply_filters('woonoow_shipping_zones', $zones_data);
}
/**
* Get available shipping methods (for adding to zones)
*/
public static function get_available_methods(): array {
$wc_methods = WC()->shipping()->get_shipping_methods();
$methods = [];
foreach ($wc_methods as $method) {
$methods[] = [
'id' => $method->id,
'title' => $method->method_title,
'description' => $method->method_description,
];
}
/**
* Filter: Allow addons to register custom shipping methods
*/
return apply_filters('woonoow_available_shipping_methods', $methods);
}
}
```
### REST API Endpoint
```php
<?php
// includes/API/ShippingController.php
class ShippingController {
public static function register_routes() {
register_rest_route('woonoow/v1', '/shipping/zones', [
'methods' => 'GET',
'callback' => [self::class, 'get_zones'],
'permission_callback' => [self::class, 'check_permission'],
]);
register_rest_route('woonoow/v1', '/shipping/methods', [
'methods' => 'GET',
'callback' => [self::class, 'get_methods'],
'permission_callback' => [self::class, 'check_permission'],
]);
}
public static function get_zones(WP_REST_Request $request) {
$zones = ShippingMethodRegistry::get_zones();
return rest_ensure_response($zones);
}
public static function get_methods(WP_REST_Request $request) {
$methods = ShippingMethodRegistry::get_available_methods();
return rest_ensure_response($methods);
}
}
```
### Frontend: Dynamic Shipping Loading
```typescript
// src/routes/Settings/Shipping.tsx
import { useQuery } from '@tanstack/react-query';
import { api } from '@/lib/api';
export default function ShippingPage() {
// Fetch zones from API (includes addon methods)
const { data: zones = [], isLoading } = useQuery({
queryKey: ['shipping-zones'],
queryFn: () => api.get('/shipping/zones'),
});
return (
<SettingsLayout title="Shipping & Delivery">
{/* Shipping Zones */}
<SettingsCard title="Shipping Zones">
{zones.map(zone => (
<ShippingZoneCard key={zone.id} zone={zone} />
))}
</SettingsCard>
</SettingsLayout>
);
}
```
---
## Implementation Timeline
### Phase 1: Foundation (Week 1)
- [ ] Create PaymentProviderRegistry.php
- [ ] Create ShippingMethodRegistry.php
- [ ] Add REST API endpoints
- [ ] Update Payments.tsx to use API
- [ ] Update Shipping.tsx to use API
### Phase 2: Setup Wizard (Week 2)
- [ ] Create wizard UI components
- [ ] Implement 5-step flow
- [ ] Add smart defaults
- [ ] Add skip logic
- [ ] Create completion screen
### Phase 3: Addon Support (Week 3)
- [ ] Document filter hooks
- [ ] Create example addons
- [ ] Test with real payment gateways
- [ ] Test with shipping plugins
### Phase 4: Polish (Week 4)
- [ ] Add animations/transitions
- [ ] Improve error handling
- [ ] Add help documentation
- [ ] User testing & feedback
---
## Success Metrics
1. **Setup Time** - < 10 minutes average
2. **Completion Rate** - > 80% complete wizard
3. **Payment Setup** - > 90% enable at least one method
4. **Shipping Setup** - > 70% configure shipping
5. **First Sale** - < 24 hours after setup
---
## Future Enhancements
1. **AI-Powered Suggestions**
- Detect industry from store name
- Suggest products based on industry
- Recommend payment methods by country
2. **Video Tutorials**
- Embedded help videos
- Step-by-step guides
3. **Templates**
- Pre-configured setups by industry
- "Fashion Store", "Digital Products", etc.
4. **Import Wizards**
- Import from Shopify
- Import from WooCommerce
- Import from CSV
---
## Questions & Answers
### Q: How do payment addons register themselves?
**A:** Use the `woonoow_payment_providers` filter hook to add providers to the list. The addon provides metadata (name, icon, fees) and optionally a React component URL for custom settings UI.
### Q: Can addons have custom settings UI?
**A:** Yes! Addons can provide a `component_url` that points to a React component. WooNooW will dynamically load and render it in the settings page.
### Q: How does the wizard handle incomplete setup?
**A:** The wizard saves progress at each step. Users can exit and resume later. A dashboard banner reminds them to complete setup.
### Q: Can merchants skip the wizard?
**A:** Yes, but they'll see a persistent banner until they complete essential steps (store basics, at least one payment method).
### Q: How do we handle payment gateway OAuth flows?
**A:** Payment addons provide a `setup_url` that can be an OAuth redirect. After completion, the addon updates its connection status via the API.