| import React, { useState } from 'react'; |
| import { motion } from 'framer-motion'; |
| import { Upload, Image as ImageIcon, Loader } from 'lucide-react'; |
| import axios from 'axios'; |
|
|
| const InteriorStyleTransformer = () => { |
| const [selectedImage, setSelectedImage] = useState(null); |
| const [styleInput, setStyleInput] = useState(''); |
| const [generatedImage, setGeneratedImage] = useState(null); |
| const [isLoading, setIsLoading] = useState(false); |
| const [error, setError] = useState(null); |
|
|
| |
| const handleImageUpload = (event) => { |
| const file = event.target.files[0]; |
| if (file) { |
| setSelectedImage(URL.createObjectURL(file)); |
| setGeneratedImage(null); |
| setError(null); |
| } |
| }; |
|
|
| |
| const handleStyleInput = (event) => { |
| setStyleInput(event.target.value); |
| }; |
|
|
| |
| const handleSubmit = async () => { |
| if (!selectedImage || !styleInput) { |
| setError('Please upload an image and specify a design style.'); |
| return; |
| } |
|
|
| setIsLoading(true); |
| setError(null); |
|
|
| try { |
| |
| const formData = new FormData(); |
| const fileInput = document.querySelector('input[type="file"]'); |
| formData.append('image', fileInput.files[0]); |
| formData.append('style', styleInput); |
|
|
| |
| const response = await axios.post('https://api.example.com/transform-interior', formData, { |
| headers: { 'Content-Type': 'multipart/form-data' }, |
| }); |
|
|
| |
| setGeneratedImage(response.data.imageUrl); |
| } catch (err) { |
| setError('Failed to process the image. Please try again.'); |
| console.error(err); |
| } finally { |
| setIsLoading(false); |
| } |
| }; |
|
|
| return ( |
| <section className="py-20 bg-[#0B1118]"> |
| <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> |
| <motion.div |
| initial={{ opacity: 0, y: 20 }} |
| whileInView={{ opacity: 1, y: 0 }} |
| transition={{ duration: 0.8 }} |
| className="text-center mb-12" |
| > |
| <h2 className="text-3xl md:text-4xl font-bold mb-4 text-white"> |
| Transform Your Interior Design |
| </h2> |
| <p className="text-xl text-gray-400"> |
| Upload a photo of your space and specify your desired interior design style. |
| </p> |
| </motion.div> |
| |
| <div className="grid grid-cols-1 md:grid-cols-2 gap-8"> |
| {/* Image Upload Section */} |
| <motion.div |
| initial={{ opacity: 0, scale: 0.9 }} |
| whileInView={{ opacity: 1, scale: 1 }} |
| transition={{ duration: 0.5 }} |
| className="bg-gray-800/30 rounded-lg p-6 border border-gray-700 hover:border-blue-500/50" |
| > |
| <h3 className="text-xl font-semibold mb-4 text-white">Upload Your Room Photo</h3> |
| <div className="flex flex-col items-center"> |
| <label className="w-full flex flex-col items-center px-4 py-6 bg-gray-900/50 rounded-lg border-2 border-dashed border-gray-600 cursor-pointer hover:border-blue-500"> |
| <Upload className="h-12 w-12 text-blue-500 mb-4" /> |
| <span className="text-gray-400"> |
| {selectedImage ? 'Change Image' : 'Upload an Image'} |
| </span> |
| <input |
| type="file" |
| accept="image/*" |
| className="hidden" |
| onChange={handleImageUpload} |
| /> |
| </label> |
| {selectedImage && ( |
| <img |
| src={selectedImage} |
| alt="Uploaded room" |
| className="mt-4 max-h-64 w-full object-contain rounded-lg" |
| /> |
| )} |
| </div> |
| </motion.div> |
| |
| {/* Style Input and Generated Image Section */} |
| <motion.div |
| initial={{ opacity: 0, scale: 0.9 }} |
| whileInView={{ opacity: 1, scale: 1 }} |
| transition={{ duration: 0.5 }} |
| className="bg-gray-800/30 rounded-lg p-6 border border-gray-700 hover:border-blue-500/50" |
| > |
| <h3 className="text-xl font-semibold mb-4 text-white">Specify Design Style</h3> |
| <input |
| type="text" |
| placeholder="e.g., Modern, Scandinavian, Minimalist" |
| value={styleInput} |
| onChange={handleStyleInput} |
| className="w-full px-4 py-2 bg-gray-900 text-white rounded-lg border border-gray-600 focus:outline-none focus:border-blue-500 mb-4" |
| /> |
| <motion.button |
| whileHover={{ scale: 1.05 }} |
| whileTap={{ scale: 0.95 }} |
| onClick={handleSubmit} |
| disabled={isLoading} |
| className="w-full px-4 py-2 bg-blue-600 text-white rounded-lg font-semibold hover:bg-blue-700 disabled:bg-gray-600" |
| > |
| {isLoading ? ( |
| <div className="flex items-center justify-center"> |
| <Loader className="h-6 w-6 animate-spin mr-2" /> |
| Processing... |
| </div> |
| ) : ( |
| 'Generate Design' |
| )} |
| </motion.button> |
| {error && <p className="text-red-500 mt-4">{error}</p>} |
| {generatedImage && ( |
| <div className="mt-4"> |
| <h3 className="text-lg font-semibold text-white mb-2">Generated Design</h3> |
| <img |
| src={generatedImage} |
| alt="Generated interior design" |
| className="max-h-64 w-full object-contain rounded-lg" |
| /> |
| </div> |
| )} |
| </motion.div> |
| </div> |
| </div> |
| </section> |
| ); |
| }; |
|
|
| export default InteriorStyleTransformer; |