docs: consolidate markdown documentation into master guides and remove obsolete files
This commit is contained in:
185
docs/ADDONS_GUIDE.md
Normal file
185
docs/ADDONS_GUIDE.md
Normal file
@@ -0,0 +1,185 @@
|
||||
# WooNooW Addon & Module Development Guide
|
||||
|
||||
**Version:** 2.0.0
|
||||
**Status:** Production Ready
|
||||
|
||||
This document is the single source of truth for extending WooNooW. It covers everything from basic code snippets (Bridge Patterns) to full-featured React SPAs (Addon Modules).
|
||||
|
||||
---
|
||||
|
||||
## 📋 Table of Contents
|
||||
|
||||
1. [Philosophy & Architecture](#philosophy--architecture)
|
||||
2. [Addon Types & Integration Levels](#addon-types--integration-levels)
|
||||
- Level 1: Vanilla JS / Bridge Patterns
|
||||
- Level 2: React Runtime Expansion (Recommended)
|
||||
- Level 3: Slot-Based Components
|
||||
3. [Developing a Full Addon](#developing-a-full-addon)
|
||||
- Registration
|
||||
- Settings & Options
|
||||
- The Hook System
|
||||
4. [Addon & Built-in Module Unification](#addon--built-in-module-unification)
|
||||
5. [Examples](#examples)
|
||||
|
||||
---
|
||||
|
||||
## 1. Philosophy & Architecture
|
||||
|
||||
**WooNooW Core = Zero Addon Dependencies**
|
||||
|
||||
We don't integrate specific addons (like shipping or payment plugins) directly into WooNooW core. Instead, we provide:
|
||||
1. **Hook system** for external addons to extend functionality.
|
||||
2. **Exposed React Runtime** so addons don't have to bundle heavy libraries.
|
||||
3. **Unified Module Registry** where built-in features (like Affiliates, Newsletters) and external addons share the same UI and enablement toggles.
|
||||
|
||||
---
|
||||
|
||||
## 2. Addon Types & Integration Levels
|
||||
|
||||
### Level 1: Vanilla JS / Bridge Patterns (Basic)
|
||||
Use this for simple snippets to make existing WooCommerce plugins (e.g. Rajaongkir) work with WooNooW.
|
||||
|
||||
```javascript
|
||||
// Wait for WooNooW to load
|
||||
window.addEventListener('woonoow:loaded', function() {
|
||||
window.WooNooW.hooks.addFilter('woonoow_order_form_after_shipping', function(container, formData) {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = `<select id="custom-dest"><option>Select...</option></select>`;
|
||||
container.appendChild(div);
|
||||
return container;
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Level 2: Exposed React Runtime (Recommended)
|
||||
WooNooW exposes `React`, `ReactDOM`, its `hooks`, and its `components` on `window.WooNooW`. This allows addons to build rich UIs without bundling React.
|
||||
|
||||
**Webpack/Vite Setup (Externals):**
|
||||
```javascript
|
||||
// vite.config.js
|
||||
export default {
|
||||
build: {
|
||||
rollupOptions: {
|
||||
external: ['react', 'react-dom'],
|
||||
output: {
|
||||
globals: {
|
||||
react: 'window.WooNooW.React',
|
||||
'react-dom': 'window.WooNooW.ReactDOM'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```typescript
|
||||
const { React, hooks, components } = window.WooNooW;
|
||||
const { addFilter } = hooks;
|
||||
const { Select } = components;
|
||||
|
||||
function CustomField({ formData, setFormData }) {
|
||||
return <Select label="Custom" onChange={(val) => setFormData({...})} />;
|
||||
}
|
||||
|
||||
addFilter('woonoow_order_form_after_shipping', (container, props) => {
|
||||
const root = window.WooNooW.ReactDOM.createRoot(container);
|
||||
root.render(<CustomField {...props} />);
|
||||
return container;
|
||||
});
|
||||
```
|
||||
|
||||
### Level 3: SPA Route Injection (Admin Pages)
|
||||
You can inject entire new pages into the WooNooW admin SPA.
|
||||
```php
|
||||
add_filter('woonoow/spa_routes', function($routes) {
|
||||
$routes[] = [
|
||||
'path' => '/my-addon',
|
||||
'component_url' => plugin_dir_url(__FILE__) . 'dist/MyPage.js',
|
||||
'title' => 'My Addon',
|
||||
];
|
||||
return $routes;
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Developing a Full Addon
|
||||
|
||||
### Step 1: Registration
|
||||
Register the addon via PHP filters so WooNooW knows it exists.
|
||||
|
||||
```php
|
||||
add_filter('woonoow/addon_registry', function($addons) {
|
||||
$addons['my-addon'] = [
|
||||
'id' => 'my-addon',
|
||||
'name' => 'My Custom Addon',
|
||||
'description' => 'Does something awesome.',
|
||||
'version' => '1.0.0',
|
||||
'category' => 'shipping', // Auto-groups in the UI
|
||||
'icon' => 'truck',
|
||||
'spa_bundle' => plugin_dir_url(__FILE__) . 'dist/addon.js',
|
||||
'has_settings' => true, // Enables the ⚙️ icon
|
||||
];
|
||||
return $addons;
|
||||
});
|
||||
```
|
||||
|
||||
### Step 2: Settings & Options
|
||||
By declaring `'has_settings' => true`, WooNooW expects your settings to live at `/settings/modules/{addon_id}`.
|
||||
|
||||
**Option A: Schema-based (No React needed)**
|
||||
```php
|
||||
add_filter('woonoow/module_settings_schema', function($schemas) {
|
||||
$schemas['my-addon'] = [
|
||||
'api_key' => ['type' => 'text', 'label' => 'API Key'],
|
||||
];
|
||||
return $schemas;
|
||||
});
|
||||
```
|
||||
|
||||
**Option B: Custom React Settings Component**
|
||||
```php
|
||||
// In addon_registry registration array:
|
||||
'settings_component' => plugin_dir_url(__FILE__) . 'dist/Settings.js',
|
||||
```
|
||||
Access data in React:
|
||||
```typescript
|
||||
const { useModuleSettings } = window.WooNooW.hooks;
|
||||
const { settings, updateSettings } = useModuleSettings('my-addon');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Addon & Built-in Module Unification
|
||||
|
||||
**Concept:** External addons and built-in features (e.g. Affiliates, Newsletters) look and act exactly the same in the Admin UI.
|
||||
- Both use `ModuleRegistry`.
|
||||
- Both generate dynamic categories (e.g. "Marketing", "Shipping").
|
||||
- Both persist settings to `woonoow_module_{id}_settings`.
|
||||
|
||||
---
|
||||
|
||||
## 5. Hook System Reference
|
||||
|
||||
### Frontend Extension Hooks
|
||||
```typescript
|
||||
// Add fields
|
||||
'woonoow_order_form_after_billing'
|
||||
'woonoow_order_form_after_shipping'
|
||||
'woonoow_order_form_custom_sections'
|
||||
|
||||
// Validation & Data Modification
|
||||
'woonoow_order_form_validation'
|
||||
'woonoow_order_form_data'
|
||||
```
|
||||
|
||||
### Backend Action Hooks
|
||||
```php
|
||||
apply_filters('woonoow_before_shipping_calculate', $shipping_data);
|
||||
apply_filters('woonoow_after_shipping_calculate', $rates, $shipping_data);
|
||||
apply_filters('woonoow_shipping_data', $data);
|
||||
```
|
||||
|
||||
---
|
||||
*For specific implementation examples, consult the `examples/` directory in the repository.*
|
||||
141
docs/CUSTOMER_SPA_ARCHITECTURE.md
Normal file
141
docs/CUSTOMER_SPA_ARCHITECTURE.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# WooNooW Customer SPA Architecture & Master Plan
|
||||
|
||||
**Version:** 2.0.0
|
||||
**Status:** Production Ready
|
||||
|
||||
This document consolidates the architectural decisions, deployment modes, UI/UX standards, and routing strategies for the WooNooW Customer SPA. It is the single source of truth for frontend development on the customer-facing side.
|
||||
|
||||
---
|
||||
|
||||
## 📋 Table of Contents
|
||||
|
||||
1. [Architecture Decision: Hybrid Approach](#architecture-decision-hybrid-approach)
|
||||
2. [Deployment Modes](#deployment-modes)
|
||||
3. [Routing Strategy: HashRouter](#routing-strategy-hashrouter)
|
||||
4. [SEO & Tracking Strategy](#seo--tracking-strategy)
|
||||
5. [UI/UX Design Standards](#uiux-design-standards)
|
||||
6. [Implementation Roadmap](#implementation-roadmap)
|
||||
|
||||
---
|
||||
|
||||
## 1. Architecture Decision: Hybrid Approach
|
||||
|
||||
We previously debated whether the `customer-spa` should be built into the core plugin or sold as a separate standalone theme.
|
||||
|
||||
**The Decision: Option C (Hybrid Approach)**
|
||||
|
||||
We build the Customer SPA into the WooNooW core plugin alongside the Admin SPA.
|
||||
```text
|
||||
woonoow/
|
||||
├── admin-spa/ (Admin interface ONLY)
|
||||
├── customer-spa/ (Customer Storefront + My Account)
|
||||
└── includes/
|
||||
├── Admin/ (Backend logic for admin-spa)
|
||||
└── Frontend/ (Backend logic for customer-spa)
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Better user experience (one product to install).
|
||||
- Highest revenue potential (core plugin covers 60% of users, premium themes can be sold separately for agencies).
|
||||
- Maximum flexibility.
|
||||
|
||||
---
|
||||
|
||||
## 2. Deployment Modes
|
||||
|
||||
To accommodate all store owners (from small businesses using traditional themes to enterprises wanting App-like experiences), the Customer SPA supports flexible deployment:
|
||||
|
||||
### Mode 1: Shortcode Mode (Default / Recommended)
|
||||
**Use Case:** Works with ANY WordPress theme (Divi, Elementor, Flatsome).
|
||||
**How it works:** Basic components are injected via shortcodes (`[woonoow_cart]`, `[woonoow_checkout]`).
|
||||
**Benefit:** Zero theme conflicts, progressive enhancement.
|
||||
|
||||
### Mode 2: Full SPA Mode
|
||||
**Use Case:** Maximum performance, standalone app-like experience.
|
||||
**How it works:** WooNooW takes over the entire frontend routing via a dedicated settings toggle.
|
||||
**Benefit:** Offline PWA support, fastest page transitions.
|
||||
|
||||
### Mode 3: Hybrid Rendering
|
||||
**Use Case:** Best of both worlds for SEO and speed.
|
||||
**How it works:** Product/Category pages use traditional WordPress PHP templates (SSR) for robust SEO, while Cart/Checkout/MyAccount use full SPA rendering for interactivity.
|
||||
|
||||
---
|
||||
|
||||
## 3. Routing Strategy: HashRouter
|
||||
|
||||
Direct SPA URLs (like `https://woonoow.local/product/foo`) conflict heavily with WordPress's native rewrite rules. We cannot reliably override WordPress routing without breaking standard themes or SEO canonicals.
|
||||
|
||||
**The Solution: HashRouter for SPA interactions**
|
||||
|
||||
```text
|
||||
https://woonoow.local/shop#/product/edukasi-anak
|
||||
↑
|
||||
```
|
||||
|
||||
### Why HashRouter?
|
||||
- **Zero WordPress Conflicts:** WordPress loads the base `/shop` page template. React Router takes over everything after the `#`.
|
||||
- **Direct Access Works:** Users can bookmark or share the URL, and it will load flawlessly.
|
||||
- **Consistent with Admin SPA:** Both Admin and Customer SPAs utilize memory/hash routing to prevent 404s and permalink crashes.
|
||||
|
||||
*(Note: For strict SEO product pages in Hybrid mode, the actual WooCommerce Product URL is indexed, while internal SPA browsing uses the HashRouter).*
|
||||
|
||||
---
|
||||
|
||||
## 4. SEO & Tracking Strategy
|
||||
|
||||
### Hybrid SEO Compatibility
|
||||
Because pure SPAs hurt SEO (empty HTML sent to crawler), we utilize Hybrid Rendering:
|
||||
1. **Product Pages = SSR:** WordPress outputs full HTML with schema markup using standard hooks so Yoast / RankMath work perfectly.
|
||||
2. **Checkout/Cart = CSR:** These pages don't need SEO indexing, so they are pure React.
|
||||
|
||||
### Analytics Tracking
|
||||
To ensure compatibility with Google Analytics, PixelMySite, Facebook Pixel, etc., the React components **trigger standard WooCommerce jQuery events**.
|
||||
|
||||
```javascript
|
||||
// Example: Triggering a native woo event inside React
|
||||
jQuery(document.body).trigger('added_to_cart', [product.id, quantity, product.price]);
|
||||
```
|
||||
This guarantees that 3rd-party tracking plugins installed on the site continue to function out-of-the-box without requiring custom API webhooks for the storefront.
|
||||
|
||||
---
|
||||
|
||||
## 5. UI/UX Design Standards
|
||||
|
||||
Our frontend philosophy: **Pragmatic, not dogmatic.** Follow e-commerce conventions for learned behaviors (e.g. swiping), rely on UX research when conventions are broken, and prioritize mobile-first performance.
|
||||
|
||||
### Core Layout Rules
|
||||
- **Typography:** Hierarchy is `Title > Price`. We optimize for Brand Stores, not chaotic Marketplaces.
|
||||
- **Variation Selectors:** Use Pills/Buttons. **Never** use Dropdowns for variation selection (high friction).
|
||||
- **Product Information:** Use Vertical Accordions instead of Horizontal Tabs (27% of users overlook horizontal tabs).
|
||||
- **Images:**
|
||||
- Mobile: Use dots (learned behavior from Amazon/Tokopedia).
|
||||
- Desktop: Use small horizontal thumbnails below the main image.
|
||||
|
||||
### Buy Section Hierarchy
|
||||
1. Product Title (H1)
|
||||
2. Price & Sale formatting
|
||||
3. Stock Status Badge
|
||||
4. Variation Selectors (Pills)
|
||||
5. Quantity Spinner
|
||||
6. **Add to Cart (Primary CTA)**
|
||||
7. Trust Badges (Shipping, Returns)
|
||||
|
||||
---
|
||||
|
||||
## 6. Implementation Roadmap
|
||||
|
||||
### Phase 1: Core Commerce (MVP)
|
||||
- Basic Product listing / catalog with filters.
|
||||
- Shopping Cart sidebar/drawer (state managed by Zustand).
|
||||
- Single-page checkout (HashRouter).
|
||||
- My Account dashboard (React Router).
|
||||
|
||||
### Phase 2: Trust & Conversion
|
||||
- Wishlist / Save for later functionality.
|
||||
- Product reviews integration with WooCommerce comments.
|
||||
- Related Products and Cross-Sells carousels.
|
||||
|
||||
### Phase 3: Advanced
|
||||
- Subscriptions & Memberships UI.
|
||||
- Digital Downloads manager in My Account.
|
||||
- Progressive Web App (PWA) manifest generation and offline Service Worker.
|
||||
91
docs/PRODUCT_PAGE_ARCHITECTURE.md
Normal file
91
docs/PRODUCT_PAGE_ARCHITECTURE.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# WooNooW Product Page Architecture & UX Guide
|
||||
|
||||
**Version:** 2.0.0
|
||||
**Status:** Production Ready
|
||||
|
||||
This document serves as the master guide for the WooNooW Customer SPA Product Page. It consolidates our design decision framework, standard operating procedures (SOP), and implementation phases.
|
||||
|
||||
---
|
||||
|
||||
## 📋 Table of Contents
|
||||
|
||||
1. [Design Decision Framework](#design-decision-framework)
|
||||
2. [Layout & Structure SOP](#layout--structure-sop)
|
||||
3. [Implementation Phases](#implementation-phases)
|
||||
|
||||
---
|
||||
|
||||
## 1. Design Decision Framework
|
||||
|
||||
When building the WooNooW SPA, we constantly face the dilemma: **Should we follow E-commerce Convention (e.g. Tokopedia, Shopify) or UX Research (e.g. Baymard Institute)?**
|
||||
|
||||
**Our Approach: Context-Driven Hybrid Decisions**
|
||||
|
||||
| Pattern | Convention | Research | Our Decision | Rationale |
|
||||
|---|---|---|---|---|
|
||||
| **Image Thumbnails** | Dots (Mobile) | Visible Thumbs | **Hybrid** | Small thumbnails + dots underneath. Retains swipeability but adds information scent. |
|
||||
| **Variation Selector** | Pills | Pills | **Pills** | Clear winner. Dropdowns add unnecessary friction. |
|
||||
| **Typography** | Varies | Title > Price | **Title > Price** | We optimize for Brand Stores (product focus) rather than Marketplaces (price focus). |
|
||||
| **Description** | Varies | Visible | **Auto-Expand** | Primary content must be visible. Secondary tabs (Reviews/Specs) can be categorized. |
|
||||
| **Sticky Bottom Bar** | Common | Good | **Yes** | Essential for long-scrolling mobile experiences. |
|
||||
|
||||
**The Meta-Lesson:**
|
||||
- Follow Convention for strongly learned behaviors (e.g., swiping).
|
||||
- Follow Research when convention is weak or when research points to a clear, frictionless improvement.
|
||||
- Always optimize for OUR context: We are building a high-conversion, brand-focused store SPA, not a massive chaotic marketplace.
|
||||
|
||||
---
|
||||
|
||||
## 2. Layout & Structure SOP
|
||||
|
||||
### 2.1 Hero Section (Above the Fold)
|
||||
The visual hierarchy must prioritize the core purchasing loop:
|
||||
1. **Product Images** (Left on Desktop, Top on Mobile)
|
||||
2. **Title & Price** (Right on Desktop, Below Image on Mobile)
|
||||
3. **Rating & Review Count**
|
||||
4. **Variation Selectors** (Pills)
|
||||
5. **Quantity & Add to Cart CTA**
|
||||
6. **Trust Badges**
|
||||
|
||||
### 2.2 Image Gallery Requirements
|
||||
- **Main Image:** High-res, zoomable/lightbox enabled.
|
||||
- **Thumbnail Slider:** Horizontal scrolling, 4-6 visible thumbnails. Active thumbnail highlighted.
|
||||
- **Variation Auto-Switch:** Selecting a color pill MUST instantly switch the main gallery image to the corresponding photo.
|
||||
|
||||
### 2.3 Product Information (Below the Fold)
|
||||
**AVOID HORIZONTAL TABS.** Research indicates 27% of users overlook them.
|
||||
Instead, use **Vertical Collapsed Sections (Accordions)**:
|
||||
- Description (Auto-expanded)
|
||||
- Specifications Table
|
||||
- Shipping / Returns Policy
|
||||
- Reviews
|
||||
- Related Products
|
||||
|
||||
### 2.4 Mobile Optimization
|
||||
- Image gallery must be native-feel swipeable.
|
||||
- Sticky Add-to-Cart bottom bar on scroll.
|
||||
- Touch targets minimum 44x44px.
|
||||
|
||||
---
|
||||
|
||||
## 3. Implementation Phases
|
||||
|
||||
If extending or modifying the product page, follow this feature prioritization:
|
||||
|
||||
### Phase 1: Core E-Commerce Loop (MVP)
|
||||
- Horizontal thumbnail slider with arrow navigation on desktop.
|
||||
- Variation selector with automatic image switching and price updating.
|
||||
- Add to Cart functionality with stock validation (disable button if no variation chosen).
|
||||
- Vertical accordion layout for Description and Info.
|
||||
|
||||
### Phase 2: Trust & Conversion Optimization
|
||||
- Inject WooCommerce native Reviews.
|
||||
- Inject Trust elements (Secure checkout, Payment methods).
|
||||
- Auto-calculate and display Free Shipping thresholds.
|
||||
- Related products carousel.
|
||||
|
||||
### Phase 3: Advanced Media & Personalization (Future)
|
||||
- Wishlist / Save for later.
|
||||
- Social Proof badges ("20 people viewing this").
|
||||
- 360° product views and Video embeds.
|
||||
- Auto-apply coupons and bulk tier discounts.
|
||||
186
docs/SHIPPING_GUIDE.md
Normal file
186
docs/SHIPPING_GUIDE.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# WooNooW Shipping & Integrations Guide
|
||||
|
||||
**Version:** 2.0.0
|
||||
**Status:** Production Ready
|
||||
|
||||
This document outlines how shipping methods work within WooNooW, and how to bridge complex external/API shipping plugins (such as RajaOngkir or Sicepat) fully into the Customer SPA Order Form.
|
||||
|
||||
---
|
||||
|
||||
## 📋 Table of Contents
|
||||
|
||||
1. [How WooNooW Handles Shipping](#how-woonoow-handles-shipping)
|
||||
2. [The Shipping Bridge Pattern](#the-shipping-bridge-pattern)
|
||||
3. [RajaOngkir Integration Example](#rajaongkir-integration-example)
|
||||
4. [Custom Shipping Addons](#custom-shipping-addons)
|
||||
|
||||
---
|
||||
|
||||
## 1. How WooNooW Handles Shipping
|
||||
|
||||
### Two Types of Shipping Methods
|
||||
|
||||
WooCommerce Core inherently provides two types of shipping:
|
||||
|
||||
**1. Static Methods (e.g. Free Shipping, Flat Rate)**
|
||||
- Immediate calculation (no API).
|
||||
- Configured via basic Address fields (Country, State, City, ZIP).
|
||||
|
||||
**2. Live Rate Methods (API Based)**
|
||||
- Need an API Call (e.g., UPS, FedEx, or local Indonesian couriers like JNE/J&T).
|
||||
- May require extremely specific address fragments to calculate rates accurately.
|
||||
- *International APIs (UPS/FedEx):* Usually rely on **Postal Code**.
|
||||
- *Indonesian APIs (RajaOngkir/Biteship):* Usually rely on **Subdistrict IDs**.
|
||||
|
||||
### The Problem
|
||||
|
||||
If a customer uses an Indonesian shipping plugin, the plugin may remove default WooCommerce fields (like `city`/`state`) and inject a custom dropdown that searches an API for a destination. The plugin then writes that Destination ID to the WooCommerce Session and forces shipping recalculation.
|
||||
|
||||
Because WooNooW's SPA bypasses normal PHP frontend rendering, native injected dropdowns from external plugins will not appear automatically.
|
||||
|
||||
---
|
||||
|
||||
## 2. The Shipping Bridge Pattern
|
||||
|
||||
To make external shipping plugins work natively within WooNooW's SPA checkout, use our Bridge Hook System.
|
||||
|
||||
You need 3 components:
|
||||
1. **REST API Endpoint:** To let the SPA search the provider's valid locations.
|
||||
2. **Checkout Field Injection:** To inject a `searchable_select` field into the SPA order form natively.
|
||||
3. **Bridge Action Hook:** To take the selected value from the order form and write it to the WooCommerce Session before shipping calculates.
|
||||
|
||||
### Generic Bridge Skeleton
|
||||
|
||||
```php
|
||||
// 1. Endpoint for SPA to search locations
|
||||
add_action('rest_api_init', function() {
|
||||
register_rest_route('woonoow/v1', '/provider/search', [
|
||||
'methods' => 'GET',
|
||||
'callback' => 'my_provider_search_func',
|
||||
'permission_callback' => '__return_true',
|
||||
]);
|
||||
});
|
||||
|
||||
// 2. Inject field into WooNooW SPA (native JSON structure, not HTML)
|
||||
add_filter('woocommerce_checkout_fields', function($fields) {
|
||||
if (!class_exists('My_Shipping_Class')) return $fields;
|
||||
|
||||
$fields['shipping']['shipping_provider_field'] = [
|
||||
'type' => 'searchable_select',
|
||||
'label' => 'Select Location',
|
||||
'required' => true,
|
||||
'priority' => 85,
|
||||
'search_endpoint' => '/provider/search', // Relative to wp-json/woonoow/v1
|
||||
'search_param' => 'search',
|
||||
'min_chars' => 3,
|
||||
];
|
||||
return $fields;
|
||||
}, 20);
|
||||
|
||||
// 3. Bridge Data to Provider Session
|
||||
add_action('woonoow/shipping/before_calculate', function($shipping, $items) {
|
||||
if (!class_exists('My_Shipping_Class')) return;
|
||||
|
||||
$val = $shipping['shipping_provider_field'] ?? null;
|
||||
if ($val) {
|
||||
WC()->session->set('my_provider_session_key', $val);
|
||||
// Force recalc
|
||||
WC()->session->set('shipping_for_package_0', false);
|
||||
}
|
||||
}, 10, 2);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. RajaOngkir Integration Example
|
||||
|
||||
If your user wants RajaOngkir running natively inside the WooNooW SPA checkout, this snippet represents the "Best Practice Bridge".
|
||||
|
||||
*Note: Drop this into a Code Snippets plugin or functions.php*
|
||||
|
||||
```php
|
||||
<?php
|
||||
// 1. Search Endpoint
|
||||
add_action('rest_api_init', function() {
|
||||
register_rest_route('woonoow/v1', '/rajaongkir/destinations', [
|
||||
'methods' => 'GET',
|
||||
'callback' => function($req) {
|
||||
$search = sanitize_text_field($req->get_param('search') ?? '');
|
||||
if (strlen($search) < 3 || !class_exists('Cekongkir_API')) return [];
|
||||
|
||||
$api = Cekongkir_API::get_instance();
|
||||
$results = $api->search_destination_api($search);
|
||||
|
||||
$formatted = [];
|
||||
if (is_array($results)) {
|
||||
foreach ($results as $r) {
|
||||
$formatted[] = [
|
||||
'value' => (string) ($r['id'] ?? ''),
|
||||
'label' => $r['label'] ?? $r['text'] ?? '',
|
||||
];
|
||||
}
|
||||
}
|
||||
return array_slice($formatted, 0, 50);
|
||||
},
|
||||
'permission_callback' => '__return_true'
|
||||
]);
|
||||
});
|
||||
|
||||
// 2. Register Native SPA Field & cleanup unnecessary native fields
|
||||
add_filter('woocommerce_checkout_fields', function($fields) {
|
||||
if (!class_exists('Cekongkir_API')) return $fields;
|
||||
|
||||
// Check if store only ships to Indonesia to safely hide fallback fields
|
||||
$allowed = WC()->countries->get_allowed_countries();
|
||||
$indonesia_only = (count($allowed) === 1 && isset($allowed['ID']));
|
||||
|
||||
if ($indonesia_only) {
|
||||
$fields['shipping']['shipping_country']['type'] = 'hidden';
|
||||
$fields['shipping']['shipping_state']['type'] = 'hidden';
|
||||
$fields['shipping']['shipping_city']['type'] = 'hidden';
|
||||
$fields['shipping']['shipping_postcode']['type'] = 'hidden';
|
||||
}
|
||||
|
||||
$dest_field = [
|
||||
'type' => 'searchable_select',
|
||||
'label' => __('Destination (Province, City, Subdistrict)', 'woonoow'),
|
||||
'required' => $indonesia_only,
|
||||
'priority' => 85,
|
||||
'search_endpoint' => '/rajaongkir/destinations',
|
||||
'search_param' => 'search',
|
||||
'min_chars' => 3,
|
||||
'custom_attributes' => ['data-show-for-country' => 'ID'],
|
||||
];
|
||||
|
||||
$fields['billing']['billing_destination_id'] = $dest_field;
|
||||
$fields['shipping']['shipping_destination_id'] = $dest_field;
|
||||
return $fields;
|
||||
}, 20);
|
||||
|
||||
// 3. Bridge Selection back into WooCommerce specific session key
|
||||
add_action('woonoow/shipping/before_calculate', function($shipping, $items) {
|
||||
if (!class_exists('Cekongkir_API')) return;
|
||||
|
||||
$country = $shipping['country'] ?? WC()->customer->get_shipping_country();
|
||||
if ($country !== 'ID') return;
|
||||
|
||||
$dest_id = $shipping['destination_id']
|
||||
?? $shipping['shipping_destination_id']
|
||||
?? $shipping['billing_destination_id'] ?? null;
|
||||
|
||||
if ($dest_id) {
|
||||
WC()->session->set('selected_destination_id', intval($dest_id));
|
||||
WC()->session->set('shipping_for_package_0', false);
|
||||
}
|
||||
}, 10, 2);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Custom Shipping Addons
|
||||
|
||||
If you do not want to use an external plugin and instead wish to build an official WooNooW extension (like `WooNooW Indonesia Shipping` with Biteship capabilities), treat it as a standard WooNooW Addon Module.
|
||||
|
||||
1. Develop a native React UI component using `ADDONS_GUIDE.md`.
|
||||
2. Intercept `woonoow_order_form_after_shipping` via Hook.
|
||||
3. Validate and handle the custom data payload via the standard WooCommerce REST endpoints.
|
||||
Reference in New Issue
Block a user