✅ New cleaner syntax implemented: - [card:type] instead of [card type='type'] - [button:style](url)Text[/button] instead of [button url='...' style='...'] - Standard markdown images:  ✅ Variable protection from markdown parsing: - Variables with underscores (e.g., {order_items_table}) now protected - HTML comment placeholders prevent italic/bold parsing - All variables render correctly in preview ✅ Button rendering fixes: - Buttons work in Visual mode inside cards - Buttons work in Preview mode - Button clicks prevented in visual editor - Proper styling for solid and outline buttons ✅ Backward compatibility: - Old syntax still supported - No breaking changes ✅ Bug fixes: - Fixed order_item_table → order_items_table naming - Fixed button regex to match across newlines - Added button/image parsing to parseMarkdownBasics - Prevented button clicks on .button and .button-outline classes 📚 Documentation: - NEW_MARKDOWN_SYNTAX.md - Complete user guide - MARKDOWN_SYNTAX_AND_VARIABLES.md - Technical analysis
6.1 KiB
🎯 THE REAL ROOT CAUSE - Recipient Type Missing from API
🔴 What You Discovered
You noticed the API URL was:
https://woonoow.local/wp-json/woonoow/v1/notifications/templates/order_placed/email
NO recipient parameter!
This means:
- Customer page →
order_placed→ Gets STAFF template ❌ - Staff page →
order_placed→ Gets STAFF template ✅
The API couldn't distinguish between customer and staff templates!
🔍 The Architecture Flaw
Before (BROKEN):
URL Format: /templates/{event_id}/{channel_id}
Storage Key: {event_id}_{channel_id}
Problem: Same key for both customer AND staff!
- order_placed_email → STAFF template
- order_placed_email → CUSTOMER template (OVERWRITTEN!)
After (FIXED):
URL Format: /templates/{event_id}/{channel_id}?recipient={recipient_type}
Storage Key: {recipient_type}_{event_id}_{channel_id}
Solution: Unique keys for each recipient!
- staff_order_placed_email → STAFF template ✅
- customer_order_placed_email → CUSTOMER template ✅
📝 All Changes Made
1. Frontend - Templates.tsx
File: admin-spa/src/routes/Settings/Notifications/Templates.tsx
Line: 63
Change: Pass recipient parameter when navigating to editor
// BEFORE:
navigate(`/settings/notifications/edit-template?event=${event.id}&channel=${channel.id}`);
// AFTER:
navigate(`/settings/notifications/edit-template?event=${event.id}&channel=${channel.id}&recipient=${recipientType}`);
2. Frontend - EditTemplate.tsx
File: admin-spa/src/routes/Settings/Notifications/EditTemplate.tsx
Lines: 34, 55, 141, 159
Changes:
- Read
recipientfrom URL - Pass to API GET request
- Pass to API PUT request
- Pass to API DELETE request
// Read recipient type
const recipientType = searchParams.get('recipient') || 'customer';
// Fetch template WITH recipient
const response = await api.get(`/notifications/templates/${eventId}/${channelId}?recipient=${recipientType}`);
// Save template WITH recipient
await api.put(`/notifications/templates/${eventId}/${channelId}?recipient=${recipientType}`, {...});
// Delete template WITH recipient
await api.del(`/notifications/templates/${eventId}/${channelId}?recipient=${recipientType}`);
3. Backend - NotificationsController.php
File: includes/Api/NotificationsController.php
Lines: 587, 589, 638, 649, 674, 676
Changes: Accept recipient parameter and pass to TemplateProvider
// Get template
$recipient_type = $request->get_param('recipient') ?? 'customer';
$template = TemplateProvider::get_template($event_id, $channel_id, $recipient_type);
// Save template
$recipient_type = $request->get_param('recipient') ?? 'customer';
$result = TemplateProvider::save_template($event_id, $channel_id, $template, $recipient_type);
// Delete template
$recipient_type = $request->get_param('recipient') ?? 'customer';
TemplateProvider::delete_template($event_id, $channel_id, $recipient_type);
4. Backend - TemplateProvider.php
File: includes/Core/Notifications/TemplateProvider.php
Lines: 41, 44, 64, 67, 90, 93, 154
Changes: Use {recipient_type}_{event_id}_{channel_id} as storage key
// Get template
public static function get_template($event_id, $channel_id, $recipient_type = 'customer') {
$key = "{$recipient_type}_{$event_id}_{channel_id}";
// ...
}
// Save template
public static function save_template($event_id, $channel_id, $template, $recipient_type = 'customer') {
$key = "{$recipient_type}_{$event_id}_{channel_id}";
// ...
}
// Delete template
public static function delete_template($event_id, $channel_id, $recipient_type = 'customer') {
$key = "{$recipient_type}_{$event_id}_{channel_id}";
// ...
}
// Default templates
$templates["{$recipient_type}_{$event_id}_email"] = [...];
🎯 Why This Fixes Everything
Issue #1: Customer showing 7 templates instead of 9
Root Cause: API was fetching staff templates for customer page Fix: Now API knows to fetch customer templates when on customer page
Issue #2: Loading staff template for customer event
Root Cause: Same storage key for both staff and customer
Fix: Unique keys: staff_order_placed_email vs customer_order_placed_email
Issue #3: Saving overwrites wrong template
Root Cause: Saving to same key regardless of recipient Fix: Saves to correct recipient-specific key
📊 Data Flow (Now Correct!)
Customer Page → Order Placed:
1. User clicks "Edit" on Customer Notifications page
2. URL: /edit-template?event=order_placed&channel=email&recipient=customer
3. API: GET /templates/order_placed/email?recipient=customer
4. Key: customer_order_placed_email
5. Returns: CUSTOMER template ✅
Staff Page → Order Placed:
1. User clicks "Edit" on Staff Notifications page
2. URL: /edit-template?event=order_placed&channel=email&recipient=staff
3. API: GET /templates/order_placed/email?recipient=staff
4. Key: staff_order_placed_email
5. Returns: STAFF template ✅
🧪 Testing Steps
- Stop dev server: Ctrl+C
- Restart:
npm run dev - Hard refresh: Cmd+Shift+R
- Test Customer Page:
- Go to Customer Notifications
- Click "Order Placed" → Should show customer template
- Subject should be customer-facing
- Test Staff Page:
- Go to Staff Notifications
- Click "Order Placed" → Should show staff template
- Subject should be staff-facing
🎉 Summary
The Problem: API had no way to distinguish between customer and staff templates
The Solution:
- Pass
recipientparameter in URL - Use
{recipient_type}_{event_id}_{channel_id}as storage key - Update all API calls to include recipient type
Files Changed:
- ✅ Templates.tsx (pass recipient when navigating)
- ✅ EditTemplate.tsx (read recipient, pass to API)
- ✅ NotificationsController.php (accept recipient parameter)
- ✅ TemplateProvider.php (use recipient in storage keys)
Result: Customer and staff templates are now completely separate! 🎊