This commit is contained in:
Tizian.Breuch
2025-10-29 18:54:23 +01:00
parent 9173f9b625
commit 8df2420aa0
6 changed files with 67 additions and 42 deletions

View File

@@ -18,7 +18,8 @@ h4[card-header] { margin-bottom: 0; }
.form-label { font-weight: 500; color: #334155; } .form-label { font-weight: 500; color: #334155; }
.required-indicator { color: var(--color-danger); margin-left: 4px; } .required-indicator { color: var(--color-danger); margin-left: 4px; }
.form-hint { font-size: 0.875rem; color: var(--text-color-secondary); margin-top: -0.75rem; } .form-hint { font-size: 0.875rem; color: var(--text-color-secondary); margin-top: -0.75rem; }
.input-with-button { display: flex; gap: 0.5rem; } .input-with-button { display: flex; flex-direction: row; gap: 0.5rem; }
.sku-input {width: 100%;}
.input-with-button .form-input { flex-grow: 1; } .input-with-button .form-input { flex-grow: 1; }
.price-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: var(--grid-gap); } .price-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: var(--grid-gap); }

View File

@@ -75,29 +75,26 @@
</app-form-group> </app-form-group>
<app-form-group title="Organisation" description=""> <app-form-group title="Organisation" description="">
<app-card>
<h4 card-header>Organisation</h4>
<div class="form-section">
<div class="input-with-button"> <div class="input-with-button">
<app-form-field label="SKU (Artikelnummer)" type="text" formControlName="sku" [control]="productForm.get('sku')"></app-form-field> <app-form-field class="sku-input" label="SKU (Artikelnummer)" type="text" formControlName="sku" [control]="productForm.get('sku')"></app-form-field>
<app-button buttonType="icon" (click)="generateSku()" iconName="placeholder"></app-button> <app-button buttonType="icon" (click)="generateSku()" iconName="placeholder"></app-button>
</div> </div>
<app-form-field label="Lagerbestand" type="number" formControlName="stockQuantity" [control]="productForm.get('stockQuantity')"></app-form-field> <app-form-field label="Lagerbestand" type="number" formControlName="stockQuantity" [control]="productForm.get('stockQuantity')"></app-form-field>
<app-form-field label="Gewicht (kg)" type="number" formControlName="weight" [control]="productForm.get('weight')"></app-form-field> <app-form-field label="Gewicht (kg)" type="number" formControlName="weight" [control]="productForm.get('weight')"></app-form-field>
<app-form-select label="Lieferant" [options]="supplierOptions" formControlName="supplierId"></app-form-select> <app-form-select label="Lieferant" [options]="supplierOptions" formControlName="supplierId"></app-form-select>
</div>
</app-card>
</app-form-group>
<app-card>
<h4 card-header>Kategorien</h4>
<div class="form-section">
<div class="multi-select-container"> <div class="multi-select-container">
<div class="selected-pills"> <div class="selected-pills">
<span *ngFor="let catId of categorieIds.value" class="pill"> <app-status-pill
{{ getCategoryName(catId) }} *ngFor="let catId of categorieIds.value"
<app-icon iconName="x" (click)="removeCategoryById(catId)"></app-icon> [text]="getCategoryName(catId)"
</span> status="info"
(remove)="removeCategoryById(catId)">
</app-status-pill>
<span *ngIf="categorieIds.length === 0" class="placeholder">Keine ausgewählt</span> <span *ngIf="categorieIds.length === 0" class="placeholder">Keine ausgewählt</span>
</div> </div>
<div class="category-checkbox-group"> <div class="category-checkbox-group">
@@ -107,8 +104,9 @@
</label> </label>
</div> </div>
</div> </div>
</div>
</app-card> </app-form-group>
</div> </div>
</div> </div>

View File

