99 lines
3.0 KiB
JavaScript
99 lines
3.0 KiB
JavaScript
import { useRef, useState, useContext } from "react";
|
||
import { ConfigContext } from "../../context/ConfigContext";
|
||
import "../../styles/components/ImageUploadSection.css";
|
||
|
||
/**
|
||
* Reusable image upload component with camera and gallery options
|
||
* @param {Object} props
|
||
* @param {string} props.imagePreview - Base64 preview URL or null
|
||
* @param {Function} props.onImageChange - Callback when image is selected (file)
|
||
* @param {Function} props.onImageRemove - Callback to remove image
|
||
* @param {string} props.title - Section title (optional)
|
||
*/
|
||
export default function ImageUploadSection({
|
||
imagePreview,
|
||
onImageChange,
|
||
onImageRemove,
|
||
title = "Item Image (Optional)"
|
||
}) {
|
||
const cameraInputRef = useRef(null);
|
||
const galleryInputRef = useRef(null);
|
||
const [sizeError, setSizeError] = useState(null);
|
||
const { config } = useContext(ConfigContext);
|
||
|
||
const MAX_FILE_SIZE = config ? config.maxFileSizeMB * 1024 * 1024 : 20 * 1024 * 1024;
|
||
const MAX_FILE_SIZE_MB = config ? config.maxFileSizeMB : 20;
|
||
|
||
const handleFileChange = (e) => {
|
||
const file = e.target.files[0];
|
||
if (file) {
|
||
// Check file size
|
||
if (file.size > MAX_FILE_SIZE) {
|
||
const sizeMB = (file.size / (1024 * 1024)).toFixed(2);
|
||
setSizeError(`Image size (${sizeMB}MB) exceeds the ${MAX_FILE_SIZE_MB}MB limit. Please choose a smaller image.`);
|
||
// Reset the input
|
||
e.target.value = '';
|
||
return;
|
||
}
|
||
// Clear any previous error
|
||
setSizeError(null);
|
||
onImageChange(file);
|
||
}
|
||
};
|
||
|
||
const handleCameraClick = () => {
|
||
cameraInputRef.current?.click();
|
||
};
|
||
|
||
const handleGalleryClick = () => {
|
||
galleryInputRef.current?.click();
|
||
};
|
||
|
||
return (
|
||
<div className="image-upload-section">
|
||
<h3 className="image-upload-title">{title}</h3>
|
||
{sizeError && (
|
||
<div className="image-upload-error">
|
||
{sizeError}
|
||
</div>
|
||
)}
|
||
<div className="image-upload-content">
|
||
{!imagePreview ? (
|
||
<div className="image-upload-options">
|
||
<button onClick={handleCameraClick} className="image-upload-btn camera" type="button">
|
||
📷 Use Camera
|
||
</button>
|
||
<button onClick={handleGalleryClick} className="image-upload-btn gallery" type="button">
|
||
🖼️ Choose from Gallery
|
||
</button>
|
||
</div>
|
||
) : (
|
||
<div className="image-upload-preview">
|
||
<img src={imagePreview} alt="Preview" />
|
||
<button type="button" onClick={onImageRemove} className="image-upload-remove">
|
||
× Remove
|
||
</button>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<input
|
||
ref={cameraInputRef}
|
||
type="file"
|
||
accept="image/*"
|
||
capture="environment"
|
||
onChange={handleFileChange}
|
||
style={{ display: "none" }}
|
||
/>
|
||
|
||
<input
|
||
ref={galleryInputRef}
|
||
type="file"
|
||
accept="image/*"
|
||
onChange={handleFileChange}
|
||
style={{ display: "none" }}
|
||
/>
|
||
</div>
|
||
);
|
||
}
|