import React, { useState } from 'react'; import { __ } from '@/lib/i18n'; import { BlockRenderer } from './BlockRenderer'; import { Button } from '@/components/ui/button'; import { Card, CardContent } from '@/components/ui/card'; 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, Monitor, Image as ImageIcon } from 'lucide-react'; import { useMediaQuery } from '@/hooks/use-media-query'; import { parseMarkdownBasics } from '@/lib/markdown-utils'; import { htmlToMarkdown } from '@/lib/html-to-markdown'; import type { EmailBlock, CardBlock, ButtonBlock, ImageBlock, SpacerBlock, CardType, ButtonStyle, ContentWidth, ContentAlign } from './types'; interface EmailBuilderProps { blocks: EmailBlock[]; onChange: (blocks: EmailBlock[]) => void; variables?: string[]; } export function EmailBuilder({ blocks, onChange, variables = [] }: EmailBuilderProps) { const isDesktop = useMediaQuery('(min-width: 768px)'); const [editingBlockId, setEditingBlockId] = useState(null); const [editDialogOpen, setEditDialogOpen] = useState(false); const [editingContent, setEditingContent] = useState(''); const [editingCardType, setEditingCardType] = useState('default'); const [editingButtonText, setEditingButtonText] = useState(''); const [editingButtonLink, setEditingButtonLink] = useState(''); const [editingButtonStyle, setEditingButtonStyle] = useState('solid'); const [editingWidthMode, setEditingWidthMode] = useState('fit'); const [editingCustomMaxWidth, setEditingCustomMaxWidth] = useState(undefined); const [editingAlign, setEditingAlign] = useState('center'); const [editingImageSrc, setEditingImageSrc] = useState(''); // WordPress Media Library integration const openMediaLibrary = (callback: (url: string) => void) => { // Check if wp.media is available if (typeof (window as any).wp === 'undefined' || typeof (window as any).wp.media === 'undefined') { console.error('WordPress media library is not available'); return; } const frame = (window as any).wp.media({ title: __('Select or Upload Image'), button: { text: __('Use this image'), }, multiple: false, library: { type: 'image', }, }); frame.on('select', () => { const attachment = frame.state().get('selection').first().toJSON(); callback(attachment.url); }); frame.open(); }; const addBlock = (type: EmailBlock['type']) => { const newBlock: EmailBlock = (() => { const id = `block-${Date.now()}`; switch (type) { case 'card': return { id, type, cardType: 'default', content: '

Card Title

Your content here...

' }; case 'button': return { id, type, text: 'Click Here', link: '{order_url}', style: 'solid', widthMode: 'fit', align: 'center' }; case 'image': return { id, type, src: 'https://via.placeholder.com/600x200', alt: 'Image', widthMode: 'fit', align: 'center' }; 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) => { console.log('[EmailBuilder] openEditDialog called', { blockId: block.id, blockType: block.type }); setEditingBlockId(block.id); if (block.type === 'card') { // Convert markdown to HTML for rich text editor const htmlContent = parseMarkdownBasics(block.content); console.log('[EmailBuilder] Card content parsed', { original: block.content, html: htmlContent }); setEditingContent(htmlContent); setEditingCardType(block.cardType); } else if (block.type === 'button') { setEditingButtonText(block.text); setEditingButtonLink(block.link); setEditingButtonStyle(block.style); setEditingWidthMode(block.widthMode || 'fit'); setEditingCustomMaxWidth(block.customMaxWidth); setEditingAlign(block.align || 'center'); } else if (block.type === 'image') { setEditingImageSrc(block.src); setEditingWidthMode(block.widthMode); setEditingCustomMaxWidth(block.customMaxWidth); setEditingAlign(block.align); } console.log('[EmailBuilder] Setting editDialogOpen to true'); setEditDialogOpen(true); }; const saveEdit = () => { if (!editingBlockId) return; const newBlocks = blocks.map(block => { if (block.id !== editingBlockId) return block; if (block.type === 'card') { // Convert HTML from rich text editor back to markdown for storage const markdownContent = htmlToMarkdown(editingContent); return { ...block, content: markdownContent, cardType: editingCardType }; } else if (block.type === 'button') { return { ...block, text: editingButtonText, link: editingButtonLink, style: editingButtonStyle, widthMode: editingWidthMode, customMaxWidth: editingCustomMaxWidth, align: editingAlign, }; } else if (block.type === 'image') { return { ...block, src: editingImageSrc, widthMode: editingWidthMode, customMaxWidth: editingCustomMaxWidth, align: editingAlign, }; } return block; }); onChange(newBlocks); setEditDialogOpen(false); setEditingBlockId(null); }; const editingBlock = blocks.find(b => b.id === editingBlockId); // Mobile fallback if (!isDesktop) { return (

{__('Desktop Only Feature')}

{__('The email builder requires a desktop screen for the best editing experience. Please switch to a desktop or tablet device to use this feature.')}

{__('Minimum screen width: 768px')}

); } return (
{/* Add Block Toolbar */}
{__('Add Block:')}
{/* Email Canvas */}
{blocks.length === 0 ? (

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

) : ( blocks.map((block, index) => ( openEditDialog(block)} onDelete={() => deleteBlock(block.id)} onMoveUp={() => moveBlock(block.id, 'up')} onMoveDown={() => moveBlock(block.id, 'down')} isFirst={index === 0} isLast={index === blocks.length - 1} /> )) )}
{/* Edit Dialog */} { // Only prevent closing if WordPress media modal is open const wpMediaOpen = document.querySelector('.media-modal'); if (wpMediaOpen) { e.preventDefault(); } // Otherwise, allow the dialog to close normally via outside click }} onEscapeKeyDown={(e) => { // Only prevent escape if WP media modal is open const wpMediaOpen = document.querySelector('.media-modal'); if (wpMediaOpen) { e.preventDefault(); } // Otherwise, allow escape to close dialog }} > {editingBlock?.type === 'card' && __('Edit Card')} {editingBlock?.type === 'button' && __('Edit Button')} {editingBlock?.type === 'image' && __('Edit Image')} {__('Make changes to your block. You can use variables like {customer_name} or {order_number}.')}
{editingBlock?.type === 'card' && ( <>

{__('Use the toolbar to format text. HTML will be generated automatically.')}

)} {editingBlock?.type === 'button' && ( <>
setEditingButtonText(e.target.value)} />
setEditingButtonLink(e.target.value)} placeholder="{order_url}" /> {variables.length > 0 && (
{variables.filter(v => v.includes('_url')).map((variable) => ( setEditingButtonLink(editingButtonLink + `{${variable}}`)} > {`{${variable}}`} ))}
)}
{editingWidthMode === 'custom' && (
setEditingCustomMaxWidth(e.target.value ? parseInt(e.target.value, 10) : undefined)} />
)}
)} {editingBlock?.type === 'image' && ( <>
setEditingImageSrc(e.target.value)} placeholder="https://example.com/image.jpg" className="flex-1" />

{__('Enter image URL or click the icon to select from WordPress media library')}

{editingWidthMode === 'custom' && (
setEditingCustomMaxWidth(e.target.value ? parseInt(e.target.value, 10) : undefined)} />
)}
)}
); }