# Email Template Editor Layout Redesign

## Current Issues
- 40/40/20 split wastes horizontal space by showing both editors simultaneously
- Variables table cramped in narrow 20% panel (~300-400px)
- Preview iframes too small to be useful
- No visual focus indication for active editor

## Recommended Solution: 60/40 Tabbed Layout

### New Structure
```
┌─────────────────────────────────────────────────────────────┐
│ Toolbar: Back | Name | Category | [Subject Input] | Test Save│
├──────────────────────────────┬──────────────────────────────┤
│ Editor Tabs (60%)            │ Utilities Tabs (40%)         │
│ ┌──────────┬──────────┐      │ ┌─────────┬──────┬──────┐   │
│ │ HTML │ Text │                │ │Variables│HTML  │Text  │   │
│ └──────────┴──────────┘      │ └─────────┴──────┴──────┘   │
│                               │                              │
│ [Monaco Editor - Full Width] │ [Variables Table - 50%]      │
│                               │ [Sample Data Inputs - 50%]   │
│                               │                              │
└───────────────────────────────┴──────────────────────────────┘
```

### Benefits
1. **Editor space**: 60% width (up from 40%) for active editor
2. **Variables table**: 40% width (~768px on 1920px screen, up from ~384px)
3. **Preview usability**: 40% width iframes are actually readable
4. **Focused editing**: Only one editor visible at a time (matches typical workflow)
5. **Vertical space**: Move subject to toolbar (saves 52px)

### Implementation Files

#### 1. Extract VariablesPanel Component
**File**: `admin/src/components/email-templates/VariablesPanel.tsx`

```tsx
import { Table, Input, Typography, Tag } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import type { EmailTemplate, EmailTemplateVariable } from '@/types/api';

const { Text } = Typography;

interface VariablesPanelProps {
  template: EmailTemplate;
  sampleData: Record<string, string>;
  onSampleDataChange: (data: Record<string, string>) => void;
}

export default function VariablesPanel({
  template,
  sampleData,
  onSampleDataChange,
}: VariablesPanelProps) {
  const variableColumns: ColumnsType<EmailTemplateVariable> = [
    {
      title: 'Variable',
      dataIndex: 'key',
      width: 140,
      render: (key: string) => (
        <Text code style={{ fontSize: 11 }}>
          {'{{' + key + '}}'}
        </Text>
      ),
    },
    {
      title: 'Label',
      dataIndex: 'label',
      width: 120,
    },
    {
      title: 'Description',
      dataIndex: 'description',
      ellipsis: { showTitle: false },
      render: (desc: string | null) => (
        <Text
          type="secondary"
          ellipsis={{ tooltip: desc || undefined }}
          style={{ fontSize: 12 }}
        >
          {desc || '—'}
        </Text>
      ),
    },
    {
      title: 'Req',
      dataIndex: 'isRequired',
      width: 50,
      align: 'center',
      render: (isRequired: boolean) =>
        isRequired ? (
          <Tag color="red" style={{ fontSize: 10, margin: 0 }}>
            Req
          </Tag>
        ) : null,
    },
  ];

  return (
    <div
      style={{ display: 'flex', flexDirection: 'column', height: '100%' }}
    >
      {/* Variables Reference Table - Top Half */}
      <div
        style={{
          flex: '0 0 50%',
          overflow: 'auto',
          borderBottom: '1px solid #d9d9d9',
        }}
      >
        <div style={{ padding: '8px 12px', backgroundColor: '#fafafa' }}>
          <Text strong>Available Variables</Text>
        </div>
        <Table
          dataSource={template.variables}
          columns={variableColumns}
          rowKey="id"
          size="small"
          pagination={false}
          scroll={{ y: 'calc(50vh - 200px)' }}
        />
      </div>

      {/* Sample Data Inputs - Bottom Half */}
      <div style={{ flex: '0 0 50%', padding: 16, overflow: 'auto' }}>
        <Text strong style={{ display: 'block', marginBottom: 12 }}>
          Sample Data (for preview)
        </Text>
        <div
          style={{
            display: 'grid',
            gridTemplateColumns: template.variables.length > 4 ? '1fr 1fr' : '1fr',
            gap: 12,
          }}
        >
          {template.variables.map((v) => (
            <div key={v.key}>
              <Text
                type="secondary"
                style={{
                  fontSize: 11,
                  display: 'block',
                  marginBottom: 4,
                }}
              >
                {v.label}
              </Text>
              <Input
                size="small"
                value={sampleData[v.key] || ''}
                onChange={(e) =>
                  onSampleDataChange({ ...sampleData, [v.key]: e.target.value })
                }
                placeholder={v.sampleValue || ''}
              />
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}
```

