From 5601cd011052f5e7b40e6ec3d08fc848bd9f9187 Mon Sep 17 00:00:00 2001 From: "Tizian.Breuch" Date: Tue, 9 Sep 2025 11:47:48 +0200 Subject: [PATCH] styles --- public/icons/bolt.svg | 1 + public/icons/delete.svg | 1 + public/icons/edit.svg | 1 + public/icons/eye.svg | 1 + public/icons/group.svg | 1 + public/icons/money.svg | 1 + public/icons/shopping_bag.svg | 1 + src/app/app.config.ts | 27 ++- .../components/demo2/demo2.component.html | 225 ++++++------------ .../kpi-card/kpi-card.component.css | 23 +- .../kpi-card/kpi-card.component.html | 20 +- .../kpi-card/kpi-card.component.ts | 11 +- .../ui/button/button.component.html | 7 +- .../components/ui/button/button.component.ts | 13 +- .../components/ui/icon/icon.component.css | 10 +- .../components/ui/icon/icon.component.ts | 82 +++++-- 16 files changed, 223 insertions(+), 202 deletions(-) create mode 100644 public/icons/bolt.svg create mode 100644 public/icons/delete.svg create mode 100644 public/icons/edit.svg create mode 100644 public/icons/eye.svg create mode 100644 public/icons/group.svg create mode 100644 public/icons/money.svg create mode 100644 public/icons/shopping_bag.svg diff --git a/public/icons/bolt.svg b/public/icons/bolt.svg new file mode 100644 index 0000000..a52742b --- /dev/null +++ b/public/icons/bolt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/delete.svg b/public/icons/delete.svg new file mode 100644 index 0000000..e14f217 --- /dev/null +++ b/public/icons/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/edit.svg b/public/icons/edit.svg new file mode 100644 index 0000000..2f14bcc --- /dev/null +++ b/public/icons/edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/eye.svg b/public/icons/eye.svg new file mode 100644 index 0000000..bd73013 --- /dev/null +++ b/public/icons/eye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/group.svg b/public/icons/group.svg new file mode 100644 index 0000000..5c61dee --- /dev/null +++ b/public/icons/group.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/money.svg b/public/icons/money.svg new file mode 100644 index 0000000..b9ed77a --- /dev/null +++ b/public/icons/money.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/shopping_bag.svg b/public/icons/shopping_bag.svg new file mode 100644 index 0000000..8cdb9b3 --- /dev/null +++ b/public/icons/shopping_bag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/app.config.ts b/src/app/app.config.ts index 11f35e5..5df1e55 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -1,15 +1,34 @@ import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; -import { provideAnimations } from '@angular/platform-browser/animations'; // Importieren +import { provideAnimations } from '@angular/platform-browser/animations'; + +import { provideHttpClient, withFetch } from '@angular/common/http'; +import { provideClientHydration } from '@angular/platform-browser'; + +// +++ HIER IST DIE DEFINITIVE KORREKTUR FÜR FORMS-PROVIDER +++ +import { + ReactiveFormsModule, // <-- Importieren des Moduls selbst + FormsModule // <-- Importieren des Moduls für Template-driven forms (falls benötigt) +} from '@angular/forms'; import { routes } from './app.routes'; -import { provideClientHydration, withEventReplay } from '@angular/platform-browser'; export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), - provideClientHydration(withEventReplay()), - provideAnimations() // Hier hinzufügen + provideAnimations(), + + provideHttpClient(withFetch()), + provideClientHydration(), + + // +++ Korrigierte Verwendung der Forms-Provider +++ + // Dies macht die Provider für Reactive Forms global verfügbar + ReactiveFormsModule.withConfig({ + warnOnNgModelWithFormControl: 'never' // Optional: Schaltet eine NgModel Warnung aus + }).providers!, // <--- Korrigiert + + // Falls Sie Template-Driven Forms (mit NgModel) benötigen, würden Sie das hinzufügen: + // FormsModule.withConfig({}).providers! ] }; \ No newline at end of file diff --git a/src/app/features/demo/components/demo2/demo2.component.html b/src/app/features/demo/components/demo2/demo2.component.html index 929b3fa..96c6974 100644 --- a/src/app/features/demo/components/demo2/demo2.component.html +++ b/src/app/features/demo/components/demo2/demo2.component.html @@ -88,76 +88,48 @@
- - - - - - - - - - - - - - - - -

