# WooNooW Indonesia Shipping (Biteship Integration)

## Plugin Specification

**Plugin Name:** WooNooW Indonesia Shipping  
**Description:** Simple Indonesian shipping integration using Biteship Rate API  
**Version:** 1.0.0  
**Requires:** WooNooW 1.0.0+, WooCommerce 8.0+  
**License:** GPL v2 or later  

---

## Overview

A lightweight shipping plugin that integrates Biteship's Rate API with WooNooW SPA, providing:
- ✅ Indonesian address fields (Province, City, District, Subdistrict)
- ✅ Real-time shipping rate calculation
- ✅ Multiple courier support (JNE, SiCepat, J&T, AnterAja, etc.)
- ✅ Works in both frontend checkout AND admin order form
- ✅ No subscription required (uses free Biteship Rate API)

---

## Features Roadmap

### Phase 1: Core Functionality
- [ ] WooCommerce Shipping Method integration
- [ ] Biteship Rate API integration
- [ ] Indonesian address database (Province → Subdistrict)
- [ ] Frontend checkout integration
- [ ] Admin settings page

### Phase 2: SPA Integration
- [ ] REST API endpoints for address data
- [ ] REST API for rate calculation
- [ ] React components (SubdistrictSelector, CourierSelector)
- [ ] Hook integration with WooNooW OrderForm
- [ ] Admin order form support

### Phase 3: Advanced Features
- [ ] Rate caching (reduce API calls)
- [ ] Custom rate markup
- [ ] Free shipping threshold
- [ ] Multi-origin support
- [ ] Shipping label generation (optional, requires paid Biteship plan)

---

## Plugin Structure

```
woonoow-indonesia-shipping/
├── woonoow-indonesia-shipping.php          # Main plugin file
├── includes/
│   ├── class-shipping-method.php           # WooCommerce shipping method
│   ├── class-biteship-api.php              # Biteship API client
│   ├── class-address-database.php          # Indonesian address data
│   ├── class-addon-integration.php         # WooNooW addon integration
│   └── Api/
│       └── AddressController.php           # REST API endpoints
├── admin/
│   ├── class-settings.php                  # Admin settings page
│   └── views/
│       └── settings-page.php               # Settings UI
├── admin-spa/
│   ├── src/
│   │   ├── components/
│   │   │   ├── SubdistrictSelector.tsx    # Address selector
│   │   │   └── CourierSelector.tsx        # Courier selection
│   │   ├── hooks/
│   │   │   ├── useAddressData.ts          # Fetch address data
│   │   │   └── useRateCalculation.ts      # Calculate rates
│   │   └── index.ts                        # Addon registration
│   ├── package.json
│   └── vite.config.ts
├── data/
│   └── indonesia-areas.sql                 # Address database dump
└── README.md
```

---

## Database Schema

```sql
CREATE TABLE `wp_woonoow_indonesia_areas` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `biteship_area_id` varchar(50) NOT NULL,
  `name` varchar(255) NOT NULL,
  `type` enum('province','city','district','subdistrict') NOT NULL,
  `parent_id` bigint(20) DEFAULT NULL,
  `postal_code` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `biteship_area_id` (`biteship_area_id`),
  KEY `parent_id` (`parent_id`),
  KEY `type` (`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```

---

## WooCommerce Shipping Method

```php
<?php
// includes/class-shipping-method.php

class WooNooW_Indonesia_Shipping_Method extends WC_Shipping_Method {
    
    public function __construct($instance_id = 0) {
        $this->id = 'woonoow_indonesia_shipping';
        $this->instance_id = absint($instance_id);
        $this->method_title = __('Indonesia Shipping', 'woonoow-indonesia-shipping');
        $this->supports = array('shipping-zones', 'instance-settings');
        $this->init();
    }
    
    public function init_form_fields() {
        $this->instance_form_fields = array(
            'api_key' => array(
                'title' => 'Biteship API Key',
                'type' => 'text'
            ),
            'origin_subdistrict_id' => array(
                'title' => 'Origin Subdistrict',
                'type' => 'select',
                'options' => $this->get_subdistrict_options()
            ),
            'couriers' => array(
                'title' => 'Available Couriers',
                'type' => 'multiselect',
                'options' => array(
                    'jne' => 'JNE',
                    'sicepat' => 'SiCepat',
                    'jnt' => 'J&T Express'
                )
            )
        );
    }
    
    public function calculate_shipping($package = array()) {
        $origin = $this->get_option('origin_subdistrict_id');
        $destination = $package['destination']['subdistrict_id'] ?? null;
        
        if (!$origin || !$destination) return;
        
        $api = new WooNooW_Biteship_API($this->get_option('api_key'));
        $rates = $api->get_rates($origin, $destination, $package);
        
        foreach ($rates as $rate) {
            $this->add_rate(array(
                'id' => $this->id . ':' . $rate['courier_code'],
                'label' => $rate['courier_name'] . ' - ' . $rate['service_name'],
                'cost' => $rate['price']
            ));
        }
    }
}
```

---

## REST API Endpoints

```php
<?php
// includes/Api/AddressController.php

register_rest_route('woonoow/v1', '/indonesia-shipping/provinces', array(
    'methods' => 'GET',
    'callback' => 'get_provinces'
));

register_rest_route('woonoow/v1', '/indonesia-shipping/calculate-rates', array(
    'methods' => 'POST',
    'callback' => 'calculate_rates'
));
```

---

## React Components

```typescript
// admin-spa/src/components/SubdistrictSelector.tsx

export function SubdistrictSelector({ value, onChange }) {
  const [provinceId, setProvinceId] = useState('');
  const [cityId, setCityId] = useState('');
  
  const { data: provinces } = useQuery({
    queryKey: ['provinces'],
    queryFn: () => api.get('/indonesia-shipping/provinces')
  });
  
  return (
    <div className="space-y-3">
      <Select label="Province" options={provinces} />
      <Select label="City" options={cities} />
      <Select label="Subdistrict" onChange={onChange} />
    </div>
  );
}
```

---

## WooNooW Hook Integration

```typescript
// admin-spa/src/index.ts

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

addonLoader.register({
  id: 'indonesia-shipping',
  name: 'Indonesia Shipping',
  version: '1.0.0',
  init: () => {
    // Add subdistrict selector in order form
    addFilter('woonoow_order_form_after_shipping', (content, formData, setFormData) => {
      return (
        <>
          {content}
          <SubdistrictSelector
            value={formData.shipping?.subdistrict_id}
            onChange={(id) => setFormData({
              ...formData,
              shipping: { ...formData.shipping, subdistrict_id: id }
            })}
          />
        </>
      );
    });
  }
});
```

---

## Implementation Timeline

**Week 1: Backend**
- Day 1-2: Database schema + address data import
- Day 3-4: WooCommerce shipping method class
- Day 5: Biteship API integration

**Week 2: Frontend**
- Day 1-2: REST API endpoints
- Day 3-4: React components
- Day 5: Hook integration + testing

**Week 3: Polish**
- Day 1-2: Error handling + loading states
- Day 3: Rate caching
- Day 4-5: Documentation + testing

---

**Status:** Specification Complete - Ready for Implementation
