data display
This commit is contained in:
@@ -1,265 +1,19 @@
|
||||
<!-- =================================================================================
|
||||
FINALES & VOLLSTÄNDIGES DEMO-LAYOUT (VERSION 5.0)
|
||||
Aufgebaut aus wiederverwendbaren Komponenten
|
||||
================================================================================== -->
|
||||
<div class="dashboard-container">
|
||||
<!-- =================================================================== -->
|
||||
<!-- 1. SIDEBAR (Statisch, da sehr spezifisch für dieses Layout) -->
|
||||
<!-- =================================================================== -->
|
||||
|
||||
<app-sidebar></app-sidebar>
|
||||
<!-- =================================================================== -->
|
||||
<!-- 2. HAUPTINHALT -->
|
||||
<!-- =================================================================== -->
|
||||
<main class="main-content">
|
||||
<app-page-header></app-page-header>
|
||||
|
||||
<div class="dashboard-grid">
|
||||
<app-kpi-card
|
||||
value="€ 14.750"
|
||||
label="Umsatz"
|
||||
color="green"
|
||||
iconName="money"
|
||||
></app-kpi-card>
|
||||
|
||||
<app-kpi-card
|
||||
value="1.284"
|
||||
label="Neue Nutzer"
|
||||
color="blue"
|
||||
iconName="group"
|
||||
></app-kpi-card>
|
||||
|
||||
<app-kpi-card
|
||||
value="312"
|
||||
label="Bestellungen"
|
||||
color="orange"
|
||||
iconName="shopping_bag"
|
||||
></app-kpi-card>
|
||||
|
||||
<app-kpi-card
|
||||
value="99.8%"
|
||||
label="Verfügbarkeit"
|
||||
color="purple"
|
||||
iconName="bolt"
|
||||
></app-kpi-card>
|
||||
|
||||
<app-card class="grid-col-span-2">
|
||||
<h3 class="card-header">Umsatzentwicklung</h3>
|
||||
<div class="chart-container">
|
||||
<div class="chart-bar" style="height: 60%"><span>Jan</span></div>
|
||||
<div class="chart-bar" style="height: 75%"><span>Feb</span></div>
|
||||
<div class="chart-bar" style="height: 50%"><span>Mär</span></div>
|
||||
<div class="chart-bar" style="height: 85%"><span>Apr</span></div>
|
||||
<div class="chart-bar" style="height: 90%"><span>Mai</span></div>
|
||||
<div class="chart-bar" style="height: 65%"><span>Jun</span></div>
|
||||
</div>
|
||||
</app-card>
|
||||
|
||||
<app-card class="grid-col-span-2">
|
||||
<h3 class="card-header">Letzte Bestellungen</h3>
|
||||
<app-orders-table
|
||||
[orders]="ordersData"
|
||||
(deleteOrder)="handleDeleteOrder($event)"
|
||||
>
|
||||
</app-orders-table>
|
||||
<app-paginator
|
||||
[currentPage]="currentPage"
|
||||
[totalItems]="totalItems"
|
||||
[itemsPerPage]="itemsPerPage"
|
||||
(pageChange)="onPageChange($event)"
|
||||
></app-paginator>
|
||||
</app-card>
|
||||
|
||||
<!-- UI Komponenten Showcase -->
|
||||
<app-card class="grid-col-span-2">
|
||||
<h3 class="card-header">Moderne Formular-Elemente</h3>
|
||||
<div class="component-grid">
|
||||
<app-form-field label="Name" type="text"></app-form-field>
|
||||
<app-form-select label="Stadt" [options]="cityOptions" ></app-form-select>
|
||||
|
||||
<app-form-textarea label="Nachricht"></app-form-textarea>
|
||||
|
||||
<app-slide-toggle></app-slide-toggle>
|
||||
</div>
|
||||
</app-card>
|
||||
|
||||
<app-card class="grid-col-span-2">
|
||||
<h3 class="card-header">Buttons, Chips & Interaktion</h3>
|
||||
<div class="component-grid">
|
||||
<div class="button-group">
|
||||
<app-button buttonType="primary" tooltip="Primary"
|
||||
>Primary</app-button
|
||||
>
|
||||
<app-button buttonType="secondary">Secondary</app-button>
|
||||
<app-button buttonType="stroked">Stroked</app-button>
|
||||
<app-button buttonType="flat">Flat</app-button>
|
||||
<app-button
|
||||
buttonType="icon"
|
||||
tooltip="Favorit hinzufügen"
|
||||
iconName="favorite"
|
||||
svgColor="red"
|
||||
></app-button>
|
||||
|
||||
<app-button
|
||||
buttonType="icon"
|
||||
tooltip="Details anzeigen"
|
||||
iconName="eye"
|
||||
></app-button>
|
||||
</div>
|
||||
|
||||
<div class="chip-set">
|
||||
<app-chip label="Technologie" [removable]="true"></app-chip>
|
||||
<app-chip
|
||||
label="Angular"
|
||||
[active]="true"
|
||||
[removable]="true"
|
||||
></app-chip>
|
||||
</div>
|
||||
<div class="badge-showcase">
|
||||
<div class="badge-container">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path>
|
||||
<path d="M13.73 21a2 2 0 0 1-3.46 0"></path></svg
|
||||
><span class="badge-dot">3</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<app-menu [items]="actionMenuItems"></app-menu>
|
||||
</div>
|
||||
</app-card>
|
||||
|
||||
<app-card class="grid-col-span-2">
|
||||
<h3 class="card-header">Indikatoren & Feedback</h3>
|
||||
<div class="card-body component-grid">
|
||||
<app-button buttonType="secondary" (click)="triggerSnackbar()"
|
||||
>Snackbar anzeigen</app-button
|
||||
>
|
||||
<app-alert type="success"
|
||||
><strong>Erfolg!</strong> Ihre Änderungen wurden
|
||||
gespeichert.</app-alert
|
||||
>
|
||||
<app-alert type="danger"
|
||||
><strong>Fehler!</strong> Bitte füllen Sie alle Felder
|
||||
aus.</app-alert
|
||||
>
|
||||
</div>
|
||||
</app-card>
|
||||
|
||||
<app-card class="grid-col-span-2">
|
||||
<h3 class="card-header">Navigation & Layout</h3>
|
||||
<div class="component-grid">
|
||||
<div class="tab-group">
|
||||
<button class="tab-link active">Profil</button
|
||||
><button class="tab-link">Konto</button>
|
||||
</div>
|
||||
<div class="form-group-inline">
|
||||
<label>Lautstärke</label
|
||||
><input
|
||||
type="range"
|
||||
class="form-slider"
|
||||
min="0"
|
||||
max="100"
|
||||
value="50"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<app-expansion-panel title="Weitere Details anzeigen">
|
||||
Dieser Inhalt wird dynamisch ein- und ausgeblendet. Lorem ipsum
|
||||
dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada
|
||||
lacus ex, sit amet blandit leo lobortis eget.
|
||||
</app-expansion-panel>
|
||||
|
||||
<div class="stepper">
|
||||
<div class="step step-complete">
|
||||
<div class="step-icon">✓</div>
|
||||
<span>Profil</span>
|
||||
</div>
|
||||
<div class="step-connector"></div>
|
||||
<div class="step step-active">
|
||||
<div class="step-icon">2</div>
|
||||
<span>Konto</span>
|
||||
</div>
|
||||
<div class="step-connector"></div>
|
||||
<div class="step">
|
||||
<div class="step-icon">3</div>
|
||||
<span>Abschluss</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</app-card>
|
||||
|
||||
<app-card class="grid-col-span-2">
|
||||
<h3 class="card-header">Ladezustände (Skeleton)</h3>
|
||||
<div *ngIf="isLoading" class="component-grid">
|
||||
<div class="skeleton-card card">
|
||||
<app-skeleton type="avatar"></app-skeleton>
|
||||
<div class="skeleton-content">
|
||||
<app-skeleton type="line"></app-skeleton
|
||||
><app-skeleton type="line" width="70%"></app-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="skeleton-card card">
|
||||
<app-skeleton type="avatar"></app-skeleton>
|
||||
<div class="skeleton-content">
|
||||
<app-skeleton type="line" width="50%"></app-skeleton
|
||||
><app-skeleton type="line" width="80%"></app-skeleton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body" *ngIf="!isLoading">
|
||||
<app-alert type="success"
|
||||
><strong>Inhalt erfolgreich geladen!</strong></app-alert
|
||||
>
|
||||
</div>
|
||||
</app-card>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- 3. OVERLAYS -->
|
||||
<app-dialog
|
||||
[isOpen]="isDialogOpen"
|
||||
(close)="closeDialog()"
|
||||
title="Bestellung löschen?"
|
||||
<div class="dashboard-grid">
|
||||
<app-kpi-card
|
||||
*ngFor="let kpi of kpiData"
|
||||
[value]="kpi.value"
|
||||
[label]="kpi.label"
|
||||
[color]="kpi.color"
|
||||
[iconName]="kpi.iconName"
|
||||
>
|
||||
<div dialog-content>
|
||||
<div class="dialog-icon-container">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path
|
||||
d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"
|
||||
></path>
|
||||
<line x1="12" y1="9" x2="12" y2="13"></line>
|
||||
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
||||
</svg>
|
||||
</div>
|
||||
<p>Sind Sie sicher? Diese Aktion kann nicht rückgängig gemacht werden.</p>
|
||||
</div>
|
||||
<div dialog-actions>
|
||||
<app-button buttonType="stroked" (click)="closeDialog()"
|
||||
>Abbrechen</app-button
|
||||
>
|
||||
<app-button buttonType="primary" (click)="closeDialog()"
|
||||
>Ja, endgültig löschen</app-button
|
||||
>
|
||||
</div>
|
||||
</app-dialog>
|
||||
</app-kpi-card>
|
||||
</div>
|
||||
|
||||
<app-orders-table
|
||||
[data]="ordersData"
|
||||
[itemsPerPage]="5"
|
||||
(view)="handleViewDetails($event)"
|
||||
(edit)="handleEditOrder($event)"
|
||||
(delete)="handleDeleteOrder($event)"
|
||||
>
|
||||
</app-orders-table>
|
||||
|
||||
@@ -1,147 +1,157 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { SnackbarService } from '../../../../shared/services/snackbar.service';
|
||||
|
||||
// Importieren ALLER wiederverwendbaren Komponenten, die im Template genutzt werden
|
||||
import { ButtonComponent } from '../../../../shared/components/ui/button/button.component';
|
||||
import { CardComponent } from '../../../../shared/components/ui/card/card.component';
|
||||
import { ChipComponent } from '../../../../shared/components/ui/chip/chip.component';
|
||||
import { FormFieldComponent } from '../../../../shared/components/form/form-field/form-field.component';
|
||||
import { KpiCardComponent } from '../../../../shared/components/data-display/kpi-card/kpi-card.component';
|
||||
import { PageHeaderComponent } from '../../../../shared/components/layout/page-header/page-header.component';
|
||||
import { SlideToggleComponent } from '../../../../shared/components/form/slide-toggle/slide-toggle.component';
|
||||
import { StatusPillComponent } from '../../../../shared/components/ui/status-pill/status-pill.component';
|
||||
import { DialogComponent } from '../../../../shared/components/overlays/dialog/dialog.component';
|
||||
// Wir müssen KpiColor hier importieren, um es als Typ verwenden zu können
|
||||
import {
|
||||
MenuComponent,
|
||||
MenuItem,
|
||||
} from '../../../../shared/components/overlays/menu/menu.component';
|
||||
import { AlertComponent } from '../../../../shared/components/ui/alert/alert.component';
|
||||
KpiCardComponent,
|
||||
KpiColor,
|
||||
} from '../../../../shared/components/data-display/kpi-card/kpi-card.component';
|
||||
import {
|
||||
OrdersTableComponent,
|
||||
Order,
|
||||
} from '../../../../shared/components/data-display/orders-table/orders-table.component';
|
||||
import { PaginatorComponent } from '../../../../shared/components/data-display/paginator/paginator.component';
|
||||
import { SkeletonComponent } from '../../../../shared/components/ui/skeleton/skeleton.component';
|
||||
import { ExpansionPanelComponent } from '../../../../shared/components/layout/expansion-panel/expansion-panel.component';
|
||||
import { SidebarComponent } from '../../../../shared/components/layout/sidebar/sidebar.component';
|
||||
|
||||
import { OrdersTableComponent, Order } from '../../../../shared/components/data-display/orders-table/orders-table.component';
|
||||
import { FormSelectComponent, SelectOption } from '../../../../shared/components/form/form-select/form-select.component';
|
||||
import { FormTextareaComponent } from '../../../../shared/components/form/form-textarea/form-textarea.component';
|
||||
// Wir definieren ein Interface für unsere KPI-Daten für Typsicherheit
|
||||
interface Kpi {
|
||||
value: string;
|
||||
label: string;
|
||||
color: KpiColor; // <-- Hier verwenden wir den importierten Typ
|
||||
iconName: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-demo2',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
ButtonComponent,
|
||||
CardComponent,
|
||||
ChipComponent,
|
||||
FormFieldComponent,
|
||||
KpiCardComponent,
|
||||
PageHeaderComponent,
|
||||
SlideToggleComponent,
|
||||
StatusPillComponent,
|
||||
DialogComponent,
|
||||
MenuComponent,
|
||||
AlertComponent,
|
||||
PaginatorComponent,
|
||||
SkeletonComponent,
|
||||
ExpansionPanelComponent,
|
||||
SidebarComponent,
|
||||
OrdersTableComponent,
|
||||
FormSelectComponent,
|
||||
FormTextareaComponent
|
||||
PaginatorComponent,
|
||||
],
|
||||
templateUrl: './demo2.component.html',
|
||||
styleUrl: './demo2.component.css',
|
||||
})
|
||||
export class Demo2Component implements OnInit {
|
||||
// Zustands-Variablen für diese Demo-Seite
|
||||
isLoading = true;
|
||||
isDialogOpen = false;
|
||||
// isComponentMenuOpen = false; // <--- DIESE ZEILE ENTFERNEN, DA SIE NICHT MEHR BENÖTIGT WIRD
|
||||
|
||||
// Eigenschaften für den Paginator
|
||||
currentPage = 1;
|
||||
totalItems = 123;
|
||||
itemsPerPage = 10;
|
||||
|
||||
actionMenuItems: MenuItem[] = [
|
||||
export class Demo2Component {
|
||||
kpiData: Kpi[] = [
|
||||
{
|
||||
label: 'Bearbeiten',
|
||||
action: () => this.snackbarService.show('Bearbeiten geklickt!'),
|
||||
value: '€ 14.750',
|
||||
label: 'Umsatz',
|
||||
color: 'green',
|
||||
iconName: 'placeholder',
|
||||
},
|
||||
{
|
||||
label: 'Kopieren',
|
||||
action: () => console.log('Kopieren geklickt!'),
|
||||
value: '1.284',
|
||||
label: 'Neue Nutzer',
|
||||
color: 'blue',
|
||||
iconName: 'placeholder',
|
||||
},
|
||||
{
|
||||
dividerBefore: true,
|
||||
label: 'Löschen',
|
||||
action: () => this.openDialog(), // Öffnet z.B. den Bestätigungs-Dialog
|
||||
isDanger: true,
|
||||
value: '312',
|
||||
label: 'Bestellungen',
|
||||
color: 'orange',
|
||||
iconName: 'placeholder',
|
||||
},
|
||||
{
|
||||
value: '99.8%',
|
||||
label: 'Verfügbarkeit',
|
||||
color: 'purple',
|
||||
iconName: 'placeholder',
|
||||
},
|
||||
];
|
||||
|
||||
ordersData: Order[] = [
|
||||
ordersData: Order[] = [
|
||||
{
|
||||
id: '10543',
|
||||
user: { name: 'Max Mustermann', email: 'max.mustermann@example.com', avatarUrl: 'https://i.pravatar.cc/40?u=max' },
|
||||
user: {
|
||||
name: 'Max Mustermann',
|
||||
email: 'max.m@example.com',
|
||||
avatarUrl: 'https://i.pravatar.cc/40?u=max',
|
||||
},
|
||||
amount: '€ 129,99',
|
||||
status: 'success',
|
||||
statusText: 'Abgeschlossen'
|
||||
statusText: 'Abgeschlossen',
|
||||
},
|
||||
{
|
||||
id: '10542',
|
||||
user: { name: 'Erika Mustermann', email: 'erika.m@example.com', avatarUrl: 'https://i.pravatar.cc/40?u=erika' },
|
||||
user: {
|
||||
name: 'Erika Mustermann',
|
||||
email: 'erika.m@example.com',
|
||||
avatarUrl: 'https://i.pravatar.cc/40?u=erika',
|
||||
},
|
||||
amount: '€ 49,50',
|
||||
status: 'warning',
|
||||
statusText: 'In Bearbeitung'
|
||||
statusText: 'In Bearbeitung',
|
||||
},
|
||||
{
|
||||
id: '10541',
|
||||
user: { name: 'Peter Pan', email: 'peter.pan@example.com', avatarUrl: 'https://i.pravatar.cc/40?u=peter' },
|
||||
user: {
|
||||
name: 'Peter Pan',
|
||||
email: 'peter.p@example.com',
|
||||
avatarUrl: 'https://i.pravatar.cc/40?u=peter',
|
||||
},
|
||||
amount: '€ 87,00',
|
||||
status: 'danger',
|
||||
statusText: 'Storniert'
|
||||
}
|
||||
statusText: 'Storniert',
|
||||
},
|
||||
{
|
||||
id: '10543',
|
||||
user: {
|
||||
name: 'Max Mustermann',
|
||||
email: 'max.m@example.com',
|
||||
avatarUrl: 'https://i.pravatar.cc/40?u=max',
|
||||
},
|
||||
amount: '€ 129,99',
|
||||
status: 'success',
|
||||
statusText: 'Abgeschlossen',
|
||||
},
|
||||
{
|
||||
id: '10542',
|
||||
user: {
|
||||
name: 'Erika Mustermann',
|
||||
email: 'erika.m@example.com',
|
||||
avatarUrl: 'https://i.pravatar.cc/40?u=erika',
|
||||
},
|
||||
amount: '€ 49,50',
|
||||
status: 'warning',
|
||||
statusText: 'In Bearbeitung',
|
||||
},
|
||||
{
|
||||
id: '10541',
|
||||
user: {
|
||||
name: 'Peter Pan',
|
||||
email: 'peter.p@example.com',
|
||||
avatarUrl: 'https://i.pravatar.cc/40?u=peter',
|
||||
},
|
||||
amount: '€ 87,00',
|
||||
status: 'danger',
|
||||
statusText: 'Storniert',
|
||||
},
|
||||
];
|
||||
|
||||
cityOptions: SelectOption[] = [
|
||||
{ value: 'berlin', label: 'Berlin' },
|
||||
{ value: 'munich', label: 'München' },
|
||||
{ value: 'hamburg', label: 'Hamburg' }
|
||||
];
|
||||
// Eigenschaften für den Paginator
|
||||
currentPage = 1;
|
||||
totalItems = this.ordersData.length;
|
||||
itemsPerPage = 10;
|
||||
|
||||
// --- EVENT-HANDLER FÜR DIE KIND-KOMPONENTEN ---
|
||||
|
||||
constructor(private snackbarService: SnackbarService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
setTimeout(() => {
|
||||
this.isLoading = false;
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
// Methoden für den Dialog
|
||||
openDialog(): void {
|
||||
this.isDialogOpen = true;
|
||||
}
|
||||
closeDialog(): void {
|
||||
this.isDialogOpen = false;
|
||||
}
|
||||
|
||||
// Methode für den Snackbar-Trigger
|
||||
triggerSnackbar(): void {
|
||||
const time = new Date().toLocaleTimeString();
|
||||
this.snackbarService.show('Neues Ereignis um ' + time);
|
||||
}
|
||||
|
||||
// Methode für den Paginator
|
||||
onPageChange(newPage: number): void {
|
||||
this.currentPage = newPage;
|
||||
console.log('Wechsle zu Seite:', newPage);
|
||||
// Hier würde die Logik zum Neuladen der Tabellendaten folgen
|
||||
console.log('Seite gewechselt zu:', newPage);
|
||||
// In einer echten Anwendung würden Sie hier die Daten neu laden
|
||||
}
|
||||
|
||||
handleDeleteOrder(orderId: string) {
|
||||
handleDeleteOrder(orderId: string): void {
|
||||
console.log('Lösche Bestellung mit ID:', orderId);
|
||||
this.openDialog(); // Öffnet z.B. den globalen Dialog
|
||||
// Hier könnten Sie z.B. einen Bestätigungs-Dialog öffnen
|
||||
}
|
||||
handleViewDetails(orderId: string): void {
|
||||
console.log('View Bestellung mit ID:', orderId);
|
||||
// Hier könnten Sie z.B. einen Bestätigungs-Dialog öffnen
|
||||
}
|
||||
handleEditOrder(orderId: string): void {
|
||||
console.log('Edit Bestellung mit ID:', orderId);
|
||||
// Hier könnten Sie z.B. einen Bestätigungs-Dialog öffnen
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user