#### 2. Update EmailTemplateEditor Component
**File**: `admin/src/components/email-templates/EmailTemplateEditor.tsx`

**Changes needed**:

1. **Add new state** (after line 45):
```tsx
const [activeEditorTab, setActiveEditorTab] = useState<'html' | 'text'>('html');
```

2. **Import VariablesPanel** (after line 25):
```tsx
import VariablesPanel from '@/components/email-templates/VariablesPanel';
```

3. **Replace toolbar** (lines 205-233) with subject-in-toolbar version:
```tsx
<div
  style={{
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'space-between',
    padding: '8px 16px',
    borderBottom: `1px solid ${token.colorBorderSecondary}`,
    flexShrink: 0,
  }}
>
  <Space>
    <Button type="text" icon={<ArrowLeftOutlined />} onClick={handleClose} />
    <Text strong>{template.name}</Text>
    <Tag color={getCategoryColor(template.category)}>{template.category}</Tag>
    {template.isSystem && <Tag color="blue">SYSTEM</Tag>}
  </Space>

  <div style={{ flex: 1, maxWidth: 600, margin: '0 24px' }}>
    <Input
      value={subjectLine}
      onChange={(e) => setSubjectLine(e.target.value)}
      placeholder="Subject Line (use {{VARIABLES}})"
      prefix={<MailOutlined />}
      size="small"
    />
  </div>

  <Space>
    <Button onClick={() => setTestModalOpen(true)} icon={<SendOutlined />}>
      Test
    </Button>
    <Button type="primary" loading={saving} onClick={handleSave} icon={<SaveOutlined />}>
      Save
    </Button>
  </Space>
</div>
```

4. **Remove standalone subject line row** (delete lines 236-244)

