generated from nhcarrigan/template
feat: user menu
This commit is contained in:
@@ -35,17 +35,30 @@ import { ApiService } from '../../services/api.service';
|
|||||||
|
|
||||||
<div class="auth-section">
|
<div class="auth-section">
|
||||||
@if (authService.user(); as user) {
|
@if (authService.user(); as user) {
|
||||||
<span class="welcome">Welcome, {{ user.username }}!</span>
|
<div class="user-menu">
|
||||||
|
@if (user.avatar) {
|
||||||
|
<img
|
||||||
|
[src]="user.avatar"
|
||||||
|
[alt]="user.username"
|
||||||
|
class="user-avatar"
|
||||||
|
(click)="toggleDropdown()"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
@if (showDropdown()) {
|
||||||
|
<div class="dropdown-menu">
|
||||||
@if (!user.isAdmin) {
|
@if (!user.isAdmin) {
|
||||||
<a routerLink="/my-suggestions" class="user-link">My Suggestions</a>
|
<a routerLink="/my-suggestions" class="dropdown-item" (click)="closeDropdown()">My Suggestions</a>
|
||||||
}
|
}
|
||||||
<a routerLink="/my-likes" class="user-link">My Likes</a>
|
<a routerLink="/my-likes" class="dropdown-item" (click)="closeDropdown()">My Likes</a>
|
||||||
@if (user.isAdmin) {
|
@if (user.isAdmin) {
|
||||||
<a routerLink="/admin/users" class="admin-badge">Users</a>
|
<a routerLink="/admin/users" class="dropdown-item" (click)="closeDropdown()">Users</a>
|
||||||
<a routerLink="/admin/audit" class="admin-badge">Audit</a>
|
<a routerLink="/admin/audit" class="dropdown-item" (click)="closeDropdown()">Audit</a>
|
||||||
<a routerLink="/admin/suggestions" class="admin-badge">Suggestions</a>
|
<a routerLink="/admin/suggestions" class="dropdown-item" (click)="closeDropdown()">Suggestions</a>
|
||||||
}
|
}
|
||||||
<button (click)="logout()" class="btn btn-secondary">Logout</button>
|
<button (click)="logout()" class="dropdown-item logout-btn">Logout</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
<button (click)="login()" class="btn btn-primary">Login with Discord</button>
|
<button (click)="login()" class="btn btn-primary">Login with Discord</button>
|
||||||
}
|
}
|
||||||
@@ -122,6 +135,75 @@ import { ApiService } from '../../services/api.service';
|
|||||||
color: var(--witch-lavender);
|
color: var(--witch-lavender);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.user-menu {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid var(--witch-lavender);
|
||||||
|
transition: all 0.3s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-avatar:hover {
|
||||||
|
border-color: var(--witch-moon);
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
position: absolute;
|
||||||
|
top: 50px;
|
||||||
|
right: 0;
|
||||||
|
background-color: var(--witch-purple);
|
||||||
|
border: 2px solid var(--witch-lavender);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
min-width: 180px;
|
||||||
|
box-shadow: 0 4px 12px var(--witch-shadow);
|
||||||
|
z-index: 1000;
|
||||||
|
animation: fadeIn 0.2s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
color: var(--witch-lavender);
|
||||||
|
text-decoration: none;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item:hover {
|
||||||
|
background-color: var(--witch-plum);
|
||||||
|
color: var(--witch-moon);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-btn {
|
||||||
|
border-top: 1px solid var(--witch-lavender);
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
.admin-badge {
|
.admin-badge {
|
||||||
background-color: var(--witch-rose);
|
background-color: var(--witch-rose);
|
||||||
color: var(--witch-moon);
|
color: var(--witch-moon);
|
||||||
@@ -190,6 +272,7 @@ export class HeaderComponent implements OnInit {
|
|||||||
authService = inject(AuthService);
|
authService = inject(AuthService);
|
||||||
private apiService = inject(ApiService);
|
private apiService = inject(ApiService);
|
||||||
version = signal<string | null>(null);
|
version = signal<string | null>(null);
|
||||||
|
showDropdown = signal<boolean>(false);
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.apiService.get<{ version: string }>('/version').subscribe({
|
this.apiService.get<{ version: string }>('/version').subscribe({
|
||||||
@@ -198,11 +281,20 @@ export class HeaderComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleDropdown() {
|
||||||
|
this.showDropdown.update(v => !v);
|
||||||
|
}
|
||||||
|
|
||||||
|
closeDropdown() {
|
||||||
|
this.showDropdown.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
login() {
|
login() {
|
||||||
this.authService.login();
|
this.authService.login();
|
||||||
}
|
}
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
|
this.closeDropdown();
|
||||||
this.authService.logout().subscribe();
|
this.authService.logout().subscribe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user