## Issues Fixed: ### 1. Shipping rates fetched on page load ✅ **Problem:** - Open New Order form → Shipping already calculated - Using cached/legacy values - Should wait for address to be filled **Solution:** Added address completeness check: ```ts const isShippingAddressComplete = useMemo(() => { if (!shippingData.country) return false; if (!shippingData.city) return false; // If country has states, require state const countryStates = states[shippingData.country]; if (countryStates && Object.keys(countryStates).length > 0) { if (!shippingData.state) return false; } return true; }, [shippingData.country, shippingData.state, shippingData.city]); ``` Query only enabled when address is complete: ```ts enabled: isShippingAddressComplete && items.length > 0 ``` ### 2. Unnecessary refetches ✅ **Problem:** - Every keystroke triggered refetch - staleTime: 0 meant always refetch **Solution:** ```ts staleTime: 5 * 60 * 1000 // Cache for 5 minutes ``` Query key still includes all address fields, so: - Change country → Refetch (key changed) - Change state → Refetch (key changed) - Change city → Refetch (key changed) - Change postcode → Refetch (key changed) - Same values → Use cache (key unchanged) ### 3. Order preview fetching too early ✅ **Problem:** - Preview calculated before shipping method selected - Incomplete data **Solution:** ```ts enabled: items.length > 0 && !!bCountry && !!shippingMethod ``` ## New Behavior: ### On Page Load: - ❌ No shipping fetch - ❌ No preview fetch - ✅ Clean state ### User Fills Address: 1. Enter country → Not enough 2. Enter state → Not enough 3. Enter city → ✅ **Fetch shipping rates** 4. Rates appear → First auto-selected 5. ✅ **Fetch order preview** (has method now) ### User Changes Address: 1. Change Jakarta → Bandung 2. Query key changes (city changed) 3. ✅ **Refetch shipping rates** 4. New rates appear → First auto-selected 5. ✅ **Refetch order preview** ### User Types in Same Field: 1. Type "Jak..." → "Jakarta" 2. Query key same (city still "Jakarta") 3. ❌ No refetch (use cache) 4. Efficient! ## Benefits: - ✅ No premature fetching - ✅ No unnecessary API calls - ✅ Smart caching (5 min) - ✅ Only refetch when address actually changes - ✅ Better UX and performance
WooNooW
WooNooW is a modern experience layer for WooCommerce — enhancing UX, speed, and reliability without data migration.
It keeps WooCommerce as the core engine while providing a modern React-powered interface for both the storefront (cart, checkout, my‑account) and the admin (orders, dashboard).
Three Admin Modes:
- Normal Mode: Traditional wp-admin integration (
/wp-admin/admin.php?page=woonoow) - Fullscreen Mode: Distraction-free interface (toggle in header)
- Standalone Mode: Complete standalone app at
yoursite.com/adminwith custom login ✨
🔍 Background
WooCommerce is the most used e‑commerce engine in the world, but its architecture has become heavy and fragmented.
With React‑based blocks (Checkout, Cart, Product Edit) and HPOS now rolling out, many existing addons are becoming obsolete or unstable.
WooNooW bridges the gap between Woo’s legacy PHP system and the new modern stack — so users get performance and simplicity without losing compatibility.
🚀 Key Principles
- No Migration Needed – Woo data stays intact.
- Safe Activate/Deactivate – revert to native Woo anytime, no data loss.
- Hybrid by Default – SSR + React islands for Cart/Checkout/My‑Account.
- Full SPA Toggle – optional React‑only mode for max performance.
- HPOS Mandatory – optimized datastore and async operations.
- Compat Layer – hook mirror + slot rendering for legacy addons.
- Async Mail & Tasks – powered by Action Scheduler.
🧱 Tech Stack
| Layer | Technology |
|---|---|
| Backend | PHP 8.2+, WordPress, WooCommerce (HPOS), Action Scheduler |
| Frontend | React 18 + TypeScript, Vite, React Query, Tailwind (optional) |
| Build & Package | Composer, NPM, ESM scripts, Zip automation |
| Architecture | Modular PSR‑4 classes, REST‑driven SPA islands |
🧩 Project Structure
woonoow/
├── admin-spa/
│ ├── src/
│ │ ├── components/
│ │ │ ├── filters/
│ │ │ │ ├── DateRange.tsx
│ │ │ │ └── OrderBy.tsx
│ │ │ └── CommandPalette.tsx
│ │ ├── hooks/
│ │ │ └── useShortcuts.tsx
│ │ ├── lib/
│ │ │ ├── api.ts
│ │ │ ├── currency.ts
│ │ │ ├── dates.ts
│ │ │ ├── query-params.ts
│ │ │ ├── useCommandStore.ts
│ │ │ └── utils.ts
│ │ ├── pages/
│ │ │ └── orders/
│ │ │ ├── partials
│ │ │ │ └── OrderForm.tsx
│ │ │ ├── Orders.tsx
│ │ │ ├── OrdersNew.tsx
│ │ │ └── OrderShow.tsx
│ │ ├── routes/
│ │ │ └── Dashboard.tsx
│ │ ├── types/
│ │ │ └── qrcode.d.ts
│ │ ├── App.tsx
│ │ ├── index.css
│ │ └── main.tsx
│ └── vite.config.ts
├── includes/
│ ├── Admin/
│ │ ├── Assets.php
│ │ └── Menu.php
│ ├── Api/
│ │ ├── CheckoutController.php
│ │ ├── OrdersController.php
│ │ ├── Permissions.php
│ │ └── Routes.php
│ ├── Compat/
│ │ ├── HideWooMenus.php
│ │ └── HooksShim.php
│ └── Core/
│ ├── DataStores/
│ │ ├── OrderStore_HPOS.php
│ │ └── OrderStore.php
│ ├── Mail/
│ │ ├── MailQueue.php
│ │ └── WooEmailOverride.php
│ ├── Bootstrap.php
│ └── Features.php
├── woonoow.php
└── docs (project notes, SOP, etc.)
⚙️ Development Workflow
- LocalWP / Docker setup with WordPress + WooCommerce.
- Activate plugin:
WooNooWshould appear in the admin menu. - Build SPAs:
npm run build - Package zip:
npm run pack - Upload
dist/woonoow.zipinto WordPress → Plugins → Add New → Upload.
🧭 Vision
“WooCommerce, reimagined for now.”
WooNooW delivers modern speed and UX while keeping WooCommerce’s ecosystem alive.
No migration. No lock‑in. Just Woo, evolved.