Adding users grid, allowing the change of user roles
This commit is contained in:
+170
-4
@@ -1,20 +1,186 @@
|
|||||||
import React, { useEffect, useState } from "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 Dashboard = () => {
|
||||||
const [role, setRole] = useState("");
|
const [role, setRole] = useState("");
|
||||||
|
const [users, setUsers] = useState([]);
|
||||||
|
const [newRoles, setNewRoles] = useState({});
|
||||||
|
const [selectedUsers, setSelectedUsers] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const role = localStorage.getItem("role");
|
const currentRole = localStorage.getItem("role");
|
||||||
if (role) {
|
setRole(currentRole);
|
||||||
setRole(role);
|
|
||||||
|
if (currentRole === "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 toggleUserSelection = (username) => {
|
||||||
|
setSelectedUsers((prev) =>
|
||||||
|
prev.includes(username)
|
||||||
|
? prev.filter((u) => u !== username)
|
||||||
|
: [...prev, username]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ color: "#fff", textAlign: "center", marginTop: "2rem" }}>
|
<div style={{ color: "#fff", textAlign: "center", marginTop: "2rem" }}>
|
||||||
<h1>Dashboard</h1>
|
<h1>Dashboard</h1>
|
||||||
<p>Welcome! You are logged in.</p>
|
<p>Welcome! You are logged in.</p>
|
||||||
{role === "SUPER" && <p style={{ fontWeight: "bold" }}>You are SUPER</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.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 && (
|
||||||
|
<button
|
||||||
|
onClick={() => updateUserRole(user.username)}
|
||||||
|
style={{
|
||||||
|
padding: "0.4rem 0.8rem",
|
||||||
|
backgroundColor: "#444",
|
||||||
|
color: "#fff",
|
||||||
|
border: "none",
|
||||||
|
borderRadius: "4px",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
)}
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user