Letzte Bestellungen

+ + + + + + + +

Umsatzentwicklung

+
+
Jan
+
Feb
+
Mär
+
Apr
+
Mai
+
Jun
+
+
+ + +

Letzte Bestellungen

@@ -212,65 +184,26 @@ -
€ 129,99 - - - - - + + + + - - - -
@@ -282,24 +215,9 @@ >
- - -

Umsatzentwicklung

-
-
Jan
-
Feb
-
Mär
-
Apr
-
Mai
-
Jun
-
-
- - - -

Moderne Formular-Elemente

+

Moderne Formular-Elemente

@@ -325,26 +243,21 @@ -

Buttons, Chips & Interaktion

+

Buttons, Chips & Interaktion

Primary Secondary + Stroked + Flat - ... + +
@@ -373,11 +286,13 @@ >3
+ +
-

Indikatoren & Feedback

+

Indikatoren & Feedback

Snackbar anzeigen -

Navigation & Layout

+

Navigation & Layout

-

Ladezustände (Skeleton)

+

Ladezustände (Skeleton)

diff --git a/src/app/shared/components/data-display/kpi-card/kpi-card.component.css b/src/app/shared/components/data-display/kpi-card/kpi-card.component.css index 086b07a..80d944f 100644 --- a/src/app/shared/components/data-display/kpi-card/kpi-card.component.css +++ b/src/app/shared/components/data-display/kpi-card/kpi-card.component.css @@ -16,19 +16,28 @@ border-radius: 50%; display: grid; place-items: center; - color: #fff; flex-shrink: 0; + background-color: var(--color-surface); } -.kpi-icon ::ng-deep svg { +.kpi-icon app-icon { width: 24px; height: 24px; + color: #fff; } -.icon-sales { background: linear-gradient(135deg, #2ecc71, #27ae60); } -.icon-users { background: linear-gradient(135deg, #3498db, #2980b9); } -.icon-orders { background: linear-gradient(135deg, #f39c12, #f1c40f); } -.icon-performance { background: linear-gradient(135deg, #9b59b6, #8e44ad); } +.icon-blue { + background: linear-gradient(135deg, #3498db, #2980b9); +} +.icon-green { + background: linear-gradient(135deg, #2ecc71, #27ae60); +} +.icon-orange { + background: linear-gradient(135deg, #f39c12, #f1c40f); +} +.icon-purple { + background: linear-gradient(135deg, #9b59b6, #8e44ad); +} .kpi-content { display: flex; @@ -44,4 +53,4 @@ .kpi-label { font-size: 0.9rem; color: var(--color-text-light); -} \ No newline at end of file +} diff --git a/src/app/shared/components/data-display/kpi-card/kpi-card.component.html b/src/app/shared/components/data-display/kpi-card/kpi-card.component.html index 6a07791..768cb10 100644 --- a/src/app/shared/components/data-display/kpi-card/kpi-card.component.html +++ b/src/app/shared/components/data-display/kpi-card/kpi-card.component.html @@ -1,15 +1,19 @@
-
- - + [class.icon-blue]="color === 'blue'" + [class.icon-green]="color === 'green'" + [class.icon-orange]="color === 'orange'" + [class.icon-purple]="color === 'purple'" + > +
{{ value }} {{ label }}
-
\ No newline at end of file +
diff --git a/src/app/shared/components/data-display/kpi-card/kpi-card.component.ts b/src/app/shared/components/data-display/kpi-card/kpi-card.component.ts index dad6ede..e82288a 100644 --- a/src/app/shared/components/data-display/kpi-card/kpi-card.component.ts +++ b/src/app/shared/components/data-display/kpi-card/kpi-card.component.ts @@ -1,17 +1,20 @@ import { Component, Input } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { IconComponent } from '../../ui/icon/icon.component'; -type KpiColor = 'sales' | 'users' | 'orders' | 'performance'; +type KpiColor = 'blue' | 'green' | 'orange' | 'purple'; @Component({ selector: 'app-kpi-card', standalone: true, - imports: [CommonModule], + imports: [CommonModule, IconComponent], templateUrl: './kpi-card.component.html', - styleUrl: './kpi-card.component.css' + styleUrl: './kpi-card.component.css', }) export class KpiCardComponent { @Input() value: string = ''; @Input() label: string = ''; - @Input() color: KpiColor = 'users'; + @Input() color: KpiColor = 'blue'; + @Input() iconName: string | null = null; + @Input() svgColor: string | null = null; } \ No newline at end of file diff --git a/src/app/shared/components/ui/button/button.component.html b/src/app/shared/components/ui/button/button.component.html index 708c027..1fbd80a 100644 --- a/src/app/shared/components/ui/button/button.component.html +++ b/src/app/shared/components/ui/button/button.component.html @@ -9,8 +9,9 @@ [class.btn-icon]="color === 'icon' || color === 'icon-danger'" [class.btn-icon-danger]="color === 'icon-danger'" [class.btn-full-width]="fullWidth" - [attr.data-tooltip]="tooltip"> - - + [attr.data-tooltip]="tooltip" +> + + \ No newline at end of file diff --git a/src/app/shared/components/ui/button/button.component.ts b/src/app/shared/components/ui/button/button.component.ts index 897eac5..e034126 100644 --- a/src/app/shared/components/ui/button/button.component.ts +++ b/src/app/shared/components/ui/button/button.component.ts @@ -1,13 +1,16 @@ import { Component, Input } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { IconComponent } from '../icon/icon.component'; -// Definiert die erlaubten Varianten für den Button type ButtonColor = 'primary' | 'secondary' | 'stroked' | 'flat' | 'icon' | 'icon-danger'; @Component({ selector: 'app-button', - - imports: [CommonModule], + standalone: true, + imports: [ + CommonModule, + IconComponent + ], templateUrl: './button.component.html', styleUrl: './button.component.css' }) @@ -17,6 +20,8 @@ export class ButtonComponent { @Input() disabled = false; @Input() fullWidth = false; - // Ein spezieller Input für Tooltips @Input() tooltip: string | null = null; + @Input() iconName: string | null = null; + // --- HIER IST DIE KORREKTUR: Umbenennung zu svgColor --- + @Input() svgColor: string | null = null; // Farbe des SVG-Inhalts im Button } \ No newline at end of file diff --git a/src/app/shared/components/ui/icon/icon.component.css b/src/app/shared/components/ui/icon/icon.component.css index 5c23ba6..956773a 100644 --- a/src/app/shared/components/ui/icon/icon.component.css +++ b/src/app/shared/components/ui/icon/icon.component.css @@ -3,12 +3,16 @@ display: inline-flex; align-items: center; justify-content: center; - width: 1em; /* Passt sich an die Schriftgröße des Elternelements an */ - height: 1em; + width: 1.75rem; + height: 1.75rem; + color: inherit; /* Wichtig, damit currentColor vom Elternelement übernommen wird */ } -/* Wir verwenden ::ng-deep, da das SVG-Element dynamisch eingefügt wird */ ::ng-deep .icon-svg { width: 100%; height: 100%; + stroke: currentColor; + /* HIER IST DIE KORREKTUR: fill muss ein gültiger CSS-Wert sein */ + stroke: currentColor; + fill: currentColor; } \ No newline at end of file diff --git a/src/app/shared/components/ui/icon/icon.component.ts b/src/app/shared/components/ui/icon/icon.component.ts index e7573a4..f117ae5 100644 --- a/src/app/shared/components/ui/icon/icon.component.ts +++ b/src/app/shared/components/ui/icon/icon.component.ts @@ -1,35 +1,89 @@ -import { Component, Input, OnChanges, SimpleChanges, ElementRef, Renderer2 } from '@angular/core'; -import { CommonModule } from '@angular/common'; +import { + Component, + Input, + OnChanges, + SimpleChanges, + ElementRef, + Renderer2, + Inject, + PLATFORM_ID, + TransferState, + makeStateKey, + StateKey +} from '@angular/core'; + +import { CommonModule, isPlatformBrowser } from '@angular/common'; import { HttpClient, HttpClientModule } from '@angular/common/http'; +import { tap } from 'rxjs/operators'; + +const ICON_SVG_KEY_PREFIX = 'icon-svg-'; + @Component({ selector: 'app-icon', - standalone: true, + standalone: true, imports: [CommonModule, HttpClientModule], - template: '', // Leeres Template, da wir das SVG direkt einfügen + template: '', styleUrl: './icon.component.css' }) export class IconComponent implements OnChanges { @Input() name: string = ''; + // --- HIER IST DIE KORREKTUR: Umbenennung zu svgColor --- + @Input() svgColor: string | null = null; // Farbe des SVG-Inhalts (Füllung/Linie) constructor( private http: HttpClient, private el: ElementRef, - private renderer: Renderer2 + private renderer: Renderer2, + private transferState: TransferState, + @Inject(PLATFORM_ID) private platformId: Object ) {} ngOnChanges(changes: SimpleChanges): void { - if (changes['name'] && this.name) { - // Lädt das SVG aus dem assets-Ordner und fügt es in die Komponente ein - this.http.get(`assets/icons/${this.name}.svg`, { responseType: 'text' }) + // Überprüfe Änderungen an 'name' ODER 'svgColor' + if ((changes['name'] && this.name) || (changes['svgColor'] && this.name)) { + this.loadSvg(); + } + } + + private loadSvg(): void { + const svgStateKey: StateKey = makeStateKey(ICON_SVG_KEY_PREFIX + this.name); + const cachedSvg = this.transferState.get(svgStateKey, null); + + this.el.nativeElement.innerHTML = ''; + + if (cachedSvg) { + this.setSvg(cachedSvg); + } else { + this.http.get(`icons/${this.name}.svg`, { responseType: 'text' }) + .pipe( + tap(svg => { + if (!isPlatformBrowser(this.platformId)) { + this.transferState.set(svgStateKey, svg); + } + }) + ) .subscribe(svg => { - this.el.nativeElement.innerHTML = svg; - // Optional: Fügt dem -Element selbst eine Klasse hinzu - const svgElement = this.el.nativeElement.querySelector('svg'); - if (svgElement) { - this.renderer.addClass(svgElement, 'icon-svg'); - } + this.setSvg(svg); }); } } + + private setSvg(svgContent: string): void { + this.el.nativeElement.innerHTML = svgContent; + const svgElement = this.el.nativeElement.querySelector('svg'); + if (svgElement) { + this.renderer.addClass(svgElement, 'icon-svg'); + + // --- HIER IST DIE KORREKTUR: svgColor anwenden --- + if (this.svgColor) { + this.renderer.setStyle(svgElement, 'fill', this.svgColor); // Füllfarbe + this.renderer.setStyle(svgElement, 'stroke', this.svgColor); // Linienfarbe + } else { + // Fallback zu currentColor, wenn keine Farbe übergeben wird + this.renderer.setStyle(svgElement, 'fill', 'currentColor'); + this.renderer.setStyle(svgElement, 'stroke', 'currentColor'); + } + } + } } \ No newline at end of file