costco-grocery-list/frontend/src/components/AddItemWithDetailsModal.jsx

187 lines
5.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 { useRef, useState } from "react";
import { ITEM_GROUPS, ITEM_TYPES, getItemTypeLabel, getZoneValues } from "../constants/classifications";
import "../styles/AddItemWithDetailsModal.css";
export default function AddItemWithDetailsModal({ itemName, onConfirm, onSkip, onCancel }) {
const [selectedImage, setSelectedImage] = useState(null);
const [imagePreview, setImagePreview] = useState(null);
const [itemType, setItemType] = useState("");
const [itemGroup, setItemGroup] = useState("");
const [zone, setZone] = useState("");
const cameraInputRef = useRef(null);
const galleryInputRef = useRef(null);
const handleImageChange = (e) => {
const file = e.target.files[0];
if (file) {
setSelectedImage(file);
const reader = new FileReader();
reader.onloadend = () => {
setImagePreview(reader.result);
};
reader.readAsDataURL(file);
}
};
const removeImage = () => {
setSelectedImage(null);
setImagePreview(null);
};
const handleItemTypeChange = (e) => {
const newType = e.target.value;
setItemType(newType);
// Reset item group when type changes
setItemGroup("");
};
const handleConfirm = () => {
// Validate classification if provided
if (itemType && !itemGroup) {
alert("Please select an item group");
return;
}
const classification = itemType ? {
item_type: itemType,
item_group: itemGroup,
zone: zone || null
} : null;
onConfirm(selectedImage, classification);
};
const handleSkip = () => {
onSkip();
};
const handleCameraClick = () => {
cameraInputRef.current?.click();
};
const handleGalleryClick = () => {
galleryInputRef.current?.click();
};
const availableGroups = itemType ? ITEM_GROUPS[itemType] || [] : [];
return (
<div className="add-item-details-overlay" onClick={onCancel}>
<div className="add-item-details-modal" onClick={(e) => e.stopPropagation()}>
<h2 className="add-item-details-title">Add Details for "{itemName}"</h2>
<p className="add-item-details-subtitle">Add an image and classification to help organize your list</p>
{/* Image Section */}
<div className="add-item-details-section">
<h3 className="add-item-details-section-title">Item Image (Optional)</h3>
<div className="add-item-details-image-content">
{!imagePreview ? (
<div className="add-item-details-image-options">
<button onClick={handleCameraClick} className="add-item-details-image-btn camera">
📷 Use Camera
</button>
<button onClick={handleGalleryClick} className="add-item-details-image-btn gallery">
🖼 Choose from Gallery
</button>
</div>
) : (
<div className="add-item-details-image-preview">
<img src={imagePreview} alt="Preview" />
<button type="button" onClick={removeImage} className="add-item-details-remove-image">
× Remove
</button>
</div>
)}
</div>
<input
ref={cameraInputRef}
type="file"
accept="image/*"
capture="environment"
onChange={handleImageChange}
style={{ display: "none" }}
/>
<input
ref={galleryInputRef}
type="file"
accept="image/*"
onChange={handleImageChange}
style={{ display: "none" }}
/>
</div>
{/* Classification Section */}
<div className="add-item-details-section">
<h3 className="add-item-details-section-title">Item Classification (Optional)</h3>
<div className="add-item-details-field">
<label>Item Type</label>
<select
value={itemType}
onChange={handleItemTypeChange}
className="add-item-details-select"
>
<option value="">-- Select Type --</option>
{Object.values(ITEM_TYPES).map((type) => (
<option key={type} value={type}>
{getItemTypeLabel(type)}
</option>
))}
</select>
</div>
{itemType && (
<div className="add-item-details-field">
<label>Item Group</label>
<select
value={itemGroup}
onChange={(e) => setItemGroup(e.target.value)}
className="add-item-details-select"
>
<option value="">-- Select Group --</option>
{availableGroups.map((group) => (
<option key={group} value={group}>
{group}
</option>
))}
</select>
</div>
)}
<div className="add-item-details-field">
<label>Store Zone</label>
<select
value={zone}
onChange={(e) => setZone(e.target.value)}
className="add-item-details-select"
>
<option value="">-- Select Zone --</option>
{getZoneValues().map((z) => (
<option key={z} value={z}>
{z}
</option>
))}
</select>
</div>
</div>
{/* Actions */}
<div className="add-item-details-actions">
<button onClick={onCancel} className="add-item-details-btn cancel">
Cancel
</button>
<button onClick={handleSkip} className="add-item-details-btn skip">
Skip All
</button>
<button onClick={handleConfirm} className="add-item-details-btn confirm">
Add Item
</button>
</div>
</div>
</div>
);
}