feat: Complete markdown syntax refinement and variable protection

 New cleaner syntax implemented:
- [card:type] instead of [card type='type']
- [button:style](url)Text[/button] instead of [button url='...' style='...']
- Standard markdown images: ![alt](url)

 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
This commit is contained in:
dwindown
2025-11-15 20:05:50 +07:00
parent 550b3b69ef
commit 4471cd600f
45 changed files with 9194 additions and 508 deletions

206
RECIPIENT_TYPE_FIX.md Normal file
View File

@@ -0,0 +1,206 @@
# 🎯 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
```typescript
// 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:**
1. Read `recipient` from URL
2. Pass to API GET request
3. Pass to API PUT request
4. Pass to API DELETE request
```typescript
// 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
```php
// 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
```php
// 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
1. **Stop dev server:** Ctrl+C
2. **Restart:** `npm run dev`
3. **Hard refresh:** Cmd+Shift+R
4. **Test Customer Page:**
- Go to Customer Notifications
- Click "Order Placed" → Should show customer template
- Subject should be customer-facing
5. **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:**
1. Pass `recipient` parameter in URL
2. Use `{recipient_type}_{event_id}_{channel_id}` as storage key
3. 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! 🎊