diff --git a/src/components/ItemDetails.js b/src/components/ItemDetails.js index fb7b99f..30d6398 100644 --- a/src/components/ItemDetails.js +++ b/src/components/ItemDetails.js @@ -1,5 +1,5 @@ // src/components/ItemDetails.js -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { TextField, Button, Container, Avatar } from '@mui/material'; import axios from 'axios'; @@ -8,6 +8,7 @@ export default function ItemDetails({ item, token, onSave }) { const [description, setDescription] = useState(item.description); const [imagePath, setImagePath] = useState(item.image_path || ''); const [imageSrc, setImageSrc] = useState('/images/default.jpg'); // Initial default image + const fileInputRef = useRef(null); // Add this line to define fileInputRef useEffect(() => { // Function to fetch image similar to getImageSrc in Items.js @@ -51,15 +52,44 @@ export default function ItemDetails({ item, token, onSave }) { getImageSrc(item.ID).then(dataUrl => setImageSrc(dataUrl)); }, [item.ID, token]); - const handleSave = () => { - axios.put(`${process.env.REACT_APP_API_URL}/items/${item.ID}`, - { name, description, image_path: imagePath }, - { - headers: { Authorization: `Bearer ${token}` } - } - ).then(() => { + const handleImageUpload = async () => { + const formData = new FormData(); + formData.append('image', fileInputRef.current.files[0]); + + try { + await axios.post(`${process.env.REACT_APP_API_URL}/items/${item.ID}/upload`, formData, { + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'multipart/form-data' + } + }); + // Handle successful upload (e.g., show a success message) + console.log('Image uploaded successfully!'); + } catch (error) { + // Handle upload error (e.g., show an error message) + console.error('Image upload failed:', error); + } + }; + + const handleSave = async () => { + // 1. Handle image upload first if a new image is selected + if (fileInputRef.current.files[0]) { + await handleImageUpload(); + } + + // 2. Update item details (name, description, etc.) + try { + await axios.put(`${process.env.REACT_APP_API_URL}/items/${item.ID}`, + { name, description, image_path: imagePath }, // You might remove image_path here + { + headers: { Authorization: `Bearer ${token}` } + } + ); onSave(); // Notify parent to refresh items - }); + } catch (error) { + // Handle update error + console.error('Item update failed:', error); + } }; const handleImageError = (e) => { @@ -102,6 +132,27 @@ export default function ItemDetails({ item, token, onSave }) { value={imagePath} onChange={(e) => setImagePath(e.target.value)} /> + + + diff --git a/src/components/Items.js b/src/components/Items.js index 0fe90ce..11a05f2 100644 --- a/src/components/Items.js +++ b/src/components/Items.js @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useCallback } from 'react'; +import React, { useEffect, useState, useCallback, useRef } from 'react'; import { Container, List, @@ -26,6 +26,7 @@ export default function Items({ token }) { const location = useLocation(); const boxName = location.state?.boxName || 'Unknown Box'; const [itemImages, setItemImages] = useState({}); + const fileInputRef = useRef(null); const handleImageError = (e) => { if (e.target.src.startsWith('data:image/')) { @@ -43,7 +44,7 @@ export default function Items({ token }) { .catch(error => console.error("Error loading default image:", error)); }; - const getImageSrc = (itemId) => { + const getImageSrc = useCallback((itemId) => { return axios.get(`${process.env.REACT_APP_API_URL}/items/${itemId}/image`, { headers: { Authorization: `Bearer ${token}` }, responseType: 'blob' @@ -75,7 +76,7 @@ export default function Items({ token }) { img.onerror = reject; }); }); - }; + }, [token]); const fetchItems = useCallback(() => { axios.get(`${process.env.REACT_APP_API_URL}/boxes/${boxId}/items`, { @@ -93,26 +94,35 @@ export default function Items({ token }) { }); }); }); - }, [boxId, token]); + }, [boxId, token, getImageSrc]); useEffect(() => { fetchItems(); }, [boxId, token, fetchItems]); const handleAddItem = () => { - axios.post(`${process.env.REACT_APP_API_URL}/items`, - { - name: newItemName, - description: newItemDescription, - box_id: parseInt(boxId, 10), - }, - { - headers: { Authorization: `Bearer ${token}` } + const formData = new FormData(); + formData.append('name', newItemName); + formData.append('description', newItemDescription); + formData.append('box_id', parseInt(boxId, 10)); + // Append image only if a new one is selected + if (fileInputRef.current.files[0]) { + formData.append('image', fileInputRef.current.files[0]); + } + + axios.post(`${process.env.REACT_APP_API_URL}/items`, formData, { + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'multipart/form-data' // Important for file uploads } - ).then(() => { + }).then(() => { setNewItemName(''); setNewItemDescription(''); setNewItemImagePath(''); + // Clear the file input + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } fetchItems(); }); }; @@ -160,8 +170,19 @@ export default function Items({ token }) { fullWidth margin="normal" value={newItemImagePath} - onChange={(e) => setNewItemImagePath(e.target.value)} + onChange={(e) => setNewItemImagePath(e.target.files[0].name)} /> + +