diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
index 16c1407..c978050 100644
--- a/src/app/app.routes.ts
+++ b/src/app/app.routes.ts
@@ -12,9 +12,15 @@ export const routes: Routes = [
redirectTo: 'auth',
pathMatch: 'full',
},
-
{
- path: 'dashboard',
+ path: 'auth',
+ loadChildren: () =>
+ import('./features/components/auth/auth.routes').then(
+ (r) => r.AUTH_ROUTES
+ ),
+ },
+ {
+ path: 'shop',
component: DefaultLayoutComponent,
canActivate: [authGuard],
data: { requiredRole: 'Admin' },
@@ -26,60 +32,64 @@ export const routes: Routes = [
(r) => r.DASHBOARD_ROUTES
),
},
+ {
+ path: 'categories',
+ loadChildren: () =>
+ import('./features/components/categories/categories.routes').then(
+ (r) => r.CATEGORIES_ROUTES
+ ),
+ },
+ {
+ path: 'discounts',
+ loadChildren: () =>
+ import('./features/components/discounts/discounts.routes').then(
+ (r) => r.DISCOUNTS_ROUTES
+ ),
+ },
+ {
+ path: 'orders',
+ loadChildren: () =>
+ import('./features/components/orders/orders.routes').then(
+ (r) => r.ORDERS_ROUTES
+ ),
+ },
+ {
+ path: 'payment-methods',
+ loadChildren: () =>
+ import(
+ './features/components/payment-methods/payment-methods.routes'
+ ).then((r) => r.PAYMENT_METHODS_ROUTES),
+ },
+ {
+ path: 'products',
+ loadChildren: () =>
+ import('./features/components/products/products.routes').then(
+ (r) => r.PRODUCTS_ROUTES
+ ),
+ },
+ {
+ path: 'reviews',
+ loadChildren: () =>
+ import('./features/components/reviews/reviews.routes').then(
+ (r) => r.REVIEWS_ROUTES
+ ),
+ },
+ {
+ path: 'settings',
+ loadChildren: () =>
+ import('./features/components/settings/settings.routes').then(
+ (r) => r.SETTINGS_ROUTES
+ ),
+ },
+ {
+ path: 'shipping-methods',
+ loadChildren: () =>
+ import(
+ './features/components/shipping-methods/shipping-methods.routes'
+ ).then((r) => r.SHIPPING_METHODS_ROUTES),
+ },
],
},
- {
- path: 'auth',
- loadChildren: () =>
- import('./features/components/auth/auth.routes').then(
- (r) => r.AUTH_ROUTES
- ),
- },
- {
- path: 'categories',
- canActivate: [authGuard],
- data: { requiredRole: 'Admin' },
- loadChildren: () =>
- import('./features/components/categories/categories.routes').then(
- (r) => r.CATEGORIES_ROUTES
- ),
- },
- {
- path: 'discounts',
- canActivate: [authGuard],
- data: { requiredRole: 'Admin' },
- loadChildren: () =>
- import('./features/components/discounts/discounts.routes').then(
- (r) => r.DISCOUNTS_ROUTES
- ),
- },
- {
- path: 'orders',
- canActivate: [authGuard],
- data: { requiredRole: 'Admin' },
- loadChildren: () =>
- import('./features/components/orders/orders.routes').then(
- (r) => r.ORDERS_ROUTES
- ),
- },
- {
- path: 'payment-methods',
- canActivate: [authGuard],
- data: { requiredRole: 'Admin' },
- loadChildren: () =>
- import(
- './features/components/payment-methods/payment-methods.routes'
- ).then((r) => r.PAYMENT_METHODS_ROUTES),
- },
- {
- path: 'products',
- canActivate: [authGuard],
- data: { requiredRole: 'Admin' },
- loadChildren: () =>
- import('./features/components/products/products.routes').then(
- (r) => r.PRODUCTS_ROUTES
- ),
- },
{
path: 'access-denied',
component: AccessDeniedComponent,
@@ -90,7 +100,6 @@ export const routes: Routes = [
component: NotFoundComponent,
title: '404 - Seite nicht gefunden',
},
-
{
path: '**',
redirectTo: '404',
diff --git a/src/app/features/components/auth/login/login.component.ts b/src/app/features/components/auth/login/login.component.ts
index c58d130..db09024 100644
--- a/src/app/features/components/auth/login/login.component.ts
+++ b/src/app/features/components/auth/login/login.component.ts
@@ -67,7 +67,7 @@ export class LoginComponent {
if (response && response.isAuthSuccessful) {
this.logger.info('Admin login successful', { email: credentials.email });
// Erfolgreich eingeloggt -> Weiterleiten zum Admin-Dashboard
- this.router.navigate(['/dashboard']); // Passe die Route ggf. an
+ this.router.navigate(['/shop']); // Passe die Route ggf. an
} else {
// Login fehlgeschlagen (falsches Passwort etc.), vom Backend kontrolliert
this.errorMessage = 'E-Mail oder Passwort ist ungültig.';
diff --git a/src/app/features/components/products/product-list/product-list.component.html b/src/app/features/components/products/product-list/product-list.component.html
index 1f9bba8..2ebdc52 100644
--- a/src/app/features/components/products/product-list/product-list.component.html
+++ b/src/app/features/components/products/product-list/product-list.component.html
@@ -1,40 +1,120 @@
Produkte verwalten
+
diff --git a/src/app/features/components/products/product-list/product-list.component.ts b/src/app/features/components/products/product-list/product-list.component.ts
index b653525..5095adb 100644
--- a/src/app/features/components/products/product-list/product-list.component.ts
+++ b/src/app/features/components/products/product-list/product-list.component.ts
@@ -1,25 +1,36 @@
import { Component, OnInit, OnDestroy, inject } from '@angular/core';
-import { CommonModule, CurrencyPipe } from '@angular/common';
-import { FormBuilder, FormGroup, FormArray, FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
+import { CommonModule } from '@angular/common';
+import {
+ FormBuilder,
+ FormGroup,
+ FormArray,
+ FormControl,
+ ReactiveFormsModule,
+ Validators,
+} from '@angular/forms';
import { Observable, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
-// ... (alle anderen Imports bleiben gleich)
+// Models
+import {
+ AdminProduct,
+ ProductImage,
+} from '../../../../core/models/product.model';
+import { Category } from '../../../../core/models/category.model';
+import { Supplier } from '../../../../core/models/supplier.model';
+
+// Services
import { ProductService } from '../../../services/product.service';
import { CategoryService } from '../../../services/category.service';
import { SupplierService } from '../../../services/supplier.service';
-import { AdminProduct } from '../../../../core/models/product.model';
-import { Category } from '../../../../core/models/category.model';
-import { Supplier } from '../../../../core/models/supplier.model';
@Component({
selector: 'app-product-list',
standalone: true,
- imports: [CommonModule, ReactiveFormsModule, CurrencyPipe],
+ imports: [CommonModule, ReactiveFormsModule],
templateUrl: './product-list.component.html',
})
export class ProductListComponent implements OnInit, OnDestroy {
- // ... (alle Properties und der Konstruktor bleiben gleich)
private productService = inject(ProductService);
private categoryService = inject(CategoryService);
private supplierService = inject(SupplierService);
@@ -33,6 +44,11 @@ export class ProductListComponent implements OnInit, OnDestroy {
selectedProductId: string | null = null;
private nameChangeSubscription?: Subscription;
+ // Eigenschaften für das Bild-Management
+ existingImages: ProductImage[] = [];
+ mainImageFile: File | null = null;
+ additionalImageFiles: File[] = [];
+
constructor() {
this.productForm = this.fb.group({
name: ['', Validators.required],
@@ -48,37 +64,205 @@ export class ProductListComponent implements OnInit, OnDestroy {
isFeatured: [false],
featuredDisplayOrder: [0],
supplierId: [null],
- categorieIds: this.fb.array([])
+ categorieIds: this.fb.array([]),
+ imagesToDelete: this.fb.array([]), // FormArray für die IDs der zu löschenden Bilder
});
}
- // --- NEUE METHODE ZUM GENERIEREN DER SKU ---
+ // Getter für einfachen Zugriff auf FormArrays
+ get categorieIds(): FormArray {
+ return this.productForm.get('categorieIds') as FormArray;
+ }
+
+ get imagesToDelete(): FormArray {
+ return this.productForm.get('imagesToDelete') as FormArray;
+ }
+
+ ngOnInit(): void {
+ this.loadInitialData();
+ this.subscribeToNameChanges();
+ }
+
+ ngOnDestroy(): void {
+ this.nameChangeSubscription?.unsubscribe();
+ }
+
+ loadInitialData(): void {
+ this.products$ = this.productService.getAll();
+ this.allCategories$ = this.categoryService.getAll();
+ this.allSuppliers$ = this.supplierService.getAll();
+ }
+
+ selectProduct(product: AdminProduct): void {
+ this.selectedProductId = product.id;
+ this.productForm.patchValue(product);
+
+ this.categorieIds.clear();
+ product.categorieIds?.forEach((id) =>
+ this.categorieIds.push(this.fb.control(id))
+ );
+
+ this.existingImages = product.images || [];
+ }
+
+ clearSelection(): void {
+ this.selectedProductId = null;
+ this.productForm.reset({
+ name: '',
+ slug: '',
+ sku: '',
+ description: '',
+ price: 0,
+ oldPrice: null,
+ purchasePrice: null,
+ stockQuantity: 0,
+ weight: null,
+ isActive: true,
+ isFeatured: false,
+ featuredDisplayOrder: 0,
+ supplierId: null,
+ });
+ this.categorieIds.clear();
+ this.imagesToDelete.clear();
+ this.existingImages = [];
+ this.mainImageFile = null;
+ this.additionalImageFiles = [];
+ }
+
+ onMainFileChange(event: Event): void {
+ const file = (event.target as HTMLInputElement).files?.[0];
+ if (file) this.mainImageFile = file;
+ }
+
+ onAdditionalFilesChange(event: Event): void {
+ const files = (event.target as HTMLInputElement).files;
+ if (files) this.additionalImageFiles = Array.from(files);
+ }
+
+ deleteExistingImage(imageId: string, event: Event): void {
+ event.preventDefault();
+ this.imagesToDelete.push(this.fb.control(imageId));
+ this.existingImages = this.existingImages.filter(
+ (img) => img.id !== imageId
+ );
+ }
+
+ onCategoryChange(event: Event): void {
+ const checkbox = event.target as HTMLInputElement;
+ const categoryId = checkbox.value;
+ if (checkbox.checked) {
+ if (!this.categorieIds.value.includes(categoryId)) {
+ this.categorieIds.push(new FormControl(categoryId));
+ }
+ } else {
+ const index = this.categorieIds.controls.findIndex(
+ (x) => x.value === categoryId
+ );
+ if (index !== -1) {
+ this.categorieIds.removeAt(index);
+ }
+ }
+ }
+
+ isCategorySelected(categoryId: string): boolean {
+ return this.categorieIds.value.includes(categoryId);
+ }
+
generateSku(): void {
const name = this.productForm.get('name')?.value || 'PROD';
- // Nimmt die ersten 4 Buchstaben des Namens (oder weniger, falls kürzer)
const prefix = name.substring(0, 4).toUpperCase().replace(/\s+/g, '');
- // Hängt einen zufälligen, 6-stelligen alphanumerischen String an
const randomPart = Math.random().toString(36).substring(2, 8).toUpperCase();
const sku = `${prefix}-${randomPart}`;
this.productForm.get('sku')?.setValue(sku);
}
- // --- ENDE NEUE METHODE ---
+ onSubmit(): void {
+ if (this.productForm.invalid) return;
- get categorieIds(): FormArray {
- return this.productForm.get('categorieIds') as FormArray;
+ const formData = new FormData();
+ const formValue = this.productForm.value;
+
+ Object.keys(formValue).forEach((key) => {
+ const value = formValue[key];
+ if (key === 'categorieIds' || key === 'imagesToDelete') {
+ // FormArrays müssen speziell behandelt werden
+ (value as string[]).forEach((id) =>
+ formData.append(this.capitalizeFirstLetter(key), id)
+ );
+ } else if (value !== null && value !== undefined && value !== '') {
+ // Leere Strings für optionale number-Felder nicht mitsenden
+ if (
+ ['oldPrice', 'purchasePrice', 'weight'].includes(key) &&
+ value === ''
+ )
+ return;
+ formData.append(this.capitalizeFirstLetter(key), value);
+ }
+ });
+
+ if (this.mainImageFile) {
+ formData.append('MainImageFile', this.mainImageFile);
+ }
+ this.additionalImageFiles.forEach((file) => {
+ formData.append('AdditionalImageFiles', file);
+ });
+
+ if (this.selectedProductId) {
+ formData.append('Id', this.selectedProductId);
+ this.productService
+ .update(this.selectedProductId, formData)
+ .subscribe(() => this.reset());
+ } else {
+ this.productService.create(formData).subscribe(() => this.reset());
+ }
}
- ngOnInit(): void { this.loadInitialData(); this.subscribeToNameChanges(); }
- ngOnDestroy(): void { this.nameChangeSubscription?.unsubscribe(); }
- loadInitialData(): void { this.products$ = this.productService.getAll(); this.allCategories$ = this.categoryService.getAll(); this.allSuppliers$ = this.supplierService.getAll(); }
- selectProduct(product: AdminProduct): void { this.selectedProductId = product.id; this.productForm.patchValue(product); this.categorieIds.clear(); product.categorieIds?.forEach(id => this.categorieIds.push(this.fb.control(id))); }
- clearSelection(): void { this.selectedProductId = null; this.productForm.reset({ price: 0, stockQuantity: 0, isActive: true, isFeatured: false, featuredDisplayOrder: 0 }); this.categorieIds.clear(); }
- onCategoryChange(event: Event): void { const checkbox = event.target as HTMLInputElement; const categoryId = checkbox.value; if (checkbox.checked) { if (!this.categorieIds.value.includes(categoryId)) { this.categorieIds.push(new FormControl(categoryId)); } } else { const index = this.categorieIds.controls.findIndex(x => x.value === categoryId); if (index !== -1) { this.categorieIds.removeAt(index); } } }
- isCategorySelected(categoryId: string): boolean { return this.categorieIds.value.includes(categoryId); }
- onSubmit(): void { if (this.productForm.invalid) return; const formData = new FormData(); const formValue = this.productForm.value; Object.keys(formValue).forEach(key => { const value = formValue[key]; if (key === 'categorieIds') { (value as string[]).forEach(id => formData.append('CategorieIds', id)); } else if (value !== null && value !== undefined && value !== '') { if (['oldPrice', 'purchasePrice', 'weight'].includes(key) && value === '') return; formData.append(key, value); } }); if (this.selectedProductId) { formData.append('Id', this.selectedProductId); this.productService.update(this.selectedProductId, formData).subscribe(() => this.reset()); } else { this.productService.create(formData).subscribe(() => this.reset()); } }
- onDelete(id: string): void { if (confirm('Produkt wirklich löschen?')) { this.productService.delete(id).subscribe(() => this.loadInitialData()); } }
- private reset(): void { this.loadInitialData(); this.clearSelection(); }
- private subscribeToNameChanges(): void { this.nameChangeSubscription = this.productForm.get('name')?.valueChanges.pipe(debounceTime(300), distinctUntilChanged()).subscribe(name => { if (name && !this.productForm.get('slug')?.dirty) { const slug = this.generateSlug(name); this.productForm.get('slug')?.setValue(slug); } }); }
- private generateSlug(name: string): string { return name.toLowerCase().replace(/\s+/g, '-').replace(/[äöüß]/g, (char) => { switch (char) { case 'ä': return 'ae'; case 'ö': return 'oe'; case 'ü': return 'ue'; case 'ß': return 'ss'; default: return ''; } }).replace(/[^a-z0-9-]/g, '').replace(/-+/g, '-'); }
-
-}
\ No newline at end of file
+
+ onDelete(id: string): void {
+ if (confirm('Produkt wirklich löschen?')) {
+ this.productService.delete(id).subscribe(() => this.loadInitialData());
+ }
+ }
+
+ private reset(): void {
+ this.loadInitialData();
+ this.clearSelection();
+ }
+
+ private subscribeToNameChanges(): void {
+ this.nameChangeSubscription = this.productForm
+ .get('name')
+ ?.valueChanges.pipe(debounceTime(300), distinctUntilChanged())
+ .subscribe((name) => {
+ if (name && !this.productForm.get('slug')?.dirty) {
+ const slug = this.generateSlug(name);
+ this.productForm.get('slug')?.setValue(slug);
+ }
+ });
+ }
+
+ private generateSlug(name: string): string {
+ return name
+ .toLowerCase()
+ .replace(/\s+/g, '-')
+ .replace(/[äöüß]/g, (char) => {
+ switch (char) {
+ case 'ä':
+ return 'ae';
+ case 'ö':
+ return 'oe';
+ case 'ü':
+ return 'ue';
+ case 'ß':
+ return 'ss';
+ default:
+ return '';
+ }
+ })
+ .replace(/[^a-z0-9-]/g, '')
+ .replace(/-+/g, '-');
+ }
+
+ private capitalizeFirstLetter(string: string): string {
+ return string.charAt(0).toUpperCase() + string.slice(1);
+ }
+}
diff --git a/src/app/features/components/reviews/review-list/review-list.component.html b/src/app/features/components/reviews/review-list/review-list.component.html
index 8c12577..0724a43 100644
--- a/src/app/features/components/reviews/review-list/review-list.component.html
+++ b/src/app/features/components/reviews/review-list/review-list.component.html
@@ -1,30 +1,60 @@
+
+
Bewertungen verwalten
-
+
+
- | Kunde |
- Produkt |
- Bewertung |
- Titel |
+ Datum |
Status |
+ Produkt |
+ Kunde |
+ Bewertung (1-5) |
+ Titel / Kommentar |
Aktionen |
-
- | {{ review.customerName }} |
- {{ review.productName }} |
- {{ review.rating }}/5 |
- {{ review.title }} |
- {{ review.isApproved ? "Freigegeben" : "Ausstehend" }} |
-
-
-
- |
-
+
+
+
+ | Keine Bewertungen gefunden. |
+
+
+
+
+ | {{ review.reviewDate | date:'dd.MM.yyyy HH:mm' }} |
+
+
+ {{ review.isApproved ? 'Freigegeben' : 'Ausstehend' }}
+
+ |
+ {{ review.productName || 'N/A' }} |
+ {{ review.customerName }} |
+ {{ review.rating }} |
+
+
+
+
+ |
+
+
-
+
+
+
+
+ | Lade Bewertungen... |
+
+
+
+
\ No newline at end of file
diff --git a/src/app/features/components/reviews/review-list/review-list.component.ts b/src/app/features/components/reviews/review-list/review-list.component.ts
index 1707846..a481dc0 100644
--- a/src/app/features/components/reviews/review-list/review-list.component.ts
+++ b/src/app/features/components/reviews/review-list/review-list.component.ts
@@ -1,14 +1,19 @@
+// /src/app/features/admin/components/reviews/review-list/review-list.component.ts
+
import { Component, OnInit, inject } from '@angular/core';
-import { CommonModule } from '@angular/common';
+import { CommonModule, DatePipe } from '@angular/common';
import { Observable } from 'rxjs';
+
+// Models & Services
import { Review } from '../../../../core/models/review.model';
import { ReviewService } from '../../../services/review.service';
@Component({
selector: 'app-review-list',
standalone: true,
- imports: [CommonModule],
+ imports: [CommonModule, DatePipe], // DatePipe für die Formatierung des Datums hinzufügen
templateUrl: './review-list.component.html',
+ styleUrl: './review-list.component.css' // Optional: CSS für besseres Tabellen-Layout
})
export class ReviewListComponent implements OnInit {
private reviewService = inject(ReviewService);
@@ -23,12 +28,26 @@ export class ReviewListComponent implements OnInit {
}
onApprove(id: string): void {
- this.reviewService.approve(id).subscribe(() => this.loadReviews());
+ if (confirm('Möchten Sie diese Bewertung wirklich freigeben?')) {
+ this.reviewService.approve(id).subscribe({
+ next: () => {
+ console.log(`Review ${id} approved successfully.`);
+ this.loadReviews(); // Liste neu laden, um den geänderten Status anzuzeigen
+ },
+ error: (err) => console.error(`Failed to approve review ${id}`, err)
+ });
+ }
}
onDelete(id: string): void {
- if (confirm('Bewertung wirklich löschen?')) {
- this.reviewService.delete(id).subscribe(() => this.loadReviews());
+ if (confirm('Möchten Sie diese Bewertung wirklich endgültig löschen?')) {
+ this.reviewService.delete(id).subscribe({
+ next: () => {
+ console.log(`Review ${id} deleted successfully.`);
+ this.loadReviews(); // Liste neu laden
+ },
+ error: (err) => console.error(`Failed to delete review ${id}`, err)
+ });
}
}
}
\ No newline at end of file
diff --git a/src/app/features/components/reviews/reviews.routes.ts b/src/app/features/components/reviews/reviews.routes.ts
new file mode 100644
index 0000000..f0efff7
--- /dev/null
+++ b/src/app/features/components/reviews/reviews.routes.ts
@@ -0,0 +1,10 @@
+import { Routes } from '@angular/router';
+import { ReviewListComponent } from './review-list/review-list.component';
+
+export const REVIEWS_ROUTES: Routes = [
+ {
+ path: '',
+ component: ReviewListComponent,
+ title: '',
+ },
+];
diff --git a/src/app/features/components/settings/settings.routes.ts b/src/app/features/components/settings/settings.routes.ts
new file mode 100644
index 0000000..cf09401
--- /dev/null
+++ b/src/app/features/components/settings/settings.routes.ts
@@ -0,0 +1,10 @@
+import { Routes } from '@angular/router';
+import { SettingsComponent } from './settings/settings.component';
+
+export const SETTINGS_ROUTES: Routes = [
+ {
+ path: '',
+ component: SettingsComponent,
+ title: '',
+ },
+];
diff --git a/src/app/features/components/settings/settings/settings.component.ts b/src/app/features/components/settings/settings/settings.component.ts
index 4fcc5ef..4e6df98 100644
--- a/src/app/features/components/settings/settings/settings.component.ts
+++ b/src/app/features/components/settings/settings/settings.component.ts
@@ -39,7 +39,7 @@ export class SettingsComponent implements OnInit {
key: [setting.key],
value: [setting.value],
isActive: [setting.isActive]
- }));
+ }));
});
});
});
diff --git a/src/app/features/components/shipping-methods/shipping-method-list/shipping-method-list.component.html b/src/app/features/components/shipping-methods/shipping-method-list/shipping-method-list.component.html
index e28253b..7a810f8 100644
--- a/src/app/features/components/shipping-methods/shipping-method-list/shipping-method-list.component.html
+++ b/src/app/features/components/shipping-methods/shipping-method-list/shipping-method-list.component.html
@@ -1,21 +1,70 @@
\ No newline at end of file
+
diff --git a/src/app/features/components/shipping-methods/shipping-method-list/shipping-method-list.component.ts b/src/app/features/components/shipping-methods/shipping-method-list/shipping-method-list.component.ts
index 6e70faa..4b4d847 100644
--- a/src/app/features/components/shipping-methods/shipping-method-list/shipping-method-list.component.ts
+++ b/src/app/features/components/shipping-methods/shipping-method-list/shipping-method-list.component.ts
@@ -1,5 +1,5 @@
import { Component, OnInit, inject } from '@angular/core';
-import { CommonModule } from '@angular/common';
+import { CommonModule, CurrencyPipe } from '@angular/common';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { Observable } from 'rxjs';
import { ShippingMethod } from '../../../../core/models/shipping.model';
@@ -8,7 +8,7 @@ import { ShippingMethodService } from '../../../services/shipping-method.service
@Component({
selector: 'app-shipping-method-list',
standalone: true,
- imports: [CommonModule, ReactiveFormsModule],
+ imports: [CommonModule, ReactiveFormsModule, CurrencyPipe],
templateUrl: './shipping-method-list.component.html',
})
export class ShippingMethodListComponent implements OnInit {
@@ -24,7 +24,9 @@ export class ShippingMethodListComponent implements OnInit {
name: ['', Validators.required],
description: [''],
cost: [0, [Validators.required, Validators.min(0)]],
- isActive: [true]
+ isActive: [true],
+ minDeliveryDays: [1, [Validators.required, Validators.min(0)]],
+ maxDeliveryDays: [3, [Validators.required, Validators.min(0)]]
});
}
@@ -38,12 +40,25 @@ export class ShippingMethodListComponent implements OnInit {
clearSelection(): void {
this.selectedMethodId = null;
- this.methodForm.reset({ isActive: true });
+ this.methodForm.reset({
+ name: '',
+ description: '',
+ cost: 0,
+ isActive: true,
+ minDeliveryDays: 1,
+ maxDeliveryDays: 3
+ });
}
+ // --- KORREKTUR: onSubmit sendet jetzt direkt das Formularwert-Objekt als JSON ---
onSubmit(): void {
if (this.methodForm.invalid) return;
- const dataToSend = { ...this.methodForm.value, id: this.selectedMethodId || '0' };
+
+ // Das Formular-Objekt hat bereits die richtige Struktur, die das Backend erwartet.
+ const dataToSend: ShippingMethod = {
+ id: this.selectedMethodId || '00000000-0000-0000-0000-000000000000',
+ ...this.methodForm.value
+ };
if (this.selectedMethodId) {
this.shippingMethodService.update(this.selectedMethodId, dataToSend).subscribe(() => this.reset());
@@ -51,6 +66,7 @@ export class ShippingMethodListComponent implements OnInit {
this.shippingMethodService.create(dataToSend).subscribe(() => this.reset());
}
}
+ // --- ENDE KORREKTUR ---
onDelete(id: string): void {
if (confirm('Versandmethode wirklich löschen?')) {
diff --git a/src/app/features/components/shipping-methods/shipping-methods.routes.ts b/src/app/features/components/shipping-methods/shipping-methods.routes.ts
new file mode 100644
index 0000000..05d4d19
--- /dev/null
+++ b/src/app/features/components/shipping-methods/shipping-methods.routes.ts
@@ -0,0 +1,10 @@
+import { Routes } from '@angular/router';
+import { ShippingMethodListComponent } from './shipping-method-list/shipping-method-list.component';
+
+export const SHIPPING_METHODS_ROUTES: Routes = [
+ {
+ path: '',
+ component: ShippingMethodListComponent,
+ title: '',
+ },
+];