diff --git a/admin-spa/src/components/EmailBuilder/BlockRenderer.tsx b/admin-spa/src/components/EmailBuilder/BlockRenderer.tsx new file mode 100644 index 0000000..6e74f32 --- /dev/null +++ b/admin-spa/src/components/EmailBuilder/BlockRenderer.tsx @@ -0,0 +1,130 @@ +import React from 'react'; +import { EmailBlock } from './types'; +import { __ } from '@/lib/i18n'; + +interface BlockRendererProps { + block: EmailBlock; + isEditing: boolean; + onEdit: () => void; + onDelete: () => void; + onMoveUp: () => void; + onMoveDown: () => void; + isFirst: boolean; + isLast: boolean; +} + +export function BlockRenderer({ + block, + isEditing, + onEdit, + onDelete, + onMoveUp, + onMoveDown, + isFirst, + isLast +}: BlockRendererProps) { + + const renderBlockContent = () => { + switch (block.type) { + case 'header': + return ( +
Your text content here...
' }; + case 'card': + return { id, type, cardType: 'default', content: 'Card content...
' }; + case 'button': + return { id, type, text: 'Click Here', link: '{order_url}', style: 'solid' }; + case 'divider': + return { id, type }; + case 'spacer': + return { id, type, height: 32 }; + default: + throw new Error(`Unknown block type: ${type}`); + } + })(); + + onChange([...blocks, newBlock]); + }; + + const deleteBlock = (id: string) => { + onChange(blocks.filter(b => b.id !== id)); + }; + + const moveBlock = (id: string, direction: 'up' | 'down') => { + const index = blocks.findIndex(b => b.id === id); + if (index === -1) return; + + const newIndex = direction === 'up' ? index - 1 : index + 1; + if (newIndex < 0 || newIndex >= blocks.length) return; + + const newBlocks = [...blocks]; + [newBlocks[index], newBlocks[newIndex]] = [newBlocks[newIndex], newBlocks[index]]; + onChange(newBlocks); + }; + + const openEditDialog = (block: EmailBlock) => { + setEditingBlockId(block.id); + + if (block.type === 'header' || block.type === 'text') { + setEditingContent(block.content); + } else if (block.type === 'card') { + setEditingContent(block.content); + setEditingCardType(block.cardType); + } else if (block.type === 'button') { + setEditingButtonText(block.text); + setEditingButtonLink(block.link); + setEditingButtonStyle(block.style); + } + + setEditDialogOpen(true); + }; + + const saveEdit = () => { + if (!editingBlockId) return; + + const newBlocks = blocks.map(block => { + if (block.id !== editingBlockId) return block; + + if (block.type === 'header') { + return { ...block, content: editingContent }; + } else if (block.type === 'text') { + return { ...block, content: editingContent }; + } else if (block.type === 'card') { + return { ...block, content: editingContent, cardType: editingCardType }; + } else if (block.type === 'button') { + return { ...block, text: editingButtonText, link: editingButtonLink, style: editingButtonStyle }; + } + + return block; + }); + + onChange(newBlocks); + setEditDialogOpen(false); + setEditingBlockId(null); + }; + + const editingBlock = blocks.find(b => b.id === editingBlockId); + + return ( +{__('No blocks yet. Add blocks using the toolbar above.')}
+Card content goes here...
'} -[/card]\n\n`; + // Sync blocks to body when switching to code mode + const handleCodeModeToggle = () => { + if (!codeMode) { + // Switching TO code mode: convert blocks to HTML + setBody(blocksToHTML(blocks)); } else { - cardText = `[card] -${content || 'Card content goes here...
'} -[/card]\n\n`; + // Switching FROM code mode: convert HTML to blocks + setBlocks(htmlToBlocks(body)); } - - setBody(body + cardText); - toast.success(__('Card inserted')); - }; - - const openButtonDialog = () => { - setButtonText('Click Here'); - setButtonLink('{order_url}'); - setButtonType('solid'); - setButtonDialogOpen(true); + setCodeMode(!codeMode); }; - const insertButton = () => { - const buttonClass = buttonType === 'solid' ? 'button' : 'button-outline'; - const buttonHtml = ``; - setBody(body + buttonHtml + '\n'); - setButtonDialogOpen(false); - toast.success(__('Button inserted')); + // Update blocks and sync to body + const handleBlocksChange = (newBlocks: EmailBlock[]) => { + setBlocks(newBlocks); + setBody(blocksToHTML(newBlocks)); }; // Get variable keys for the rich text editor @@ -378,187 +360,42 @@ ${content || 'Card content goes here...
'} - {/* Card Insert Buttons */} - {!codeMode && ( -+ {__('Build your email visually. Add blocks, edit content, and see live preview.')} +