error-handling #1
|
@ -6,6 +6,7 @@ import Login from './components/Login';
|
||||||
import Boxes from './components/Boxes';
|
import Boxes from './components/Boxes';
|
||||||
import Items from './components/Items';
|
import Items from './components/Items';
|
||||||
import Navbar from './components/Navbar'; // Correct import here
|
import Navbar from './components/Navbar'; // Correct import here
|
||||||
|
import Admin from './components/Admin'; // Correct import here
|
||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
import './styles.css'
|
import './styles.css'
|
||||||
|
|
||||||
|
@ -52,6 +53,10 @@ function AppRoutes({ token, setToken }) {
|
||||||
path="/boxes/:id/items"
|
path="/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="/login" replace />}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path="/admin"
|
||||||
|
element={token ? <Admin token={token}/> : <Navigate to="/login" replace />}
|
||||||
|
/>
|
||||||
<Route path="*" element={<Navigate to={token ? "/boxes" : "/login"} replace />} />
|
<Route path="*" element={<Navigate to={token ? "/boxes" : "/login"} replace />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -36,6 +36,7 @@ export default function Navbar() {
|
||||||
<Button color="inherit" component={Link} to="/login">Login</Button>
|
<Button color="inherit" component={Link} to="/login">Login</Button>
|
||||||
<Button color="inherit" component={Link} to="/boxes">Boxes</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="/items">Items</Button>
|
||||||
|
<Button color="inherit" component={Link} to="/admin">Admin</Button>
|
||||||
<Button color="inherit" onClick={handleLogout}>Logout</Button>
|
<Button color="inherit" onClick={handleLogout}>Logout</Button>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
|
|
Loading…
Reference in New Issue