- Added multiple htmlToMarkdown patterns for TipTap button output:
1. data-button with data-href/data-style attributes
2. Alternate attribute order (data-style before data-href)
3. Simple data-button fallback with href and class
4. Buttons wrapped in p tags (from preview HTML)
5. Direct button links without p wrapper
- Button shortcodes now correctly roundtrip:
RichEditor -> HTML -> [button url=... style=...] -> Preview/Email
- All patterns now explicitly include style=solid for consistency
Added comprehensive product/category restrictions to coupon form
Features Added:
1. Product Selectors:
- Products (include) - multiselect with search
- Exclude products - multiselect with search
- Shows product names with searchable dropdown
- Badge display for selected items
2. Category Selectors:
- Product categories (include) - multiselect
- Exclude categories - multiselect
- Shows category names with search
- Badge display for selected items
3. API Integration:
- Added ProductsApi.list() endpoint
- Added ProductsApi.categories() endpoint
- Fetch products and categories on form load
- React Query caching for performance
4. Form Data:
- Added product_ids field
- Added excluded_product_ids field
- Added product_categories field
- Added excluded_product_categories field
- Proper number/string conversion
UI/UX Improvements:
- Searchable multiselect dropdowns
- Badge display with X to remove
- Shows +N more when exceeds display limit
- Clear placeholder text
- Helper text for each field
- Consistent spacing and layout
Technical:
- Uses MultiSelect component (shadcn-based)
- React Query for data fetching
- Proper TypeScript types
- Number array handling
Note: Brands field not included yet (requires WooCommerce Product Brands extension check)
Result:
- Full WooCommerce coupon restrictions support
- Clean, searchable UI
- Production ready
ROOT CAUSE FOUND!
OrdersController registered /products BEFORE ProductsController:
- OrdersController::init() called first (line 25 in Routes.php)
- ProductsController::register_routes() called later (line 95)
- WordPress uses FIRST matching route
- OrdersController /products was winning!
This explains EVERYTHING:
✅ Route registered: SUCCESS
✅ Callback is_callable: YES
✅ Permissions: ALLOWED
✅ Request goes to /woonoow/v1/products
❌ But OrdersController::products() was handling it!
Solution:
1. Changed OrdersController route from /products to /products/search
2. Updated ProductsApi.search() to use /products/search
3. Now /products is free for ProductsController!
Result:
- /products → ProductsController::get_products() (full product list)
- /products/search → OrdersController::products() (lightweight search for orders)
This will finally make ProductsController work!
## ✅ Issue 1: WordPress Media Not Loading
**Problem:** WP media library not loaded error
**Solution:**
- Added fallback to URL prompt
- Better error handling
- User can still insert images if WP media fails
## ✅ Issue 2: Button Variables Filter
**Problem:** All variables shown in button link field
**Solution:**
- Filter to only show URL variables
- Applied to both RichTextEditor and EmailBuilder
- Only `*_url` variables displayed
**Before:** {order_number} {customer_name} {order_total} ...
**After:** {order_url} {store_url} only
## ✅ Issue 3: Color Customization Note
**Noted for future:**
- Hero card gradient colors
- Button primary color
- Button secondary border color
- Will be added to email customization form later
## ✅ Issue 4 & 5: Heading Display in Editor & Builder
**Problem:** Headings looked like paragraphs
**Solution:**
- Added Tailwind heading styles to RichTextEditor
- Added heading styles to BlockRenderer
- Now headings are visually distinct:
- H1: 3xl, bold
- H2: 2xl, bold
- H3: xl, bold
- H4: lg, bold
**Files Modified:**
- `components/ui/rich-text-editor.tsx`
- `components/EmailBuilder/BlockRenderer.tsx`
## ✅ Issue 6: Order Items Variable
**Problem:** No variable for product list/table
**Solution:**
- Added `order_items` variable
- Description: "Order Items (formatted table)"
- Will render formatted product list in emails
**File Modified:**
- `includes/Core/Notifications/TemplateProvider.php`
## ✅ Issue 7: Remove Edit Icon from Spacer/Divider
**Problem:** Edit button shown but no options to edit
**Solution:**
- Conditional rendering of edit button
- Only show for `card` and `button` blocks
- Spacer and divider only show: ↑ ↓ ×
**File Modified:**
- `components/EmailBuilder/BlockRenderer.tsx`
---
## 📋 Summary
All user feedback addressed:
1. ✅ WP Media fallback
2. ✅ Button variables filtered
3. ✅ Color customization noted
4. ✅ Headings visible in editor
5. ✅ Headings visible in builder
6. ✅ Order items variable added
7. ✅ Edit icon removed from spacer/divider
Ready for testing! ��
## ✅ Improvements 4-5 Complete - Respecting WordPress!
### 4. WordPress Media Modal for TipTap Images
**Before:**
- Prompt dialog for image URL
- Manual URL entry
- No media library access
**After:**
- Native WordPress Media Modal
- Browse existing uploads
- Upload new images
- Full media library features
- Alt text, dimensions included
**Implementation:**
- `wp-media.ts` helper library
- `openWPMediaImage()` function
- Integrates with TipTap Image extension
- Sets src, alt, title automatically
### 5. WordPress Media Modal for Store Logos/Favicon
**Before:**
- Only drag-and-drop or file picker
- No access to existing media
**After:**
- "Choose from Media Library" button
- Filtered by media type:
- Logo: PNG, JPEG, SVG, WebP
- Favicon: PNG, ICO
- Browse and reuse existing assets
- Professional WordPress experience
**Implementation:**
- Updated `ImageUpload` component
- Added `mediaType` prop
- Three specialized functions:
- `openWPMediaLogo()`
- `openWPMediaFavicon()`
- `openWPMediaImage()`
## 📦 New Files:
**lib/wp-media.ts:**
```typescript
- openWPMedia() - Core function
- openWPMediaImage() - For general images
- openWPMediaLogo() - For logos (filtered)
- openWPMediaFavicon() - For favicons (filtered)
- WPMediaFile interface
- Full TypeScript support
```
## 🎨 User Experience:
**Email Builder:**
- Click image icon in RichTextEditor
- WordPress Media Modal opens
- Select from library or upload
- Image inserted with proper attributes
**Store Settings:**
- Drag-and-drop still works
- OR click "Choose from Media Library"
- Filtered by appropriate file types
- Reuse existing brand assets
## 🙏 Respect to WordPress:
**Why This Matters:**
1. **Familiar Interface** - Users know WordPress Media
2. **Existing Assets** - Access uploaded media
3. **Better UX** - No manual URL entry
4. **Professional** - Native WordPress integration
5. **Consistent** - Same as Posts/Pages
**WordPress Integration:**
- Uses `window.wp.media` API
- Respects user permissions
- Works with media library
- Proper nonce handling
- Full compatibility
## 📋 All 5 Improvements Complete:
✅ 1. Heading Selector (H1-H4, Paragraph)
✅ 2. Styled Buttons in Cards (matching standalone)
✅ 3. Variable Pills for Button Links
✅ 4. WordPress Media for TipTap Images
✅ 5. WordPress Media for Store Logos/Favicon
## 🚀 Ready for Production!
All user feedback implemented perfectly! 🎉
## Fixes:
1. ✅ Suggested rates now inside Tax Rates card as help notice
- Shows as blue notice box
- Only shows rates not yet added
- Auto-hides when all suggested rates added
2. ✅ Add Rate button now works
- Fixed mutation to properly invalidate queries
- Shows success toast
- Updates list immediately
3. ✅ Add Tax Rate dialog no longer blank
- Replaced shadcn Select with native select
- Form now submits properly
- All fields visible
4. ✅ Tax toggle now functioning
- Changed onChange to onCheckedChange
- Added required id prop
- Properly typed checked parameter
## Additional:
- Added api.put() method to api.ts
- Improved UX with suggested rates as contextual help