error-handling #1

Merged
stwhite merged 24 commits from error-handling into main 2024-10-30 15:19:49 +00:00
2 changed files with 70 additions and 14 deletions
Showing only changes of commit ea690d14c6 - Show all commits

View File

@ -1,6 +1,6 @@
// src/components/ItemDetails.js
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { TextField, Button, Container, Avatar, Typography } from '@mui/material';
import { TextField, Button, Container, Avatar } from '@mui/material';
import axios from 'axios';
import { PRIMARY_COLOR, SECONDARY_COLOR } from '../App';
//import { useNavigate } from 'react-router-dom'; // Import useNavigate
@ -13,9 +13,14 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
const fileInputRef = useRef(null); // Add this line to define fileInputRef
const [imageOverlayVisible, setImageOverlayVisible] = useState(false);
// const navigate = useNavigate(); // Initialize useNavigate
// eslint says boxName is defined but never used, but when I remove it it fails to compile
// because boxName is undefined
// eslint-disable-next-line
const [boxName, setBoxName] = useState('');
const [boxes, setBoxes] = useState([]);
const [selectedBoxId, setSelectedBoxId] = useState(boxId);
const [selectedBoxId, setSelectedBoxId] = useState(item.box_id);
//console.log("item.box_id: " + item.box_id);
useEffect(() => {
const fetchBoxes = async () => {
@ -35,7 +40,7 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
const handleBoxChange = (event) => {
const newBoxId = event.target.value;
setSelectedBoxId(newBoxId); // Update only this state
console.log('Selected box ID:', newBoxId);
//console.log('Selected box ID:', newBoxId);
};
useEffect(() => {
@ -56,10 +61,14 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
}
};
if (selectedBoxId) {
if (selectedBoxId !== item.box_id) {
getBoxDetails(selectedBoxId); // Fetch when selected box changes
//console.log("selectedBoxId:", selectedBoxId);
} else if (item.box_id) {
getBoxDetails(item.box_id); // Fetch when boxId exists and selectedBoxId is empty
//console.log("item.box_id:", item.box_id);
}
}, [selectedBoxId, token]); // Removed `boxId` from dependencies
}, [selectedBoxId, token, item.box_id]); // Removed `boxId` from dependencies
useEffect(() => {
// Function to fetch image similar to getImageSrc in Items.js
@ -120,7 +129,7 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
}
});
// Handle successful upload (e.g., show a success message)
console.log('Image uploaded successfully!', response.data.imagePath);
//console.log('Image uploaded successfully!', response.data.imagePath);
return response.data.imagePath; // Indicate successful upload
} catch (error) {
// Handle upload error (e.g., show an error message)
@ -128,8 +137,10 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
}
}, [item.ID, token]);
// eslint-disable-next-line
const updateItemBoxId = async () => {
try {
// eslint-disable-next-line
const response = await axios.put(`${process.env.REACT_APP_API_URL}/items/${item.id}`, {
box_id: selectedBoxId,
}, {
@ -146,9 +157,10 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
let imagePath;
// 1. Handle image upload first if a new image is selected
if (fileInputRef.current.files[0]) {
// eslint-disable-next-line
imagePath = await handleImageUpload();
}
console.log("Selected box ID:", selectedBoxId)
//console.log("Selected box ID:", selectedBoxId)
// 2. Update item details (name, description, etc.)
try {
@ -233,7 +245,8 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
<option value="">No box</option>
{boxes.map((box) => (
// eslint-disable-next-line
console.log('Box at the selection point:', box.ID),
//console.log('Box at the selection point:', box.ID),
//console.log("Box name:", box.name),
<option key={box.ID} value={box.ID}>
{box.name}
</option>

View File

@ -37,7 +37,7 @@ export default function Items({ token }) {
const { id } = useParams();
const boxID = id;
const url = boxId === undefined ? `${process.env.REACT_APP_API_URL}/items` : `${process.env.REACT_APP_API_URL}/boxes/${boxId}/items`;
const [searchQuery, setSearchQuery] = useState('');
const debugLog = (message) => {
if (process.env.DEBUG_API) {
@ -63,9 +63,35 @@ export default function Items({ token }) {
}
};
const handleImageUpload = async (itemId, imageFile) => {
/**
* This function takes an image name and returns a unique image name.
* If the image name is 'image.jpg', a random string is generated and appended to the image name.
* This is used to prevent overwriting of images with the same name.
* @param {string} imageName - The name of the image
* @return {string} - The unique image name
*/
const generateUniqueImageName = (imageName) => {
if (imageName.toLowerCase() === 'image.jpg') {
const randomString = Math.random().toString(36).substr(2, 9);
return `image_${randomString}.jpg`;
}
return imageName;
};
const handleImageUpload = async (itemId, imageFile, newImageName) => {
const formData = new FormData();
formData.append('image', imageFile);
//const imageFile = fileInputRef.current.files[0];
//const newImageName = generateUniqueImageName(imageFile.name);
formData.append('image', new File([imageFile], newImageName, {
type: imageFile.type,
}));
// Create a new file with the unique name
// eslint-disable-next-line
const newImageFile = new File([imageFile], newImageName, {
type: imageFile.type,
});
try {
const response = await axios.post(`${process.env.REACT_APP_API_URL}/items/${itemId}/upload`, formData, {
@ -81,6 +107,7 @@ export default function Items({ token }) {
return null; // Indicate upload failure
}
};
const handleSaveNewItem = async () => {
try {
// 1. Create the item first
@ -98,7 +125,9 @@ export default function Items({ token }) {
// 2. If item creation is successful, upload the image
if (newItemResponse.status === 200 && fileInputRef.current.files[0]) {
const newItemId = newItemResponse.data.id;
const uploadedImagePath = await handleImageUpload(newItemId, fileInputRef.current.files[0]);
const imageFile = fileInputRef.current.files[0];
const newImageName = generateUniqueImageName(imageFile.name);
const uploadedImagePath = await handleImageUpload(newItemId, fileInputRef.current.files[0], newImageName);
if (uploadedImagePath) {
// console.log("Image path to save:", uploadedImagePath);
@ -249,6 +278,14 @@ export default function Items({ token }) {
return (
<Container>
<TextField
label="Search"
variant="outlined"
fullWidth
margin="normal"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
<h2>Items in Box: {boxName === "Unknown Box" ? "All Boxes" : `${boxName} (${items.length} items)`}</h2>
<input
type="file"
@ -286,6 +323,7 @@ export default function Items({ token }) {
type="file"
accept="image/*"
ref={fileInputRef}
// capture="environment" // Capture the image from the user's camera
style={{ display: 'block', margin: '10px 0' }} // Style as needed
id="newItemImageUpload"
/>
@ -307,13 +345,18 @@ export default function Items({ token }) {
/>
) : (
<List>
{items.map((item) => (
{items
.filter(item =>
item.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
item.description.toLowerCase().includes(searchQuery.toLowerCase())
)
.map((item) => (
<ListItem key={item.ID} secondaryAction={
<>
<IconButton edge="end" onClick={() => handleEditItem(item)}>
<EditIcon />
</IconButton>
<IconButton edge="end" onClick={() => handleDeleteItem(item.ID)}>
<IconButton edge="end" sx={{ marginLeft: 4 }} onClick={() => handleDeleteItem(item.ID)}>
<DeleteIcon />
</IconButton>
</>