238 lines
7.6 KiB
React
238 lines
7.6 KiB
React
import React, { useEffect, useState } from "react";
|
|
import config from "../config";
|
|
|
|
const thStyle = {
|
|
padding: "0.75rem",
|
|
backgroundColor: "#333",
|
|
borderBottom: "1px solid #555",
|
|
color: "#fff",
|
|
position: "sticky",
|
|
top: 0,
|
|
zIndex: 1,
|
|
textAlign: "center",
|
|
};
|
|
|
|
const tdStyle = {
|
|
padding: "0.5rem 1rem",
|
|
borderBottom: "1px solid #444",
|
|
textAlign: "center",
|
|
color: "#fff",
|
|
};
|
|
|
|
const Dashboard = () => {
|
|
const [role, setRole] = useState("");
|
|
const [currentUser, setCurrentUser] = useState("");
|
|
const [users, setUsers] = useState([]);
|
|
const [newRoles, setNewRoles] = useState({});
|
|
const [selectedUsers, setSelectedUsers] = useState([]);
|
|
|
|
useEffect(() => {
|
|
const storedRole = localStorage.getItem("role");
|
|
const storedUsername = localStorage.getItem("username");
|
|
setRole(storedRole);
|
|
setCurrentUser(storedUsername);
|
|
|
|
if (storedRole === "SUPER") {
|
|
fetchUsers();
|
|
}
|
|
}, []);
|
|
|
|
const fetchUsers = async () => {
|
|
const token = localStorage.getItem("token");
|
|
|
|
try {
|
|
const res = await fetch(`${config.apiBaseUrl}/api/Auth/users`, {
|
|
headers: {
|
|
Authorization: `Bearer ${token}`,
|
|
},
|
|
});
|
|
|
|
if (!res.ok) throw new Error("Failed to fetch users");
|
|
|
|
const data = await res.json();
|
|
setUsers(data);
|
|
} catch (err) {
|
|
console.error("Error fetching users:", err);
|
|
}
|
|
};
|
|
|
|
const handleRoleChange = (username, value) => {
|
|
setNewRoles({ ...newRoles, [username]: value });
|
|
};
|
|
|
|
const updateUserRole = async (username) => {
|
|
const token = localStorage.getItem("token");
|
|
const newRole = newRoles[username];
|
|
|
|
try {
|
|
const res = await fetch(`${config.apiBaseUrl}/api/Auth/role`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Authorization: `Bearer ${token}`,
|
|
},
|
|
body: JSON.stringify({ username, newRole }),
|
|
});
|
|
|
|
if (!res.ok) throw new Error("Failed to update role");
|
|
|
|
fetchUsers();
|
|
} catch (err) {
|
|
console.error("Error updating role:", err);
|
|
}
|
|
};
|
|
|
|
const deleteUser = async (username) => {
|
|
if (!window.confirm(`Are you sure you want to delete ${username}?`)) return;
|
|
|
|
const token = localStorage.getItem("token");
|
|
|
|
try {
|
|
const res = await fetch(`${config.apiBaseUrl}/api/User?username=${encodeURIComponent(username)}`, {
|
|
method: "DELETE",
|
|
headers: {
|
|
Authorization: `Bearer ${token}`,
|
|
},
|
|
});
|
|
|
|
if (!res.ok) throw new Error("Failed to delete user");
|
|
|
|
fetchUsers();
|
|
} catch (err) {
|
|
console.error("Error deleting user:", err);
|
|
}
|
|
};
|
|
|
|
const toggleUserSelection = (username) => {
|
|
setSelectedUsers((prev) =>
|
|
prev.includes(username)
|
|
? prev.filter((u) => u !== username)
|
|
: [...prev, username]
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div style={{ color: "#fff", textAlign: "center", marginTop: "2rem" }}>
|
|
<h1>Dashboard</h1>
|
|
<p>Welcome! You are logged in.</p>
|
|
|
|
{role === "SUPER" && (
|
|
<>
|
|
<p style={{ fontWeight: "bold" }}>You are SUPER</p>
|
|
|
|
<div
|
|
style={{
|
|
maxHeight: "320px",
|
|
overflowY: "auto",
|
|
margin: "2rem auto 0 auto",
|
|
width: "fit-content",
|
|
border: "1px solid #444",
|
|
borderRadius: "4px",
|
|
}}
|
|
>
|
|
<table style={{ borderCollapse: "collapse", minWidth: "600px" }}>
|
|
<thead>
|
|
<tr>
|
|
<th style={thStyle}></th>
|
|
<th style={thStyle}>Username</th>
|
|
<th style={thStyle}>Role</th>
|
|
{selectedUsers.length > 0 && <th style={thStyle}>Action</th>}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{users
|
|
.filter((user) => user.username !== currentUser)
|
|
.map((user) => {
|
|
const isSelected = selectedUsers.includes(user.username);
|
|
const currentNewRole = newRoles[user.username] ?? user.role;
|
|
|
|
return (
|
|
<tr key={user.username}>
|
|
<td style={tdStyle}>
|
|
<input
|
|
type="checkbox"
|
|
checked={isSelected}
|
|
onChange={() => toggleUserSelection(user.username)}
|
|
/>
|
|
</td>
|
|
<td style={tdStyle}>{user.username}</td>
|
|
<td style={tdStyle}>
|
|
{isSelected ? (
|
|
<select
|
|
value={currentNewRole}
|
|
onChange={(e) =>
|
|
handleRoleChange(
|
|
user.username,
|
|
e.target.value
|
|
)
|
|
}
|
|
style={{
|
|
padding: "0.3rem",
|
|
backgroundColor: "#2a2a2a",
|
|
color: "#fff",
|
|
border: "1px solid #444",
|
|
}}
|
|
>
|
|
<option value="USER">USER</option>
|
|
<option value="SUPER">SUPER</option>
|
|
</select>
|
|
) : (
|
|
user.role
|
|
)}
|
|
</td>
|
|
{selectedUsers.length > 0 && (
|
|
<td style={tdStyle}>
|
|
{isSelected && (
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
gap: "0.5rem",
|
|
justifyContent: "center",
|
|
}}
|
|
>
|
|
<button
|
|
onClick={() =>
|
|
updateUserRole(user.username)
|
|
}
|
|
style={{
|
|
padding: "0.4rem 0.8rem",
|
|
backgroundColor: "#444",
|
|
color: "#fff",
|
|
border: "none",
|
|
borderRadius: "4px",
|
|
cursor: "pointer",
|
|
}}
|
|
>
|
|
Update
|
|
</button>
|
|
<button
|
|
onClick={() => deleteUser(user.username)}
|
|
style={{
|
|
padding: "0.4rem 0.8rem",
|
|
backgroundColor: "#aa3333",
|
|
color: "#fff",
|
|
border: "none",
|
|
borderRadius: "4px",
|
|
cursor: "pointer",
|
|
}}
|
|
>
|
|
Delete
|
|
</button>
|
|
</div>
|
|
)}
|
|
</td>
|
|
)}
|
|
</tr>
|
|
);
|
|
})}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Dashboard;
|