Files
WooNooW/ADDON_BRIDGE_PATTERN.md
dwindown 0c1f5d5047 docs: Critical audit and strategy documents
## Point 1: Addon Bridge Pattern 

Created ADDON_BRIDGE_PATTERN.md documenting:
- WooNooW Core = Zero addon dependencies
- Bridge snippet pattern for Rajaongkir compatibility
- Proper addon development approach
- Hook system usage

**Key Decision:**
-  No Rajaongkir integration in core
-  Provide bridge snippets for compatibility
-  Encourage proper WooNooW addons
-  Keep core clean and maintainable

---

## Point 2: Calculation Efficiency Audit 🚨 CRITICAL

Created CALCULATION_EFFICIENCY_AUDIT.md revealing:

**BLOATED Implementation Found:**
- 2 separate API calls (/shipping/calculate + /orders/preview)
- Cart initialized TWICE
- Shipping calculated TWICE
- Taxes calculated TWICE
- ~1000ms total time

**Recommended Solution:**
- Single /orders/calculate endpoint
- ONE cart initialization
- ONE calculation
- ~300ms total time (70% faster!)
- 50% fewer requests
- 50% less server load

**This is exactly what we discussed at the beginning:**
> "WooCommerce is bloated because of separate requests. We need efficient flow that handles everything at once."

**Current implementation repeats WooCommerce's mistake!**

**Status:**  NOT IMPLEMENTED YET
**Priority:** 🚨 CRITICAL
**Impact:** 🔥 HIGH - Performance bottleneck

---

## Point 3: Settings Placement Strategy 

Created SETTINGS_PLACEMENT_STRATEGY.md proposing:

**No separate "WooNooW Settings" page.**

Instead:
- Store Logo → WooCommerce > Settings > General
- Order Format → WooCommerce > Settings > Orders
- Product Settings → WooCommerce > Settings > Products
- UI Settings → WooCommerce > Settings > Admin UI (new tab)

**Benefits:**
- Contextual placement
- Familiar to users
- No clutter
- Seamless integration
- Feels native to WooCommerce

**Philosophy:**
WooNooW should feel like a native part of WooCommerce, not a separate plugin.

---

## Summary

**Point 1:**  Documented addon bridge pattern
**Point 2:** 🚨 CRITICAL - Current calculation is bloated, needs refactoring
**Point 3:**  Settings placement strategy documented

**Next Action Required:**
Implement unified /orders/calculate endpoint to fix performance bottleneck.
2025-11-10 20:24:23 +07:00

8.4 KiB

Addon Bridge Pattern - Rajaongkir Example

Philosophy

WooNooW Core = Zero Addon Dependencies

We don't integrate specific addons into WooNooW core. Instead, we provide:

  1. Hook system for addons to extend functionality
  2. Bridge snippets for compatibility with existing plugins
  3. Addon development guide for building proper WooNooW addons

Problem: Rajaongkir Plugin

Rajaongkir is a WooCommerce plugin that:

  • Removes standard address fields (city, state)
  • Adds custom destination dropdown
  • Stores data in WooCommerce session
  • Works on WooCommerce checkout page

It doesn't work with WooNooW OrderForm because:

  • OrderForm uses standard WooCommerce fields
  • Rajaongkir expects session-based destination
  • No destination = No shipping calculation

Solution: Bridge Snippet (Not Core Integration!)

Option A: Standalone Bridge Plugin

Create a tiny bridge plugin that makes Rajaongkir work with WooNooW:

<?php
/**
 * Plugin Name: WooNooW Rajaongkir Bridge
 * Description: Makes Rajaongkir plugin work with WooNooW OrderForm
 * Version: 1.0.0
 * Requires: WooNooW, Rajaongkir Official
 */

// Hook into WooNooW's shipping calculation
add_filter('woonoow_before_shipping_calculate', function($shipping_data) {
    // If Indonesia and has city, convert to Rajaongkir destination
    if ($shipping_data['country'] === 'ID' && !empty($shipping_data['city'])) {
        // Search Rajaongkir API for destination
        $api = Cekongkir_API::get_instance();
        $results = $api->search_destination_api($shipping_data['city']);
        
        if (!empty($results[0])) {
            // Set Rajaongkir session data
            WC()->session->set('selected_destination_id', $results[0]['id']);
            WC()->session->set('selected_destination_label', $results[0]['text']);
        }
    }
    
    return $shipping_data;
});

// Add Rajaongkir destination field to OrderForm via hook system
add_action('wp_enqueue_scripts', function() {
    if (!is_admin()) return;
    
    wp_enqueue_script(
        'woonoow-rajaongkir-bridge',
        plugin_dir_url(__FILE__) . 'dist/bridge.js',
        ['woonoow-admin'],
        '1.0.0',
        true
    );
});

Frontend (bridge.js):

import { addonLoader, addFilter } from '@woonoow/hooks';

addonLoader.register({
  id: 'rajaongkir-bridge',
  name: 'Rajaongkir Bridge',
  version: '1.0.0',
  init: () => {
    // Add destination search field after shipping address
    addFilter('woonoow_order_form_after_shipping', (content, formData, setFormData) => {
      // Only for Indonesia
      if (formData.shipping?.country !== 'ID') return content;
      
      return (
        <>
          {content}
          <div className="border rounded-lg p-4 mt-4">
            <h3 className="font-medium mb-3">📍 Shipping Destination</h3>
            <RajaongkirDestinationSearch
              value={formData.shipping?.destination_id}
              onChange={(id, label) => {
                setFormData({
                  ...formData,
                  shipping: {
                    ...formData.shipping,
                    destination_id: id,
                    destination_label: label,
                  }
                });
              }}
            />
          </div>
        </>
      );
    });
  }
});