@@ -24,6 +24,7 @@ import { FormTextareaComponent } from '../../../../shared/components/form/form-t
import { SlideToggleComponent } from '../../../../shared/components/form/slide-toggle/slide-toggle.component'; import { SlideToggleComponent } from '../../../../shared/components/form/slide-toggle/slide-toggle.component';
import { SnackbarService } from '../../../../shared/services/snackbar.service'; import { SnackbarService } from '../../../../shared/services/snackbar.service';
import { FormGroupComponent } from '../../../../shared/components/form/form-group/form-group.component'; import { FormGroupComponent } from '../../../../shared/components/form/form-group/form-group.component';
import { StatusPillComponent } from '../../../../shared/components/ui/status-pill/status-pill.component';
// Interface für eine einheitliche Bild-Datenstruktur, die von der Elternkomponente kommt // Interface für eine einheitliche Bild-Datenstruktur, die von der Elternkomponente kommt
export interface ImagePreview { export interface ImagePreview {
@@ -47,6 +48,7 @@ export interface ImagePreview {
FormTextareaComponent, FormTextareaComponent,
SlideToggleComponent, SlideToggleComponent,
FormGroupComponent, FormGroupComponent,
StatusPillComponent
], ],
templateUrl: './product-form.component.html', templateUrl: './product-form.component.html',
styleUrls: ['./product-form.component.css'], styleUrls: ['./product-form.component.css'],

View File

@@ -49,3 +49,5 @@
.pill-inactive { color: rgb(168, 168, 168); background-color: #ececec; border-color: #777777; } .pill-inactive { color: rgb(168, 168, 168); background-color: #ececec; border-color: #777777; }
:host-context(body.dark-theme) .pill-inactive { color: rgb(168, 168, 168); background-color: #ececec; border-color: #777777; } :host-context(body.dark-theme) .pill-inactive { color: rgb(168, 168, 168); background-color: #ececec; border-color: #777777; }

View File

@@ -1,3 +1,5 @@
<!-- /src/app/shared/components/ui/status-pill/status-pill.component.html -->
<div class="status-pill" [ngClass]="cssClass"> <div class="status-pill" [ngClass]="cssClass">
{{ displayText }} <span>{{ displayText }}</span>
</div> </div>

View File

@@ -1,23 +1,35 @@
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; // /src/app/shared/components/ui/status-pill/status-pill.component.ts
import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
import { CommonModule, NgClass } from '@angular/common'; import { CommonModule, NgClass } from '@angular/common';
// import { OrderStatus } from '../../../../core/types/order'; import { IconComponent } from '../icon/icon.component'; // IconComponent importieren
@Component({ @Component({
selector: 'app-status-pill', selector: 'app-status-pill',
standalone: true, standalone: true,
imports: [CommonModule, NgClass], imports: [CommonModule, NgClass, IconComponent], // IconComponent hinzufügen
templateUrl: './status-pill.component.html', templateUrl: './status-pill.component.html',
styleUrl: './status-pill.component.css' styleUrls: ['./status-pill.component.css']
}) })
export class StatusPillComponent implements OnChanges { export class StatusPillComponent implements OnChanges {
// Nimmt jetzt den neuen, sprechenden Status entgegen // --- INPUTS ---
// Nimmt den Status für die Farbe entgegen
@Input() status: string | boolean = 'info'; @Input() status: string | boolean = 'info';
// Diese Eigenschaften werden vom Template verwendet // NEU: Nimmt einen expliziten Text entgegen. Hat Vorrang vor dem Status-Text.
@Input() text?: string;
// NEU: Steuert, ob der "Entfernen"-Button angezeigt wird
@Input() removable = false;
// --- OUTPUT ---
// NEU: Wird ausgelöst, wenn der Entfernen-Button geklickt wird
@Output() remove = new EventEmitter<void>();
// --- Interne Eigenschaften für das Template ---
public displayText = ''; public displayText = '';
public cssClass = ''; public cssClass = '';
// Eine Map, die Statusnamen auf Text und CSS-Klasse abbildet
private statusMap = new Map<any, { text: string, css: string }>([ private statusMap = new Map<any, { text: string, css: string }>([
['completed', { text: 'Abgeschlossen', css: 'pill-success' }], ['completed', { text: 'Abgeschlossen', css: 'pill-success' }],
['processing', { text: 'In Bearbeitung', css: 'pill-warning' }], ['processing', { text: 'In Bearbeitung', css: 'pill-warning' }],
@@ -28,16 +40,24 @@ export class StatusPillComponent implements OnChanges {
]); ]);
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
if (changes['status']) { if (changes['status'] || changes['text']) {
let statusKey = this.status; let statusKey = this.status;
// Konvertiere boolean in einen String-Key
if (typeof statusKey === 'boolean') { if (typeof statusKey === 'boolean') {
statusKey = statusKey ? 'active' : 'inactive'; statusKey = statusKey ? 'active' : 'inactive';
} }
const details = this.statusMap.get(statusKey as string) || { text: statusKey.toString(), css: 'pill-secondary' }; const details = this.statusMap.get(statusKey as string) || { text: 'Info', css: 'pill-secondary' };
this.displayText = details.text;
// NEUE LOGIK: Wenn ein expliziter Text übergeben wird, hat dieser Vorrang
this.displayText = this.text ?? details.text;
this.cssClass = details.css; this.cssClass = details.css;
} }
} }
// Methode, die das Event auslöst
onRemove(): void {
this.remove.emit();
}
} }