Skip to content

Commit a3df86a

Browse files
committed
feat: Add header and sidebar UI components with user profile management and authentication features.
1 parent 7655985 commit a3df86a

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

src/client/views/components/header.ejs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@
4646
</div>
4747
<div>
4848
<p id="user-name" class="text-sm font-semibold text-slate-900">User</p>
49-
<p id="user-email" class="text-xs text-slate-500">user@stackdev.cloud</p>
49+
<div class="flex items-center gap-2">
50+
<p id="user-email" class="text-xs text-slate-500">user@stackdev.cloud</p>
51+
<span id="user-role-badge" class="px-1.5 py-0.5 text-[10px] font-bold rounded uppercase tracking-wider bg-primary/10 text-primary">Role</span>
52+
</div>
5053
</div>
5154
</div>
5255
<div class="py-2">
@@ -85,6 +88,21 @@
8588
if (userName) userName.textContent = user.name;
8689
if (userEmail) userEmail.textContent = user.email || "";
8790
91+
const userRoleBadge = document.getElementById("user-role-badge");
92+
if (userRoleBadge) {
93+
const role = user.role || 'user';
94+
userRoleBadge.textContent = role === 'user' ? 'Author' : role;
95+
96+
// Simple color coding for roles
97+
if (role === 'admin') {
98+
userRoleBadge.className = "px-1.5 py-0.5 text-[10px] font-bold rounded uppercase tracking-wider bg-orange-100 text-orange-700";
99+
} else if (role === 'viewer') {
100+
userRoleBadge.className = "px-1.5 py-0.5 text-[10px] font-bold rounded uppercase tracking-wider bg-slate-100 text-slate-700";
101+
} else {
102+
userRoleBadge.className = "px-1.5 py-0.5 text-[10px] font-bold rounded uppercase tracking-wider bg-primary/10 text-primary";
103+
}
104+
}
105+
88106
const defaultAvatar = `https://ui-avatars.com/api/?name=${encodeURIComponent(user.name)}&background=0f766e&color=fff`;
89107
const avatarUrl = user.avatar || defaultAvatar;
90108

src/client/views/layouts/sidebar.ejs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111

1212
<nav class="space-y-1 mb-10">
1313
<% modules.forEach(function(module) {
14+
// Role-based visibility check
15+
if (module.roles && (!locals.user || !module.roles.includes(locals.user.role))) {
16+
return;
17+
}
18+
1419
const isActive = module.activeUrls
1520
? module.activeUrls.some(u => currentPath === u || currentPath.startsWith(u + '/'))
1621
: (currentPath === module.url || currentPath.startsWith(module.url + '/'));

src/client/views/pages/users.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ function renderUsers() {
193193
<td class="px-6 py-4 text-sm text-foreground/80">${user.email || '-'}</td>
194194
<td class="px-6 py-4">
195195
<span class="px-2 py-1 text-xs font-medium rounded-full ${getRoleBadgeClass(user.role)}">
196-
${user.role}
196+
${getRoleDisplayName(user.role)}
197197
</span>
198198
</td>
199199
<td class="px-6 py-4">
@@ -233,6 +233,11 @@ function getRoleBadgeClass(role: UserRole): string {
233233
return classes[role as keyof typeof classes] || classes.user;
234234
}
235235

236+
function getRoleDisplayName(role: UserRole): string {
237+
if (role === 'user') return 'Author';
238+
return role.charAt(0).toUpperCase() + role.slice(1);
239+
}
240+
236241
function formatDate(dateString?: string | null): string {
237242
if (!dateString) return 'Never';
238243
const date = new Date(dateString);

0 commit comments

Comments
 (0)