diff --git a/src/app/core/models/dashboard.model.ts b/src/app/core/models/dashboard.model.ts
index 393f23b..2a687eb 100644
--- a/src/app/core/models/dashboard.model.ts
+++ b/src/app/core/models/dashboard.model.ts
@@ -1,9 +1,9 @@
-import { KpiColor } from "../types/dashboard";
+// import { KpiColor } from "../types/dashboard";
export interface Kpi {
value: string;
label: string;
- color: KpiColor; // <-- Hier verwenden wir den importierten Typ
+ color: any; // <-- Hier verwenden wir den importierten Typ
iconName: string;
}
\ No newline at end of file
diff --git a/src/app/core/types/dashboard.ts b/src/app/core/types/dashboard.ts
deleted file mode 100644
index 0dfe432..0000000
--- a/src/app/core/types/dashboard.ts
+++ /dev/null
@@ -1 +0,0 @@
-export type KpiColor = 'blue' | 'green' | 'orange' | 'purple';
\ No newline at end of file
diff --git a/src/app/core/types/order.ts b/src/app/core/types/order.ts
deleted file mode 100644
index d57aad1..0000000
--- a/src/app/core/types/order.ts
+++ /dev/null
@@ -1 +0,0 @@
-export type OrderStatus = 'completed' | 'processing' | 'cancelled' | 'info';
\ No newline at end of file
diff --git a/src/app/core/types/status-pill.ts b/src/app/core/types/status-pill.ts
deleted file mode 100644
index 8a59cfe..0000000
--- a/src/app/core/types/status-pill.ts
+++ /dev/null
@@ -1 +0,0 @@
-export type PillStatus = 'success' | 'warning' | 'danger' | 'info';
\ No newline at end of file
diff --git a/src/app/features/components/categories/category-list/category-list.component.css b/src/app/features/components/categories/category-list/category-list.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/features/components/categories/category-list/category-list.component.html b/src/app/features/components/categories/category-list/category-list.component.html
new file mode 100644
index 0000000..b49570c
--- /dev/null
+++ b/src/app/features/components/categories/category-list/category-list.component.html
@@ -0,0 +1,29 @@
+
+
Kategorien verwalten
+
+
+
+
+
+
+
+
Bestehende Kategorien
+
+ -
+ {{ category.name }} (Slug: {{ category.slug }}) - Aktiv: {{ category.isActive }}
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/features/components/categories/category-list/category-list.component.ts b/src/app/features/components/categories/category-list/category-list.component.ts
new file mode 100644
index 0000000..fc8bce1
--- /dev/null
+++ b/src/app/features/components/categories/category-list/category-list.component.ts
@@ -0,0 +1,91 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
+import { Observable } from 'rxjs';
+import { Category } from '../../../../core/models/category.model';
+import { CategoryService } from '../../../services/category.service';
+
+@Component({
+ selector: 'app-category-list',
+ standalone: true,
+ imports: [CommonModule, ReactiveFormsModule],
+ templateUrl: './category-list.component.html',
+})
+export class CategoryListComponent implements OnInit {
+ private categoryService = inject(CategoryService);
+ private fb = inject(FormBuilder);
+
+ categories$!: Observable;
+ categoryForm: FormGroup;
+ selectedCategoryId: string | null = null;
+ selectedFile: File | null = null;
+
+ constructor() {
+ this.categoryForm = this.fb.group({
+ name: ['', Validators.required],
+ slug: ['', Validators.required],
+ description: [''],
+ isActive: [true],
+ });
+ }
+
+ ngOnInit(): void {
+ this.loadCategories();
+ }
+
+ loadCategories(): void {
+ this.categories$ = this.categoryService.getAll();
+ }
+
+ onFileChange(event: Event): void {
+ const element = event.currentTarget as HTMLInputElement;
+ let fileList: FileList | null = element.files;
+ if (fileList) {
+ this.selectedFile = fileList[0];
+ }
+ }
+
+ selectCategory(category: Category): void {
+ this.selectedCategoryId = category.id;
+ this.categoryForm.patchValue(category);
+ }
+
+ clearSelection(): void {
+ this.selectedCategoryId = null;
+ this.categoryForm.reset({ isActive: true });
+ this.selectedFile = null;
+ }
+
+ onSubmit(): void {
+ if (this.categoryForm.invalid) return;
+
+ const formData = new FormData();
+ Object.keys(this.categoryForm.value).forEach(key => {
+ formData.append(key, this.categoryForm.value[key]);
+ });
+
+ if (this.selectedFile) {
+ formData.append('ImageFile', this.selectedFile, this.selectedFile.name);
+ }
+
+ if (this.selectedCategoryId) {
+ // Update
+ formData.append('Id', this.selectedCategoryId);
+ this.categoryService.update(this.selectedCategoryId, formData).subscribe(() => this.reset());
+ } else {
+ // Create
+ this.categoryService.create(formData).subscribe(() => this.reset());
+ }
+ }
+
+ onDelete(id: string): void {
+ if (confirm('Möchten Sie diese Kategorie wirklich löschen?')) {
+ this.categoryService.delete(id).subscribe(() => this.loadCategories());
+ }
+ }
+
+ private reset(): void {
+ this.loadCategories();
+ this.clearSelection();
+ }
+}
\ No newline at end of file
diff --git a/src/app/features/components/dashboard/dashboard/dashboard.component.css b/src/app/features/components/dashboard/dashboard/dashboard.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/features/components/dashboard/dashboard/dashboard.component.html b/src/app/features/components/dashboard/dashboard/dashboard.component.html
new file mode 100644
index 0000000..cf3861f
--- /dev/null
+++ b/src/app/features/components/dashboard/dashboard/dashboard.component.html
@@ -0,0 +1,19 @@
+
+
Admin Dashboard
+
+
+
+
+
+
+
+
KPIs
+
{{ data.kpiSummary | json }}
+
+
Verkäufe
+
{{ data.salesOverTime | json }}
+
+
Top Produkte
+
{{ data.topPerformingProducts | json }}
+
+
\ No newline at end of file
diff --git a/src/app/features/components/dashboard/dashboard/dashboard.component.ts b/src/app/features/components/dashboard/dashboard/dashboard.component.ts
new file mode 100644
index 0000000..54617a9
--- /dev/null
+++ b/src/app/features/components/dashboard/dashboard/dashboard.component.ts
@@ -0,0 +1,25 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { Observable } from 'rxjs';
+import { Analytics } from '../../../../core/models/analytics.model';
+import { AnalyticsService } from '../../../services/analytics.service';
+import { AnalyticsPeriod } from '../../../../core/enums/shared.enum';
+
+@Component({
+ selector: 'app-admin-dashboard',
+ standalone: true,
+ imports: [CommonModule],
+ templateUrl: './dashboard.component.html',
+})
+export class AdminDashboardComponent implements OnInit {
+ private analyticsService = inject(AnalyticsService);
+ analytics$!: Observable;
+
+ ngOnInit(): void {
+ this.loadAnalytics('Last30Days');
+ }
+
+ loadAnalytics(period: AnalyticsPeriod): void {
+ this.analytics$ = this.analyticsService.get(period);
+ }
+}
diff --git a/src/app/features/components/dashboard/kpi-card/kpi-card.component.ts b/src/app/features/components/dashboard/kpi-card/kpi-card.component.ts
index b4b680a..79bac58 100644
--- a/src/app/features/components/dashboard/kpi-card/kpi-card.component.ts
+++ b/src/app/features/components/dashboard/kpi-card/kpi-card.component.ts
@@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common';
import { IconComponent } from '../../../../shared/components/ui/icon/icon.component';
import { CardComponent } from '../../../../shared/components/ui/card/card.component';
-import { KpiColor } from '../../../../core/types/dashboard';
+// import { KpiColor } from '../../../../core/types/dashboard';
@Component({
selector: 'app-kpi-card',
@@ -15,7 +15,7 @@ import { KpiColor } from '../../../../core/types/dashboard';
export class KpiCardComponent {
@Input() value: string = '';
@Input() label: string = '';
- @Input() color: KpiColor = 'blue';
+ @Input() color: any = 'blue';
@Input() iconName: string | null = null;
@Input() svgColor: string | null = null;
}
diff --git a/src/app/features/components/discounts/discount-list/discount-list.component.css b/src/app/features/components/discounts/discount-list/discount-list.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/features/components/discounts/discount-list/discount-list.component.html b/src/app/features/components/discounts/discount-list/discount-list.component.html
new file mode 100644
index 0000000..f8bb460
--- /dev/null
+++ b/src/app/features/components/discounts/discount-list/discount-list.component.html
@@ -0,0 +1,47 @@
+
diff --git a/src/app/features/components/discounts/discount-list/discount-list.component.ts b/src/app/features/components/discounts/discount-list/discount-list.component.ts
new file mode 100644
index 0000000..525d066
--- /dev/null
+++ b/src/app/features/components/discounts/discount-list/discount-list.component.ts
@@ -0,0 +1,86 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
+import { Observable } from 'rxjs';
+import { Discount } from '../../../../core/models/discount.model';
+import { DiscountService } from '../../../services/discount.service';
+import { DiscountType } from '../../../../core/enums/shared.enum';
+
+@Component({
+ selector: 'app-discount-list',
+ standalone: true,
+ imports: [CommonModule, ReactiveFormsModule],
+ templateUrl: './discount-list.component.html',
+})
+export class DiscountListComponent implements OnInit {
+ private discountService = inject(DiscountService);
+ private fb = inject(FormBuilder);
+
+ discounts$!: Observable;
+ discountForm: FormGroup;
+ selectedDiscountId: string | null = null;
+ discountTypes: DiscountType[] = ['Percentage', 'FixedAmount'];
+
+ constructor() {
+ this.discountForm = this.fb.group({
+ name: ['', Validators.required],
+ discountType: ['Percentage', Validators.required],
+ discountValue: [0, [Validators.required, Validators.min(0)]],
+ couponCode: [''],
+ requiresCouponCode: [false],
+ isActive: [true],
+ startDate: [new Date().toISOString().split('T')[0], Validators.required]
+ });
+ }
+
+ ngOnInit(): void { this.loadDiscounts(); }
+ loadDiscounts(): void { this.discounts$ = this.discountService.getAll(); }
+
+ selectDiscount(discount: Discount): void {
+ this.selectedDiscountId = discount.id;
+ // Format date for the input[type=date]
+ const formattedDiscount = {
+ ...discount,
+ startDate: new Date(discount.startDate).toISOString().split('T')[0]
+ };
+ this.discountForm.patchValue(formattedDiscount);
+ }
+
+ clearSelection(): void {
+ this.selectedDiscountId = null;
+ this.discountForm.reset({
+ discountType: 'Percentage',
+ isActive: true,
+ requiresCouponCode: false,
+ startDate: new Date().toISOString().split('T')[0]
+ });
+ }
+
+ onSubmit(): void {
+ if (this.discountForm.invalid) return;
+
+ const formValue = this.discountForm.value;
+ const dataToSend: Discount = {
+ ...formValue,
+ id: this.selectedDiscountId || '00000000-0000-0000-0000-000000000000', // Dummy ID for create
+ startDate: new Date(formValue.startDate).toISOString()
+ };
+
+ if (this.selectedDiscountId) {
+ this.discountService.update(this.selectedDiscountId, dataToSend).subscribe(() => this.reset());
+ } else {
+ this.discountService.create(dataToSend).subscribe(() => this.reset());
+ }
+ }
+
+ onDelete(id: string): void {
+ if (confirm('Rabatt wirklich löschen?')) {
+ this.discountService.delete(id).subscribe(() => this.loadDiscounts());
+ }
+ }
+
+ private reset(): void {
+ this.loadDiscounts();
+ this.clearSelection();
+ }
+}
\ No newline at end of file
diff --git a/src/app/features/components/orders/order-list/order-list.component.css b/src/app/features/components/orders/order-list/order-list.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/features/components/orders/order-list/order-list.component.html b/src/app/features/components/orders/order-list/order-list.component.html
new file mode 100644
index 0000000..f63ae6a
--- /dev/null
+++ b/src/app/features/components/orders/order-list/order-list.component.html
@@ -0,0 +1,46 @@
+
+
Bestellungen verwalten
+
+
+
+
+
+ | Bestellnr. |
+ Datum |
+ Kunde |
+ Betrag |
+ Status |
+ Aktionen |
+
+
+
+
+ | {{ order.orderNumber }} |
+ {{ order.orderDate | date : "short" }} |
+ {{ order.customerName }} |
+ {{ order.totalAmount | currency : "EUR" }} |
+
+
+ |
+ |
+
+
+
+
+
+
+
+
+
Details für Bestellung {{ selectedOrder.orderNumber }}
+
{{ selectedOrder | json }}
+
+
+
diff --git a/src/app/features/components/orders/order-list/order-list.component.ts b/src/app/features/components/orders/order-list/order-list.component.ts
new file mode 100644
index 0000000..464a16e
--- /dev/null
+++ b/src/app/features/components/orders/order-list/order-list.component.ts
@@ -0,0 +1,49 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { Observable } from 'rxjs';
+import { OrderDetail, OrderSummary } from '../../../../core/models/order.model';
+import { OrderService } from '../../../services/order.service';
+import { OrderStatus } from '../../../../core/enums/shared.enum';
+
+@Component({
+ selector: 'app-order-list',
+ standalone: true,
+ imports: [CommonModule],
+ templateUrl: './order-list.component.html',
+})
+export class OrderListComponent implements OnInit {
+ private orderService = inject(OrderService);
+
+ orders$!: Observable;
+ selectedOrder: OrderDetail | null = null;
+ orderStatuses: OrderStatus[] = [
+ 'Pending',
+ 'Processing',
+ 'Shipped',
+ 'Delivered',
+ 'Cancelled',
+ 'Refunded',
+ ];
+
+ ngOnInit(): void {
+ this.loadOrders();
+ }
+
+ loadOrders(): void {
+ this.orders$ = this.orderService.getAll();
+ this.selectedOrder = null;
+ }
+
+ viewDetails(id: string): void {
+ this.orderService.getById(id).subscribe((details) => {
+ this.selectedOrder = details;
+ });
+ }
+
+ updateStatus(id: string, event: Event): void {
+ const newStatus = (event.target as HTMLSelectElement).value as OrderStatus;
+ this.orderService.updateStatus(id, { newStatus }).subscribe(() => {
+ this.loadOrders(); // Lade alles neu, um die Änderungen zu sehen
+ });
+ }
+}
diff --git a/src/app/features/components/payment-methods/payment-method-list/payment-method-list.component.css b/src/app/features/components/payment-methods/payment-method-list/payment-method-list.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/features/components/payment-methods/payment-method-list/payment-method-list.component.html b/src/app/features/components/payment-methods/payment-method-list/payment-method-list.component.html
new file mode 100644
index 0000000..8618b2e
--- /dev/null
+++ b/src/app/features/components/payment-methods/payment-method-list/payment-method-list.component.html
@@ -0,0 +1,23 @@
+
+
Zahlungsmethoden verwalten
+
+
+
Bestehende Methoden
+
+ -
+ {{ method.name }} (Typ: {{ method.paymentGatewayType }}) - Aktiv: {{ method.isActive }}
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/features/components/payment-methods/payment-method-list/payment-method-list.component.ts b/src/app/features/components/payment-methods/payment-method-list/payment-method-list.component.ts
new file mode 100644
index 0000000..3d32b1d
--- /dev/null
+++ b/src/app/features/components/payment-methods/payment-method-list/payment-method-list.component.ts
@@ -0,0 +1,67 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
+import { Observable } from 'rxjs';
+import { AdminPaymentMethod } from '../../../../core/models/payment.model';
+import { PaymentGatewayType } from '../../../../core/enums/shared.enum';
+import { PaymentMethodService } from '../../../services/payment-method.service';
+
+@Component({
+ selector: 'app-payment-method-list',
+ standalone: true,
+ imports: [CommonModule, ReactiveFormsModule],
+ templateUrl: './payment-method-list.component.html',
+})
+export class PaymentMethodListComponent implements OnInit {
+ private paymentMethodService = inject(PaymentMethodService);
+ private fb = inject(FormBuilder);
+
+ methods$!: Observable;
+ methodForm: FormGroup;
+ selectedMethodId: string | null = null;
+ gatewayTypes: PaymentGatewayType[] = ['BankTransfer', 'Invoice', 'PayPal', 'Stripe', 'CashOnDelivery'];
+
+ constructor() {
+ this.methodForm = this.fb.group({
+ name: ['', Validators.required],
+ description: [''],
+ isActive: [true],
+ paymentGatewayType: ['Invoice', Validators.required]
+ });
+ }
+
+ ngOnInit(): void { this.loadMethods(); }
+ loadMethods(): void { this.methods$ = this.paymentMethodService.getAll(); }
+
+ selectMethod(method: AdminPaymentMethod): void {
+ this.selectedMethodId = method.id;
+ this.methodForm.patchValue(method);
+ }
+
+ clearSelection(): void {
+ this.selectedMethodId = null;
+ this.methodForm.reset({ isActive: true, paymentGatewayType: 'Invoice' });
+ }
+
+ onSubmit(): void {
+ if (this.methodForm.invalid) return;
+ const dataToSend = { ...this.methodForm.value, id: this.selectedMethodId || '0' };
+
+ if (this.selectedMethodId) {
+ this.paymentMethodService.update(this.selectedMethodId, dataToSend).subscribe(() => this.reset());
+ } else {
+ this.paymentMethodService.create(dataToSend).subscribe(() => this.reset());
+ }
+ }
+
+ onDelete(id: string): void {
+ if (confirm('Zahlungsmethode wirklich löschen?')) {
+ this.paymentMethodService.delete(id).subscribe(() => this.loadMethods());
+ }
+ }
+
+ private reset(): void {
+ this.loadMethods();
+ this.clearSelection();
+ }
+}
\ No newline at end of file
diff --git a/src/app/features/components/products/product-list/product-list.component.css b/src/app/features/components/products/product-list/product-list.component.css
new file mode 100644
index 0000000..e69de29
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
new file mode 100644
index 0000000..8c5c9f6
--- /dev/null
+++ b/src/app/features/components/products/product-list/product-list.component.html
@@ -0,0 +1,29 @@
+
\ No newline at end of file
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
new file mode 100644
index 0000000..28cbb6e
--- /dev/null
+++ b/src/app/features/components/products/product-list/product-list.component.ts
@@ -0,0 +1,74 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
+import { Observable } from 'rxjs';
+import { AdminProduct } from '../../../../core/models/product.model';
+import { ProductService } from '../../../services/product.service';
+
+@Component({
+ selector: 'app-product-list',
+ standalone: true,
+ imports: [CommonModule, ReactiveFormsModule],
+ templateUrl: './product-list.component.html',
+})
+export class ProductListComponent implements OnInit {
+ private productService = inject(ProductService);
+ private fb = inject(FormBuilder);
+
+ products$!: Observable;
+ productForm: FormGroup;
+ selectedProductId: string | null = null;
+
+ constructor() {
+ this.productForm = this.fb.group({
+ name: ['', Validators.required],
+ slug: ['', Validators.required],
+ sku: ['', Validators.required],
+ description: [''],
+ price: [0, [Validators.required, Validators.min(0)]],
+ stockQuantity: [0, [Validators.required, Validators.min(0)]],
+ isActive: [true],
+ isFeatured: [false]
+ });
+ }
+
+ ngOnInit(): void { this.loadProducts(); }
+ loadProducts(): void { this.products$ = this.productService.getAll(); }
+
+ selectProduct(product: AdminProduct): void {
+ this.selectedProductId = product.id;
+ this.productForm.patchValue(product);
+ }
+
+ clearSelection(): void {
+ this.selectedProductId = null;
+ this.productForm.reset({ isActive: true, isFeatured: false });
+ }
+
+ onSubmit(): void {
+ if (this.productForm.invalid) return;
+
+ const formData = new FormData();
+ Object.keys(this.productForm.value).forEach(key => {
+ formData.append(key, this.productForm.value[key]);
+ });
+
+ 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.loadProducts());
+ }
+ }
+
+ private reset(): void {
+ this.loadProducts();
+ this.clearSelection();
+ }
+}
\ No newline at end of file
diff --git a/src/app/features/components/reviews/review-list/review-list.component.css b/src/app/features/components/reviews/review-list/review-list.component.css
new file mode 100644
index 0000000..e69de29
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
new file mode 100644
index 0000000..8c12577
--- /dev/null
+++ b/src/app/features/components/reviews/review-list/review-list.component.html
@@ -0,0 +1,30 @@
+
+
Bewertungen verwalten
+
+
+
+ | Kunde |
+ Produkt |
+ Bewertung |
+ Titel |
+ Status |
+ Aktionen |
+
+
+
+
+ | {{ review.customerName }} |
+ {{ review.productName }} |
+ {{ review.rating }}/5 |
+ {{ review.title }} |
+ {{ review.isApproved ? "Freigegeben" : "Ausstehend" }} |
+
+
+
+ |
+
+
+
+
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
new file mode 100644
index 0000000..1707846
--- /dev/null
+++ b/src/app/features/components/reviews/review-list/review-list.component.ts
@@ -0,0 +1,34 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { Observable } from 'rxjs';
+import { Review } from '../../../../core/models/review.model';
+import { ReviewService } from '../../../services/review.service';
+
+@Component({
+ selector: 'app-review-list',
+ standalone: true,
+ imports: [CommonModule],
+ templateUrl: './review-list.component.html',
+})
+export class ReviewListComponent implements OnInit {
+ private reviewService = inject(ReviewService);
+ reviews$!: Observable;
+
+ ngOnInit(): void {
+ this.loadReviews();
+ }
+
+ loadReviews(): void {
+ this.reviews$ = this.reviewService.getAll();
+ }
+
+ onApprove(id: string): void {
+ this.reviewService.approve(id).subscribe(() => this.loadReviews());
+ }
+
+ onDelete(id: string): void {
+ if (confirm('Bewertung wirklich löschen?')) {
+ this.reviewService.delete(id).subscribe(() => this.loadReviews());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/features/components/settings/settings/settings.component.css b/src/app/features/components/settings/settings/settings.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/features/components/settings/settings/settings.component.html b/src/app/features/components/settings/settings/settings.component.html
new file mode 100644
index 0000000..9055778
--- /dev/null
+++ b/src/app/features/components/settings/settings/settings.component.html
@@ -0,0 +1,29 @@
+
+
Einstellungen verwalten
+
+
diff --git a/src/app/features/components/settings/settings/settings.component.ts b/src/app/features/components/settings/settings/settings.component.ts
new file mode 100644
index 0000000..4fcc5ef
--- /dev/null
+++ b/src/app/features/components/settings/settings/settings.component.ts
@@ -0,0 +1,54 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormBuilder, FormGroup, FormArray, ReactiveFormsModule } from '@angular/forms';
+import { Setting } from '../../../../core/models/setting.model';
+import { SettingService } from '../../../services/setting.service';
+
+@Component({
+ selector: 'app-settings',
+ standalone: true,
+ imports: [CommonModule, ReactiveFormsModule],
+ templateUrl: './settings.component.html',
+})
+export class SettingsComponent implements OnInit {
+ private settingService = inject(SettingService);
+ private fb = inject(FormBuilder);
+
+ settingsForm: FormGroup;
+ settingGroups: { groupName: string, settings: Setting[] }[] = [];
+
+ constructor() {
+ this.settingsForm = this.fb.group({
+ settings: this.fb.array([])
+ });
+ }
+
+ get settingsArray(): FormArray {
+ return this.settingsForm.get('settings') as FormArray;
+ }
+
+ ngOnInit(): void {
+ this.settingService.getAllGrouped().subscribe(groupedSettings => {
+ this.settingsArray.clear();
+ this.settingGroups = [];
+ Object.keys(groupedSettings).forEach(groupName => {
+ const settings = groupedSettings[groupName];
+ this.settingGroups.push({ groupName, settings });
+ settings.forEach(setting => {
+ this.settingsArray.push(this.fb.group({
+ key: [setting.key],
+ value: [setting.value],
+ isActive: [setting.isActive]
+ }));
+ });
+ });
+ });
+ }
+
+ onSubmit(): void {
+ if (this.settingsForm.invalid) return;
+ this.settingService.update(this.settingsForm.value.settings).subscribe(() => {
+ alert('Einstellungen gespeichert!');
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/app/features/components/shipping-methods/shipping-method-list/shipping-method-list.component.css b/src/app/features/components/shipping-methods/shipping-method-list/shipping-method-list.component.css
new file mode 100644
index 0000000..e69de29
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
new file mode 100644
index 0000000..e28253b
--- /dev/null
+++ b/src/app/features/components/shipping-methods/shipping-method-list/shipping-method-list.component.html
@@ -0,0 +1,21 @@
+
\ 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
new file mode 100644
index 0000000..6e70faa
--- /dev/null
+++ b/src/app/features/components/shipping-methods/shipping-method-list/shipping-method-list.component.ts
@@ -0,0 +1,65 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
+import { Observable } from 'rxjs';
+import { ShippingMethod } from '../../../../core/models/shipping.model';
+import { ShippingMethodService } from '../../../services/shipping-method.service';
+
+@Component({
+ selector: 'app-shipping-method-list',
+ standalone: true,
+ imports: [CommonModule, ReactiveFormsModule],
+ templateUrl: './shipping-method-list.component.html',
+})
+export class ShippingMethodListComponent implements OnInit {
+ private shippingMethodService = inject(ShippingMethodService);
+ private fb = inject(FormBuilder);
+
+ methods$!: Observable;
+ methodForm: FormGroup;
+ selectedMethodId: string | null = null;
+
+ constructor() {
+ this.methodForm = this.fb.group({
+ name: ['', Validators.required],
+ description: [''],
+ cost: [0, [Validators.required, Validators.min(0)]],
+ isActive: [true]
+ });
+ }
+
+ ngOnInit(): void { this.loadMethods(); }
+ loadMethods(): void { this.methods$ = this.shippingMethodService.getAll(); }
+
+ selectMethod(method: ShippingMethod): void {
+ this.selectedMethodId = method.id;
+ this.methodForm.patchValue(method);
+ }
+
+ clearSelection(): void {
+ this.selectedMethodId = null;
+ this.methodForm.reset({ isActive: true });
+ }
+
+ onSubmit(): void {
+ if (this.methodForm.invalid) return;
+ const dataToSend = { ...this.methodForm.value, id: this.selectedMethodId || '0' };
+
+ if (this.selectedMethodId) {
+ this.shippingMethodService.update(this.selectedMethodId, dataToSend).subscribe(() => this.reset());
+ } else {
+ this.shippingMethodService.create(dataToSend).subscribe(() => this.reset());
+ }
+ }
+
+ onDelete(id: string): void {
+ if (confirm('Versandmethode wirklich löschen?')) {
+ this.shippingMethodService.delete(id).subscribe(() => this.loadMethods());
+ }
+ }
+
+ private reset(): void {
+ this.loadMethods();
+ this.clearSelection();
+ }
+}
\ No newline at end of file
diff --git a/src/app/features/components/shop-info/shop-info/shop-info.component.css b/src/app/features/components/shop-info/shop-info/shop-info.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/features/components/shop-info/shop-info/shop-info.component.html b/src/app/features/components/shop-info/shop-info/shop-info.component.html
new file mode 100644
index 0000000..592c5d2
--- /dev/null
+++ b/src/app/features/components/shop-info/shop-info/shop-info.component.html
@@ -0,0 +1,15 @@
+
+
Shop-Stammdaten verwalten
+
+
\ No newline at end of file
diff --git a/src/app/features/components/shop-info/shop-info/shop-info.component.ts b/src/app/features/components/shop-info/shop-info/shop-info.component.ts
new file mode 100644
index 0000000..395f97b
--- /dev/null
+++ b/src/app/features/components/shop-info/shop-info/shop-info.component.ts
@@ -0,0 +1,42 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
+import { AdminShopInfo } from '../../../../core/models/shop.model';
+import { ShopInfoService } from '../../../services/shop-info.service';
+
+@Component({
+ selector: 'app-shop-info',
+ standalone: true,
+ imports: [CommonModule, ReactiveFormsModule],
+ templateUrl: './shop-info.component.html',
+})
+export class ShopInfoComponent implements OnInit {
+ private shopInfoService = inject(ShopInfoService);
+ private fb = inject(FormBuilder);
+
+ shopInfoForm!: FormGroup;
+
+ ngOnInit(): void {
+ this.shopInfoForm = this.fb.group({
+ shopName: ['', Validators.required],
+ slogan: [''],
+ contactEmail: ['', [Validators.required, Validators.email]],
+ phoneNumber: [''],
+ street: [''],
+ city: [''],
+ postalCode: [''],
+ country: ['']
+ });
+
+ this.shopInfoService.get().subscribe(data => {
+ this.shopInfoForm.patchValue(data);
+ });
+ }
+
+ onSubmit(): void {
+ if (this.shopInfoForm.invalid) return;
+ this.shopInfoService.update(this.shopInfoForm.value).subscribe(() => {
+ alert('Shop-Informationen gespeichert!');
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/app/features/components/suppliers/supplier-list/supplier-list.component.css b/src/app/features/components/suppliers/supplier-list/supplier-list.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/features/components/suppliers/supplier-list/supplier-list.component.html b/src/app/features/components/suppliers/supplier-list/supplier-list.component.html
new file mode 100644
index 0000000..374f425
--- /dev/null
+++ b/src/app/features/components/suppliers/supplier-list/supplier-list.component.html
@@ -0,0 +1,34 @@
+
diff --git a/src/app/features/components/suppliers/supplier-list/supplier-list.component.ts b/src/app/features/components/suppliers/supplier-list/supplier-list.component.ts
new file mode 100644
index 0000000..c8bd402
--- /dev/null
+++ b/src/app/features/components/suppliers/supplier-list/supplier-list.component.ts
@@ -0,0 +1,66 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
+import { Observable } from 'rxjs';
+import { Supplier } from '../../../../core/models/supplier.model';
+import { SupplierService } from '../../../services/supplier.service';
+
+@Component({
+ selector: 'app-supplier-list',
+ standalone: true,
+ imports: [CommonModule, ReactiveFormsModule],
+ templateUrl: './supplier-list.component.html',
+})
+export class SupplierListComponent implements OnInit {
+ private supplierService = inject(SupplierService);
+ private fb = inject(FormBuilder);
+
+ suppliers$!: Observable;
+ supplierForm: FormGroup;
+ selectedSupplierId: string | null = null;
+
+ constructor() {
+ this.supplierForm = this.fb.group({
+ name: ['', Validators.required],
+ contactPerson: [''],
+ email: ['', Validators.email],
+ phoneNumber: ['']
+ });
+ }
+
+ ngOnInit(): void { this.loadSuppliers(); }
+ loadSuppliers(): void { this.suppliers$ = this.supplierService.getAll(); }
+
+ selectSupplier(supplier: Supplier): void {
+ this.selectedSupplierId = supplier.id;
+ this.supplierForm.patchValue(supplier);
+ }
+
+ clearSelection(): void {
+ this.selectedSupplierId = null;
+ this.supplierForm.reset();
+ }
+
+ onSubmit(): void {
+ if (this.supplierForm.invalid) return;
+
+ const dataToSend = { ...this.supplierForm.value, id: this.selectedSupplierId || '0' };
+
+ if (this.selectedSupplierId) {
+ this.supplierService.update(this.selectedSupplierId, dataToSend).subscribe(() => this.reset());
+ } else {
+ this.supplierService.create(dataToSend).subscribe(() => this.reset());
+ }
+ }
+
+ onDelete(id: string): void {
+ if (confirm('Lieferant wirklich löschen?')) {
+ this.supplierService.delete(id).subscribe(() => this.loadSuppliers());
+ }
+ }
+
+ private reset(): void {
+ this.loadSuppliers();
+ this.clearSelection();
+ }
+}
\ No newline at end of file
diff --git a/src/app/features/components/users/user-list/user-list.component.css b/src/app/features/components/users/user-list/user-list.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/features/components/users/user-list/user-list.component.html b/src/app/features/components/users/user-list/user-list.component.html
new file mode 100644
index 0000000..6d8f50b
--- /dev/null
+++ b/src/app/features/components/users/user-list/user-list.component.html
@@ -0,0 +1,24 @@
+
+
Benutzer verwalten
+
+
+
+ | Email |
+ Name |
+ Rollen |
+ Aktionen |
+
+
+
+
+ | {{ user.email }} |
+ {{ user.firstName }} {{ user.lastName }} |
+ {{ user.roles?.join(', ') }} |
+
+
+
+ |
+
+
+
+
\ No newline at end of file
diff --git a/src/app/features/components/users/user-list/user-list.component.ts b/src/app/features/components/users/user-list/user-list.component.ts
new file mode 100644
index 0000000..16d62e8
--- /dev/null
+++ b/src/app/features/components/users/user-list/user-list.component.ts
@@ -0,0 +1,25 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { Observable } from 'rxjs';
+import { User } from '../../../../core/models/user.model';
+import { UserService } from '../../../services/user.service';
+
+@Component({
+ selector: 'app-user-list',
+ standalone: true,
+ imports: [CommonModule],
+ templateUrl: './user-list.component.html',
+})
+export class UserListComponent implements OnInit {
+ private userService = inject(UserService);
+ users$!: Observable;
+
+ ngOnInit(): void { this.loadUsers(); }
+ loadUsers(): void { this.users$ = this.userService.getAll(); }
+
+ onDelete(user: User): void {
+ if (confirm(`Benutzer ${user.email} wirklich löschen?`)) {
+ this.userService.delete(user.id!).subscribe(() => this.loadUsers());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/shared/components/data-display/orders-table/orders-table.component.ts b/src/app/shared/components/data-display/orders-table/orders-table.component.ts
index e37d68e..38434d8 100644
--- a/src/app/shared/components/data-display/orders-table/orders-table.component.ts
+++ b/src/app/shared/components/data-display/orders-table/orders-table.component.ts
@@ -11,7 +11,7 @@ import { ButtonComponent } from '../../ui/button/button.component';
import { PaginatorComponent } from '../paginator/paginator.component';
-import { OrderStatus } from '../../../../core/types/order';
+// import { any } from '../../../../core/types/order';
import { SearchBarComponent } from '../../layout/search-bar/search-bar.component';
@Component({
@@ -38,7 +38,7 @@ export class OrdersTableComponent {
@Output() delete = new EventEmitter();
public searchTerm = '';
- public selectedStatus: OrderStatus | 'all' = 'all';
+ public selectedStatus: any | 'all' = 'all';
public statusOptions: any[] = [
{ value: 'all', label: 'Alle' },
@@ -52,7 +52,7 @@ export class OrdersTableComponent {
public displayedOrders: any[] = [];
public currentPage = 1;
- private statusTextMap = new Map([
+ private statusTextMap = new Map([
['completed', 'Abgeschlossen'],
['processing', 'In Bearbeitung'],
['cancelled', 'Storniert'],
@@ -76,7 +76,7 @@ export class OrdersTableComponent {
}
// Called when a status pill is clicked
- onStatusChange(status: OrderStatus | 'all'): void {
+ onStatusChange(status: any | 'all'): void {
this.selectedStatus = status;
this.applyFiltersAndPagination();
}
diff --git a/src/app/shared/components/ui/status-pill/status-pill.component.ts b/src/app/shared/components/ui/status-pill/status-pill.component.ts
index d5cbc2a..56cc86a 100644
--- a/src/app/shared/components/ui/status-pill/status-pill.component.ts
+++ b/src/app/shared/components/ui/status-pill/status-pill.component.ts
@@ -1,6 +1,6 @@
import { Component, Input, OnChanges } from '@angular/core';
import { CommonModule, NgClass } from '@angular/common';
-import { OrderStatus } from '../../../../core/types/order';
+// import { OrderStatus } from '../../../../core/types/order';
@Component({
selector: 'app-status-pill',
@@ -11,14 +11,14 @@ import { OrderStatus } from '../../../../core/types/order';
})
export class StatusPillComponent implements OnChanges {
// Nimmt jetzt den neuen, sprechenden Status entgegen
- @Input() status: OrderStatus = 'info';
+ @Input() status: any = 'info';
// Diese Eigenschaften werden vom Template verwendet
public displayText = '';
public cssClass = '';
// Eine Map, die Statusnamen auf Text und CSS-Klasse abbildet
- private statusMap = new Map([
+ private statusMap = new Map([
['completed', { text: 'Abgeschlossen', css: 'pill-success' }],
['processing', { text: 'In Bearbeitung', css: 'pill-warning' }],
['cancelled', { text: 'Storniert', css: 'pill-danger' }],