From db6ddf67bd53540d1e9882237d23b570b052f15f Mon Sep 17 00:00:00 2001 From: dwindown Date: Thu, 13 Nov 2025 06:55:20 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20Polish=20Email=20Builder=20-=20Perfect?= =?UTF-8?q?=20UX!=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 🎨 4 Major Improvements Based on Feedback: ### 1. ✅ Move Tabs to Message Body Section **Before:** - Tabs at top level - Subject shown in preview (unnecessary) **After:** - Tabs inside Message Body section - Subject removed from preview (it's just a string) - Cleaner, more focused UI **Layout:** ``` Subject / Title [input field] Message Body [Editor | Preview] [Code Mode] ┌─────────────────────────────────────────────────┐ │ Email Builder / Preview │ └─────────────────────────────────────────────────┘ ``` ### 2. ✅ Darker Canvas Background **Before:** - Light gray canvas (bg-gray-50) - White email wrapper - Cards hard to see **After:** - Darker canvas (bg-gray-100) - Light gray email wrapper (bg-gray-50) - Cards stand out clearly - Better visual hierarchy ### 3. ✅ Editor Matches Preview Exactly **Problem:** - Editor used Tailwind classes - Preview used inline styles - Different rendering! **Solution:** - Editor now uses inline styles - Matches email rendering exactly - WYSIWYG is truly WYSIWYG **Card Styles (Inline):** ```tsx default: { background: "#ffffff", borderRadius: "8px", padding: "32px 40px" } success: { background: "#e8f5e9", border: "1px solid #4caf50", ... } ``` **Button Styles (Inline):** ```tsx solid: { background: "#7f54b3", color: "#fff", padding: "14px 28px", ... } outline: { border: "2px solid #7f54b3", color: "#7f54b3", ... } ``` **Result:** - What you see in editor = What you get in email - No surprises! - Honest rendering ### 4. ✅ RichTextEditor in Edit Dialog **Before:** - Plain textarea for content - Manual HTML typing - No formatting toolbar **After:** - Full RichTextEditor with toolbar - Bold, Italic, Lists, Links - Variable insertion - HTML generated automatically **Benefits:** - ✅ Easy to use - ✅ No HTML knowledge needed - ✅ Professional formatting - ✅ Variable support - ✅ Much better UX **Dialog UI:** ``` Edit Card ───────────────────────────── Card Type: [Default ▼] Content: ┌─────────────────────────────┐ │ [B] [I] [List] [Link] [Undo]│ │ │ │ Your content here... │ │ │ └─────────────────────────────┘ Available Variables: {customer_name} {order_number} ... [Cancel] [Save Changes] ``` ## Summary: All 4 improvements implemented: 1. ✅ Tabs moved to Message Body 2. ✅ Darker canvas for better contrast 3. ✅ Editor matches preview exactly 4. ✅ RichTextEditor for easy editing **The Email Builder is now PERFECT for non-technical users!** 🎉 --- .../components/EmailBuilder/BlockRenderer.tsx | 73 +++++++++--- .../components/EmailBuilder/EmailBuilder.tsx | 37 +++--- .../Settings/Notifications/EditTemplate.tsx | 110 +++++++----------- 3 files changed, 120 insertions(+), 100 deletions(-) diff --git a/admin-spa/src/components/EmailBuilder/BlockRenderer.tsx b/admin-spa/src/components/EmailBuilder/BlockRenderer.tsx index 6e74f32..cbd93e2 100644 --- a/admin-spa/src/components/EmailBuilder/BlockRenderer.tsx +++ b/admin-spa/src/components/EmailBuilder/BlockRenderer.tsx @@ -39,33 +39,80 @@ export function BlockRenderer({ ); case 'card': - const cardClasses = { - default: 'bg-white border border-gray-200', - success: 'bg-green-50 border border-green-200', - info: 'bg-blue-50 border border-blue-200', - warning: 'bg-orange-50 border border-orange-200', - hero: 'bg-gradient-to-r from-purple-500 to-indigo-600 text-white' + const cardStyles: { [key: string]: React.CSSProperties } = { + default: { + background: '#ffffff', + borderRadius: '8px', + padding: '32px 40px', + marginBottom: '24px' + }, + success: { + background: '#e8f5e9', + border: '1px solid #4caf50', + borderRadius: '8px', + padding: '32px 40px', + marginBottom: '24px' + }, + info: { + background: '#f0f7ff', + border: '1px solid #0071e3', + borderRadius: '8px', + padding: '32px 40px', + marginBottom: '24px' + }, + warning: { + background: '#fff8e1', + border: '1px solid #ff9800', + borderRadius: '8px', + padding: '32px 40px', + marginBottom: '24px' + }, + hero: { + background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', + color: '#fff', + borderRadius: '8px', + padding: '32px 40px', + marginBottom: '24px' + } }; return ( -
+
); case 'button': - const buttonClasses = block.style === 'solid' - ? 'bg-purple-600 text-white hover:bg-purple-700' - : 'border-2 border-purple-600 text-purple-600 hover:bg-purple-50'; + const buttonStyle: React.CSSProperties = block.style === 'solid' + ? { + display: 'inline-block', + background: '#7f54b3', + color: '#fff', + padding: '14px 28px', + borderRadius: '6px', + textDecoration: 'none', + fontWeight: 600 + } + : { + display: 'inline-block', + background: 'transparent', + color: '#7f54b3', + padding: '12px 26px', + border: '2px solid #7f54b3', + borderRadius: '6px', + textDecoration: 'none', + fontWeight: 600 + }; return ( -
+
{block.text} diff --git a/admin-spa/src/components/EmailBuilder/EmailBuilder.tsx b/admin-spa/src/components/EmailBuilder/EmailBuilder.tsx index 770b37a..4d248b8 100644 --- a/admin-spa/src/components/EmailBuilder/EmailBuilder.tsx +++ b/admin-spa/src/components/EmailBuilder/EmailBuilder.tsx @@ -5,6 +5,7 @@ import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; +import { RichTextEditor } from '@/components/ui/rich-text-editor'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Plus, Type, Square, MousePointer, Minus, Space } from 'lucide-react'; @@ -179,8 +180,8 @@ export function EmailBuilder({ blocks, onChange, variables = [] }: EmailBuilderP
{/* Email Canvas */} -
-
+
+
{blocks.length === 0 ? (

{__('No blocks yet. Add blocks using the toolbar above.')}

@@ -221,14 +222,16 @@ export function EmailBuilder({ blocks, onChange, variables = [] }: EmailBuilderP
{(editingBlock?.type === 'header' || editingBlock?.type === 'text') && (
- -