235 lines
6.7 KiB
JavaScript
235 lines
6.7 KiB
JavaScript
// 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';
|
|
import './Admin.css'; // Import the CSS file
|
|
import {
|
|
Typography,
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableContainer,
|
|
TableHead,
|
|
TableRow,
|
|
Paper,
|
|
Button,
|
|
Alert,
|
|
Container,
|
|
Box,
|
|
TextField,
|
|
Tab
|
|
} from '@mui/material';
|
|
|
|
|
|
export default function Admin() {
|
|
const [users, setUsers] = useState([]);
|
|
const [username, setUsername] = useState('');
|
|
const [email, setEmail] = 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 fetchUsers = async () => {
|
|
try {
|
|
const response = await axios.get(`${process.env.REACT_APP_API_URL}/admin/user`, {
|
|
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
|
|
});
|
|
setUsers(response.data);
|
|
} catch (error) {
|
|
console.error('Error fetching users:', error);
|
|
// Optionally, set an error message
|
|
// setErrorMessage('Failed to fetch users. Please try again.');
|
|
}
|
|
};
|
|
|
|
const handleCreateUser = async (e) => {
|
|
e.preventDefault();
|
|
try {
|
|
const response = await axios.post(`${process.env.REACT_APP_API_URL}/admin/user`, {
|
|
username,
|
|
password,
|
|
email
|
|
}, {
|
|
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
|
|
});
|
|
setUsers([...users, response.data]);
|
|
setUsername('');
|
|
setPassword('');
|
|
setEmail('');
|
|
} 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));
|
|
//setUsers(prevUsers => prevUsers.filter(user => user.id !== id));
|
|
fetchUsers();
|
|
|
|
} 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 (
|
|
<Container maxWidth="md">
|
|
<Typography variant="h4" gutterBottom>
|
|
Admin
|
|
</Typography>
|
|
|
|
<Box component="form" onSubmit={handleCreateUser} sx={{ mb: 4 }}>
|
|
<Typography variant="h6" gutterBottom>
|
|
Add New User
|
|
</Typography>
|
|
<TextField
|
|
label="Username"
|
|
variant="outlined"
|
|
value={username}
|
|
onChange={(e) => setUsername(e.target.value)}
|
|
sx={{ mr: 2 }}
|
|
/>
|
|
<TextField
|
|
label="Password"
|
|
type="password"
|
|
variant="outlined"
|
|
value={password}
|
|
onChange={(e) => setPassword(e.target.value)}
|
|
sx={{ mr: 2 }}
|
|
/>
|
|
<TextField
|
|
label="Email"
|
|
variant="outlined"
|
|
value={email}
|
|
onChange={(e) => setEmail(e.target.value)}
|
|
sx={{ mr: 2 }}
|
|
/>
|
|
<Button type="submit" sx={{ backgroundColor: PRIMARY_COLOR, borderBottom: '1px solid', borderColor: '#444', color: SECONDARY_COLOR }} variant="contained" color="primary">
|
|
Add User
|
|
</Button>
|
|
</Box>
|
|
|
|
<TableContainer component={Paper}>
|
|
<Table>
|
|
<TableHead>
|
|
<TableRow>
|
|
<TableCell>ID</TableCell>
|
|
<TableCell>Username</TableCell>
|
|
<TableCell>Email</TableCell>
|
|
<TableCell>Actions</TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{users.map(user => (
|
|
<TableRow key={user.ID}>
|
|
<TableCell style={{ width: '30px' }}>{user.ID}</TableCell>
|
|
<TableCell style={{ width: '100px'}}>{user.username}</TableCell>
|
|
<TableCell style={{ width: '300px'}}>{user.email}</TableCell>
|
|
<TableCell>
|
|
<Button
|
|
variant="contained"
|
|
color="error"
|
|
onClick={() => handleDeleteUser(user.ID)}
|
|
>
|
|
Delete User
|
|
</Button>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</TableContainer>
|
|
|
|
<Box sx={{ mt: 4 }}>
|
|
<Button
|
|
variant="contained"
|
|
color="primary"
|
|
onClick={handleBackupDatabase}
|
|
sx={{ mr: 2, backgroundColor: PRIMARY_COLOR, borderBottom: '1px solid', borderColor: '#444', color: SECONDARY_COLOR }}
|
|
>
|
|
Backup Database
|
|
</Button>
|
|
|
|
<Button
|
|
variant="contained"
|
|
color="secondary"
|
|
component="label"
|
|
sx={{ backgroundColor: PRIMARY_COLOR, borderBottom: '1px solid', borderColor: '#444', color: SECONDARY_COLOR }}
|
|
>
|
|
Restore Database
|
|
<input
|
|
type="file"
|
|
hidden
|
|
ref={fileInputRef}
|
|
onChange={handleRestoreDatabase}
|
|
/>
|
|
</Button>
|
|
</Box>
|
|
</Container>
|
|
);
|
|
} |