error-handling #1

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

View File

@ -40,24 +40,24 @@ function AppRoutes({ token, setToken }) {
return ( return (
<> <>
<Routes> <Routes>
<Route path="/login" element={<Login setToken={setToken} />} /> <Route path="/api/v1/login" element={<Login setToken={setToken} />} />
<Route <Route
path="/boxes" path="/api/v1/boxes"
element={token ? <Boxes token={token} /> : <Navigate to="/login" replace />} element={token ? <Boxes token={token} /> : <Navigate to="/api/v1/login" replace />}
/> />
<Route <Route
path="/items" path="/api/v1/items"
element={token ? <Items token={token} /> : <Navigate to="/login" replace />} element={token ? <Items token={token} /> : <Navigate to="/api/v1/login" replace />}
/> />
<Route <Route
path="/boxes/:id/items" path="/api/v1/boxes/:id/items"
element={token ? <Items box_id={id} token={token} /> : <Navigate to="/login" replace />} element={token ? <Items box_id={id} token={token} /> : <Navigate to="/api/v1/login" replace />}
/> />
<Route <Route
path="/admin" path="/api/v1/admin"
element={token ? <Admin token={token}/> : <Navigate to="/login" replace />} element={token ? <Admin token={token}/> : <Navigate to="/api/v1/login" replace />}
/> />
<Route path="*" element={<Navigate to={token ? "/boxes" : "/login"} replace />} /> <Route path="*" element={<Navigate to={token ? "/api/v1/boxes" : "/api/v1/login"} replace />} />
</Routes> </Routes>
</> </>
); );

View File

@ -32,7 +32,7 @@ export default function Admin() {
useEffect(() => { useEffect(() => {
axios.get(`${process.env.REACT_APP_API_URL}/admin/user`, { axios.get(`${process.env.REACT_APP_API_URL}/api/v1/admin/user`, {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` } headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
}) })
.then(response => { .then(response => {
@ -45,7 +45,7 @@ export default function Admin() {
const fetchUsers = async () => { const fetchUsers = async () => {
try { try {
const response = await axios.get(`${process.env.REACT_APP_API_URL}/admin/user`, { const response = await axios.get(`${process.env.REACT_APP_API_URL}/api/v1/admin/user`, {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` } headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
}); });
setUsers(response.data); setUsers(response.data);
@ -59,7 +59,7 @@ export default function Admin() {
const handleCreateUser = async (e) => { const handleCreateUser = async (e) => {
e.preventDefault(); e.preventDefault();
try { try {
const response = await axios.post(`${process.env.REACT_APP_API_URL}/admin/user`, { const response = await axios.post(`${process.env.REACT_APP_API_URL}/api/v1/admin/user`, {
username, username,
password, password,
email email
@ -77,7 +77,7 @@ export default function Admin() {
const handleDeleteUser = async (id) => { const handleDeleteUser = async (id) => {
try { try {
await axios.delete(`${process.env.REACT_APP_API_URL}/admin/user/${id}`, { await axios.delete(`${process.env.REACT_APP_API_URL}/api/v1/admin/user/${id}`, {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` } headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
}); });
setUsers(users.filter(user => user.id !== id)); setUsers(users.filter(user => user.id !== id));
@ -91,7 +91,7 @@ export default function Admin() {
const handleBackupDatabase = async () => { const handleBackupDatabase = async () => {
try { try {
const response = await axios.get(`${process.env.REACT_APP_API_URL}/admin/db`, { const response = await axios.get(`${process.env.REACT_APP_API_URL}/api/v1/admin/db`, {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }, headers: { Authorization: `Bearer ${localStorage.getItem('token')}` },
responseType: 'blob' responseType: 'blob'
}); });
@ -119,7 +119,7 @@ export default function Admin() {
throw new Error('No token found in local storage'); throw new Error('No token found in local storage');
} }
const response = await axios.post(`${process.env.REACT_APP_API_URL}/admin/db`, formData, { const response = await axios.post(`${process.env.REACT_APP_API_URL}/api/v1/admin/db`, formData, {
headers: { headers: {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
'Content-Type': 'multipart/form-data' 'Content-Type': 'multipart/form-data'

View File

@ -20,7 +20,7 @@ export default function Boxes({ token }) {
useEffect(() => { useEffect(() => {
//console.log('Token:' + token); //console.log('Token:' + token);
axios.get(`${process.env.REACT_APP_API_URL}/boxes`, { axios.get(`${process.env.REACT_APP_API_URL}/api/v1/boxes`, {
headers: { Authorization: `Bearer ${token}` } headers: { Authorization: `Bearer ${token}` }
}).then(response => { }).then(response => {
setBoxes(response.data); setBoxes(response.data);
@ -33,7 +33,7 @@ export default function Boxes({ token }) {
}, [boxes]); }, [boxes]);
const handleCreateBox = () => { const handleCreateBox = () => {
axios.post(`${process.env.REACT_APP_API_URL}/boxes`, { name: newBoxName }, { axios.post(`${process.env.REACT_APP_API_URL}/api/v1/boxes`, { name: newBoxName }, {
headers: { Authorization: `Bearer ${token}` } headers: { Authorization: `Bearer ${token}` }
}).then(response => { }).then(response => {
setBoxes([...boxes, response.data]); setBoxes([...boxes, response.data]);
@ -42,7 +42,7 @@ export default function Boxes({ token }) {
}; };
const handleDeleteBox = (id) => { const handleDeleteBox = (id) => {
axios.delete(`${process.env.REACT_APP_API_URL}/boxes/${id}`, { axios.delete(`${process.env.REACT_APP_API_URL}/api/v1/boxes/${id}`, {
headers: { Authorization: `Bearer ${token}` } headers: { Authorization: `Bearer ${token}` }
}).then(() => { }).then(() => {
setBoxes(boxes.filter(box => box.ID !== id)); setBoxes(boxes.filter(box => box.ID !== id));
@ -64,7 +64,7 @@ export default function Boxes({ token }) {
{boxes.map((box) => ( {boxes.map((box) => (
<TableRow key={box.ID}> <TableRow key={box.ID}>
<TableCell> <TableCell>
<RouterLink to={`/boxes/${box.ID}/items`} state={{ boxName: box.name, boxID: box.ID }}> <RouterLink to={`/api/v1/boxes/${box.ID}/items`} state={{ boxName: box.name, boxID: box.ID }}>
{box.name} {box.name}
</RouterLink> </RouterLink>
</TableCell> </TableCell>

View File

@ -25,7 +25,7 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
useEffect(() => { useEffect(() => {
const fetchBoxes = async () => { const fetchBoxes = async () => {
try { try {
const response = await axios.get(`${process.env.REACT_APP_API_URL}/boxes`, { const response = await axios.get(`${process.env.REACT_APP_API_URL}/api/v1/boxes`, {
headers: { Authorization: `Bearer ${token}` } headers: { Authorization: `Bearer ${token}` }
}); });
setBoxes(response.data); setBoxes(response.data);
@ -52,7 +52,7 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
console.error('Invalid boxId:', boxId); console.error('Invalid boxId:', boxId);
return; return;
} }
const response = await axios.get(`${process.env.REACT_APP_API_URL}/boxes/${boxIdNumber}`, { const response = await axios.get(`${process.env.REACT_APP_API_URL}/api/v1/boxes/${boxIdNumber}`, {
headers: { Authorization: `Bearer ${token}` } headers: { Authorization: `Bearer ${token}` }
}); });
setBoxName(response.data.name); setBoxName(response.data.name);
@ -73,7 +73,7 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
useEffect(() => { useEffect(() => {
// Function to fetch image similar to getImageSrc in Items.js // Function to fetch image similar to getImageSrc in Items.js
const getImageSrc = (itemId) => { const getImageSrc = (itemId) => {
return axios.get(`${process.env.REACT_APP_API_URL}/items/${itemId}/image`, { return axios.get(`${process.env.REACT_APP_API_URL}/api/v1/items/${itemId}/image`, {
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },
responseType: 'blob' responseType: 'blob'
}) })
@ -122,7 +122,7 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
formData.append('image', fileInputRef.current.files[0]); formData.append('image', fileInputRef.current.files[0]);
try { try {
const response = await axios.post(`${process.env.REACT_APP_API_URL}/items/${item.ID}/upload`, formData, { const response = await axios.post(`${process.env.REACT_APP_API_URL}/api/v1/items/${item.ID}/upload`, formData, {
headers: { headers: {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
'Content-Type': 'multipart/form-data' 'Content-Type': 'multipart/form-data'
@ -141,7 +141,7 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
const updateItemBoxId = async () => { const updateItemBoxId = async () => {
try { try {
// eslint-disable-next-line // 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}/api/v1/items/${item.id}`, {
box_id: selectedBoxId, box_id: selectedBoxId,
}, { }, {
headers: { Authorization: `Bearer ${token}` } headers: { Authorization: `Bearer ${token}` }
@ -164,7 +164,7 @@ export default function ItemDetails({ item, token, onSave, onClose, boxId }) {
// 2. Update item details (name, description, etc.) // 2. Update item details (name, description, etc.)
try { try {
await axios.put(`${process.env.REACT_APP_API_URL}/items/${item.ID}`, { await axios.put(`${process.env.REACT_APP_API_URL}/api/v1/items/${item.ID}`, {
name, name,
description, description,
box_id: +selectedBoxId, // Ensure the updated selected box is saved box_id: +selectedBoxId, // Ensure the updated selected box is saved

View File

@ -45,7 +45,7 @@ export default function Items({ token }) {
const [openAddItemDialog, setOpenAddItemDialog] = useState(false); // For Add Item dialog const [openAddItemDialog, setOpenAddItemDialog] = useState(false); // For Add Item dialog
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}/api/v1/items` : `${process.env.REACT_APP_API_URL}/api/v1/boxes/${boxId}/items`;
const [searchQuery, setSearchQuery] = useState(''); const [searchQuery, setSearchQuery] = useState('');
const debugLog = (message) => { const debugLog = (message) => {
@ -109,7 +109,7 @@ export default function Items({ token }) {
}); });
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}/api/v1/items/${itemId}/upload`, formData, {
headers: { headers: {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
'Content-Type': 'multipart/form-data' 'Content-Type': 'multipart/form-data'
@ -137,7 +137,7 @@ export default function Items({ token }) {
// This sends a request to the API to create a new item with the // This sends a request to the API to create a new item with the
// name and description provided. The box_id is set to the selected // name and description provided. The box_id is set to the selected
// box ID. // box ID.
const newItemResponse = await axios.post(`${process.env.REACT_APP_API_URL}/items`, { const newItemResponse = await axios.post(`${process.env.REACT_APP_API_URL}/api/v1/items`, {
name: newItemName, name: newItemName,
description: newItemDescription, description: newItemDescription,
box_id: parseInt(boxId, 10) // Ensure boxId is converted to an integer box_id: parseInt(boxId, 10) // Ensure boxId is converted to an integer
@ -218,7 +218,7 @@ export default function Items({ token }) {
}; };
const getImageSrc = useCallback((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}/api/v1/items/${itemId}/image`, {
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },
responseType: 'blob' responseType: 'blob'
}) })
@ -302,7 +302,7 @@ export default function Items({ token }) {
// }; // };
const handleDeleteItem = (itemId) => { const handleDeleteItem = (itemId) => {
axios.delete(`${process.env.REACT_APP_API_URL}/items/${itemId}`, { axios.delete(`${process.env.REACT_APP_API_URL}/api/v1/items/${itemId}`, {
headers: { Authorization: `Bearer ${token}` } headers: { Authorization: `Bearer ${token}` }
}).then(() => { }).then(() => {
fetchItems(); fetchItems();

View File

@ -16,7 +16,7 @@ export default function Login({ setToken }) {
setLoginError(false); // Reset error state on each login attempt setLoginError(false); // Reset error state on each login attempt
try { try {
// eslint-disable-next-line no-template-curly-in-string // eslint-disable-next-line no-template-curly-in-string
const response = await axios.post(`${process.env.REACT_APP_API_URL}/login`, { username, password }); const response = await axios.post(`${process.env.REACT_APP_API_URL}/api/v1/login`, { username, password });
setToken(response.data.token); setToken(response.data.token);
navigate('/boxes'); navigate('/boxes');
} catch (error) { } catch (error) {

View File

@ -33,10 +33,10 @@ export default function Navbar() {
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}> <Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Boxes Boxes
</Typography> </Typography>
<Button color="inherit" component={Link} to="/login">Login</Button> <Button color="inherit" component={Link} to="/api/v1/login">Login</Button>
<Button color="inherit" component={Link} to="/boxes">Boxes</Button> <Button color="inherit" component={Link} to="/api/v1/boxes">Boxes</Button>
<Button color="inherit" component={Link} to="/items">Items</Button> <Button color="inherit" component={Link} to="/api/v1/items">Items</Button>
<Button color="inherit" component={Link} to="/admin">Admin</Button> <Button color="inherit" component={Link} to="/api/v1/admin">Admin</Button>
<Button color="inherit" onClick={handleLogout}>Logout</Button> <Button color="inherit" onClick={handleLogout}>Logout</Button>
</Toolbar> </Toolbar>
</AppBar> </AppBar>