init
This commit is contained in:
@@ -3,15 +3,30 @@ import { Routes } from '@angular/router';
|
||||
import { AccessDeniedComponent } from './core/components/access-denied/access-denied.component';
|
||||
import { NotFoundComponent } from './core/components/not-found/not-found.component';
|
||||
|
||||
import { DefaultLayoutComponent } from './core/components/default-layout/default-layout.component';
|
||||
|
||||
import { DashboardPageComponent } from './features/dashboard/pages/dashboard-page/dashboard-page.component';
|
||||
|
||||
export const routes: Routes = [
|
||||
// Regel 1: Leerer Pfad (Startseite der Anwendung)
|
||||
// Ein Benutzer, der die Haupt-URL Ihrer Seite aufruft (z.B. "http://localhost:4200/"),
|
||||
// wird sofort und ohne Umwege zur Login-Seite weitergeleitet.
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'auth',
|
||||
pathMatch: 'full',
|
||||
},
|
||||
|
||||
{
|
||||
path: 'dashboard',
|
||||
component: DefaultLayoutComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
loadChildren: () =>
|
||||
import('./features/dashboard/dashboard.routes').then(
|
||||
(r) => r.DASHBOARD_ROUTES
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'auth',
|
||||
loadChildren: () =>
|
||||
@@ -28,8 +43,13 @@ export const routes: Routes = [
|
||||
title: 'Zugriff verweigert',
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
path: '404',
|
||||
component: NotFoundComponent,
|
||||
title: '404 - Seite nicht gefunden',
|
||||
},
|
||||
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: '404',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
.main-layout-container {
|
||||
display: flex;
|
||||
background-color: var(--color-body-bg);
|
||||
}
|
||||
.main-content {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<div class="main-layout-container">
|
||||
<app-sidebar></app-sidebar>
|
||||
<div class="main-content">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { SidebarComponent } from '../../../shared/components/layout/sidebar/sidebar.component';
|
||||
import { RouterOutlet } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-default-layout',
|
||||
imports: [SidebarComponent,RouterOutlet],
|
||||
templateUrl: './default-layout.component.html',
|
||||
styleUrl: './default-layout.component.css'
|
||||
})
|
||||
export class DefaultLayoutComponent {
|
||||
|
||||
}
|
||||
9
src/app/features/dashboard/dashboard.module.ts
Normal file
9
src/app/features/dashboard/dashboard.module.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [CommonModule],
|
||||
})
|
||||
export class DashboardModule {}
|
||||
12
src/app/features/dashboard/dashboard.routes.ts
Normal file
12
src/app/features/dashboard/dashboard.routes.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { DashboardPageComponent } from './pages/dashboard-page/dashboard-page.component';
|
||||
// Importiere dein spezielles Layout für Auth-Seiten und alle Komponenten
|
||||
|
||||
export const DASHBOARD_ROUTES: Routes = [
|
||||
{ path: '', redirectTo: 'home', pathMatch: 'full' },
|
||||
{
|
||||
path: 'home',
|
||||
component: DashboardPageComponent,
|
||||
title: 'Dashboard Übersicht',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,56 @@
|
||||
<p>dashboard-page works!</p>
|
||||
<p>
|
||||
Key Performance Indicators (KPIs) – Das "Big Picture" Dies sind die
|
||||
wichtigsten Kennzahlen, die den Geschäftserfolg auf einen Blick zeigen. Sie
|
||||
sollten prominent ganz oben platziert werden. Alle diese Daten stammen direkt
|
||||
aus dem KpiSummaryDto, das Sie vom /api/v1/admin/AdminAnalytics-Endpunkt
|
||||
bekommen. Gesamtumsatz (totalRevenue): Die wichtigste Kennzahl. Zeigt, wie
|
||||
viel Geld der Shop einnimmt. Anzahl der Bestellungen (totalOrders): Zeigt die
|
||||
Aktivität im Shop. Durchschnittlicher Bestellwert (averageOrderValue): Hilft
|
||||
zu beurteilen, ob Kunden tendenziell mehr oder weniger pro Einkauf ausgeben.
|
||||
Anzahl der Neukunden (newCustomersThisPeriod): Wichtig für das Wachstum.
|
||||
Zeigt, wie viele neue Kunden im gewählten Zeitraum registriert wurden.
|
||||
Darstellung: Am besten als einzelne, große "KPI-Karten", wie wir es im
|
||||
vorherigen Beispiel hatten.
|
||||
</p>
|
||||
|
||||
<br />
|
||||
<p>
|
||||
Handlungsrelevante Aufgaben – "Was muss ich jetzt tun?" Das ist der vielleicht
|
||||
wichtigste Teil des Dashboards. Er sollte dem Admin direkt zeigen, wo seine
|
||||
Aufmerksamkeit benötigt wird. Bestellungen zur Bearbeitung: Eine Zählung und
|
||||
eine Liste der letzten Bestellungen mit dem Status Pending oder Processing.
|
||||
Dies signalisiert "Hier muss etwas verpackt und versendet werden!".
|
||||
API-Endpunkt: GET /api/v1/admin/AdminOrders – Sie müssten die zurückgegebene
|
||||
Liste clientseitig nach dem Status filtern. Produkte mit niedrigem
|
||||
Lagerbestand: Eine Warnung oder eine Liste von Produkten, deren stockQuantity
|
||||
unter einen bestimmten Schwellenwert fällt. API-Endpunkt: Das
|
||||
InventoryStatusDto aus dem AdminAnalytics-Endpunkt liefert Ihnen direkt die
|
||||
Anzahl (productsWithLowStock). Zu genehmigende Bewertungen (Reviews): Falls
|
||||
Sie ein Freigabeverfahren für Kundenbewertungen haben, ist eine Anzeige wie "3
|
||||
neue Bewertungen warten auf Freigabe" extrem hilfreich. API-Endpunkt: GET
|
||||
/api/v1/admin/AdminReviews – Sie müssten hier eine Zählung der noch nicht
|
||||
genehmigten Reviews durchführen. Darstellung: Als auffällige
|
||||
Benachrichtigungs-Boxen oder "To-Do"-Listen.
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
Jüngste Aktivitäten – "Was passiert gerade im Shop?" Diese Sektion gibt dem
|
||||
Admin ein Gefühl für die aktuelle Dynamik im Shop. Letzte Bestellungen: Eine
|
||||
kurze Liste der 5-10 neuesten Bestellungen, unabhängig vom Status. Zeigt den
|
||||
Namen des Kunden, den Bestellwert und das Datum. API-Endpunkt: GET
|
||||
/api/v1/admin/AdminOrders. Umsatzverlauf der letzten 30 Tage: Ein einfaches
|
||||
Linien- oder Balkendiagramm, das den täglichen Umsatz anzeigt. API-Endpunkt:
|
||||
Die salesOverTime-Daten aus dem AdminAnalytics-Endpunkt sind perfekt dafür
|
||||
gemacht.
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
Top-Listen – "Was läuft am besten?" Diese Informationen sind strategisch
|
||||
wertvoll, um zu wissen, welche Produkte populär sind. Top 5 meistverkaufte
|
||||
Produkte: Eine einfache Tabelle mit den Produkten, die den meisten Umsatz
|
||||
generieren oder am häufigsten verkauft wurden. API-Endpunkt: Die Liste
|
||||
topPerformingProducts aus dem AdminAnalytics-Endpunkt liefert Ihnen genau
|
||||
diese Daten.
|
||||
</p>
|
||||
<br />
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard-page',
|
||||
imports: [],
|
||||
templateUrl: './dashboard-page.component.html',
|
||||
styleUrl: './dashboard-page.component.css'
|
||||
})
|
||||
export class DashboardPageComponent {
|
||||
|
||||
}
|
||||
@@ -105,6 +105,37 @@
|
||||
</app-form-group>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="grid-col-span-2">
|
||||
<app-form-group
|
||||
title="Layout Components"
|
||||
description="Diese Informationen sind öffentlich sichtbar."
|
||||
>
|
||||
|
||||
<h3 card-header>Umsatzentwicklung</h3>
|
||||
|
||||
<!-- Das card-body dient als Container für das Diagramm -->
|
||||
<div class="chart-wrapper">
|
||||
<ngx-charts-bar-vertical
|
||||
[results]="salesData"
|
||||
scheme="vivid"
|
||||
[xAxis]="true"
|
||||
[yAxis]="true"
|
||||
[legend]="false"
|
||||
[showXAxisLabel]="true"
|
||||
[showYAxisLabel]="true"
|
||||
xAxisLabel="Monat"
|
||||
yAxisLabel="Umsatz in €">
|
||||
</ngx-charts-bar-vertical>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</app-form-group>
|
||||
</div>
|
||||
|
||||
<div class="grid-col-span-2">
|
||||
<app-form-group title="Button Components" description="UI Components">
|
||||
<!-- Sektion 1: Standard-Buttons -->
|
||||
|
||||
@@ -47,6 +47,8 @@ import { ChipComponent } from '../../../../shared/components/ui/chip/chip.compon
|
||||
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
import { NgxChartsModule } from '@swimlane/ngx-charts';
|
||||
|
||||
// Wir definieren ein Interface für unsere KPI-Daten für Typsicherheit
|
||||
interface Kpi {
|
||||
value: string;
|
||||
@@ -73,7 +75,8 @@ interface Kpi {
|
||||
PageHeaderComponent,
|
||||
ButtonComponent,
|
||||
ChipComponent,
|
||||
ReactiveFormsModule
|
||||
ReactiveFormsModule,
|
||||
NgxChartsModule
|
||||
],
|
||||
templateUrl: './demo2.component.html',
|
||||
})
|
||||
@@ -231,6 +234,23 @@ export class Demo2Component {
|
||||
private readonly darkModeKey = 'app-dark-mode-setting';
|
||||
darkModeAktiv: boolean = false;
|
||||
|
||||
// +++ NEUE EIGENSCHAFTEN FÜR DAS DIAGRAMM +++
|
||||
|
||||
// 1. Die Daten für das Diagramm im von ngx-charts erwarteten Format
|
||||
salesData = [
|
||||
{ name: 'Jan', value: 12500 },
|
||||
{ name: 'Feb', value: 14750 },
|
||||
{ name: 'Mär', value: 11800 },
|
||||
{ name: 'Apr', value: 18600 },
|
||||
{ name: 'Mai', value: 21500 },
|
||||
{ name: 'Jun', value: 19800 }
|
||||
];
|
||||
|
||||
// 2. (Optional) Ein benutzerdefiniertes Farbschema, das zu Ihrem Theme passt
|
||||
customColorScheme = {
|
||||
domain: ['#3498db', '#2980b9', '#2ecc71', '#27ae60', '#f39c12', '#f1c40f']
|
||||
};
|
||||
|
||||
|
||||
constructor(
|
||||
private renderer: Renderer2,
|
||||
|
||||
@@ -1,66 +1,152 @@
|
||||
/* Verschieben Sie alle .sidebar... und .nav-item... Klassen aus styles.css hierher */
|
||||
/* Globale Variablen für einfachere Wartung */
|
||||
:host {
|
||||
display: block;
|
||||
--sidebar-width-expanded: 280px;
|
||||
--sidebar-width-collapsed: 96px;
|
||||
--sidebar-padding: 1rem;
|
||||
--sidebar-margin: 1rem;
|
||||
--transition-speed: 0.3s;
|
||||
--transition-ease: ease-in-out;
|
||||
}
|
||||
|
||||
/* 1. Der Sidebar-Container */
|
||||
.sidebar {
|
||||
width: 260px;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1.5rem;
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: var(--glass-backdrop-filter);
|
||||
-webkit-backdrop-filter: var(--glass-backdrop-filter);
|
||||
border-right: 1px solid var(--color-border);
|
||||
transition: background-color var(--transition-speed),
|
||||
border-color var(--transition-speed);
|
||||
gap: 2rem;
|
||||
width: var(--sidebar-width-expanded);
|
||||
height: calc(100vh - (var(--sidebar-margin) * 2));
|
||||
margin: var(--sidebar-margin);
|
||||
padding: var(--sidebar-padding);
|
||||
background-color: #fff;
|
||||
border: 1px solid #e5e7eb; /* Helle Umrandung */
|
||||
border-radius: 1rem;
|
||||
transition: width var(--transition-speed) var(--transition-ease);
|
||||
}
|
||||
|
||||
/* 2. Der Header-Bereich */
|
||||
.sidebar-header {
|
||||
margin-bottom: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem; /* Abstand zwischen Logo und Titel */
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.sidebar-logo {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
|
||||
.sidebar-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 900;
|
||||
margin: 0;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
opacity: 1;
|
||||
overflow: hidden;
|
||||
transition: opacity 0.2s ease-in-out,
|
||||
width 0.3s ease-in-out 0.05s,
|
||||
transform 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
/* ======================================================= */
|
||||
/* --- HIER PASSIERT DIE MAGIE FÜR DEN BUTTON --- */
|
||||
/* ======================================================= */
|
||||
.sidebar-header app-button {
|
||||
/* Weist den Button an, den gesamten verfügbaren Platz als linken Abstand zu nutzen */
|
||||
margin-left: auto;
|
||||
|
||||
/* Verhindert, dass der Button schrumpft */
|
||||
flex-shrink: 0;
|
||||
|
||||
/* Fügt eine sanfte Drehanimation hinzu */
|
||||
transition: transform var(--transition-speed) var(--transition-ease);
|
||||
transform: rotate(0deg); /* Startposition der Animation */
|
||||
}
|
||||
|
||||
/* 3. Die Navigation (angepasst an das neue Design) */
|
||||
.sidebar-nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.sidebar-footer {
|
||||
margin-top: auto;
|
||||
flex-grow: 1; /* Nimmt den restlichen vertikalen Platz ein */
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: var(--border-radius-md);
|
||||
color: var(--color-text-light);
|
||||
font-weight: 500;
|
||||
border-radius: 0.5rem;
|
||||
text-decoration: none;
|
||||
transition: all var(--transition-speed);
|
||||
}
|
||||
.nav-item app-icon {
|
||||
font-size: 20px; /* Steuert die Größe des Icons */
|
||||
transition: color var(--transition-speed);
|
||||
font-weight: 500;
|
||||
color: #4b5563;
|
||||
white-space: nowrap;
|
||||
transition: background-color 0.2s, color 0.2s;
|
||||
}
|
||||
|
||||
.nav-item:hover {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
color: var(--color-text);
|
||||
}
|
||||
:host-context(body.dark-theme) .nav-item:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
background-color: #f3f4f6;
|
||||
}
|
||||
|
||||
.nav-item.active {
|
||||
background: var(--color-primary-gradient);
|
||||
background-color: #3b82f6;
|
||||
color: #fff;
|
||||
box-shadow: 0 4px 10px rgba(52, 152, 219, 0.4);
|
||||
}
|
||||
.nav-item.active app-icon {
|
||||
color: #fff;
|
||||
|
||||
.nav-item app-icon {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.sidebar-footer {
|
||||
margin-top: auto; /* Schiebt den Footer nach unten */
|
||||
}
|
||||
|
||||
/* ======================================================= */
|
||||
/* --- Stile für den eingeklappten Zustand (.collapsed) --- */
|
||||
/* ======================================================= */
|
||||
|
||||
.sidebar.collapsed {
|
||||
width: var(--sidebar-width-collapsed);
|
||||
}
|
||||
|
||||
.sidebar.collapsed .sidebar-header {
|
||||
justify-content: center; /* Zentriert das Logo, wenn der Titel weg ist */
|
||||
}
|
||||
|
||||
.sidebar.collapsed .sidebar-title {
|
||||
opacity: 0;
|
||||
width: 0; /* Wichtig: expliziter Endwert für die Breiten-Animation */
|
||||
transform: translateX(-10px); /* Leichte Bewegung nach links */
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Dreht den Button um 180 Grad, wenn die Sidebar eingeklappt ist */
|
||||
.sidebar.collapsed .sidebar-header app-button {
|
||||
transform: rotate(180deg);
|
||||
margin-left: 0; /* Setzt den Margin zurück, da 'justify-content' jetzt die Positionierung übernimmt */
|
||||
}
|
||||
|
||||
.sidebar.collapsed .nav-item {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.nav-item span {
|
||||
white-space: nowrap;
|
||||
opacity: 1;
|
||||
|
||||
/* === NEU: Präzise Transition auch hier === */
|
||||
overflow: hidden;
|
||||
transition: opacity 0.2s ease-in-out,
|
||||
width 0.3s ease-in-out 0.05s;
|
||||
}
|
||||
|
||||
|
||||
.sidebar.collapsed .nav-item span {
|
||||
opacity: 0;
|
||||
width: 0; /* Wichtig: expliziter Endwert für die Breiten-Animation */
|
||||
pointer-events: none;
|
||||
}
|
||||
@@ -1,13 +1,33 @@
|
||||
<aside class="sidebar">
|
||||
<aside class="sidebar" [class.collapsed]="isCollapsed">
|
||||
<div class="sidebar-header">
|
||||
<h1 class="sidebar-title">CustomDash</h1>
|
||||
<div class="sidebar-logo">
|
||||
<!-- Ersetzen Sie dies durch Ihr Logo, z.B. als <img> oder <svg> -->
|
||||
<svg
|
||||
viewBox="0 0 48 48"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
d="M24 8C19.2 8 15.2 9.4 12 11.8C15.4 12.8 18.3 15.6 19.4 19C20.6 18.6 21.8 18.4 23 18.4C24.4 18.4 25.6 18.6 26.8 19C27.9 15.6 30.8 12.8 34.2 11.8C31 9.4 27.2 8 24 8ZM11.8 12.2C8.6 14.6 6 18.2 4.6 22.4C7.8 22.8 10.6 24.6 12.4 27.2C11.4 25.4 10.8 23.2 10.6 21C9.4 17.6 10 14.4 11.8 12.2ZM36.2 12.2C38 14.4 38.6 17.6 37.4 21C37.2 23.2 36.6 25.4 35.6 27.2C37.4 24.6 40.2 22.8 43.4 22.4C42 18.2 39.4 14.6 36.2 12.2ZM4.2 24C4 25.2 4 26.4 4 27.8C4 32.8 6 37.4 9.4 40.6C10.2 37.6 12 35 14.4 33C12 30.8 10.2 28.2 9.2 25.4C7.2 25.2 5.4 24.6 4.2 24ZM20.8 27.8C18.4 29.8 16.6 32.4 15.4 35.4C17.6 38.2 20.6 40 24 40C27.4 40 30.4 38.2 32.6 35.4C31.4 32.4 29.6 29.8 27.2 27.8C25.6 29 24.2 29.2 23.2 29.2C22.4 29.2 21.4 29 20.8 27.8ZM38.8 25.4C37.8 28.2 36 30.8 33.6 33C36 35 37.8 37.6 38.6 40.6C42 37.4 44 32.8 44 27.8C44 26.4 44 25.2 43.8 24C42.6 24.6 40.8 25.2 38.8 25.4Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1 class="sidebar-title">Wetask</h1>
|
||||
<app-button
|
||||
buttonType="icon"
|
||||
iconName="double_arrow"
|
||||
(click)="toggleSidebar()"
|
||||
></app-button>
|
||||
</div>
|
||||
|
||||
<!-- 2. Der Button zum Ein- und Ausklappen. Er ruft unsere neue Methode auf. -->
|
||||
|
||||
<nav class="sidebar-nav">
|
||||
<a
|
||||
class="nav-item"
|
||||
[class.active]="activeRoute === 'dashboard'"
|
||||
(click)="setActive('dashboard')"
|
||||
title="Übersicht"
|
||||
>
|
||||
<app-icon name="placeholder"></app-icon>
|
||||
<span>Übersicht</span>
|
||||
@@ -17,6 +37,7 @@
|
||||
class="nav-item"
|
||||
[class.active]="activeRoute === 'analytics'"
|
||||
(click)="setActive('analytics')"
|
||||
title="Analysen"
|
||||
>
|
||||
<app-icon name="placeholder"></app-icon>
|
||||
<span>Analysen</span>
|
||||
@@ -26,6 +47,7 @@
|
||||
class="nav-item"
|
||||
[class.active]="activeRoute === 'reports'"
|
||||
(click)="setActive('reports')"
|
||||
title="Berichte"
|
||||
>
|
||||
<app-icon name="placeholder"></app-icon>
|
||||
<span>Berichte</span>
|
||||
@@ -37,6 +59,7 @@
|
||||
class="nav-item"
|
||||
[class.active]="activeRoute === 'settings'"
|
||||
(click)="setActive('settings')"
|
||||
title="Einstellungen"
|
||||
>
|
||||
<app-icon name="placeholder"></app-icon>
|
||||
<span>Einstellungen</span>
|
||||
|
||||
@@ -1,21 +1,29 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { IconComponent } from '../../ui/icon/icon.component';
|
||||
import { ButtonComponent } from '../../ui/button/button.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-sidebar',
|
||||
standalone: true,
|
||||
imports: [CommonModule, IconComponent],
|
||||
imports: [CommonModule, IconComponent,ButtonComponent],
|
||||
templateUrl: './sidebar.component.html',
|
||||
styleUrl: './sidebar.component.css'
|
||||
})
|
||||
export class SidebarComponent {
|
||||
// Wir verwalten nur noch, welcher Link aktiv ist. 'dashboard' ist der Standard.
|
||||
// Dummy-Eigenschaft für die aktive Route, damit der Code funktioniert
|
||||
activeRoute = 'dashboard';
|
||||
|
||||
// Methode, um den aktiven Link bei einem Klick zu ändern.
|
||||
// In einer echten App würde dies durch den Angular Router gesteuert werden.
|
||||
// NEU: Eigenschaft, um den Zustand der Sidebar zu speichern
|
||||
public isCollapsed = false;
|
||||
|
||||
// Dummy-Methode, damit der Code funktioniert
|
||||
setActive(route: string): void {
|
||||
this.activeRoute = route;
|
||||
}
|
||||
|
||||
// NEU: Methode, um den Zustand umzuschalten
|
||||
toggleSidebar(): void {
|
||||
this.isCollapsed = !this.isCollapsed;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* =================================================================================
|
||||
GLOBALE STYLING-GRUNDLAGE (THEME & UTILITIES)
|
||||
================================================================================== */
|
||||
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700;900&display=swap");
|
||||
/* @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700;900&display=swap"); */
|
||||
|
||||
/* =================================================================================
|
||||
* 1. CSS-VARIABLEN (DESIGN TOKENS)
|
||||
|
||||
Reference in New Issue
Block a user