Simple Managment webapp [LLM]

This commit is contained in:
2025-12-03 17:20:50 +01:00
parent b521f74951
commit e7f613b5dc
76 changed files with 20009 additions and 1 deletions

View File

@@ -0,0 +1,71 @@
<nz-layout class="app-layout">
<nz-sider
class="menu-sidebar"
nzCollapsible
nzBreakpoint="md"
[nzCollapsed]="isCollapsed()"
(nzCollapsedChange)="isCollapsed.set($event)"
[nzWidth]="240"
[nzCollapsedWidth]="80"
>
<div class="sidebar-logo">
@if (!isCollapsed()) {
<span>SimpleCloudNotifier</span>
} @else {
<span>SCN</span>
}
</div>
<ul nz-menu nzTheme="dark" nzMode="inline" [nzInlineCollapsed]="isCollapsed()">
<li nz-menu-item nzMatchRouter routerLink="/messages">
<span nz-icon nzType="mail"></span>
<span>Messages</span>
</li>
<li nz-menu-item nzMatchRouter routerLink="/channels">
<span nz-icon nzType="send"></span>
<span>Channels</span>
</li>
<li nz-menu-item nzMatchRouter routerLink="/subscriptions">
<span nz-icon nzType="link"></span>
<span>Subscriptions</span>
</li>
<li nz-menu-item nzMatchRouter routerLink="/keys">
<span nz-icon nzType="key"></span>
<span>Keys</span>
</li>
<li nz-menu-item nzMatchRouter routerLink="/clients">
<span nz-icon nzType="desktop"></span>
<span>Clients</span>
</li>
<li nz-menu-item nzMatchRouter routerLink="/senders">
<span nz-icon nzType="team"></span>
<span>Senders</span>
</li>
<li nz-menu-item nzMatchRouter routerLink="/account">
<span nz-icon nzType="user"></span>
<span>Account</span>
</li>
</ul>
</nz-sider>
<nz-layout>
<nz-header class="app-header">
<div class="header-left">
<span
class="header-trigger"
(click)="toggleCollapsed()"
>
<span nz-icon [nzType]="isCollapsed() ? 'menu-unfold' : 'menu-fold'"></span>
</span>
</div>
<div class="header-right">
<span class="user-id mono">{{ userId }}</span>
<button nz-button nzType="text" nzDanger (click)="logout()">
<span nz-icon nzType="logout"></span>
Logout
</button>
</div>
</nz-header>
<nz-content class="content-area">
<router-outlet></router-outlet>
</nz-content>
</nz-layout>
</nz-layout>

View File

@@ -0,0 +1,88 @@
.app-layout {
min-height: 100vh;
}
.menu-sidebar {
position: fixed;
left: 0;
top: 0;
bottom: 0;
z-index: 100;
overflow: auto;
overflow-x: hidden;
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.05);
}
.sidebar-logo {
height: 64px;
display: flex;
align-items: center;
justify-content: center;
padding: 0 16px;
background: #001529;
color: #fff;
font-size: 16px;
font-weight: 600;
overflow: hidden;
white-space: nowrap;
}
.app-header {
background: #fff;
padding: 0 24px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
position: sticky;
top: 0;
z-index: 99;
}
.header-left {
display: flex;
align-items: center;
}
.header-trigger {
font-size: 18px;
cursor: pointer;
padding: 0 16px;
transition: color 0.3s;
&:hover {
color: #1890ff;
}
}
.header-right {
display: flex;
align-items: center;
gap: 16px;
.user-id {
color: #666;
font-size: 13px;
}
}
.content-area {
margin-left: 240px;
transition: margin-left 0.2s;
min-height: calc(100vh - 64px);
background: #f0f2f5;
}
:host-context(.ant-layout-sider-collapsed) + nz-layout .content-area,
nz-layout:has(.ant-layout-sider-collapsed) .content-area {
margin-left: 80px;
}
// Handle collapsed state with sibling selector
:host {
display: block;
.ant-layout-sider-collapsed ~ nz-layout .content-area {
margin-left: 80px;
}
}

View File

@@ -0,0 +1,42 @@
import { Component, inject, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet, RouterLink, Router } from '@angular/router';
import { NzLayoutModule } from 'ng-zorro-antd/layout';
import { NzMenuModule } from 'ng-zorro-antd/menu';
import { NzIconModule } from 'ng-zorro-antd/icon';
import { NzButtonModule } from 'ng-zorro-antd/button';
import { NzDropDownModule } from 'ng-zorro-antd/dropdown';
import { AuthService } from '../../core/services/auth.service';
@Component({
selector: 'app-main-layout',
standalone: true,
imports: [
CommonModule,
RouterOutlet,
RouterLink,
NzLayoutModule,
NzMenuModule,
NzIconModule,
NzButtonModule,
NzDropDownModule,
],
templateUrl: './main-layout.component.html',
styleUrl: './main-layout.component.scss'
})
export class MainLayoutComponent {
private authService = inject(AuthService);
private router = inject(Router);
isCollapsed = signal(false);
userId = this.authService.getUserId();
toggleCollapsed(): void {
this.isCollapsed.update(v => !v);
}
logout(): void {
this.authService.logout();
this.router.navigate(['/login']);
}
}