forked from innovacion/playground
Initial commit
This commit is contained in:
98
frontend/components/image-card.tsx
Normal file
98
frontend/components/image-card.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
'use client';
|
||||
|
||||
import { Download, Maximize2 } from 'lucide-react';
|
||||
import { downloadImage, generateImageFilename } from '@/lib/utils';
|
||||
import { useState } from 'react';
|
||||
|
||||
interface ImageCardProps {
|
||||
imageData: string; // Base64
|
||||
prompt: string;
|
||||
model: string;
|
||||
index?: number;
|
||||
}
|
||||
|
||||
export function ImageCard({ imageData, prompt, model, index = 0 }: ImageCardProps) {
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
|
||||
const handleDownload = () => {
|
||||
const filename = generateImageFilename(prompt);
|
||||
downloadImage(imageData, filename);
|
||||
};
|
||||
|
||||
const handleFullscreen = () => {
|
||||
setIsFullscreen(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="group relative bg-secondary rounded-lg overflow-hidden border border-border hover:border-primary transition-all">
|
||||
{/* Imagen */}
|
||||
<div className="relative aspect-square">
|
||||
<img
|
||||
src={`data:image/png;base64,${imageData}`}
|
||||
alt={prompt}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
|
||||
{/* Overlay con acciones */}
|
||||
<div className="absolute inset-0 bg-black/60 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center gap-3">
|
||||
<button
|
||||
onClick={handleFullscreen}
|
||||
className="p-3 bg-white/90 hover:bg-white rounded-full transition-all"
|
||||
title="Ver en pantalla completa"
|
||||
>
|
||||
<Maximize2 className="w-5 h-5 text-gray-900" />
|
||||
</button>
|
||||
<button
|
||||
onClick={handleDownload}
|
||||
className="p-3 bg-white/90 hover:bg-white rounded-full transition-all"
|
||||
title="Descargar imagen"
|
||||
>
|
||||
<Download className="w-5 h-5 text-gray-900" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Info */}
|
||||
<div className="p-3 space-y-1">
|
||||
<p className="text-xs text-muted-foreground line-clamp-2">
|
||||
{prompt}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Modelo: {model}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Modal fullscreen */}
|
||||
{isFullscreen && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black/95 z-50 flex items-center justify-center p-4"
|
||||
onClick={() => setIsFullscreen(false)}
|
||||
>
|
||||
<button
|
||||
onClick={() => setIsFullscreen(false)}
|
||||
className="absolute top-4 right-4 text-white text-4xl hover:text-gray-300"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
<img
|
||||
src={`data:image/png;base64,${imageData}`}
|
||||
alt={prompt}
|
||||
className="max-w-full max-h-full object-contain"
|
||||
/>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleDownload();
|
||||
}}
|
||||
className="absolute bottom-4 right-4 px-4 py-2 bg-white text-black rounded-lg hover:bg-gray-200 transition-all flex items-center gap-2"
|
||||
>
|
||||
<Download className="w-4 h-4" />
|
||||
Descargar
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user