139 lines
4.3 KiB
TypeScript
139 lines
4.3 KiB
TypeScript
import { Camera, Plus, Scaling, Trash } from "lucide-react";
|
||
|
||
interface ImageUploadSectionProps {
|
||
selectedImages: Array<{ file: File; url: string }>;
|
||
onUploadClick: () => void;
|
||
onRemoveImage: (index: number) => void;
|
||
onScaleImage: (index: number) => void;
|
||
onImageSelect: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||
fileInputRef: React.RefObject<HTMLInputElement>;
|
||
}
|
||
|
||
// Helper function to check if file is a video
|
||
const isVideoFile = (file: File): boolean => {
|
||
if (!file) {
|
||
console.log("No file provided to isVideoFile");
|
||
return false;
|
||
}
|
||
|
||
// Check by MIME type first
|
||
if (file.type && file.type.startsWith("video/")) {
|
||
return true;
|
||
}
|
||
|
||
// Fallback: check by file extension if MIME type is not available
|
||
const fileExtension = file.name.toLowerCase().split(".").pop();
|
||
const videoExtensions = [
|
||
"mp4",
|
||
"webm",
|
||
"ogg",
|
||
"avi",
|
||
"mov",
|
||
"wmv",
|
||
"flv",
|
||
"mkv",
|
||
"3gp",
|
||
];
|
||
|
||
return videoExtensions.includes(fileExtension || "");
|
||
};
|
||
|
||
export const ImageUploadSection: React.FC<ImageUploadSectionProps> = ({
|
||
selectedImages,
|
||
onUploadClick,
|
||
onRemoveImage,
|
||
onScaleImage,
|
||
onImageSelect,
|
||
fileInputRef,
|
||
}: ImageUploadSectionProps) => {
|
||
return (
|
||
<div className="flex flex-col p-6 border-b items-center justify-center">
|
||
<div className="grid grid-cols-3 gap-3 items-center justify-center w-full max-w-sm">
|
||
{selectedImages.length <= 1 && <div />}
|
||
{/* Selected Images and Videos */}
|
||
{selectedImages.map((image, index) => {
|
||
const isVideo = isVideoFile(image.file);
|
||
|
||
return (
|
||
<div
|
||
key={index}
|
||
className="relative aspect-square border rounded-lg"
|
||
>
|
||
{isVideo ? (
|
||
<video
|
||
src={image.url}
|
||
className="w-full h-full object-cover select-none rounded-lg"
|
||
muted
|
||
autoPlay
|
||
loop
|
||
/>
|
||
) : (
|
||
<img
|
||
src={image.url}
|
||
alt={`Selected product ${index + 1}`}
|
||
className="w-full h-full object-contain select-none rounded-lg"
|
||
/>
|
||
)}
|
||
<div className="rounded-b-lg py-2 absolute -bottom-[1px] w-full bg-BLACK text-WHITE text-center flex items-center justify-around">
|
||
{/* Only show scaling option for images, not videos */}
|
||
{!isVideo && (
|
||
<Scaling
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
onScaleImage(index);
|
||
}}
|
||
className="w-5 h-5 cursor-pointer hover:scale-110 transition-transform"
|
||
/>
|
||
)}
|
||
<Trash
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
onRemoveImage(index);
|
||
}}
|
||
className="w-5 h-5 cursor-pointer hover:scale-110 transition-transform"
|
||
/>
|
||
</div>
|
||
</div>
|
||
);
|
||
})}
|
||
{/* Upload Container */}
|
||
<div
|
||
onClick={onUploadClick}
|
||
onKeyDown={(e) => {
|
||
if (e.key === "Enter" || e.key === " ") {
|
||
e.preventDefault();
|
||
onUploadClick();
|
||
}
|
||
}}
|
||
role="button"
|
||
tabIndex={0}
|
||
className="aspect-square relative rounded-lg border-2 border-dashed border-GRAY3 flex flex-col items-center justify-between cursor-pointer hover:border-GRAY2 transition-colors bg-WHITE3"
|
||
>
|
||
<div className="flex-1 flex items-center justify-center mb-4">
|
||
<Camera className="w-8 h-8 text-GRAY" />
|
||
</div>
|
||
<div className="rounded-b-lg py-2 absolute -bottom-[1px] w-full bg-BLACK text-WHITE text-center flex items-center justify-center">
|
||
<Plus className="w-5 h-5" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{selectedImages.length > 0 && (
|
||
<p className="text-sm text-GRAY text-center mt-4">
|
||
{selectedImages.length} فایل انتخاب شده
|
||
</p>
|
||
)}
|
||
|
||
{/* Hidden file input - now accepts both images and videos */}
|
||
<input
|
||
ref={fileInputRef}
|
||
type="file"
|
||
accept="image/*,video/*"
|
||
multiple
|
||
onChange={onImageSelect}
|
||
className="hidden"
|
||
/>
|
||
</div>
|
||
);
|
||
};
|