Skip to content

Commit f70820f

Browse files
author
Uttam Singh
committed
feat: add Users tab and improved AdminDashboard layout
1 parent 80c2a0a commit f70820f

File tree

1 file changed

+175
-123
lines changed

1 file changed

+175
-123
lines changed

frontend/src/pages/AdminDashboard.jsx

Lines changed: 175 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,22 @@ export default function AdminDashboard() {
1111
});
1212

1313
const [message, setMessage] = useState("");
14+
const [users, setUsers] = useState([]);
1415
const [dropdownOpen, setDropdownOpen] = useState(false);
1516
const [isCompact, setIsCompact] = useState(false);
17+
const [activeTab, setActiveTab] = useState("Dashboard");
1618
const dropdownRef = useRef(null);
17-
const [logoSrc, setLogoSrc] = useState(""); // ✅ Dynamic logo handler
19+
const [logoSrc, setLogoSrc] = useState("");
1820

1921
// === Logo handling ===
2022
useEffect(() => {
2123
const logoPath = `${import.meta.env.BASE_URL || "/"}edme_logo.png`;
22-
23-
// Check if logo exists on Render
2424
fetch(logoPath)
2525
.then((res) => {
2626
if (res.ok) setLogoSrc(logoPath);
2727
else throw new Error("Logo not found");
2828
})
2929
.catch(() => {
30-
// fallback hosted logo
3130
setLogoSrc(
3231
"https://upload.wikimedia.org/wikipedia/commons/f/fc/Edme_logo_placeholder.png"
3332
);
@@ -53,6 +52,7 @@ export default function AdminDashboard() {
5352
const data = await res.json();
5453
if (data.ok) {
5554
setMessage("✅ User created successfully!");
55+
fetchUsers();
5656
setFormData({
5757
name: "",
5858
email: "",
@@ -69,6 +69,25 @@ export default function AdminDashboard() {
6969
}
7070
};
7171

72+
// === Fetch Users ===
73+
const fetchUsers = async () => {
74+
try {
75+
const res = await fetch(
76+
"https://fat-eibl-backend-x1sp.onrender.com/users/all"
77+
);
78+
const data = await res.json();
79+
if (data.ok) setUsers(data.users);
80+
else setUsers([]);
81+
} catch (e) {
82+
console.error(e);
83+
setUsers([]);
84+
}
85+
};
86+
87+
useEffect(() => {
88+
fetchUsers();
89+
}, []);
90+
7291
// === Handle Dropdown ===
7392
useEffect(() => {
7493
const handleClickOutside = (event) => {
@@ -123,15 +142,17 @@ export default function AdminDashboard() {
123142
</div>
124143

125144
<nav style={styles.navCenter}>
126-
{["Dashboard", "Users", "Departments", "Reports", "Settings"].map(
127-
(link, i) => (
128-
<a
145+
{["Dashboard", "Users", "Departments", "Reports"].map(
146+
(tab, i) => (
147+
<span
129148
key={i}
130-
href="#"
131-
style={i === 0 ? styles.activeLink : styles.navLink}
149+
style={
150+
activeTab === tab ? styles.activeLink : styles.navLink
151+
}
152+
onClick={() => setActiveTab(tab)}
132153
>
133-
{link}
134-
</a>
154+
{tab}
155+
</span>
135156
)
136157
)}
137158
</nav>
@@ -162,98 +183,135 @@ export default function AdminDashboard() {
162183

163184
{/* === MAIN CONTENT === */}
164185
<main style={styles.main}>
165-
<h1 style={styles.title}>Admin Dashboard</h1>
186+
<h1 style={styles.title}>{activeTab}</h1>
166187
<p style={styles.subtitle}>
167-
Manage users, departments, and system access.
188+
{activeTab === "Dashboard"
189+
? "Manage users, departments, and system access."
190+
: activeTab === "Users"
191+
? "View and manage registered users."
192+
: ""}
168193
</p>
169194

170-
{/* === CREATE USER CARD === */}
171-
<div style={styles.card}>
172-
<h2 style={styles.cardTitle}>Create New User</h2>
173-
<form onSubmit={handleSubmit} style={styles.form}>
174-
<div style={styles.row}>
175-
<input
176-
type="text"
177-
name="name"
178-
placeholder="Full Name"
179-
value={formData.name}
180-
onChange={handleChange}
181-
style={styles.input}
182-
required
183-
/>
184-
<input
185-
type="email"
186-
name="email"
187-
placeholder="Email"
188-
value={formData.email}
189-
onChange={handleChange}
190-
style={styles.input}
191-
required
192-
/>
193-
</div>
195+
{/* === DASHBOARD === */}
196+
{activeTab === "Dashboard" && (
197+
<div style={styles.card}>
198+
<h2 style={styles.cardTitle}>Create New User</h2>
199+
<form onSubmit={handleSubmit} style={styles.form}>
200+
<div style={styles.row}>
201+
<input
202+
type="text"
203+
name="name"
204+
placeholder="Full Name"
205+
value={formData.name}
206+
onChange={handleChange}
207+
style={styles.input}
208+
required
209+
/>
210+
<input
211+
type="email"
212+
name="email"
213+
placeholder="Email"
214+
value={formData.email}
215+
onChange={handleChange}
216+
style={styles.input}
217+
required
218+
/>
219+
</div>
194220

195-
<div style={styles.row}>
196-
<input
197-
type="password"
198-
name="password"
199-
placeholder="Password"
200-
value={formData.password}
201-
onChange={handleChange}
202-
style={styles.input}
203-
required
204-
/>
205-
<input
206-
type="text"
207-
name="department"
208-
placeholder="Department"
209-
value={formData.department}
210-
onChange={handleChange}
211-
style={styles.input}
212-
/>
213-
</div>
221+
<div style={styles.row}>
222+
<input
223+
type="password"
224+
name="password"
225+
placeholder="Password"
226+
value={formData.password}
227+
onChange={handleChange}
228+
style={styles.input}
229+
required
230+
/>
231+
<input
232+
type="text"
233+
name="department"
234+
placeholder="Department"
235+
value={formData.department}
236+
onChange={handleChange}
237+
style={styles.input}
238+
/>
239+
</div>
214240

215-
<div style={styles.row}>
216-
<input
217-
type="email"
218-
name="manager_email"
219-
placeholder="Manager Email"
220-
value={formData.manager_email}
221-
onChange={handleChange}
222-
style={styles.input}
223-
/>
224-
<select
225-
name="role"
226-
value={formData.role}
227-
onChange={handleChange}
228-
style={styles.select}
229-
>
230-
<option value="auditee">Auditee</option>
231-
<option value="auditor">Auditor</option>
232-
<option value="admin">Admin</option>
233-
</select>
234-
</div>
241+
<div style={styles.row}>
242+
<input
243+
type="email"
244+
name="manager_email"
245+
placeholder="Manager Email"
246+
value={formData.manager_email}
247+
onChange={handleChange}
248+
style={styles.input}
249+
/>
250+
<select
251+
name="role"
252+
value={formData.role}
253+
onChange={handleChange}
254+
style={styles.select}
255+
>
256+
<option value="auditee">Auditee</option>
257+
<option value="auditor">Auditor</option>
258+
<option value="admin">Admin</option>
259+
</select>
260+
</div>
261+
262+
<button type="submit" style={styles.button}>
263+
Create User
264+
</button>
265+
</form>
235266

236-
<button type="submit" style={styles.button}>
237-
Create User
238-
</button>
239-
</form>
267+
{message && (
268+
<p
269+
style={{
270+
marginTop: "15px",
271+
textAlign: "center",
272+
color: message.startsWith("✅")
273+
? "green"
274+
: message.startsWith("⚠️")
275+
? "#c27b00"
276+
: "red",
277+
}}
278+
>
279+
{message}
280+
</p>
281+
)}
282+
</div>
283+
)}
240284

241-
{message && (
242-
<p
243-
style={{
244-
marginTop: "15px",
245-
textAlign: "center",
246-
color: message.startsWith("✅")
247-
? "green"
248-
: message.startsWith("⚠️")
249-
? "#c27b00"
250-
: "red",
251-
}}
252-
>
253-
{message}
254-
</p>
255-
)}
256-
</div>
285+
{/* === USERS TAB === */}
286+
{activeTab === "Users" && (
287+
<div style={styles.card}>
288+
<h2 style={styles.cardTitle}>Registered Users</h2>
289+
{users.length === 0 ? (
290+
<p style={{ color: "#6b7a99" }}>No users found.</p>
291+
) : (
292+
<table style={styles.table}>
293+
<thead>
294+
<tr>
295+
<th>Name</th>
296+
<th>Email</th>
297+
<th>Department</th>
298+
<th>Role</th>
299+
</tr>
300+
</thead>
301+
<tbody>
302+
{users.map((u, i) => (
303+
<tr key={i}>
304+
<td>{u.name}</td>
305+
<td>{u.email}</td>
306+
<td>{u.department || "-"}</td>
307+
<td>{u.role}</td>
308+
</tr>
309+
))}
310+
</tbody>
311+
</table>
312+
)}
313+
</div>
314+
)}
257315
</main>
258316
</div>
259317
);
@@ -284,7 +342,7 @@ const styles = {
284342
objectFit: "contain",
285343
},
286344
brand: { fontSize: "1.3rem", fontWeight: "700", color: "#fff" },
287-
navCenter: { display: "flex", gap: "25px" },
345+
navCenter: { display: "flex", gap: "25px", cursor: "pointer" },
288346
navLink: {
289347
color: "#dce7ff",
290348
textDecoration: "none",
@@ -297,8 +355,18 @@ const styles = {
297355
paddingBottom: "2px",
298356
},
299357
userMenu: { position: "relative" },
300-
userWrapper: { display: "flex", alignItems: "center", gap: "8px", cursor: "pointer" },
301-
avatar: { width: "40px", height: "40px", borderRadius: "50%", border: "2px solid #fff" },
358+
userWrapper: {
359+
display: "flex",
360+
alignItems: "center",
361+
gap: "8px",
362+
cursor: "pointer",
363+
},
364+
avatar: {
365+
width: "40px",
366+
height: "40px",
367+
borderRadius: "50%",
368+
border: "2px solid #fff",
369+
},
302370
userName: { color: "#fff", fontWeight: "500" },
303371
dropdown: {
304372
position: "absolute",
@@ -337,30 +405,14 @@ const styles = {
337405
display: "inline-block",
338406
marginBottom: "20px",
339407
},
340-
form: { display: "flex", flexDirection: "column", gap: "15px" },
341-
row: { display: "flex", gap: "15px", flexWrap: "wrap" },
342-
input: {
343-
flex: 1,
344-
padding: "12px",
345-
borderRadius: "8px",
346-
border: "1px solid #d0d7e2",
347-
fontSize: "1rem",
348-
},
349-
select: {
350-
flex: 1,
351-
padding: "12px",
352-
borderRadius: "8px",
353-
border: "1px solid #d0d7e2",
354-
fontSize: "1rem",
408+
table: {
409+
width: "100%",
410+
borderCollapse: "collapse",
411+
marginTop: "15px",
355412
},
356-
button: {
357-
background: "#004aad",
358-
color: "white",
359-
border: "none",
360-
padding: "12px",
361-
borderRadius: "8px",
362-
fontSize: "1rem",
363-
fontWeight: "600",
364-
cursor: "pointer",
413+
"table th, table td": {
414+
padding: "10px",
415+
borderBottom: "1px solid #e5e7eb",
416+
textAlign: "left",
365417
},
366418
};

0 commit comments

Comments
 (0)