5. **Replace main layout** (lines 247-376) with new 60/40 tabbed layout:
```tsx
{/* Main Editor Layout */}
<div style={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
  {/* Left: Tabbed Editors (60%) */}
  <div
    style={{
      flex: '0 0 60%',
      borderRight: `1px solid ${token.colorBorderSecondary}`,
      display: 'flex',
      flexDirection: 'column',
    }}
  >
    <Tabs
      activeKey={activeEditorTab}
      onChange={(key) => setActiveEditorTab(key as 'html' | 'text')}
      style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
      tabBarStyle={{ margin: 0, paddingLeft: 12, backgroundColor: token.colorBgLayout }}
      items={[
        {
          key: 'html',
          label: 'HTML Content',
          children: (
            <div style={{ height: 'calc(100vh - 160px)' }}>
              <Editor
                height="100%"
                language="html"
                theme="vs-dark"
                value={htmlContent}
                onChange={(value) => setHtmlContent(value || '')}
                options={{
                  minimap: { enabled: false },
                  fontSize: 14,
                  wordWrap: 'on',
                  lineNumbers: 'on',
                  scrollBeyondLastLine: false,
                }}
              />
            </div>
          ),
        },
        {
          key: 'text',
          label: 'Plain Text Content',
          children: (
            <div style={{ height: 'calc(100vh - 160px)' }}>
              <Editor
                height="100%"
                language="plaintext"
                theme="vs-dark"
                value={textContent}
                onChange={(value) => setTextContent(value || '')}
                options={{
                  minimap: { enabled: false },
                  fontSize: 14,
                  wordWrap: 'on',
                  lineNumbers: 'on',
                  scrollBeyondLastLine: false,
                }}
              />
            </div>
          ),
        },
      ]}
    />
  </div>

  {/* Right: Utilities Panel (40%) */}
  <div
    style={{
      flex: '0 0 40%',
      display: 'flex',
      flexDirection: 'column',
      backgroundColor: token.colorBgContainer,
    }}
  >
    <Tabs
      activeKey={activeTab}
      onChange={setActiveTab}
      style={{ flex: 1, display: 'flex', flexDirection: 'column' }}
      tabBarStyle={{ margin: 0, paddingLeft: 12 }}
      items={[
        {
          key: 'variables',
          label: 'Variables',
          children: (
            <VariablesPanel
              template={template}
              sampleData={sampleData}
              onSampleDataChange={setSampleData}
            />
          ),
        },
        {
          key: 'htmlPreview',
          label: 'HTML Preview',
          children: (
            <div style={{ height: '100%', padding: 12 }}>
              <iframe
                srcDoc={processedHtml}
                style={{
                  width: '100%',
                  height: '100%',
                  border: `1px solid ${token.colorBorder}`,
                  borderRadius: 4,
                }}
                sandbox="allow-same-origin"
                title="HTML Preview"
              />
            </div>
          ),
        },
        {
          key: 'textPreview',
          label: 'Text Preview',
          children: (
            <div style={{ height: '100%', padding: 12, overflow: 'auto' }}>
              <pre
                style={{
                  whiteSpace: 'pre-wrap',
                  fontFamily: 'monospace',
                  fontSize: 12,
                  lineHeight: 1.5,
                  padding: 12,
                  backgroundColor: token.colorBgLayout,
                  borderRadius: 4,
                  border: `1px solid ${token.colorBorder}`,
                }}
              >
                {processedText}
              </pre>
            </div>
          ),
        },
        {
          key: 'splitPreview',
          label: 'Split Preview',
          children: (
            <div
              style={{
                display: 'flex',
                flexDirection: 'column',
                height: '100%',
                padding: 12,
              }}
            >
              <div
                style={{
                  flex: '0 0 60%',
                  borderBottom: `1px solid ${token.colorBorder}`,
                  marginBottom: 12,
                }}
              >
                <div
                  style={{
                    padding: '4px 8px',
                    backgroundColor: token.colorBgLayout,
                    borderTopLeftRadius: 4,
                    borderTopRightRadius: 4,
                  }}
                >
                  <Text strong style={{ fontSize: 11 }}>
                    HTML
                  </Text>
                </div>
                <iframe
                  srcDoc={processedHtml}
                  style={{
                    width: '100%',
                    height: 'calc(100% - 28px)',
                    border: `1px solid ${token.colorBorder}`,
                    borderBottomLeftRadius: 4,
                    borderBottomRightRadius: 4,
                  }}
                  sandbox="allow-same-origin"
                  title="HTML Preview"
                />
              </div>
              <div style={{ flex: '0 0 40%', overflow: 'auto' }}>
                <div
                  style={{
                    padding: '4px 8px',
                    backgroundColor: token.colorBgLayout,
                    borderTopLeftRadius: 4,
                    borderTopRightRadius: 4,
                  }}
                >
                  <Text strong style={{ fontSize: 11 }}>
                    Plain Text
                  </Text>
                </div>
                <pre
                  style={{
                    whiteSpace: 'pre-wrap',
                    fontFamily: 'monospace',
                    fontSize: 11,
                    lineHeight: 1.4,
                    padding: 8,
                    backgroundColor: token.colorBgLayout,
                    border: `1px solid ${token.colorBorder}`,
                    borderBottomLeftRadius: 4,
                    borderBottomRightRadius: 4,
                    margin: 0,
                  }}
                >
                  {processedText}
                </pre>
              </div>
            </div>
          ),
        },
      ]}
    />
  </div>
</div>
```

### Expected Outcomes

**Before**: 40% HTML / 40% Text / 20% Utilities
- Variables table: ~384px width (on 1920px screen)
- Preview iframe: ~384px width
- Both editors always visible (one is always unused)

**After**: 60% Active Editor / 40% Utilities
- Variables table: ~768px width (2x improvement)
- Preview iframe: ~768px width (2x improvement)
- Active editor: ~1152px width (28% improvement)
- Sample data inputs: 2-column grid (saves vertical scrolling)
- Subject line in toolbar (saves 52px vertical space)

### Migration Steps

1. Create `VariablesPanel.tsx` component
2. Update `EmailTemplateEditor.tsx` imports
3. Add `activeEditorTab` state
4. Replace toolbar section (add subject to toolbar)
5. Remove standalone subject row
6. Replace 3-column layout with 2-column tabbed layout
7. Test all functionality (save, preview, test email)
8. Consider adding "Split Preview" tab (optional enhancement)

### Backward Compatibility
- No API changes required
- No state structure changes
- All existing functionality preserved
- Only UI layout changes
