app / src /components /UploadZone.tsx
itsLu's picture
Upload 88 files
2586888 verified
import { useState, useCallback } from "react";
import { Upload, Video, X, Loader2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
interface UploadZoneProps {
onUpload: (file: File) => void;
isLoading: boolean;
}
export const UploadZone = ({ onUpload, isLoading }: UploadZoneProps) => {
const [isDragging, setIsDragging] = useState(false);
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const handleDrag = useCallback((e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
}, []);
const handleDragIn = useCallback((e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(true);
}, []);
const handleDragOut = useCallback((e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
}, []);
const handleDrop = useCallback((e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
const files = e.dataTransfer.files;
if (files && files.length > 0) {
const file = files[0];
if (file.type.startsWith("video/")) {
setSelectedFile(file);
}
}
}, []);
const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
const files = e.target.files;
if (files && files.length > 0) {
setSelectedFile(files[0]);
}
};
const handleSubmit = () => {
if (selectedFile) {
onUpload(selectedFile);
}
};
const clearFile = () => {
setSelectedFile(null);
};
return (
<div className="mx-auto max-w-2xl">
<div
className={cn(
"upload-zone relative flex flex-col items-center justify-center p-12 text-center",
isDragging && "dragging",
selectedFile && "border-primary/50 bg-accent/30"
)}
onDragEnter={handleDragIn}
onDragLeave={handleDragOut}
onDragOver={handleDrag}
onDrop={handleDrop}
>
{!selectedFile ? (
<>
<div className="mb-6 flex h-20 w-20 items-center justify-center rounded-2xl bg-primary/10">
<Upload className="h-10 w-10 text-primary animate-float" />
</div>
<h3 className="mb-2 font-display text-xl font-semibold">
Upload Echocardiography Video
</h3>
<p className="mb-6 text-muted-foreground">
Drag and drop your video file here, or click to browse
</p>
<input
type="file"
accept="video/*"
onChange={handleFileSelect}
className="hidden"
id="file-upload"
/>
<label htmlFor="file-upload">
<Button variant="gradient" className="cursor-pointer" asChild>
<span>Select Video File</span>
</Button>
</label>
<p className="mt-4 text-xs text-muted-foreground">
Supported formats: MP4, AVI, MOV, DICOM
</p>
</>
) : (
<div className="w-full">
<div className="mb-6 flex items-center justify-center gap-4">
<div className="flex h-16 w-16 items-center justify-center rounded-xl bg-primary/10">
<Video className="h-8 w-8 text-primary" />
</div>
<div className="flex-1 text-left">
<p className="font-medium truncate max-w-xs">
{selectedFile.name}
</p>
<p className="text-sm text-muted-foreground">
{(selectedFile.size / (1024 * 1024)).toFixed(2)} MB
</p>
</div>
<Button
variant="ghost"
size="icon"
onClick={clearFile}
disabled={isLoading}
>
<X className="h-5 w-5" />
</Button>
</div>
<Button
variant="gradient"
size="lg"
onClick={handleSubmit}
disabled={isLoading}
className="w-full"
>
{isLoading ? (
<>
<Loader2 className="h-5 w-5 animate-spin" />
Analyzing...
</>
) : (
<>
<Upload className="h-5 w-5" />
Start Analysis
</>
)}
</Button>
</div>
)}
</div>
</div>
);
};