Successful image upload now

This commit is contained in:
Steve White 2024-10-10 21:17:21 -05:00
parent 3a54c5da58
commit 0fbc5721b9
2 changed files with 95 additions and 23 deletions

View File

@ -1,5 +1,5 @@
// src/components/ItemDetails.js // 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 { TextField, Button, Container, Avatar } from '@mui/material';
import axios from 'axios'; import axios from 'axios';
@ -8,6 +8,7 @@ export default function ItemDetails({ item, token, onSave }) {
const [description, setDescription] = useState(item.description); const [description, setDescription] = useState(item.description);
const [imagePath, setImagePath] = useState(item.image_path || ''); const [imagePath, setImagePath] = useState(item.image_path || '');
const [imageSrc, setImageSrc] = useState('/images/default.jpg'); // Initial default image const [imageSrc, setImageSrc] = useState('/images/default.jpg'); // Initial default image
const fileInputRef = useRef(null); // Add this line to define fileInputRef
useEffect(() => { useEffect(() => {
// Function to fetch image similar to getImageSrc in Items.js // 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)); getImageSrc(item.ID).then(dataUrl => setImageSrc(dataUrl));
}, [item.ID, token]); }, [item.ID, token]);
const handleSave = () => { const handleImageUpload = async () => {
axios.put(`${process.env.REACT_APP_API_URL}/items/${item.ID}`, const formData = new FormData();
{ name, description, image_path: imagePath }, formData.append('image', fileInputRef.current.files[0]);
{
headers: { Authorization: `Bearer ${token}` } try {
} await axios.post(`${process.env.REACT_APP_API_URL}/items/${item.ID}/upload`, formData, {
).then(() => { 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 onSave(); // Notify parent to refresh items
}); } catch (error) {
// Handle update error
console.error('Item update failed:', error);
}
}; };
const handleImageError = (e) => { const handleImageError = (e) => {
@ -102,6 +132,27 @@ export default function ItemDetails({ item, token, onSave }) {
value={imagePath} value={imagePath}
onChange={(e) => setImagePath(e.target.value)} onChange={(e) => setImagePath(e.target.value)}
/> />
<input
type="file"
accept="image/*"
ref={fileInputRef}
style={{ display: 'none' }}
id="editItemImageUpload" // Unique ID
/>
<Button variant="contained" component="label" htmlFor="editItemImageUpload">
Upload Image
<input
type="file"
accept="image/*"
id="image-upload"
style={{ display: 'none' }}
onChange={(e) => {
// You can handle image preview here if needed
setImagePath(e.target.files[0].name);
}}
/>
</Button>
<Button variant="contained" color="primary" onClick={handleSave}> <Button variant="contained" color="primary" onClick={handleSave}>
Save Changes Save Changes
</Button> </Button>

View File

@ -1,4 +1,4 @@
import React, { useEffect, useState, useCallback } from 'react'; import React, { useEffect, useState, useCallback, useRef } from 'react';
import { import {
Container, Container,
List, List,
@ -26,6 +26,7 @@ export default function Items({ token }) {
const location = useLocation(); const location = useLocation();
const boxName = location.state?.boxName || 'Unknown Box'; const boxName = location.state?.boxName || 'Unknown Box';
const [itemImages, setItemImages] = useState({}); const [itemImages, setItemImages] = useState({});
const fileInputRef = useRef(null);
const handleImageError = (e) => { const handleImageError = (e) => {
if (e.target.src.startsWith('data:image/')) { 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)); .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`, { return axios.get(`${process.env.REACT_APP_API_URL}/items/${itemId}/image`, {
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },
responseType: 'blob' responseType: 'blob'
@ -75,7 +76,7 @@ export default function Items({ token }) {
img.onerror = reject; img.onerror = reject;
}); });
}); });
}; }, [token]);
const fetchItems = useCallback(() => { const fetchItems = useCallback(() => {
axios.get(`${process.env.REACT_APP_API_URL}/boxes/${boxId}/items`, { 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(() => { useEffect(() => {
fetchItems(); fetchItems();
}, [boxId, token, fetchItems]); }, [boxId, token, fetchItems]);
const handleAddItem = () => { const handleAddItem = () => {
axios.post(`${process.env.REACT_APP_API_URL}/items`, const formData = new FormData();
{ formData.append('name', newItemName);
name: newItemName, formData.append('description', newItemDescription);
description: newItemDescription, formData.append('box_id', parseInt(boxId, 10));
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]);
headers: { Authorization: `Bearer ${token}` } }
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(''); setNewItemName('');
setNewItemDescription(''); setNewItemDescription('');
setNewItemImagePath(''); setNewItemImagePath('');
// Clear the file input
if (fileInputRef.current) {
fileInputRef.current.value = '';
}
fetchItems(); fetchItems();
}); });
}; };
@ -160,8 +170,19 @@ export default function Items({ token }) {
fullWidth fullWidth
margin="normal" margin="normal"
value={newItemImagePath} value={newItemImagePath}
onChange={(e) => setNewItemImagePath(e.target.value)} onChange={(e) => setNewItemImagePath(e.target.files[0].name)}
/> />
<input
type="file"
accept="image/*"
ref={fileInputRef}
style={{ display: 'none' }}
id="newItemImageUpload" // Unique ID
/>
<Button variant="contained" component="label" htmlFor="newItemImageUpload">
Upload Image
{/* ... rest of your button code ... */}
</Button>
<Button variant="contained" color="primary" onClick={handleAddItem}> <Button variant="contained" color="primary" onClick={handleAddItem}>
Add Item Add Item
</Button> </Button>