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