added type-down search
This commit is contained in:
parent
8424579dcb
commit
ea690d14c6
|
@ -1,6 +1,6 @@
|
||||||
// src/components/ItemDetails.js
|
// src/components/ItemDetails.js
|
||||||
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
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 axios from 'axios';
|
||||||
import { PRIMARY_COLOR, SECONDARY_COLOR } from '../App';
|
import { PRIMARY_COLOR, SECONDARY_COLOR } from '../App';
|
||||||
//import { useNavigate } from 'react-router-dom'; // Import useNavigate
|
//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 fileInputRef = useRef(null); // Add this line to define fileInputRef
|
||||||
const [imageOverlayVisible, setImageOverlayVisible] = useState(false);
|
const [imageOverlayVisible, setImageOverlayVisible] = useState(false);
|
||||||
// const navigate = useNavigate(); // Initialize useNavigate
|
// 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 [boxName, setBoxName] = useState('');
|
||||||
const [boxes, setBoxes] = 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(() => {
|
useEffect(() => {
|
||||||
const fetchBoxes = async () => {
|
const fetchBoxes = async () => {
|
||||||
|
@ -35,7 +40,7 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
|
||||||
const handleBoxChange = (event) => {
|
const handleBoxChange = (event) => {
|
||||||
const newBoxId = event.target.value;
|
const newBoxId = event.target.value;
|
||||||
setSelectedBoxId(newBoxId); // Update only this state
|
setSelectedBoxId(newBoxId); // Update only this state
|
||||||
console.log('Selected box ID:', newBoxId);
|
//console.log('Selected box ID:', newBoxId);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
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
|
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(() => {
|
useEffect(() => {
|
||||||
// Function to fetch image similar to getImageSrc in Items.js
|
// 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)
|
// 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
|
return response.data.imagePath; // Indicate successful upload
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Handle upload error (e.g., show an error message)
|
// 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]);
|
}, [item.ID, token]);
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
const updateItemBoxId = async () => {
|
const updateItemBoxId = async () => {
|
||||||
try {
|
try {
|
||||||
|
// eslint-disable-next-line
|
||||||
const response = await axios.put(`${process.env.REACT_APP_API_URL}/items/${item.id}`, {
|
const response = await axios.put(`${process.env.REACT_APP_API_URL}/items/${item.id}`, {
|
||||||
box_id: selectedBoxId,
|
box_id: selectedBoxId,
|
||||||
}, {
|
}, {
|
||||||
|
@ -146,9 +157,10 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
|
||||||
let imagePath;
|
let imagePath;
|
||||||
// 1. Handle image upload first if a new image is selected
|
// 1. Handle image upload first if a new image is selected
|
||||||
if (fileInputRef.current.files[0]) {
|
if (fileInputRef.current.files[0]) {
|
||||||
|
// eslint-disable-next-line
|
||||||
imagePath = await handleImageUpload();
|
imagePath = await handleImageUpload();
|
||||||
}
|
}
|
||||||
console.log("Selected box ID:", selectedBoxId)
|
//console.log("Selected box ID:", selectedBoxId)
|
||||||
|
|
||||||
// 2. Update item details (name, description, etc.)
|
// 2. Update item details (name, description, etc.)
|
||||||
try {
|
try {
|
||||||
|
@ -233,7 +245,8 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
|
||||||
<option value="">No box</option>
|
<option value="">No box</option>
|
||||||
{boxes.map((box) => (
|
{boxes.map((box) => (
|
||||||
// eslint-disable-next-line
|
// 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}>
|
<option key={box.ID} value={box.ID}>
|
||||||
{box.name}
|
{box.name}
|
||||||
</option>
|
</option>
|
||||||
|
|
|
@ -37,7 +37,7 @@ export default function Items({ token }) {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const boxID = id;
|
const boxID = id;
|
||||||
const url = boxId === undefined ? `${process.env.REACT_APP_API_URL}/items` : `${process.env.REACT_APP_API_URL}/boxes/${boxId}/items`;
|
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) => {
|
const debugLog = (message) => {
|
||||||
if (process.env.DEBUG_API) {
|
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();
|
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 {
|
try {
|
||||||
const response = await axios.post(`${process.env.REACT_APP_API_URL}/items/${itemId}/upload`, formData, {
|
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
|
return null; // Indicate upload failure
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSaveNewItem = async () => {
|
const handleSaveNewItem = async () => {
|
||||||
try {
|
try {
|
||||||
// 1. Create the item first
|
// 1. Create the item first
|
||||||
|
@ -98,7 +125,9 @@ export default function Items({ token }) {
|
||||||
// 2. If item creation is successful, upload the image
|
// 2. If item creation is successful, upload the image
|
||||||
if (newItemResponse.status === 200 && fileInputRef.current.files[0]) {
|
if (newItemResponse.status === 200 && fileInputRef.current.files[0]) {
|
||||||
const newItemId = newItemResponse.data.id;
|
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) {
|
if (uploadedImagePath) {
|
||||||
// console.log("Image path to save:", uploadedImagePath);
|
// console.log("Image path to save:", uploadedImagePath);
|
||||||
|
@ -249,6 +278,14 @@ export default function Items({ token }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<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>
|
<h2>Items in Box: {boxName === "Unknown Box" ? "All Boxes" : `${boxName} (${items.length} items)`}</h2>
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
|
@ -286,6 +323,7 @@ export default function Items({ token }) {
|
||||||
type="file"
|
type="file"
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
|
// capture="environment" // Capture the image from the user's camera
|
||||||
style={{ display: 'block', margin: '10px 0' }} // Style as needed
|
style={{ display: 'block', margin: '10px 0' }} // Style as needed
|
||||||
id="newItemImageUpload"
|
id="newItemImageUpload"
|
||||||
/>
|
/>
|
||||||
|
@ -307,13 +345,18 @@ export default function Items({ token }) {
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<List>
|
<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={
|
<ListItem key={item.ID} secondaryAction={
|
||||||
<>
|
<>
|
||||||
<IconButton edge="end" onClick={() => handleEditItem(item)}>
|
<IconButton edge="end" onClick={() => handleEditItem(item)}>
|
||||||
<EditIcon />
|
<EditIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton edge="end" onClick={() => handleDeleteItem(item.ID)}>
|
<IconButton edge="end" sx={{ marginLeft: 4 }} onClick={() => handleDeleteItem(item.ID)}>
|
||||||
<DeleteIcon />
|
<DeleteIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</>
|
</>
|
||||||
|
|
Loading…
Reference in New Issue