Pathora / frontend /src /components /UploadSection.tsx
malavikapradeep2001's picture
Update
3a9f19d
raw
history blame
6.1 kB
import React, { useRef } from 'react';
import { UploadIcon } from 'lucide-react';
interface UploadSectionProps {
selectedTest: string;
uploadedImage: string | null;
setUploadedImage: (image: string | null) => void;
selectedModel: string;
setSelectedModel: (model: string) => void;
onAnalyze: () => void;
}
export function UploadSection({
selectedTest,
uploadedImage,
setUploadedImage,
selectedModel,
setSelectedModel,
onAnalyze,
}: UploadSectionProps) {
const fileInputRef = useRef<HTMLInputElement>(null);
const modelOptions = {
cytology: [
{ value: 'mwt', label: 'Manalife_AI_MWT' },
{ value: 'yolo', label: 'Manalife_AI_YOLOv8' },
],
colposcopy: [
{ value: 'cin', label: 'Manalife_MaANIA_Colpo' },
],
histopathology: [
{ value: 'histopathology', label: 'ManalifeAI__Path Foundation Model' },
],
};
const sampleImages = {
cytology: [
"/cyto/neg1.bmp",
"/cyto/neg2.png",
"/cyto/LSIL1.png",
"/cyto/LSIL2.png",
"/cyto/HSIL1.jpg",
"/cyto/HSIL2.JPG",
],
colposcopy: [
"/colpo/ab1.jpg",
"/colpo/ab2.jpg",
"/colpo/ab3.jpg",
"/colpo/nor1.jpg",
"/colpo/nor2.jpg",
"/colpo/nor3.jpg",
],
histopathology: [
"/histo/hist1.png",
"/histo/hist2.png",
"/histo/hist3.jpg",
],
};
const currentModels =
modelOptions[selectedTest as keyof typeof modelOptions] || [];
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) {
const reader = new FileReader();
reader.onload = (event) => {
setUploadedImage(event.target?.result as string);
};
reader.readAsDataURL(file);
}
};
const handleDrop = (e: React.DragEvent) => {
e.preventDefault();
const file = e.dataTransfer.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (event) => {
setUploadedImage(event.target?.result as string);
};
reader.readAsDataURL(file);
}
};
// Handle click on sample image
const handleSampleClick = (imgUrl: string) => {
setUploadedImage(imgUrl);
};
return (
<div className="bg-white rounded-lg shadow-sm p-6">
<h2 className="text-2xl font-semibold text-gray-900 mb-6">
Upload an image of a tissue sample
</h2>
{/* Upload Area */}
<div
onDrop={handleDrop}
onDragOver={(e) => e.preventDefault()}
onClick={() => fileInputRef.current?.click()}
className="border-2 border-dashed border-gray-300 rounded-lg p-8 text-center cursor-pointer hover:border-blue-400 transition-colors"
>
<input
ref={fileInputRef}
type="file"
accept="image/*"
onChange={handleFileChange}
className="hidden"
/>
<div className="flex flex-col items-center">
<div className="w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
<UploadIcon className="w-8 h-8 text-gray-400" />
</div>
{uploadedImage ? (
<>
<p className="text-teal-700 font-medium mb-2">
Image uploaded successfully!
</p>
<p className="text-sm text-gray-500 mb-4">
Click to upload a different image
</p>
<div className="w-32 h-32 rounded-lg overflow-hidden border border-gray-200">
<img
src={uploadedImage}
alt="Uploaded sample"
className="w-full h-full object-cover"
/>
</div>
</>
) : (
<p className="text-gray-600">Drag and drop or click to upload</p>
)}
</div>
</div>
{/* Model Selection */}
<div className="mt-6">
<label className="block text-sm font-medium text-gray-700 mb-2">
Select Analysis Model:
</label>
<select
value={selectedModel}
onChange={(e) => setSelectedModel(e.target.value)}
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
>
<option value="">Choose a model...</option>
{currentModels.map((model) => (
<option key={model.value} value={model.value}>
{model.label}
</option>
))}
</select>
</div>
{/* Analyze Button */}
<button
type="button"
onClick={(e) => {
// Prevent clicks from bubbling to the upload area (which would trigger file select)
e.stopPropagation();
onAnalyze();
}}
disabled={!uploadedImage || !selectedModel}
className={`w-full mt-6 text-white py-3 rounded-lg font-medium transition-colors ${
!uploadedImage || !selectedModel
? 'bg-gray-300 disabled:cursor-not-allowed'
: 'bg-gradient-to-r from-teal-800 to-teal-600 hover:opacity-95'
}`}
>
Analyze
</button>
{/* Separator */}
<hr className="my-8 border-gray-200" />
{/* Sample Images Section */}
<div>
<h3 className="text-lg font-semibold text-gray-800 mb-4">
Samples Images
</h3>
<div className="flex flex-wrap gap-4">
{(sampleImages[selectedTest as keyof typeof sampleImages] || []).map(
(img, index) => (
<div
key={index}
className={`w-20 h-20 rounded-lg border-2 cursor-pointer transition-transform hover:scale-105 overflow-hidden ${
uploadedImage === img ? 'ring-2 ring-offset-1 ring-blue-800' : 'border-gray-300'
}`}
onClick={() => handleSampleClick(img)}
>
<img src={img} alt={`Sample ${index + 1}`} className="w-full h-full object-cover" />
</div>
)
)}
</div>
</div>
</div>
);
}