good
This commit is contained in:
@@ -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); }
|
||||||
|
|
||||||
|
|||||||
@@ -75,40 +75,38 @@
|
|||||||
</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>
|
<div class="multi-select-container">
|
||||||
<app-card>
|
<div class="selected-pills">
|
||||||
<h4 card-header>Kategorien</h4>
|
<app-status-pill
|
||||||
<div class="form-section">
|
*ngFor="let catId of categorieIds.value"
|
||||||
<div class="multi-select-container">
|
[text]="getCategoryName(catId)"
|
||||||
<div class="selected-pills">
|
status="info"
|
||||||
<span *ngFor="let catId of categorieIds.value" class="pill">
|
(remove)="removeCategoryById(catId)">
|
||||||
{{ getCategoryName(catId) }}
|
</app-status-pill>
|
||||||
<app-icon iconName="x" (click)="removeCategoryById(catId)"></app-icon>
|
<span *ngIf="categorieIds.length === 0" class="placeholder">Keine ausgewählt</span>
|
||||||
</span>
|
</div>
|
||||||
<span *ngIf="categorieIds.length === 0" class="placeholder">Keine ausgewählt</span>
|
<div class="category-checkbox-group">
|
||||||
</div>
|
<label *ngFor="let category of allCategories">
|
||||||
<div class="category-checkbox-group">
|
<input type="checkbox" [value]="category.id" [checked]="isCategorySelected(category.id)" (change)="onCategoryChange($event)" />
|
||||||
<label *ngFor="let category of allCategories">
|
{{ category.name }}
|
||||||
<input type="checkbox" [value]="category.id" [checked]="isCategorySelected(category.id)" (change)="onCategoryChange($event)" />
|
</label>
|
||||||
{{ category.name }}
|
</div>
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</app-card>
|
</app-form-group>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -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'],
|
||||||
|
|||||||
@@ -48,4 +48,6 @@
|
|||||||
:host-context(body.dark-theme) .pill-active { color: #a7f3d0; background-color: #166534; border-color: #22c55e; }
|
:host-context(body.dark-theme) .pill-active { color: #a7f3d0; background-color: #166534; border-color: #22c55e; }
|
||||||
|
|
||||||
.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; }
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -1,24 +1,36 @@
|
|||||||
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 ---
|
||||||
@Input() status: string | boolean = 'info';
|
// Nimmt den Status für die Farbe entgegen
|
||||||
|
@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' }],
|
||||||
['cancelled', { text: 'Storniert', css: 'pill-danger' }],
|
['cancelled', { text: 'Storniert', css: 'pill-danger' }],
|
||||||
@@ -27,17 +39,25 @@ export class StatusPillComponent implements OnChanges {
|
|||||||
['inactive', { text: 'Nein', css: 'pill-inactive' }]
|
['inactive', { text: 'Nein', css: 'pill-inactive' }]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user