feature/refactor-login #19

Merged
igorpropisnov merged 26 commits from feature/refactor-login into main 2024-09-19 13:58:12 +02:00
2 changed files with 211 additions and 166 deletions
Showing only changes of commit 609a08f479 - Show all commits

View File

@ -1,159 +1,194 @@
<div class="flex flex-col h-screen overflow-hidden"> <div class="flex h-screen w-screen bg-base-200">
<!-- Header --> <div class="flex flex-col w-full lg:w-full bg-base-100 h-screen">
<header class="w-full navbar bg-primary text-primary-content z-40"> <!-- Header mit dem Burger-Menü -->
<div class="flex-1"> <header class="w-full navbar bg-primary text-primary-content z-40">
<a class="btn btn-ghost normal-case text-xl text-primary-content"> <div class="flex-1">
[APP-NAME] <a class="btn btn-ghost normal-case text-xl text-primary-content">
</a> [APP-NAME]
</div> </a>
<!-- Der Button wird nur auf mobilen Geräten angezeigt --> </div>
<div class="flex-none lg:hidden"> <!-- Der Button wird nur auf mobilen Geräten angezeigt -->
<button <div class="flex-none lg:hidden">
(click)="toggleDrawer()" <button
class="btn btn-square btn-ghost drawer-button"> (click)="toggleDrawer()"
<svg class="btn btn-square btn-ghost drawer-button">
xmlns="http://www.w3.org/2000/svg" <svg
fill="none" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" fill="none"
class="inline-block w-6 h-6 stroke-current"> viewBox="0 0 24 24"
<path class="inline-block w-6 h-6 stroke-current">
stroke-linecap="round" <path
stroke-linejoin="round" stroke-linecap="round"
stroke-width="2" stroke-linejoin="round"
d="M4 6h16M4 12h16M4 18h16"></path> stroke-width="2"
</svg> d="M4 6h16M4 12h16M4 18h16"></path>
</button> </svg>
</div> </button>
</header> </div>
<!-- Hauptcontainer --> <!-- Compact Mode Toggle Button für Desktop -->
<div class="flex-1 flex overflow-hidden relative"> <div class="hidden lg:flex items-center space-x-2 mr-4">
<!-- Backdrop --> <button (click)="toggleCompactMode()" class="btn btn-square btn-ghost">
<div <svg
*ngIf="isDrawerOpen" xmlns="http://www.w3.org/2000/svg"
class="fixed inset-0 bg-black bg-opacity-50 z-20 lg:hidden" fill="none"
(click)="toggleDrawer()"></div> viewBox="0 0 24 24"
class="inline-block w-6 h-6 stroke-current">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M3 3h18v18H3V3z"></path>
</svg>
</button>
</div>
</header>
<!-- Drawer --> <!-- Hauptcontainer -->
<div <div class="flex-1 flex overflow-hidden">
class="h-full transition-transform duration-300 ease-in-out bg-primary text-primary-content w-64 flex flex-col lg:translate-x-0" <!-- Drawer -->
[ngClass]="{ <div
'translate-x-0': isDrawerOpen, class="h-full transition-transform duration-300 ease-in-out bg-primary text-primary-content flex flex-col lg:translate-x-0"
'-translate-x-full': !isDrawerOpen, [ngClass]="{
'fixed lg:relative': true, 'w-16': isCompact && !isDrawerOpen,
'top-0 left-0 z-30': true 'w-64': isDrawerOpen,
}"> 'fixed lg:relative': true,
<aside class="h-full flex flex-col"> 'top-0 left-0 z-30': true,
<!-- Drawer-Inhalt --> 'translate-x-0': isDrawerOpen,
<div class="flex-1 overflow-y-auto pt-16 lg:pt-0"> '-translate-x-full': !isDrawerOpen && !isCompact
<ul class="w-full p-0 m-0 [&_li>*]:rounded-none"> }">
<ng-container *ngFor="let item of menuItems"> <aside class="h-full flex flex-col">
<li class="w-full"> <!-- Drawer-Inhalt -->
<ng-container *ngIf="!item.subitems; else submenu"> <div class="flex-1 overflow-y-auto pt-16 lg:pt-0">
<a <ul class="w-full p-0 m-0 [&_li>*]:rounded-none">
[routerLink]="item.route" <ng-container *ngFor="let item of menuItems">
[class.active]="item.active" <li class="w-full">
class="flex items-center w-full px-4 py-3 transition-colors duration-200 ease-in-out focus:outline-none hover:bg-base-300 hover:text-primary" <ng-container *ngIf="!item.subitems; else submenu">
[class.bg-base-100]="item.active" <a
[class.text-base-content]="item.active" [routerLink]="item.route"
[class.text-primary]="item.active" [class.active]="item.active"
[class.font-semibold]="item.active" class="flex items-center w-full px-4 py-3 transition-colors duration-200 ease-in-out focus:outline-none hover:bg-base-300 hover:text-primary"
role="menuitem" [class.bg-base-100]="item.active"
tabindex="0" [class.text-base-content]="item.active"
(click)="onLinkClick()"> [class.text-primary]="item.active"
<span [class.font-semibold]="item.active"
class="flex-shrink-0 w-6 h-6 mr-3" role="menuitem"
[innerHTML]="item.icon"></span> tabindex="0"
<span class="flex-grow">{{ item.name }}</span> (click)="onLinkClick()">
</a> <span
</ng-container> class="flex-shrink-0 w-6 h-6 mr-3"
[innerHTML]="item.icon"></span>
<span class="flex-grow" *ngIf="isDrawerOpen">
{{ item.name }}
</span>
</a>
</ng-container>
<ng-template #submenu> <ng-template #submenu>
<div <div
(click)="toggleSubmenu(item, $event)" (click)="toggleSubmenu(item, $event)"
class="flex items-center w-full px-4 py-3 transition-colors duration-200 ease-in-out focus:outline-none hover:bg-base-300 hover:text-primary cursor-pointer" class="flex items-center w-full px-4 py-3 transition-colors duration-200 ease-in-out focus:outline-none hover:bg-base-300 hover:text-primary cursor-pointer"
[class.bg-base-300]="item.active" [class.bg-base-300]="item.active"
[class.text-primary]="item.active" [class.text-primary]="item.active"
[class.font-semibold]="item.active" [class.font-semibold]="item.active"
[class.bg-base-100]="item.isOpen" [class.bg-base-100]="item.isOpen"
[class.text-base-content]="item.isOpen"> [class.text-base-content]="item.isOpen">
<span <span
class="flex-shrink-0 w-6 h-6 mr-3" class="flex-shrink-0 w-6 h-6 mr-3"
[innerHTML]="item.icon"></span> [innerHTML]="item.icon"></span>
<span class="flex-grow">{{ item.name }}</span> <span class="flex-grow" *ngIf="isDrawerOpen">
<svg {{ item.name }}
xmlns="http://www.w3.org/2000/svg" </span>
fill="none" <svg
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"
stroke-width="1.5" fill="none"
stroke="currentColor" viewBox="0 0 24 24"
class="w-4 h-4 transition-transform" stroke-width="1.5"
[class.rotate-180]="item.isOpen"> stroke="currentColor"
<path class="w-4 h-4 transition-transform"
stroke-linecap="round" [class.rotate-180]="item.isOpen">
stroke-linejoin="round" <path
d="M19.5 8.25l-7.5 7.5-7.5-7.5" /> stroke-linecap="round"
</svg> stroke-linejoin="round"
</div> d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
<div </svg>
[@submenuAnimation]="item.isOpen ? 'open' : 'closed'" </div>
class="overflow-hidden"> <div
<ul class="bg-base-100"> [@submenuAnimation]="item.isOpen ? 'open' : 'closed'"
<li *ngFor="let subItem of item.subitems" class="w-full"> class="overflow-hidden">
<a <ul class="bg-base-100">
[routerLink]="subItem.route" <li
[class.active]="subItem.active" *ngFor="let subItem of item.subitems"
class="flex items-center w-full px-4 pl-8 py-2 transition-colors duration-200 ease-in-out focus:outline-none hover:bg-base-300 hover:text-primary" class="w-full">
[class.bg-base-300]="subItem.active" <a
[class.text-primary]="subItem.active" [routerLink]="subItem.route"
[class.font-semibold]="subItem.active" [class.active]="subItem.active"
[class.bg-base-100]="item.isOpen" class="flex items-center w-full px-4 pl-8 py-2 transition-colors duration-200 ease-in-out focus:outline-none hover:bg-base-300 hover:text-primary"
[class.text-base-content]="item.isOpen" [class.bg-base-300]="subItem.active"
role="menuitem" [class.text-primary]="subItem.active"
tabindex="0" [class.font-semibold]="subItem.active"
(click)="onLinkClick()"> [class.bg-base-100]="item.isOpen"
<span [class.text-base-content]="item.isOpen"
class="flex-shrink-0 w-5 h-5 mr-2" role="menuitem"
[innerHTML]="subItem.icon"></span> tabindex="0"
{{ subItem.name }} (click)="onLinkClick()">
</a> <span
</li> class="flex-shrink-0 w-5 h-5 mr-2"
</ul> [innerHTML]="subItem.icon"></span>
</div> {{ subItem.name }}
</ng-template> </a>
</li> </li>
</ng-container> </ul>
</ul> </div>
</div> </ng-template>
<hr class="border-t border-base-100" /> </li>
</ng-container>
<div style="background-color: rgba(0, 0, 0, 0.2)"> </ul>
<ul class="w-full px-2 py-4">
<ng-container *ngFor="let item of bottomMenuItems">
<li>
<button
(click)="executeAction(item)"
(keydown.enter)="executeAction(item)"
class="py-2 px-4 rounded flex items-center space-x-2 bg-base-100 text-base-content hover:text-primary hover:font-semibold w-full text-left">
<span [innerHTML]="item.icon"></span>
<span>{{ item.name }}</span>
</button>
</li>
</ng-container>
</ul>
</div>
</aside>
</div>
<!-- Hauptinhalt -->
<div class="flex-1 overflow-y-auto p-4 bg-base-100">
<main class="flex-1">
<div class="w-full h-full flex items-center justify-center">
<div class="w-full max-w-5xl">
<router-outlet></router-outlet>
</div> </div>
</div> <hr class="border-t border-base-100" />
</main>
<div style="background-color: rgba(0, 0, 0, 0.2)">
<ul class="w-full px-2 py-4">
<ng-container *ngFor="let item of bottomMenuItems">
<li>
<button
(click)="executeAction(item)"
(keydown.enter)="executeAction(item)"
class="py-2 px-4 rounded flex items-center space-x-2 bg-base-300 text-base-content hover:text-primary hover:font-semibold w-full text-left"
role="menuitem"
tabindex="0">
<span [innerHTML]="item.icon"></span>
<span *ngIf="isDrawerOpen">{{ item.name }}</span>
</button>
</li>
</ng-container>
</ul>
</div>
</aside>
</div>
<!-- Backdrop -->
<!-- Backdrop -->
<div
*ngIf="isDrawerOpen && !isCompact && isMobile"
class="fixed inset-0 bg-black bg-opacity-50 z-20"
(click)="toggleDrawer()"></div>
<!-- Hauptinhalt -->
<div
class="flex-1 overflow-y-auto p-4 bg-base-100"
[ngClass]="{
'lg:ml-16': isCompact && !isDrawerOpen,
'ml-0': !isDrawerOpen || isCompact
}">
<main class="flex-1">
<div class="w-full h-full flex items-center justify-center">
<div class="w-full max-w-5xl">
<router-outlet></router-outlet>
</div>
</div>
</main>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -10,6 +10,7 @@ import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
ElementRef, ElementRef,
HostListener,
OnDestroy, OnDestroy,
OnInit, OnInit,
} from '@angular/core'; } from '@angular/core';
@ -82,6 +83,8 @@ export class LayoutComponent implements OnInit, OnDestroy {
public isDesktopCollapsed: boolean = false; public isDesktopCollapsed: boolean = false;
public showMobileMenu: boolean = false; public showMobileMenu: boolean = false;
public isDrawerOpen: boolean = true; public isDrawerOpen: boolean = true;
public isCompact: boolean = false;
public isMobile: boolean = window.innerWidth < 1024;
public menuItems: TopMenuItem[] = [ public menuItems: TopMenuItem[] = [
{ {
name: 'Dashboard', name: 'Dashboard',
@ -154,12 +157,16 @@ export class LayoutComponent implements OnInit, OnDestroy {
private readonly authService: AuthService private readonly authService: AuthService
) {} ) {}
@HostListener('window:resize', ['$event'])
public onResize(event: any): void {
this.isMobile = event.target.innerWidth < 1024;
this.adjustDrawerState(event.target.innerWidth);
}
public ngOnInit(): void { public ngOnInit(): void {
this.adjustDrawerState(window.innerWidth); this.adjustDrawerState(window.innerWidth);
window.addEventListener('resize', () => { window.addEventListener('resize', this.onResize.bind(this));
this.adjustDrawerState(window.innerWidth);
});
this.updateMenuState(this.router.url); this.updateMenuState(this.router.url);
@ -175,8 +182,10 @@ export class LayoutComponent implements OnInit, OnDestroy {
}); });
} }
public onResize(): void { public ngOnDestroy(): void {
this.adjustDrawerState(window.innerWidth); window.removeEventListener('resize', this.onResize.bind(this));
this.destroy$.next();
this.destroy$.complete();
} }
public onLinkClick(): void { public onLinkClick(): void {
@ -185,22 +194,23 @@ export class LayoutComponent implements OnInit, OnDestroy {
} }
} }
public ngOnDestroy(): void {
window.removeEventListener('resize', this.onResize.bind(this));
this.destroy$.next();
this.destroy$.complete();
}
public toggleDrawer(): void { public toggleDrawer(): void {
this.isDrawerOpen = !this.isDrawerOpen; this.isDrawerOpen = !this.isDrawerOpen;
this.isCompact = !this.isDrawerOpen; // Wechsel zwischen kompaktem und vollem Zustand
}
public toggleCompactMode(): void {
this.isCompact = !this.isCompact;
this.isDrawerOpen = !this.isCompact; // Wenn kompaktes Mode aktiviert wird, Drawer geschlossen
} }
public adjustDrawerState(width: number): void { public adjustDrawerState(width: number): void {
// Hier wird geprüft, ob wir uns im mobilen Bereich befinden.
if (width < 1024) { if (width < 1024) {
this.toggleDrawer(); this.isCompact = true;
this.isDrawerOpen = false; // Kompaktmodus auf mobilen Geräten
} else { } else {
this.toggleDrawer(); this.isCompact = false;
this.isDrawerOpen = true; // Vollmodus auf Desktop
} }
} }