Refactor GTM Architect to v2: Python-driven architecture, 9-phase process, new DB and Docker setup
This commit is contained in:
103
k-pop-thumbnail-genie/components/ImageResult.tsx
Normal file
103
k-pop-thumbnail-genie/components/ImageResult.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { GenerationResult } from '../types';
|
||||
import { DownloadIcon } from './icons/DownloadIcon';
|
||||
import { MagicIcon } from './icons/MagicIcon';
|
||||
|
||||
interface ImageResultProps {
|
||||
result: GenerationResult | null;
|
||||
onRefine: (refinementPrompt: string) => void;
|
||||
masterPrompt: string;
|
||||
isLoading: boolean;
|
||||
loadingMessage: string;
|
||||
onStartOver: () => void;
|
||||
}
|
||||
|
||||
const ImageResult: React.FC<ImageResultProps> = ({ result, onRefine, masterPrompt, isLoading, loadingMessage, onStartOver }) => {
|
||||
const [refinementPrompt, setRefinementPrompt] = useState('');
|
||||
|
||||
const handleRefineSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (refinementPrompt.trim()) {
|
||||
onRefine(refinementPrompt);
|
||||
setRefinementPrompt('');
|
||||
}
|
||||
};
|
||||
|
||||
if (!result) {
|
||||
return (
|
||||
<div className="text-center">
|
||||
<p>Something went wrong. No image was generated.</p>
|
||||
<button onClick={onStartOver} className="mt-4 bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded">Start Over</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full flex flex-col lg:flex-row gap-8">
|
||||
<div className="lg:w-2/3 relative">
|
||||
<div className="aspect-w-16 aspect-h-9 bg-black rounded-lg overflow-hidden shadow-lg">
|
||||
<img src={`data:image/png;base64,${result.currentImage}`} alt="Generated thumbnail" className="w-full h-full object-contain" />
|
||||
</div>
|
||||
{isLoading && (
|
||||
<div className="absolute inset-0 bg-black/70 flex flex-col items-center justify-center text-center p-4 rounded-lg">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-purple-400 mb-4"></div>
|
||||
<p className="text-lg text-purple-300">{loadingMessage}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="lg:w-1/3 flex flex-col">
|
||||
<h2 className="text-2xl font-bold text-gray-100 mb-4">Your Masterpiece</h2>
|
||||
|
||||
<div className="flex-grow space-y-6">
|
||||
<form onSubmit={handleRefineSubmit}>
|
||||
<label htmlFor="refinement-prompt" className="block text-lg font-semibold text-purple-300 mb-2">
|
||||
Refine Your Image
|
||||
</label>
|
||||
<textarea
|
||||
id="refinement-prompt"
|
||||
value={refinementPrompt}
|
||||
onChange={(e) => setRefinementPrompt(e.target.value)}
|
||||
placeholder="e.g., 'Make the smile a little softer.' or 'Change the background to be more blurry.'"
|
||||
className="w-full bg-gray-700 border border-gray-600 rounded-lg p-3 text-base h-24 focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition"
|
||||
required
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isLoading || !refinementPrompt}
|
||||
className="w-full mt-3 bg-purple-600 hover:bg-purple-700 disabled:bg-gray-600 text-white font-bold py-2.5 px-4 rounded-lg transition-colors duration-300 flex items-center justify-center gap-2"
|
||||
>
|
||||
<MagicIcon className="w-5 h-5"/> Refine
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div>
|
||||
<details className="bg-gray-700/50 rounded-lg">
|
||||
<summary className="cursor-pointer text-purple-300 font-semibold p-3">View Master Prompt</summary>
|
||||
<p className="p-3 pt-0 text-gray-400 text-sm">{masterPrompt}</p>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 space-y-3">
|
||||
<a
|
||||
href={`data:image/png;base64,${result.currentImage}`}
|
||||
download="kpop-thumbnail.png"
|
||||
className="w-full bg-green-600 hover:bg-green-700 text-white font-bold py-3 px-4 rounded-lg transition-colors duration-300 flex items-center justify-center gap-2 text-lg"
|
||||
>
|
||||
<DownloadIcon className="w-6 h-6" /> Download Image
|
||||
</a>
|
||||
<button
|
||||
onClick={onStartOver}
|
||||
className="w-full bg-gray-600 hover:bg-gray-500 text-white font-bold py-2 px-4 rounded-lg transition-colors duration-300"
|
||||
>
|
||||
Start Over
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ImageResult;
|
||||
Reference in New Issue
Block a user