127 lines
4.0 KiB
TypeScript
127 lines
4.0 KiB
TypeScript
import { useRef } from 'react';
|
|
import { ImagePlus, X, ZoomIn, ZoomOut, RotateCcw } from 'lucide-react';
|
|
import { Button } from '@/components/ui/button';
|
|
import { useModelStore } from '@/stores/useModelStore';
|
|
import { useState } from 'react';
|
|
|
|
export function ComparePanel() {
|
|
const { compareImage, setCompareImage } = useModelStore();
|
|
const fileRef = useRef<HTMLInputElement>(null);
|
|
const [zoom, setZoom] = useState(1);
|
|
|
|
const handleFile = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const file = e.target.files?.[0];
|
|
if (!file) return;
|
|
const url = URL.createObjectURL(file);
|
|
setCompareImage(url);
|
|
setZoom(1);
|
|
};
|
|
|
|
if (!compareImage) {
|
|
return (
|
|
<div className="flex h-full flex-col items-center justify-center gap-4 bg-muted/30 p-6">
|
|
<div className="rounded-xl border-2 border-dashed border-muted-foreground/30 p-8 text-center">
|
|
<ImagePlus className="mx-auto mb-3 h-10 w-10 text-muted-foreground/50" />
|
|
<p className="mb-1 font-mono text-sm font-semibold text-foreground">
|
|
Foto Real da Peça
|
|
</p>
|
|
<p className="mb-4 font-mono text-xs text-muted-foreground">
|
|
Carregue uma foto para comparar com o modelo 3D
|
|
</p>
|
|
<Button size="sm" className="gap-2" onClick={() => fileRef.current?.click()}>
|
|
<ImagePlus className="h-3.5 w-3.5" />
|
|
Selecionar Foto
|
|
</Button>
|
|
</div>
|
|
<input
|
|
ref={fileRef}
|
|
type="file"
|
|
accept="image/*"
|
|
className="hidden"
|
|
onChange={handleFile}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="relative flex h-full flex-col bg-muted/20">
|
|
{/* Toolbar */}
|
|
<div className="flex items-center justify-between border-b bg-card/90 px-3 py-2 backdrop-blur-sm">
|
|
<span className="font-mono text-xs font-semibold text-muted-foreground uppercase tracking-widest">
|
|
Foto Real
|
|
</span>
|
|
<div className="flex items-center gap-1">
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="h-7 w-7"
|
|
onClick={() => setZoom((z) => Math.max(0.25, z - 0.25))}
|
|
title="Zoom out"
|
|
>
|
|
<ZoomOut className="h-3.5 w-3.5" />
|
|
</Button>
|
|
<span className="font-mono text-xs text-muted-foreground w-10 text-center">
|
|
{Math.round(zoom * 100)}%
|
|
</span>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="h-7 w-7"
|
|
onClick={() => setZoom((z) => Math.min(4, z + 0.25))}
|
|
title="Zoom in"
|
|
>
|
|
<ZoomIn className="h-3.5 w-3.5" />
|
|
</Button>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="h-7 w-7"
|
|
onClick={() => setZoom(1)}
|
|
title="Reset zoom"
|
|
>
|
|
<RotateCcw className="h-3.5 w-3.5" />
|
|
</Button>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="h-7 w-7"
|
|
onClick={() => fileRef.current?.click()}
|
|
title="Trocar foto"
|
|
>
|
|
<ImagePlus className="h-3.5 w-3.5" />
|
|
</Button>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="h-7 w-7"
|
|
onClick={() => { setCompareImage(null); setZoom(1); }}
|
|
title="Remover foto"
|
|
>
|
|
<X className="h-3.5 w-3.5 text-destructive" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Image */}
|
|
<div className="flex-1 overflow-auto flex items-center justify-center">
|
|
<img
|
|
src={compareImage}
|
|
alt="Foto real da peça"
|
|
className="max-w-none transition-transform duration-150"
|
|
style={{ transform: `scale(${zoom})` }}
|
|
draggable={false}
|
|
/>
|
|
</div>
|
|
|
|
<input
|
|
ref={fileRef}
|
|
type="file"
|
|
accept="image/*"
|
|
className="hidden"
|
|
onChange={handleFile}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|