0% found this document useful (0 votes)
4 views5 pages

Website Builder Frontend - TSX

The document is a React component for a website builder that allows users to create and manage a website's sections, including headings, text, images, and buttons. It features functionality for adding, updating, deleting sections, and publishing the site with a specified domain. The component includes a toolbar for section management and a modal for publishing the website.

Uploaded by

dislevelingup
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views5 pages

Website Builder Frontend - TSX

The document is a React component for a website builder that allows users to create and manage a website's sections, including headings, text, images, and buttons. It features functionality for adding, updating, deleting sections, and publishing the site with a specified domain. The component includes a toolbar for section management and a modal for publishing the website.

Uploaded by

dislevelingup
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

import { useState, useEffect } from 'react';

import { Edit, Globe, Share2, Save, Plus, Layout, Image, Type, Button as ButtonIcon
} from 'lucide-react';

const WebsiteBuilder = () => {


const [site, setSite] = useState({
title: 'My Website',
domain: '',
published: false,
sections: []
});

const [editing, setEditing] = useState(null);


const [showPublishModal, setShowPublishModal] = useState(false);

const addSection = (type) => {


setSite(prev => ({
...prev,
sections: [...prev.sections, {
id: Date.now(),
type,
content: type === 'text' ? 'Edit this text' :
type === 'heading' ? 'New Heading' :
type === 'button' ? 'Click Me' : '',
style: {}
}]
}));
};

const updateSection = (id, updates) => {


setSite(prev => ({
...prev,
sections: prev.sections.map(section =>
section.id === id ? { ...section, ...updates } : section
)
}));
};

const deleteSection = (id) => {


setSite(prev => ({
...prev,
sections: prev.sections.filter(section => section.id !== id)
}));
};

const publishSite = async () => {


try {
const response = await fetch('/api/publish', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(site)
});
const data = await response.json();
setSite(prev => ({ ...prev, published: true, domain: data.domain }));
setShowPublishModal(false);
} catch (error) {
console.error('Publishing failed:', error);
}
};

return (
<div className="min-h-screen bg-gray-50">
{/* Toolbar */}
<div className="fixed top-0 left-0 right-0 bg-white shadow-md z-50">
<div className="max-w-7xl mx-auto px-4 py-2 flex items-center justify-
between">
<div className="flex items-center space-x-4">
<button
onClick={() => addSection('heading')}
className="flex items-center px-3 py-2 bg-blue-600 text-white
rounded-md hover:bg-blue-700"
>
<Type className="w-4 h-4 mr-2" />
Add Heading
</button>
<button
onClick={() => addSection('text')}
className="flex items-center px-3 py-2 bg-blue-600 text-white
rounded-md hover:bg-blue-700"
>
<Edit className="w-4 h-4 mr-2" />
Add Text
</button>
<button
onClick={() => addSection('image')}
className="flex items-center px-3 py-2 bg-blue-600 text-white
rounded-md hover:bg-blue-700"
>
<Image className="w-4 h-4 mr-2" />
Add Image
</button>
<button
onClick={() => addSection('button')}
className="flex items-center px-3 py-2 bg-blue-600 text-white
rounded-md hover:bg-blue-700"
>
<ButtonIcon className="w-4 h-4 mr-2" />
Add Button
</button>
</div>
<div className="flex items-center space-x-4">
<button
onClick={() => setShowPublishModal(true)}
className="flex items-center px-4 py-2 bg-green-600 text-white
rounded-md hover:bg-green-700"
>
<Globe className="w-4 h-4 mr-2" />
Publish
</button>
</div>
</div>
</div>

{/* Main Content Area */}


<div className="mt-16 max-w-4xl mx-auto p-4">
{site.sections.map(section => (
<div
key={section.id}
className="relative group mb-4 p-4 bg-white rounded-lg shadow-sm
hover:shadow-md transition-shadow"
>
{editing === section.id ? (
<div className="space-y-2">
<textarea
className="w-full p-2 border rounded"
value={section.content}
onChange={(e) => updateSection(section.id, { content:
e.target.value })}
/>
<button
onClick={() => setEditing(null)}
className="px-3 py-1 bg-blue-600 text-white rounded"
>
Save
</button>
</div>
) : (
<>
{section.type === 'heading' && (
<h2 className="text-2xl font-bold" onClick={() =>
setEditing(section.id)}>
{section.content}
</h2>
)}
{section.type === 'text' && (
<p onClick={() => setEditing(section.id)}>
{section.content}
</p>
)}
{section.type === 'button' && (
<button
className="px-4 py-2 bg-blue-600 text-white rounded"
onClick={() => setEditing(section.id)}
>
{section.content}
</button>
)}
{section.type === 'image' && (
<div className="relative aspect-video bg-gray-100 rounded">
<input
type="file"
className="absolute inset-0 opacity-0"
onChange={(e) => {
// Handle image upload
}}
/>
<div className="absolute inset-0 flex items-center justify-
center">
<Image className="w-8 h-8 text-gray-400" />
</div>
</div>
)}
</>
)}
<div className="absolute top-2 right-2 hidden group-hover:flex space-x-
2">
<button
onClick={() => deleteSection(section.id)}
className="p-1 text-red-600 hover:bg-red-50 rounded"
>
Delete
</button>
</div>
</div>
))}
</div>

{/* Publish Modal */}


{showPublishModal && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center
justify-center">
<div className="bg-white p-6 rounded-lg w-96">
<h3 className="text-lg font-semibold mb-4">Publish Website</h3>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-700">
Subdomain
</label>
<input
type="text"
className="mt-1 block w-full px-3 py-2 border rounded-md"
value={site.domain}
onChange={(e) => setSite(prev => ({ ...prev, domain:
e.target.value }))}
placeholder="your-site"
/>
<p className="mt-1 text-sm text-gray-500">
Your site will be available at {site.domain}.yourservice.com
</p>
</div>
<div className="flex justify-end space-x-3">
<button
onClick={() => setShowPublishModal(false)}
className="px-4 py-2 text-gray-600 hover:text-gray-800"
>
Cancel
</button>
<button
onClick={publishSite}
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-
blue-700"
>
Publish
</button>
</div>
</div>
</div>
</div>
)}
</div>
);
};
export default WebsiteBuilder;

You might also like