Тест

import React, { useState, useRef } from ‘react’; import { Download, Copy, Trash2, Move, Plus, Type, Image, Palette, Layout } from ‘lucide-react’; const App = () => { const [blocks, setBlocks] = useState([ { id: ‘header-1’, type: ‘header’, content: { title: ‘Welcome to Your Amazing Site’, subtitle: ‘Create stunning landing pages in minutes’, ctaText: ‘Get Started’, backgroundImage: ‘https://placehold.co/1200×600/4f46e5/white?text=Header+Background’ }, styles: { backgroundColor: ‘bg-indigo-900’, textColor: ‘text-white’, padding: ‘py-20’ } }, { id: ‘features-1’, type: ‘features’, content: { title: ‘Why Choose Us’, features: [ { title: ‘Easy to Use’, description: ‘No coding required, just drag and drop’ }, { title: ‘Responsive Design’, description: ‘Looks great on all devices’ }, { title: ‘Free Forever’, description: ‘No hidden costs or subscriptions’ } ] }, styles: { backgroundColor: ‘bg-white’, textColor: ‘text-gray-800’, padding: ‘py-16’ } }, { id: ‘text-1’, type: ‘text’, content: { title: ‘About Our Service’, text: ‘Our platform empowers you to create beautiful, professional landing pages without any technical knowledge. Simply customize the content, adjust the styling, and download your ready-to-publish HTML file.’ }, styles: { backgroundColor: ‘bg-gray-50’, textColor: ‘text-gray-700’, padding: ‘py-12’ } }, { id: ‘gallery-1’, type: ‘gallery’, content: { title: ‘Our Work’, images: [ ‘https://placehold.co/400×300/6366f1/white?text=Project+1’, ‘https://placehold.co/400×300/8b5cf6/white?text=Project+2’, ‘https://placehold.co/400×300/ec4899/white?text=Project+3’ ] }, styles: { backgroundColor: ‘bg-white’, textColor: ‘text-gray-800’, padding: ‘py-16’ } } ]); const [selectedBlock, setSelectedBlock] = useState(null); const [editingField, setEditingField] = useState(null); const fileInputRef = useRef(null); const blockTypes = [ { type: ‘header’, name: ‘Header’, icon: Layout }, { type: ‘features’, name: ‘Features’, icon: Type }, { type: ‘text’, name: ‘Text Block’, icon: Type }, { type: ‘gallery’, name: ‘Gallery’, icon: Image } ]; const addBlock = (type) => { const newBlock = { id: `${type}-${Date.now()}`, type, content: getDefaultContent(type), styles: { backgroundColor: ‘bg-white’, textColor: ‘text-gray-800’, padding: ‘py-12’ } }; setBlocks([…blocks, newBlock]); }; const getDefaultContent = (type) => { switch (type) { case ‘header’: return { title: ‘New Header Title’, subtitle: ‘Header subtitle’, ctaText: ‘Button Text’, backgroundImage: ‘https://placehold.co/1200×600/6366f1/white?text=Header’ }; case ‘features’: return { title: ‘New Features Section’, features: [ { title: ‘Feature 1’, description: ‘Description for feature 1’ }, { title: ‘Feature 2’, description: ‘Description for feature 2’ } ] }; case ‘text’: return { title: ‘New Text Section’, text: ‘This is your new text content. Edit this to your liking.’ }; case ‘gallery’: return { title: ‘New Gallery’, images: [ ‘https://placehold.co/400×300/6366f1/white?text=Image+1’, ‘https://placehold.co/400×300/8b5cf6/white?text=Image+2’ ] }; default: return {}; } }; const updateBlockContent = (blockId, field, value) => { setBlocks(blocks.map(block => block.id === blockId ? { …block, content: { …block.content, [field]: value } } : block )); }; const updateBlockStyle = (blockId, style, value) => { setBlocks(blocks.map(block => block.id === blockId ? { …block, styles: { …block.styles, [style]: value } } : block )); }; const moveBlock = (fromIndex, toIndex) => { const newBlocks = […blocks]; const [movedBlock] = newBlocks.splice(fromIndex, 1); newBlocks.splice(toIndex, 0, movedBlock); setBlocks(newBlocks); }; const deleteBlock = (blockId) => { setBlocks(blocks.filter(block => block.id !== blockId)); if (selectedBlock === blockId) setSelectedBlock(null); }; const duplicateBlock = (blockId) => { const blockToDuplicate = blocks.find(block => block.id === blockId); const newBlock = { …blockToDuplicate, id: `${blockToDuplicate.type}-${Date.now()}`, content: JSON.parse(JSON.stringify(blockToDuplicate.content)) }; setBlocks([…blocks, newBlock]); }; const generateHTML = () => { const htmlContent = ` My Custom Landing Page ${blocks.map(block => renderBlockHTML(block)).join(»)} `; const blob = new Blob([htmlContent], { type: ‘text/html’ }); const url = URL.createObjectURL(blob); const a = document.createElement(‘a’); a.href = url; a.download = ‘index.html’; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }; const renderBlockHTML = (block) => { const { type, content, styles } = block; switch (type) { case ‘header’: return `

${content.title}

${content.subtitle}

`; case ‘features’: return `

${content.title}

${content.features.map(feature => `

${feature.title}

${feature.description}

`).join(»)}
`; case ‘text’: return `

${content.title}

${content.text}

`; case ‘gallery’: return `

${content.title}

${content.images.map(image => `
Gallery image
`).join(»)}
`; default: return »; } }; const renderBlock = (block, index) => { const isSelected = selectedBlock === block.id; const { type, content, styles } = block; return (
setSelectedBlock(block.id)} > {isSelected && (
)}
{type === ‘header’ && (

{editingField === `${block.id}-title` ? ( updateBlockContent(block.id, ‘title’, e.target.value)} onBlur={() => setEditingField(null)} className=»w-full bg-transparent border-b border-white focus:outline-none focus:border-blue-300″ autoFocus /> ) : ( setEditingField(`${block.id}-title`)} className=»cursor-text hover:bg-gray-200/20 p-1 rounded»> {content.title} )}

{editingField === `${block.id}-subtitle` ? ( updateBlockContent(block.id, ‘subtitle’, e.target.value)} onBlur={() => setEditingField(null)} className=»w-full bg-transparent border-b border-white focus:outline-none focus:border-blue-300″ autoFocus /> ) : ( setEditingField(`${block.id}-subtitle`)} className=»cursor-text hover:bg-gray-200/20 p-1 rounded»> {content.subtitle} )}

)} {type === ‘features’ && (

{editingField === `${block.id}-title` ? ( updateBlockContent(block.id, ‘title’, e.target.value)} onBlur={() => setEditingField(null)} className=»w-full bg-transparent border-b border-gray-800 focus:outline-none focus:border-blue-500 text-center» autoFocus /> ) : ( setEditingField(`${block.id}-title`)} className=»cursor-text hover:bg-gray-200 p-1 rounded»> {content.title} )}

{content.features.map((feature, idx) => (

{editingField === `${block.id}-feature-${idx}-title` ? ( { const newFeatures = […content.features]; newFeatures[idx].title = e.target.value; updateBlockContent(block.id, ‘features’, newFeatures); }} onBlur={() => setEditingField(null)} className=»w-full bg-transparent border-b border-gray-800 focus:outline-none focus:border-blue-500″ autoFocus /> ) : ( setEditingField(`${block.id}-feature-${idx}-title`)} className=»cursor-text hover:bg-gray-100 p-1 rounded» > {feature.title} )}

{editingField === `${block.id}-feature-${idx}-description` ? ( { const newFeatures = […content.features]; newFeatures[idx].description = e.target.value; updateBlockContent(block.id, ‘features’, newFeatures); }} onBlur={() => setEditingField(null)} className=»w-full bg-transparent border-b border-gray-800 focus:outline-none focus:border-blue-500″ autoFocus /> ) : ( setEditingField(`${block.id}-feature-${idx}-description`)} className=»cursor-text hover:bg-gray-100 p-1 rounded» > {feature.description} )}

))}
)} {type === ‘text’ && (

{editingField === `${block.id}-title` ? ( updateBlockContent(block.id, ‘title’, e.target.value)} onBlur={() => setEditingField(null)} className=»w-full bg-transparent border-b border-gray-700 focus:outline-none focus:border-blue-500″ autoFocus /> ) : ( setEditingField(`${block.id}-title`)} className=»cursor-text hover:bg-gray-200 p-1 rounded»> {content.title} )}

{editingField === `${block.id}-text` ? (