error-handling #1

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

View File

@ -6,6 +6,7 @@ import Login from './components/Login';
import Boxes from './components/Boxes';
import Items from './components/Items';
import Navbar from './components/Navbar'; // Correct import here
import Admin from './components/Admin'; // Correct import here
import { createContext } from 'react';
import './styles.css'
@ -52,6 +53,10 @@ function AppRoutes({ token, setToken }) {
path="/boxes/:id/items"
element={token ? <Items box_id={id} token={token} /> : <Navigate to="/login" replace />}
/>
<Route
path="/admin"
element={token ? <Admin token={token}/> : <Navigate to="/login" replace />}
/>
<Route path="*" element={<Navigate to={token ? "/boxes" : "/login"} replace />} />
</Routes>
</>

126
src/components/Admin.js Normal file
View File

@ -0,0 +1,126 @@
// src/components/Admin.js
import React, { useState, useEffect, useRef } from 'react';
import axios from 'axios';
import { Link, useNavigate } from 'react-router-dom';
import { PRIMARY_COLOR, SECONDARY_COLOR } from '../App';
export default function Admin() {
const [users, setUsers] = useState([]);
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate();
const fileInputRef = useRef(null);
useEffect(() => {
axios.get(`${process.env.REACT_APP_API_URL}/admin/user`, {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
})
.then(response => {
setUsers(response.data);
})
.catch(error => {
console.error(error);
});
}, []);
const handleCreateUser = async (e) => {
e.preventDefault();
try {
const response = await axios.post(`${process.env.REACT_APP_API_URL}/admin/user`, {
username,
password
}, {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
});
setUsers([...users, response.data]);
setUsername('');
setPassword('');
} catch (error) {
console.error(error);
}
};
const handleDeleteUser = async (id) => {
try {
await axios.delete(`${process.env.REACT_APP_API_URL}/admin/user/${id}`, {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
});
setUsers(users.filter(user => user.id !== id));
} catch (error) {
console.error(error);
}
};
const handleBackupDatabase = async () => {
try {
const response = await axios.get(`${process.env.REACT_APP_API_URL}/admin/db`, {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` },
responseType: 'blob'
});
const blob = new Blob([response.data], { type: 'application/x-sqlite3' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'database.db';
a.click();
} catch (error) {
console.error(error);
}
};
const handleRestoreDatabase = async (e) => {
e.preventDefault();
try {
const file = fileInputRef.current.files[0];
const formData = new FormData();
formData.append('database', file);
console.log("sending request to restore db")
const token = localStorage.getItem('token');
if (!token) {
throw new Error('No token found in local storage');
}
const response = await axios.post(`${process.env.REACT_APP_API_URL}/admin/db`, formData, {
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'multipart/form-data'
}
});
if (response.status === 200) {
alert('Database restored successfully');
navigate('/admin');
} else {
throw new Error(`Failed to restore database: ${response.statusText}`);
}
} catch (error) {
console.error(error);
}
};
return (
<div>
<h1>Admin</h1>
<ul>
{users.map(user => (
<li key={user.ID}>
{user.username}
<button onClick={() => handleDeleteUser(user.ID)}>Delete</button>
</li>
))}
</ul>
<form onSubmit={handleCreateUser}>
<input type="text" value={username} onChange={(e) => setUsername(e.target.value)} placeholder="Username" />
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" />
<button type="submit">Create User</button>
</form>
<button onClick={handleBackupDatabase}>Backup Database</button>
<form onSubmit={handleRestoreDatabase}>
<input type="file" ref={(fileInputRef)}/>
<button type="submit">Restore Database</button>
</form>
</div>
);
}

View File

@ -36,6 +36,7 @@ export default function Navbar() {
<Button color="inherit" component={Link} to="/login">Login</Button>
<Button color="inherit" component={Link} to="/boxes">Boxes</Button>
<Button color="inherit" component={Link} to="/items">Items</Button>
<Button color="inherit" component={Link} to="/admin">Admin</Button>
<Button color="inherit" onClick={handleLogout}>Logout</Button>
</Toolbar>
</AppBar>