From 93e5a9a3bc0a0bf5412ebdaf5100d480ef3beb4d Mon Sep 17 00:00:00 2001 From: dwindown Date: Mon, 10 Nov 2025 10:16:51 +0700 Subject: [PATCH] fix: Add region search filter + pre-select on edit + create plan doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## ✅ Issue #1: TAX_NOTIFICATIONS_PLAN.md Created - Complete implementation plan for Tax & Notifications - 80/20 rule: Core features vs Advanced (WooCommerce) - API endpoints defined - Implementation phases prioritized ## ✅ Issue #2: Region Search Filter - Added search input above region list - Real-time filtering as you type - Shows "No regions found" when no matches - Clears search on dialog close/cancel - Makes finding countries/states MUCH faster! ## ✅ Issue #3: Pre-select Regions on Edit - Backend now returns raw `locations` array - Frontend uses `defaultChecked` with location matching - Existing regions auto-selected when editing zone - Works correctly for countries, states, and continents ## UX Improvements: - Search placeholder: "Search regions..." - Filter is case-insensitive - Empty state when no results - Clean state management (clear on close) Now zone editing is smooth and fast! --- TAX_NOTIFICATIONS_PLAN.md | 106 +++++++++++++++++++++ admin-spa/src/routes/Settings/Shipping.tsx | 53 ++++++++--- includes/Api/ShippingController.php | 19 +++- 3 files changed, 159 insertions(+), 19 deletions(-) create mode 100644 TAX_NOTIFICATIONS_PLAN.md diff --git a/TAX_NOTIFICATIONS_PLAN.md b/TAX_NOTIFICATIONS_PLAN.md new file mode 100644 index 0000000..5c880ff --- /dev/null +++ b/TAX_NOTIFICATIONS_PLAN.md @@ -0,0 +1,106 @@ +# Tax & Notifications Implementation Plan + +## Philosophy: 80/20 Rule - Real Value, Not Menu-ing + +WooNooW provides elegant UX for 80% of daily use cases. +The 20% advanced/rare features stay in WooCommerce. + +--- + +## Tax Settings - What to Build + +### Core Features (80% use cases): + +1. **Enable/Disable Tax Calculation** + - Simple toggle + - Clear explanation + +2. **Tax Rates by Country/State** + - Add/Edit/Delete tax rates + - Country selector + - State selector (for countries with states) + - Rate percentage input + - Tax class selector (Standard, Reduced, Zero) + +3. **Prices Include Tax Toggle** + - "Prices entered with tax" vs "without tax" + - Clear explanation + +4. **Display Settings** + - Show prices in shop: including/excluding tax + - Show prices in cart: including/excluding tax + - Display suffix (e.g., "incl. VAT") + +### Advanced Features (Link to WooCommerce): + +- Complex tax classes (rare) +- Compound taxes (rare) +- Tax based on shipping vs billing (advanced) +- Custom tax tables (very rare) + +--- + +## Notifications Settings - What to Build + +### Core Features (80% use cases): + +1. **Email Enable/Disable** + - Toggle for each email type + - Already implemented ✅ + +2. **Edit Email Subjects** + - Inline editing of subject lines + - Variables support ({order_number}, {site_title}) + +3. **Sender Configuration** + - "From" name + - "From" email address + +4. **Email Preview** + - Preview button for each email + - Opens WooCommerce preview + +### Advanced Features (Link to WooCommerce): + +- Full HTML template editing (advanced) +- Custom email templates (developer) +- Header/footer customization (advanced) +- Additional recipients (rare) + +--- + +## Implementation Priority + +### Phase 1: Tax Rates (High Impact) +1. Backend: Tax rates CRUD API +2. Frontend: Tax rates list + Add/Edit dialog +3. Frontend: Enable/disable toggle +4. Frontend: Prices include tax toggle + +### Phase 2: Email Subjects (High Impact) +1. Backend: Get/update email settings API +2. Frontend: Sender name/email inputs +3. Frontend: Inline subject editing +4. Frontend: Preview links + +### Phase 3: Tax Display Settings (Medium Impact) +1. Frontend: Display settings card +2. Backend: Save display preferences + +--- + +## API Endpoints Needed + +### Tax: +- GET /settings/tax/rates +- POST /settings/tax/rates +- PUT /settings/tax/rates/{id} +- DELETE /settings/tax/rates/{id} +- GET /settings/tax/config +- POST /settings/tax/config + +### Notifications: +- GET /settings/notifications/emails +- POST /settings/notifications/emails/{id} +- GET /settings/notifications/sender +- POST /settings/notifications/sender diff --git a/admin-spa/src/routes/Settings/Shipping.tsx b/admin-spa/src/routes/Settings/Shipping.tsx index 71e86c3..aaa480d 100644 --- a/admin-spa/src/routes/Settings/Shipping.tsx +++ b/admin-spa/src/routes/Settings/Shipping.tsx @@ -42,6 +42,7 @@ export default function ShippingPage() { const [showAddZone, setShowAddZone] = useState(false); const [editingZone, setEditingZone] = useState(null); const [deletingZone, setDeletingZone] = useState(null); + const [regionSearch, setRegionSearch] = useState(''); const isDesktop = useMediaQuery("(min-width: 768px)"); // Fetch shipping zones from WooCommerce @@ -877,6 +878,7 @@ export default function ShippingPage() { if (!open) { setShowAddZone(false); setEditingZone(null); + setRegionSearch(''); } }}> @@ -927,6 +929,16 @@ export default function ShippingPage() {

