Spaces:
Sleeping
Sleeping
import React, { useState } from 'react'; | |
import { Upload } from 'lucide-react'; | |
const FaceSwapForm = () => { | |
const [sourceFile, setSourceFile] = useState(null); | |
const [targetFile, setTargetFile] = useState(null); | |
const [doEnhance, setDoEnhance] = useState(true); | |
const [sourcePreview, setSourcePreview] = useState(''); | |
const [targetPreview, setTargetPreview] = useState(''); | |
const [isLoading, setIsLoading] = useState(false); | |
const handleFileChange = (event, type) => { | |
const file = event.target.files[0]; | |
if (file) { | |
const reader = new FileReader(); | |
reader.onloadend = () => { | |
if (type === 'source') { | |
setSourceFile(file); | |
setSourcePreview(reader.result); | |
} else { | |
setTargetFile(file); | |
setTargetPreview(reader.result); | |
} | |
}; | |
reader.readAsDataURL(file); | |
} | |
}; | |
const handleSubmit = async (e) => { | |
e.preventDefault(); | |
setIsLoading(true); | |
try { | |
// Here you would implement your actual API call | |
console.log('Processing:', { sourceFile, targetFile, doEnhance }); | |
// Simulate API delay | |
await new Promise(resolve => setTimeout(resolve, 2000)); | |
} catch (error) { | |
console.error('Error:', error); | |
} finally { | |
setIsLoading(false); | |
} | |
}; | |
return ( | |
<div className="max-w-2xl mx-auto p-6 bg-white rounded-lg shadow-md"> | |
<h2 className="text-2xl font-bold mb-6 text-center">Face Swap</h2> | |
<form onSubmit={handleSubmit} className="space-y-6"> | |
<div className="grid grid-cols-2 gap-6"> | |
{/* Source Image Upload */} | |
<div className="space-y-2"> | |
<label className="block text-sm font-medium text-gray-700"> | |
Source Image | |
</label> | |
<div className="relative"> | |
{sourcePreview ? ( | |
<div className="relative h-48 rounded-lg overflow-hidden"> | |
<img | |
src={sourcePreview} | |
alt="Source preview" | |
className="w-full h-full object-cover" | |
/> | |
<button | |
type="button" | |
onClick={() => { | |
setSourceFile(null); | |
setSourcePreview(''); | |
}} | |
className="absolute top-2 right-2 bg-red-500 text-white p-1 rounded-full" | |
> | |
× | |
</button> | |
</div> | |
) : ( | |
<label className="flex flex-col items-center justify-center h-48 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50"> | |
<Upload className="w-8 h-8 text-gray-400" /> | |
<span className="mt-2 text-sm text-gray-500">Upload source image</span> | |
<input | |
type="file" | |
className="hidden" | |
accept="image/*" | |
onChange={(e) => handleFileChange(e, 'source')} | |
/> | |
</label> | |
)} | |
</div> | |
</div> | |
{/* Target Image Upload */} | |
<div className="space-y-2"> | |
<label className="block text-sm font-medium text-gray-700"> | |
Target Image | |
</label> | |
<div className="relative"> | |
{targetPreview ? ( | |
<div className="relative h-48 rounded-lg overflow-hidden"> | |
<img | |
src={targetPreview} | |
alt="Target preview" | |
className="w-full h-full object-cover" | |
/> | |
<button | |
type="button" | |
onClick={() => { | |
setTargetFile(null); | |
setTargetPreview(''); | |
}} | |
className="absolute top-2 right-2 bg-red-500 text-white p-1 rounded-full" | |
> | |
× | |
</button> | |
</div> | |
) : ( | |
<label className="flex flex-col items-center justify-center h-48 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50"> | |
<Upload className="w-8 h-8 text-gray-400" /> | |
<span className="mt-2 text-sm text-gray-500">Upload target image</span> | |
<input | |
type="file" | |
className="hidden" | |
accept="image/*" | |
onChange={(e) => handleFileChange(e, 'target')} | |
/> | |
</label> | |
)} | |
</div> | |
</div> | |
</div> | |
{/* Enhancement Option */} | |
<div className="flex items-center"> | |
<input | |
type="checkbox" | |
id="enhance" | |
checked={doEnhance} | |
onChange={(e) => setDoEnhance(e.target.checked)} | |
className="h-4 w-4 text-blue-600 rounded border-gray-300" | |
/> | |
<label htmlFor="enhance" className="ml-2 text-sm text-gray-700"> | |
Enable face enhancement | |
</label> | |
</div> | |
{/* Submit Button */} | |
<button | |
type="submit" | |
disabled={!sourceFile || !targetFile || isLoading} | |
className={`w-full py-2 px-4 rounded-md text-white font-medium ${ | |
!sourceFile || !targetFile || isLoading | |
? 'bg-gray-400 cursor-not-allowed' | |
: 'bg-blue-600 hover:bg-blue-700' | |
}`} | |
> | |
{isLoading ? 'Processing...' : 'Swap Faces'} | |
</button> | |
</form> | |
</div> | |
); | |
}; | |
export default FaceSwapForm; |