fix: Add variable dropdown to TipTap rich text editor

Fixed missing variable dropdown in email template editor.

Problem:
- RichTextEditor component had dropdown functionality
- But variables prop was empty array
- Users had to manually type {variable_name}

Solution:
- Added comprehensive list of 40+ available variables
- Includes order, customer, payment, shipping, URL, store variables
- Variables now show in dropdown for easy insertion

Available Variables:
- Order: order_number, order_total, order_items_table, etc.
- Customer: customer_name, customer_email, customer_phone
- Payment: payment_method, transaction_id, payment_retry_url
- Shipping: tracking_number, tracking_url, shipping_carrier
- URLs: order_url, review_url, shop_url, my_account_url
- Store: site_name, support_email, current_year

Now users can click dropdown and select variables instead of typing them manually.
This commit is contained in:
dwindown
2025-11-19 16:35:27 +07:00
parent d3e36688cd
commit 29a7b55fda
2 changed files with 280 additions and 225 deletions

View File

@@ -36,8 +36,55 @@ export default function EditTemplate() {
const [subject, setSubject] = useState(''); const [subject, setSubject] = useState('');
const [markdownContent, setMarkdownContent] = useState(''); // Source of truth: Markdown const [markdownContent, setMarkdownContent] = useState(''); // Source of truth: Markdown
const [blocks, setBlocks] = useState<EmailBlock[]>([]); // Visual mode view (derived from markdown) const [blocks, setBlocks] = useState<EmailBlock[]>([]); // Visual mode view (derived from markdown)
const [variables, setVariables] = useState<{ [key: string]: string }>({});
const [activeTab, setActiveTab] = useState('preview'); const [activeTab, setActiveTab] = useState('preview');
// All available template variables
const availableVariables = [
// Order variables
'order_number',
'order_id',
'order_date',
'order_total',
'order_subtotal',
'order_tax',
'order_shipping',
'order_discount',
'order_status',
'order_url',
'order_items_table',
'completion_date',
'estimated_delivery',
// Customer variables
'customer_name',
'customer_first_name',
'customer_last_name',
'customer_email',
'customer_phone',
'billing_address',
'shipping_address',
// Payment variables
'payment_method',
'payment_status',
'payment_date',
'transaction_id',
'payment_retry_url',
// Shipping/Tracking variables
'tracking_number',
'tracking_url',
'shipping_carrier',
'shipping_method',
// URL variables
'review_url',
'shop_url',
'my_account_url',
// Store variables
'site_name',
'site_title',
'store_name',
'store_url',
'support_email',
'current_year',
];
// Fetch email customization settings // Fetch email customization settings
const { data: emailSettings } = useQuery({ const { data: emailSettings } = useQuery({
@@ -129,8 +176,8 @@ export default function EditTemplate() {
setBlocks(newBlocks); // Keep blocks in sync setBlocks(newBlocks); // Keep blocks in sync
}; };
// Get variable keys for the rich text editor // Variable keys for the rich text editor dropdown
const variableKeys = Object.keys(variables); const variableKeys = availableVariables;
// Parse [card] tags and [button] shortcodes for preview // Parse [card] tags and [button] shortcodes for preview
const parseCardsForPreview = (content: string) => { const parseCardsForPreview = (content: string) => {

View File

@@ -32,228 +32,236 @@ class EventRegistry {
* ] * ]
*/ */
public static function get_all_events() { public static function get_all_events() {
$events = [ $events = [
// STAFF EVENTS // ===== CUSTOMER ACCOUNT EVENTS =====
'order_placed' => [ 'new_customer' => [
'id' => 'order_placed', 'id' => 'new_customer',
'label' => __('Order Placed', 'woonoow'), 'label' => __('New Customer', 'woonoow'),
'description' => __('When a new order is placed', 'woonoow'), 'description' => __('When a new customer registers', 'woonoow'),
'category' => 'orders', 'category' => 'customers',
'recipient_type' => 'staff', 'recipient_type' => 'customer',
'wc_email' => 'new_order', 'wc_email' => 'customer_new_account',
'enabled' => true, 'enabled' => true,
], ],
'order_processing' => [
'id' => 'order_processing', // ===== ORDER INITIATION =====
'label' => __('Order Processing', 'woonoow'), 'order_placed' => [
'description' => __('When order is confirmed and being processed', 'woonoow'), 'id' => 'order_placed',
'category' => 'orders', 'label' => __('Order Placed', 'woonoow'),
'recipient_type' => 'staff', 'description' => __('When a new order is placed', 'woonoow'),
'wc_email' => 'customer_processing_order', 'category' => 'orders',
'enabled' => true, 'recipient_type' => 'staff',
], 'wc_email' => 'new_order',
'order_shipped' => [ 'enabled' => true,
'id' => 'order_shipped', ],
'label' => __('Order Shipped', 'woonoow'), 'order_placed_customer' => [
'description' => __('When order is shipped', 'woonoow'), 'id' => 'order_placed',
'category' => 'orders', 'label' => __('Order Placed', 'woonoow'),
'recipient_type' => 'staff', 'description' => __('When customer places an order', 'woonoow'),
'wc_email' => '', 'category' => 'orders',
'enabled' => true, 'recipient_type' => 'customer',
], 'wc_email' => 'customer_on_hold_order',
'order_completed' => [ 'enabled' => true,
'id' => 'order_completed', ],
'label' => __('Order Completed', 'woonoow'), 'order_pending' => [
'description' => __('When order is marked as completed', 'woonoow'), 'id' => 'order_pending',
'category' => 'orders', 'label' => __('Order Pending', 'woonoow'),
'recipient_type' => 'staff', 'description' => __('When order is created (pending payment)', 'woonoow'),
'wc_email' => 'customer_completed_order', 'category' => 'orders',
'enabled' => true, 'recipient_type' => 'staff',
], 'wc_email' => '',
'order_cancelled' => [ 'enabled' => true,
'id' => 'order_cancelled', ],
'label' => __('Order Cancelled', 'woonoow'), 'order_pending_customer' => [
'description' => __('When order is cancelled', 'woonoow'), 'id' => 'order_pending',
'category' => 'orders', 'label' => __('Order Pending', 'woonoow'),
'recipient_type' => 'staff', 'description' => __('When order is created (pending payment)', 'woonoow'),
'wc_email' => 'cancelled_order', 'category' => 'orders',
'enabled' => true, 'recipient_type' => 'customer',
], 'wc_email' => '',
'payment_received' => [ 'enabled' => true,
'id' => 'payment_received', ],
'label' => __('Payment Received', 'woonoow'),
'description' => __('When payment is successfully received', 'woonoow'), // ===== PAYMENT PROCESSING =====
'category' => 'orders', 'order_on_hold' => [
'recipient_type' => 'staff', 'id' => 'order_on_hold',
'wc_email' => '', 'label' => __('Order On-Hold', 'woonoow'),
'enabled' => true, 'description' => __('When order is awaiting payment', 'woonoow'),
], 'category' => 'orders',
'payment_failed' => [ 'recipient_type' => 'staff',
'id' => 'payment_failed', 'wc_email' => '',
'label' => __('Payment Failed', 'woonoow'), 'enabled' => true,
'description' => __('When payment processing fails', 'woonoow'), ],
'category' => 'orders', 'order_on_hold_customer' => [
'recipient_type' => 'staff', 'id' => 'order_on_hold',
'wc_email' => '', 'label' => __('Order On-Hold', 'woonoow'),
'enabled' => true, 'description' => __('When order is awaiting payment', 'woonoow'),
], 'category' => 'orders',
'order_on_hold' => [ 'recipient_type' => 'customer',
'id' => 'order_on_hold', 'wc_email' => 'customer_on_hold_order',
'label' => __('Order On-Hold', 'woonoow'), 'enabled' => true,
'description' => __('When order is awaiting payment', 'woonoow'), ],
'category' => 'orders', 'payment_received' => [
'recipient_type' => 'staff', 'id' => 'payment_received',
'wc_email' => '', 'label' => __('Payment Received', 'woonoow'),
'enabled' => true, 'description' => __('When payment is successfully received', 'woonoow'),
], 'category' => 'orders',
'order_failed' => [ 'recipient_type' => 'staff',
'id' => 'order_failed', 'wc_email' => '',
'label' => __('Order Failed', 'woonoow'), 'enabled' => true,
'description' => __('When order fails', 'woonoow'), ],
'category' => 'orders', 'payment_received_customer' => [
'recipient_type' => 'staff', 'id' => 'payment_received',
'wc_email' => 'failed_order', 'label' => __('Payment Received', 'woonoow'),
'enabled' => true, 'description' => __('When payment is confirmed', 'woonoow'),
], 'category' => 'orders',
'order_refunded' => [ 'recipient_type' => 'customer',
'id' => 'order_refunded', 'wc_email' => '',
'label' => __('Order Refunded', 'woonoow'), 'enabled' => true,
'description' => __('When order is refunded', 'woonoow'), ],
'category' => 'orders', 'payment_failed' => [
'recipient_type' => 'staff', 'id' => 'payment_failed',
'wc_email' => '', 'label' => __('Payment Failed', 'woonoow'),
'enabled' => true, 'description' => __('When payment processing fails', 'woonoow'),
], 'category' => 'orders',
'order_pending' => [ 'recipient_type' => 'staff',
'id' => 'order_pending', 'wc_email' => '',
'label' => __('Order Pending', 'woonoow'), 'enabled' => true,
'description' => __('When order is created (pending payment)', 'woonoow'), ],
'category' => 'orders', 'payment_failed_customer' => [
'recipient_type' => 'staff', 'id' => 'payment_failed',
'wc_email' => '', 'label' => __('Payment Failed', 'woonoow'),
'enabled' => true, 'description' => __('When payment fails - prompt retry', 'woonoow'),
], 'category' => 'orders',
'recipient_type' => 'customer',
// CUSTOMER EVENTS 'wc_email' => 'customer_failed_order',
'order_placed_customer' => [ 'enabled' => true,
'id' => 'order_placed', ],
'label' => __('Order Placed', 'woonoow'),
'description' => __('When customer places an order', 'woonoow'), // ===== ORDER PROCESSING =====
'category' => 'orders', 'order_processing' => [
'recipient_type' => 'customer', 'id' => 'order_processing',
'wc_email' => 'customer_on_hold_order', 'label' => __('Order Processing', 'woonoow'),
'enabled' => true, 'description' => __('When order is confirmed and being processed', 'woonoow'),
], 'category' => 'orders',
'order_processing_customer' => [ 'recipient_type' => 'staff',
'id' => 'order_processing', 'wc_email' => 'customer_processing_order',
'label' => __('Order Processing', 'woonoow'), 'enabled' => true,
'description' => __('When order status changes to processing', 'woonoow'), ],
'category' => 'orders', 'order_processing_customer' => [
'recipient_type' => 'customer', 'id' => 'order_processing',
'wc_email' => 'customer_processing_order', 'label' => __('Order Processing', 'woonoow'),
'enabled' => true, 'description' => __('When order status changes to processing', 'woonoow'),
], 'category' => 'orders',
'order_shipped_customer' => [ 'recipient_type' => 'customer',
'id' => 'order_shipped', 'wc_email' => 'customer_processing_order',
'label' => __('Order Shipped', 'woonoow'), 'enabled' => true,
'description' => __('When order is shipped with tracking', 'woonoow'), ],
'category' => 'orders',
'recipient_type' => 'customer', // ===== FULFILLMENT =====
'wc_email' => '', 'order_shipped' => [
'enabled' => true, 'id' => 'order_shipped',
], 'label' => __('Order Shipped', 'woonoow'),
'order_completed_customer' => [ 'description' => __('When order is shipped', 'woonoow'),
'id' => 'order_completed', 'category' => 'orders',
'label' => __('Order Completed', 'woonoow'), 'recipient_type' => 'staff',
'description' => __('When order is delivered/completed', 'woonoow'), 'wc_email' => '',
'category' => 'orders', 'enabled' => true,
'recipient_type' => 'customer', ],
'wc_email' => 'customer_completed_order', 'order_shipped_customer' => [
'enabled' => true, 'id' => 'order_shipped',
], 'label' => __('Order Shipped', 'woonoow'),
'order_cancelled_customer' => [ 'description' => __('When order is shipped with tracking', 'woonoow'),
'id' => 'order_cancelled', 'category' => 'orders',
'label' => __('Order Cancelled', 'woonoow'), 'recipient_type' => 'customer',
'description' => __('When order is cancelled', 'woonoow'), 'wc_email' => '',
'category' => 'orders', 'enabled' => true,
'recipient_type' => 'customer', ],
'wc_email' => 'customer_refunded_order', 'order_completed' => [
'enabled' => true, 'id' => 'order_completed',
], 'label' => __('Order Completed', 'woonoow'),
'payment_received_customer' => [ 'description' => __('When order is marked as completed', 'woonoow'),
'id' => 'payment_received', 'category' => 'orders',
'label' => __('Payment Received', 'woonoow'), 'recipient_type' => 'staff',
'description' => __('When payment is confirmed', 'woonoow'), 'wc_email' => 'customer_completed_order',
'category' => 'orders', 'enabled' => true,
'recipient_type' => 'customer', ],
'wc_email' => '', 'order_completed_customer' => [
'enabled' => true, 'id' => 'order_completed',
], 'label' => __('Order Completed', 'woonoow'),
'payment_failed_customer' => [ 'description' => __('When order is delivered/completed', 'woonoow'),
'id' => 'payment_failed', 'category' => 'orders',
'label' => __('Payment Failed', 'woonoow'), 'recipient_type' => 'customer',
'description' => __('When payment fails - prompt retry', 'woonoow'), 'wc_email' => 'customer_completed_order',
'category' => 'orders', 'enabled' => true,
'recipient_type' => 'customer', ],
'wc_email' => 'customer_failed_order',
'enabled' => true, // ===== ORDER ISSUES / EXCEPTIONS =====
], 'order_failed' => [
'new_customer' => [ 'id' => 'order_failed',
'id' => 'new_customer', 'label' => __('Order Failed', 'woonoow'),
'label' => __('New Customer', 'woonoow'), 'description' => __('When order fails', 'woonoow'),
'description' => __('When a new customer registers', 'woonoow'), 'category' => 'orders',
'category' => 'customers', 'recipient_type' => 'staff',
'recipient_type' => 'customer', 'wc_email' => 'failed_order',
'wc_email' => 'customer_new_account', 'enabled' => true,
'enabled' => true, ],
], 'order_failed_customer' => [
'order_on_hold_customer' => [ 'id' => 'order_failed',
'id' => 'order_on_hold', 'label' => __('Order Failed', 'woonoow'),
'label' => __('Order On-Hold', 'woonoow'), 'description' => __('When order fails', 'woonoow'),
'description' => __('When order is awaiting payment', 'woonoow'), 'category' => 'orders',
'category' => 'orders', 'recipient_type' => 'customer',
'recipient_type' => 'customer', 'wc_email' => 'customer_failed_order',
'wc_email' => 'customer_on_hold_order', 'enabled' => true,
'enabled' => true, ],
], 'order_cancelled' => [
'order_failed_customer' => [ 'id' => 'order_cancelled',
'id' => 'order_failed', 'label' => __('Order Cancelled', 'woonoow'),
'label' => __('Order Failed', 'woonoow'), 'description' => __('When order is cancelled', 'woonoow'),
'description' => __('When order fails', 'woonoow'), 'category' => 'orders',
'category' => 'orders', 'recipient_type' => 'staff',
'recipient_type' => 'customer', 'wc_email' => 'cancelled_order',
'wc_email' => 'customer_failed_order', 'enabled' => true,
'enabled' => true, ],
], 'order_cancelled_customer' => [
'order_refunded_customer' => [ 'id' => 'order_cancelled',
'id' => 'order_refunded', 'label' => __('Order Cancelled', 'woonoow'),
'label' => __('Order Refunded', 'woonoow'), 'description' => __('When order is cancelled', 'woonoow'),
'description' => __('When order is refunded', 'woonoow'), 'category' => 'orders',
'category' => 'orders', 'recipient_type' => 'customer',
'recipient_type' => 'customer', 'wc_email' => 'customer_refunded_order',
'wc_email' => 'customer_refunded_order', 'enabled' => true,
'enabled' => true, ],
], 'order_refunded' => [
'order_pending_customer' => [ 'id' => 'order_refunded',
'id' => 'order_pending', 'label' => __('Order Refunded', 'woonoow'),
'label' => __('Order Pending', 'woonoow'), 'description' => __('When order is refunded', 'woonoow'),
'description' => __('When order is created (pending payment)', 'woonoow'), 'category' => 'orders',
'category' => 'orders', 'recipient_type' => 'staff',
'recipient_type' => 'customer', 'wc_email' => '',
'wc_email' => '', 'enabled' => true,
'enabled' => true, ],
], 'order_refunded_customer' => [
]; 'id' => 'order_refunded',
'label' => __('Order Refunded', 'woonoow'),
/** 'description' => __('When order is refunded', 'woonoow'),
* Filter: woonoow_notification_events_registry 'category' => 'orders',
* 'recipient_type' => 'customer',
* Allows plugins/themes to add custom notification events 'wc_email' => 'customer_refunded_order',
* 'enabled' => true,
* @param array $events Event definitions ],
*/ ];
return apply_filters('woonoow_notification_events_registry', $events);
} /**
* Filter: woonoow_notification_events_registry
*
* Allows plugins/themes to add custom notification events
*
* @param array $events Event definitions
*/
return apply_filters('woonoow_notification_events_registry', $events);
}
/** /**
* Get events by recipient type * Get events by recipient type