Vitron-Front/app/components/store/ImageUploadSection.tsx
2026-04-29 01:44:16 +03:30

139 lines
4.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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>
);
};