feat: Polish Email Builder - Perfect UX!

## 🎨 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!** 🎉
This commit is contained in:
dwindown
2025-11-13 06:55:20 +07:00
parent 4ec0f3f890
commit db6ddf67bd
3 changed files with 120 additions and 100 deletions

View File

@@ -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 (
<div className={`rounded-lg p-6 ${cardClasses[block.cardType]}`}>
<div style={cardStyles[block.cardType]}>
<div
className={`prose prose-sm max-w-none ${block.cardType === 'hero' ? 'prose-invert' : ''}`}
className="prose prose-sm max-w-none"
style={block.cardType === 'hero' ? { color: '#fff' } : {}}
dangerouslySetInnerHTML={{ __html: block.content }}
/>
</div>
);
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 (
<div className="text-center">
<div style={{ textAlign: 'center' }}>
<a
href={block.link}
className={`inline-block px-6 py-3 rounded-md font-semibold no-underline ${buttonClasses}`}
style={buttonStyle}
>
{block.text}
</a>