261 lines
8.8 KiB
HTML
261 lines
8.8 KiB
HTML
|
|
<!-- Skip to main content - GIGW 3.0 Accessibility -->
|
||
|
|
<a href="#main-content" class="skip-link">Skip to main content</a>
|
||
|
|
|
||
|
|
<div class="app-shell">
|
||
|
|
<!-- Sidebar -->
|
||
|
|
<aside
|
||
|
|
class="sidebar"
|
||
|
|
[class.sidebar-collapsed]="!sidenavOpened()"
|
||
|
|
role="navigation"
|
||
|
|
aria-label="Main navigation"
|
||
|
|
>
|
||
|
|
<!-- Logo Section -->
|
||
|
|
<div class="sidebar-header">
|
||
|
|
<div class="logo-section">
|
||
|
|
<div class="emblem-container">
|
||
|
|
<img
|
||
|
|
src="assets/images/goa-emblem.svg"
|
||
|
|
alt="Government of Goa Emblem"
|
||
|
|
class="goa-emblem"
|
||
|
|
onerror="this.style.display='none'"
|
||
|
|
/>
|
||
|
|
<div class="emblem-fallback" *ngIf="!emblemLoaded">
|
||
|
|
<mat-icon>account_balance</mat-icon>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
@if (sidenavOpened()) {
|
||
|
|
<div class="logo-text">
|
||
|
|
<span class="govt-text">Government of Goa</span>
|
||
|
|
<span class="platform-text">Blockchain e-Licensing</span>
|
||
|
|
</div>
|
||
|
|
}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Navigation Links -->
|
||
|
|
<nav class="sidebar-nav">
|
||
|
|
<div class="nav-section">
|
||
|
|
@if (sidenavOpened()) {
|
||
|
|
<span class="nav-section-title">Main Menu</span>
|
||
|
|
}
|
||
|
|
@for (item of visibleNavItems(); track item.route) {
|
||
|
|
<a
|
||
|
|
class="nav-item"
|
||
|
|
[routerLink]="item.route"
|
||
|
|
routerLinkActive="active"
|
||
|
|
[routerLinkActiveOptions]="{ exact: item.route === '/dashboard' }"
|
||
|
|
[attr.aria-label]="item.label"
|
||
|
|
[matTooltip]="!sidenavOpened() ? item.label : ''"
|
||
|
|
matTooltipPosition="right"
|
||
|
|
>
|
||
|
|
<div class="nav-icon">
|
||
|
|
<mat-icon>{{ item.icon }}</mat-icon>
|
||
|
|
</div>
|
||
|
|
@if (sidenavOpened()) {
|
||
|
|
<span class="nav-label">{{ item.label }}</span>
|
||
|
|
}
|
||
|
|
@if (item.badge && item.badge() > 0) {
|
||
|
|
<span class="nav-badge" [class.pulse]="item.badge() > 0">
|
||
|
|
{{ item.badge() }}
|
||
|
|
</span>
|
||
|
|
}
|
||
|
|
</a>
|
||
|
|
}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
@if (userType() === 'ADMIN') {
|
||
|
|
<div class="nav-section">
|
||
|
|
@if (sidenavOpened()) {
|
||
|
|
<span class="nav-section-title">Administration</span>
|
||
|
|
}
|
||
|
|
<a
|
||
|
|
class="nav-item"
|
||
|
|
routerLink="/admin"
|
||
|
|
routerLinkActive="active"
|
||
|
|
[matTooltip]="!sidenavOpened() ? 'Admin Portal' : ''"
|
||
|
|
matTooltipPosition="right"
|
||
|
|
>
|
||
|
|
<div class="nav-icon">
|
||
|
|
<mat-icon>admin_panel_settings</mat-icon>
|
||
|
|
</div>
|
||
|
|
@if (sidenavOpened()) {
|
||
|
|
<span class="nav-label">Admin Portal</span>
|
||
|
|
}
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
}
|
||
|
|
</nav>
|
||
|
|
|
||
|
|
<!-- Sidebar Footer -->
|
||
|
|
<div class="sidebar-footer">
|
||
|
|
@if (sidenavOpened()) {
|
||
|
|
<div class="blockchain-status">
|
||
|
|
<div class="status-indicator online"></div>
|
||
|
|
<div class="status-text">
|
||
|
|
<span class="status-label">Blockchain</span>
|
||
|
|
<span class="status-value">Connected</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
} @else {
|
||
|
|
<div class="blockchain-status-compact">
|
||
|
|
<div class="status-indicator online"></div>
|
||
|
|
</div>
|
||
|
|
}
|
||
|
|
</div>
|
||
|
|
</aside>
|
||
|
|
|
||
|
|
<!-- Main Content Area -->
|
||
|
|
<div class="main-wrapper">
|
||
|
|
<!-- Top Header -->
|
||
|
|
<header class="top-header" role="banner">
|
||
|
|
<div class="header-left">
|
||
|
|
<button
|
||
|
|
mat-icon-button
|
||
|
|
(click)="toggleSidenav()"
|
||
|
|
aria-label="Toggle navigation menu"
|
||
|
|
class="menu-toggle"
|
||
|
|
>
|
||
|
|
<mat-icon>{{ sidenavOpened() ? 'menu_open' : 'menu' }}</mat-icon>
|
||
|
|
</button>
|
||
|
|
|
||
|
|
<!-- Breadcrumb (optional) -->
|
||
|
|
<nav class="breadcrumb hide-mobile" aria-label="Breadcrumb">
|
||
|
|
<span class="breadcrumb-item">Dashboard</span>
|
||
|
|
</nav>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="header-right">
|
||
|
|
<!-- Search (optional) -->
|
||
|
|
<button mat-icon-button class="header-action hide-mobile" aria-label="Search">
|
||
|
|
<mat-icon>search</mat-icon>
|
||
|
|
</button>
|
||
|
|
|
||
|
|
<!-- Notifications -->
|
||
|
|
<button
|
||
|
|
mat-icon-button
|
||
|
|
class="header-action"
|
||
|
|
[matMenuTriggerFor]="notificationMenu"
|
||
|
|
aria-label="Notifications"
|
||
|
|
>
|
||
|
|
<mat-icon [matBadge]="unreadNotifications()" matBadgeColor="warn" matBadgeSize="small">
|
||
|
|
notifications
|
||
|
|
</mat-icon>
|
||
|
|
</button>
|
||
|
|
|
||
|
|
<mat-menu #notificationMenu="matMenu" class="notification-menu">
|
||
|
|
<div class="notification-header">
|
||
|
|
<span class="notification-title">Notifications</span>
|
||
|
|
<button mat-button color="primary" class="mark-read-btn">Mark all read</button>
|
||
|
|
</div>
|
||
|
|
<mat-divider></mat-divider>
|
||
|
|
<div class="notification-list">
|
||
|
|
<div class="notification-item unread">
|
||
|
|
<div class="notification-icon success">
|
||
|
|
<mat-icon>check_circle</mat-icon>
|
||
|
|
</div>
|
||
|
|
<div class="notification-content">
|
||
|
|
<span class="notification-text">Request #1234 approved</span>
|
||
|
|
<span class="notification-time">2 minutes ago</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="notification-item">
|
||
|
|
<div class="notification-icon info">
|
||
|
|
<mat-icon>info</mat-icon>
|
||
|
|
</div>
|
||
|
|
<div class="notification-content">
|
||
|
|
<span class="notification-text">New document uploaded</span>
|
||
|
|
<span class="notification-time">1 hour ago</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<mat-divider></mat-divider>
|
||
|
|
<button mat-menu-item class="view-all-btn">
|
||
|
|
View all notifications
|
||
|
|
</button>
|
||
|
|
</mat-menu>
|
||
|
|
|
||
|
|
<!-- User Profile -->
|
||
|
|
<div class="user-profile">
|
||
|
|
<button
|
||
|
|
mat-button
|
||
|
|
[matMenuTriggerFor]="userMenu"
|
||
|
|
class="user-button"
|
||
|
|
aria-label="User menu"
|
||
|
|
>
|
||
|
|
<div class="user-avatar" [style.background]="getAvatarColor()">
|
||
|
|
{{ getUserInitials() }}
|
||
|
|
</div>
|
||
|
|
@if (currentUser | async; as user) {
|
||
|
|
<div class="user-info hide-mobile">
|
||
|
|
<span class="user-name">{{ user.name }}</span>
|
||
|
|
<span class="user-role">{{ formatRole(user.type) }}</span>
|
||
|
|
</div>
|
||
|
|
}
|
||
|
|
<mat-icon class="dropdown-arrow hide-mobile">expand_more</mat-icon>
|
||
|
|
</button>
|
||
|
|
|
||
|
|
<mat-menu #userMenu="matMenu" class="user-menu">
|
||
|
|
@if (currentUser | async; as user) {
|
||
|
|
<div class="user-menu-header">
|
||
|
|
<div class="user-avatar-large" [style.background]="getAvatarColor()">
|
||
|
|
{{ getUserInitials() }}
|
||
|
|
</div>
|
||
|
|
<div class="user-details">
|
||
|
|
<span class="user-name">{{ user.name }}</span>
|
||
|
|
<span class="user-email">{{ user.email || (user.departmentCode ? user.departmentCode + '@goa.gov.in' : 'user@goa.gov.in') }}</span>
|
||
|
|
<span class="user-badge">{{ formatRole(user.type) }}</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<mat-divider></mat-divider>
|
||
|
|
}
|
||
|
|
<button mat-menu-item>
|
||
|
|
<mat-icon>person</mat-icon>
|
||
|
|
<span>My Profile</span>
|
||
|
|
</button>
|
||
|
|
<button mat-menu-item>
|
||
|
|
<mat-icon>settings</mat-icon>
|
||
|
|
<span>Settings</span>
|
||
|
|
</button>
|
||
|
|
@if (userType() === 'DEPARTMENT') {
|
||
|
|
<button mat-menu-item routerLink="/department/wallet">
|
||
|
|
<mat-icon>account_balance_wallet</mat-icon>
|
||
|
|
<span>My Wallet</span>
|
||
|
|
</button>
|
||
|
|
}
|
||
|
|
<mat-divider></mat-divider>
|
||
|
|
<button mat-menu-item (click)="logout()" class="logout-btn">
|
||
|
|
<mat-icon>logout</mat-icon>
|
||
|
|
<span>Logout</span>
|
||
|
|
</button>
|
||
|
|
</mat-menu>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</header>
|
||
|
|
|
||
|
|
<!-- Main Content -->
|
||
|
|
<main id="main-content" class="main-content" role="main">
|
||
|
|
<router-outlet></router-outlet>
|
||
|
|
</main>
|
||
|
|
|
||
|
|
<!-- Footer - DBIM Compliant -->
|
||
|
|
<footer class="main-footer" role="contentinfo">
|
||
|
|
<div class="footer-content">
|
||
|
|
<div class="footer-left">
|
||
|
|
<span class="footer-text">
|
||
|
|
This platform belongs to Government of Goa, India
|
||
|
|
</span>
|
||
|
|
<span class="footer-divider hide-mobile">|</span>
|
||
|
|
<span class="footer-text hide-mobile">
|
||
|
|
Last Updated: {{ lastUpdated }}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
<div class="footer-right">
|
||
|
|
<a href="#" class="footer-link">Website Policies</a>
|
||
|
|
<a href="#" class="footer-link">Help</a>
|
||
|
|
<a href="#" class="footer-link">Feedback</a>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</footer>
|
||
|
|
</div>
|
||
|
|
</div>
|