{__('Select countries, states, or continents for this zone')}

+ + {/* Search Filter */} + setRegionSearch(e.target.value)} + className="w-full px-3 py-2 border rounded-md mb-2" + /> +
{availableLocations.length === 0 ? (
@@ -934,20 +946,32 @@ export default function ShippingPage() {
) : (
- {availableLocations.map((location: any) => ( - - ))} + {availableLocations + .filter((location: any) => + location.label.toLowerCase().includes(regionSearch.toLowerCase()) + ) + .map((location: any) => ( + + ))} + {availableLocations.filter((location: any) => + location.label.toLowerCase().includes(regionSearch.toLowerCase()) + ).length === 0 && ( +
+ {__('No regions found')} +
+ )}
)}
@@ -960,6 +984,7 @@ export default function ShippingPage() { onClick={() => { setShowAddZone(false); setEditingZone(null); + setRegionSearch(''); }} > {__('Cancel')} diff --git a/includes/Api/ShippingController.php b/includes/Api/ShippingController.php index b584040..3314c50 100644 --- a/includes/Api/ShippingController.php +++ b/includes/Api/ShippingController.php @@ -229,8 +229,16 @@ class ShippingController extends WP_REST_Controller { // Get zone locations (regions) $locations = $zone->get_zone_locations(); $regions = array(); + $raw_locations = array(); foreach ( $locations as $location ) { + // Store raw location data for editing + $raw_locations[] = array( + 'code' => $location->code, + 'type' => $location->type, + ); + + // Format for display if ( $location->type === 'country' ) { $countries = WC()->countries->get_countries(); $regions[] = $countries[ $location->code ] ?? $location->code; @@ -280,11 +288,12 @@ class ShippingController extends WP_REST_Controller { } $zones_data[] = array( - 'id' => $zone_data['id'], - 'name' => $zone->get_zone_name(), - 'order' => $zone->get_zone_order(), - 'regions' => ! empty( $regions ) ? implode( ', ', $regions ) : __( 'No regions', 'woonoow' ), - 'rates' => $rates, + 'id' => $zone_data['id'], + 'name' => $zone->get_zone_name(), + 'order' => $zone->get_zone_order(), + 'regions' => ! empty( $regions ) ? implode( ', ', $regions ) : __( 'No regions', 'woonoow' ), + 'locations' => $raw_locations, + 'rates' => $rates, ); }