Modded to display box name instead of "Box Number"; also item details.
This commit is contained in:
parent
46fb973203
commit
4333cd5a71
|
@ -62,7 +62,7 @@ export default function Boxes({ token }) {
|
||||||
}>
|
}>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={
|
primary={
|
||||||
<RouterLink to={`/boxes/${box.ID}/items`}> {/* Use Link component */}
|
<RouterLink to={`/boxes/${box.ID}/items`} state={{ boxName: box.name}}> {/* Use Link component */}
|
||||||
{box.name}
|
{box.name}
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
// src/components/ItemDetails.js
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { TextField, Button, Container } from '@mui/material';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
export default function ItemDetails({ item, token, onSave }) {
|
||||||
|
const [name, setName] = useState(item.name);
|
||||||
|
const [description, setDescription] = useState(item.description);
|
||||||
|
const [imagePath, setImagePath] = useState(item.image_path || '');
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
axios.put(`${process.env.REACT_APP_API_URL}/items/${item.ID}`,
|
||||||
|
{ name, description, image_path: imagePath },
|
||||||
|
{
|
||||||
|
headers: { Authorization: `Bearer ${token}` }
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
onSave(); // Notify parent to refresh items
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<h3>Edit Item: {item.name}</h3>
|
||||||
|
<TextField
|
||||||
|
label="Item Name"
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
margin="normal"
|
||||||
|
value={name}
|
||||||
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
label="Item Description"
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
margin="normal"
|
||||||
|
value={description}
|
||||||
|
onChange={(e) => setDescription(e.target.value)}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
label="Item Image Path"
|
||||||
|
variant="outlined"
|
||||||
|
fullWidth
|
||||||
|
margin="normal"
|
||||||
|
value={imagePath}
|
||||||
|
onChange={(e) => setImagePath(e.target.value)}
|
||||||
|
/>
|
||||||
|
<Button variant="contained" color="primary" onClick={handleSave}>
|
||||||
|
Save Changes
|
||||||
|
</Button>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
// src/components/Items.js
|
|
||||||
import React, { useEffect, useState, useCallback } from 'react';
|
import React, { useEffect, useState, useCallback } from 'react';
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
|
@ -8,57 +7,51 @@ import {
|
||||||
TextField,
|
TextField,
|
||||||
Button,
|
Button,
|
||||||
IconButton,
|
IconButton,
|
||||||
Typography, // Import Typography for displaying image paths
|
Typography,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { Delete as DeleteIcon } from '@mui/icons-material';
|
import { Delete as DeleteIcon, Edit as EditIcon } from '@mui/icons-material';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams, useLocation } from 'react-router-dom';
|
||||||
|
import ItemDetails from './ItemDetails'; // Import the new ItemDetails component
|
||||||
|
|
||||||
export default function Items({ token }) {
|
export default function Items({ token }) {
|
||||||
const { id: boxId } = useParams();
|
const { id: boxId } = useParams();
|
||||||
const [items, setItems] = useState([]);
|
const [items, setItems] = useState([]);
|
||||||
const [newItemName, setNewItemName] = useState('');
|
const [newItemName, setNewItemName] = useState('');
|
||||||
const [newItemDescription, setNewItemDescription] = useState('');
|
const [newItemDescription, setNewItemDescription] = useState('');
|
||||||
const [newItemImagePath, setNewItemImagePath] = useState(`/images/default.jpg`);
|
const [newItemImagePath, setNewItemImagePath] = useState('/images/default.jpg');
|
||||||
|
const [editingItem, setEditingItem] = useState(null); // Track which item is being edited
|
||||||
|
const location = useLocation();
|
||||||
|
const boxName = location.state?.boxName || 'Unknown Box';
|
||||||
|
|
||||||
|
|
||||||
// Use useCallback to memoize fetchItems
|
|
||||||
const fetchItems = useCallback(() => {
|
const fetchItems = useCallback(() => {
|
||||||
console.log('Fetching items for box:', boxId);
|
|
||||||
axios.get(`${process.env.REACT_APP_API_URL}/boxes/${boxId}/items`, {
|
axios.get(`${process.env.REACT_APP_API_URL}/boxes/${boxId}/items`, {
|
||||||
headers: { Authorization: `Bearer ${token}` }
|
headers: { Authorization: `Bearer ${token}` }
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
console.log('Items:', response.data);
|
|
||||||
setItems(response.data);
|
setItems(response.data);
|
||||||
});
|
});
|
||||||
}, [boxId, token]); // Include dependencies for fetchItems
|
}, [boxId, token]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchItems();
|
fetchItems();
|
||||||
}, [boxId, token, fetchItems]);
|
}, [boxId, token, fetchItems]);
|
||||||
|
|
||||||
const handleAddItem = () => {
|
const handleAddItem = () => {
|
||||||
console.log('Adding item to box:', boxId);
|
|
||||||
console.log('Item Name:', newItemName);
|
|
||||||
console.log('Item Description:', newItemDescription);
|
|
||||||
console.log('Item Image Path:', newItemImagePath);
|
|
||||||
console.log('Token:', token);
|
|
||||||
|
|
||||||
axios.post(`${process.env.REACT_APP_API_URL}/items`,
|
axios.post(`${process.env.REACT_APP_API_URL}/items`,
|
||||||
{
|
{
|
||||||
name: newItemName,
|
name: newItemName,
|
||||||
description: newItemDescription,
|
description: newItemDescription,
|
||||||
box_id: parseInt(boxId, 10), // Assuming your API needs box_id to associate the item
|
box_id: parseInt(boxId, 10),
|
||||||
//image_path: newItemImagePath // Include the image path in the request
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headers: { Authorization: `Bearer ${token}` }
|
headers: { Authorization: `Bearer ${token}` }
|
||||||
}
|
}
|
||||||
).then(response => {
|
).then(() => {
|
||||||
setNewItemName('');
|
setNewItemName('');
|
||||||
setNewItemDescription('');
|
setNewItemDescription('');
|
||||||
setNewItemImagePath(''); // Clear the image path field
|
setNewItemImagePath('');
|
||||||
fetchItems(); // Refresh the item list after adding
|
fetchItems();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,13 +59,22 @@ export default function Items({ token }) {
|
||||||
axios.delete(`${process.env.REACT_APP_API_URL}/items/${itemId}`, {
|
axios.delete(`${process.env.REACT_APP_API_URL}/items/${itemId}`, {
|
||||||
headers: { Authorization: `Bearer ${token}` }
|
headers: { Authorization: `Bearer ${token}` }
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
fetchItems(); // Refresh the item list after deleting
|
fetchItems();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEditItem = (item) => {
|
||||||
|
setEditingItem(item); // Set the item to be edited
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveEdit = () => {
|
||||||
|
setEditingItem(null); // Clear the editing state after saving
|
||||||
|
fetchItems(); // Refresh the list after edit
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<h2>Items in Box: {boxId}</h2>
|
<h2>Items in Box: {boxName}</h2>
|
||||||
|
|
||||||
{/* Add Item Form */}
|
{/* Add Item Form */}
|
||||||
<TextField
|
<TextField
|
||||||
|
@ -103,23 +105,28 @@ export default function Items({ token }) {
|
||||||
Add Item
|
Add Item
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{console.log("Items List:", items)}
|
{/* Conditionally render the ItemDetails component if editingItem is not null */}
|
||||||
|
{editingItem ? (
|
||||||
{/* Item List */}
|
<ItemDetails item={editingItem} token={token} onSave={handleSaveEdit} />
|
||||||
|
) : (
|
||||||
<List>
|
<List>
|
||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
console.log("Item ID:", item.ID),
|
|
||||||
<ListItem key={item.ID} secondaryAction={
|
<ListItem key={item.ID} secondaryAction={
|
||||||
|
<>
|
||||||
|
<IconButton edge="end" onClick={() => handleEditItem(item)}>
|
||||||
|
<EditIcon />
|
||||||
|
</IconButton>
|
||||||
<IconButton edge="end" onClick={() => handleDeleteItem(item.ID)}>
|
<IconButton edge="end" onClick={() => handleDeleteItem(item.ID)}>
|
||||||
<DeleteIcon />
|
<DeleteIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
</>
|
||||||
}>
|
}>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={item.name}
|
primary={item.name}
|
||||||
secondary={
|
secondary={
|
||||||
<>
|
<>
|
||||||
<Typography variant="body2">{item.description}</Typography>
|
<Typography variant="body2">{item.description}</Typography>
|
||||||
{item.image_path && ( // Conditionally render image path
|
{item.image_path && (
|
||||||
<Typography variant="caption">Image: {item.image_path}</Typography>
|
<Typography variant="caption">Image: {item.image_path}</Typography>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -128,6 +135,7 @@ export default function Items({ token }) {
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
|
)}
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
Loading…
Reference in New Issue