Option B: Code Snippet (No Plugin)

For users who don't want a separate plugin, provide a code snippet:

// Add to theme's functions.php or custom plugin

// Bridge Rajaongkir with WooNooW
add_filter('woonoow_shipping_data', function($data) {
    if ($data['country'] === 'ID' && !empty($data['city'])) {
        // Auto-search and set destination
        $api = Cekongkir_API::get_instance();
        $results = $api->search_destination_api($data['city']);
        if (!empty($results[0])) {
            WC()->session->set('selected_destination_id', $results[0]['id']);
        }
    }
    return $data;
});

Proper Solution: Build WooNooW Addon

Instead of bridging Rajaongkir, build a proper WooNooW addon:

WooNooW Indonesia Shipping Addon

<?php
/**
 * Plugin Name: WooNooW Indonesia Shipping
 * Description: Indonesia shipping with Rajaongkir API
 * Version: 1.0.0
 * Requires: WooNooW 1.0.0+
 */

// Register addon
add_filter('woonoow/addon_registry', function($addons) {
    $addons['indonesia-shipping'] = [
        'id'           => 'indonesia-shipping',
        'name'         => 'Indonesia Shipping',
        'version'      => '1.0.0',
        'spa_bundle'   => plugin_dir_url(__FILE__) . 'dist/addon.js',
        'dependencies' => ['woocommerce' => '8.0'],
    ];
    return $addons;
});

// Add API endpoints
add_action('rest_api_init', function() {
    register_rest_route('woonoow/v1', '/indonesia/search-destination', [
        'methods' => 'GET',
        'callback' => function($req) {
            $query = $req->get_param('query');
            $api = new RajaongkirAPI(get_option('rajaongkir_api_key'));
            return $api->searchDestination($query);
        },
    ]);
    
    register_rest_route('woonoow/v1', '/indonesia/calculate-shipping', [
        'methods' => 'POST',
        'callback' => function($req) {
            $origin = $req->get_param('origin');
            $destination = $req->get_param('destination');
            $weight = $req->get_param('weight');
            
            $api = new RajaongkirAPI(get_option('rajaongkir_api_key'));
            return $api->calculateShipping($origin, $destination, $weight);
        },
    ]);
});

Frontend:

// dist/addon.ts

import { addonLoader, addFilter } from '@woonoow/hooks';
import { DestinationSearch } from './components/DestinationSearch';

addonLoader.register({
  id: 'indonesia-shipping',
  name: 'Indonesia Shipping',
  version: '1.0.0',
  init: () => {
    // Add destination field
    addFilter('woonoow_order_form_after_shipping', (content, formData, setFormData) => {
      if (formData.shipping?.country !== 'ID') return content;
      
      return (
        <>
          {content}
          <DestinationSearch
            value={formData.shipping?.destination_id}
            onChange={(id, label) => {
              setFormData({
                ...formData,
                shipping: { ...formData.shipping, destination_id: id, destination_label: label }
              });
            }}
          />
        </>
      );
    });
    
    // Add validation
    addFilter('woonoow_order_form_validation', (errors, formData) => {
      if (formData.shipping?.country === 'ID' && !formData.shipping?.destination_id) {
        errors.destination = 'Please select shipping destination';
      }
      return errors;
    });
  }
});

Comparison

Bridge Snippet (Quick Fix)

Works immediately No new plugin needed Minimal code Depends on Rajaongkir plugin Limited features Not ideal UX

Proper WooNooW Addon (Best Practice)

Native WooNooW integration Better UX More features Independent of Rajaongkir plugin Can use any shipping API More development effort Separate plugin to maintain


Recommendation

For WooNooW Core:

  • Don't integrate Rajaongkir
  • Provide hook system
  • Document bridge pattern
  • Provide code snippets

For Users:

  • Quick fix: Use bridge snippet
  • Best practice: Build proper addon or use community addon

For Community:

  • Build "WooNooW Indonesia Shipping" addon
  • Publish on WordPress.org
  • Support Rajaongkir, Biteship, and other Indonesian shipping APIs

Hook Points Needed in WooNooW Core

To support addons like this, WooNooW core should provide:

// Before shipping calculation
apply_filters('woonoow_before_shipping_calculate', $shipping_data);

// After shipping calculation
apply_filters('woonoow_after_shipping_calculate', $rates, $shipping_data);

// Modify shipping data
apply_filters('woonoow_shipping_data', $data);
// Frontend hooks
'woonoow_order_form_after_shipping'
'woonoow_order_form_shipping_fields'
'woonoow_order_form_validation'
'woonoow_order_form_submit'

These hooks already exist in our addon system!


Conclusion

WooNooW Core = Zero addon dependencies

Instead of integrating Rajaongkir into core:

  1. Provide hook system (Already done)
  2. Document bridge pattern (This document)
  3. Encourage community addons

This keeps WooNooW core:

  • Clean
  • Maintainable
  • Flexible
  • Extensible

Users can choose:

  • Bridge snippet (quick fix)
  • Proper addon (best practice)
  • Build their own

No bloat in core!