github-actions[bot]
Sync from GitHub: 167b65b6ddc3de7f29548d9d6ba060e50653b352
4dbceee
import React, { useState, useEffect, useRef } from 'react';
import { SlidersHorizontal, Sparkles, Brain } from 'lucide-react';
const ImagePreview = ({ imageData, fileName, onResolutionChange, onEnhanceToggle, isEnhanced, onReasoningModeToggle, useReasoning }) => {
const [resolution, setResolution] = useState(100);
const canvasRef = useRef(null);
const [originalDimensions, setOriginalDimensions] = useState({ width: 0, height: 0 });
const [currentDimensions, setCurrentDimensions] = useState({ width: 0, height: 0 });
useEffect(() => {
if (!imageData || !canvasRef.current) return;
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = () => {
if (!originalDimensions.width) {
setOriginalDimensions({ width: img.width, height: img.height });
}
// Calculate new dimensions based on resolution
const newWidth = Math.floor(img.width * (resolution / 100));
const newHeight = Math.floor(img.height * (resolution / 100));
setCurrentDimensions({ width: newWidth, height: newHeight });
// Set display size (max 400px width for preview)
const displayWidth = Math.min(400, newWidth);
const displayHeight = Math.floor(newHeight * (displayWidth / newWidth));
canvas.width = displayWidth;
canvas.height = displayHeight;
// Draw scaled image
ctx.drawImage(img, 0, 0, displayWidth, displayHeight);
// Notify parent of resolution change
if (onResolutionChange) {
const resizedCanvas = document.createElement('canvas');
resizedCanvas.width = newWidth;
resizedCanvas.height = newHeight;
const resizedCtx = resizedCanvas.getContext('2d');
resizedCtx.drawImage(img, 0, 0, newWidth, newHeight);
const resizedDataUrl = resizedCanvas.toDataURL('image/jpeg', 0.95);
onResolutionChange(resizedDataUrl, resolution);
}
};
img.src = imageData;
}, [imageData, resolution]);
const handleResolutionChange = (e) => {
const newResolution = parseInt(e.target.value);
setResolution(newResolution);
};
return (
<div className="bg-white rounded-lg shadow-md p-4 space-y-3">
<div className="flex items-center justify-between">
<h4 className="text-sm font-semibold text-gray-700">Preview: {fileName}</h4>
<span className="text-xs text-gray-500">
{currentDimensions.width} × {currentDimensions.height}px
</span>
</div>
<div className="bg-gray-50 rounded-lg p-3 flex justify-center">
<canvas ref={canvasRef} className="rounded shadow-sm" />
</div>
{/* Enhance Button */}
<button
onClick={() => onEnhanceToggle && onEnhanceToggle()}
className={`w-full py-2 px-4 rounded-lg font-medium transition-all flex items-center justify-center gap-2 ${
isEnhanced
? 'bg-purple-600 hover:bg-purple-700 text-white shadow-lg'
: 'bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600 text-white shadow-md'
}`}
>
<Sparkles className="w-4 h-4" />
{isEnhanced ? 'Enhanced ✓' : 'Enhance Image'}
</button>
{isEnhanced && (
<div className="bg-purple-50 border border-purple-200 rounded p-2 text-xs text-purple-700">
✨ Image will be enhanced with OpenCV (CLAHE, denoising, sharpening) before processing
</div>
)}
{/* Reasoning Mode Toggle */}
<button
onClick={() => onReasoningModeToggle && onReasoningModeToggle()}
className={`w-full py-2 px-4 rounded-lg font-medium transition-all flex items-center justify-center gap-2 ${
useReasoning
? 'bg-blue-600 hover:bg-blue-700 text-white shadow-lg'
: 'bg-gradient-to-r from-blue-500 to-cyan-500 hover:from-blue-600 hover:to-cyan-600 text-white shadow-md'
}`}
>
<Brain className="w-4 h-4" />
{useReasoning ? 'Reasoning ✓' : 'Simple Mode'}
</button>
{useReasoning && (
<div className="bg-blue-50 border border-blue-200 rounded p-2 text-xs text-blue-700">
🧠 VLM will use 2-step reasoning: first analyze document structure, then extract fields
</div>
)}
<div className="space-y-2">
<div className="flex items-center justify-between">
<label className="text-sm font-medium text-gray-700 flex items-center gap-2">
<SlidersHorizontal className="w-4 h-4" />
Resolution
</label>
<span className="text-sm font-bold text-primary-600">{resolution}%</span>
</div>
<input
type="range"
min="10"
max="100"
value={resolution}
onChange={handleResolutionChange}
className="w-full h-2 rounded-lg cursor-pointer"
style={{ accentColor: '#2563eb' }} // Tailwind blue-600
/>
<div className="flex justify-between text-xs text-gray-500">
<span>Low Quality</span>
<span>Original</span>
</div>
{resolution < 100 && (
<div className="bg-blue-50 border border-blue-200 rounded p-2 text-xs text-blue-700">
💡 Lower resolution = faster processing & lower cost
</div>
)}
</div>
<div className="text-xs text-gray-500 space-y-1">
<div className="flex justify-between">
<span>Original:</span>
<span className="font-medium">{originalDimensions.width} × {originalDimensions.height}px</span>
</div>
<div className="flex justify-between">
<span>Processing:</span>
<span className="font-medium text-primary-600">{currentDimensions.width} × {currentDimensions.height}px</span>
</div>
</div>
</div>
);
};
export default ImagePreview;