From 8813dc21ee36f45908ced627d45611f3431477a5 Mon Sep 17 00:00:00 2001 From: "Tizian.Breuch" Date: Fri, 10 Oct 2025 12:13:09 +0200 Subject: [PATCH] supplier und address --- src/app/app.routes.ts | 7 + .../supplier-list.component.html | 35 +++-- .../supplier-list/supplier-list.component.ts | 137 ++++++++++++++++-- .../components/suppliers/suppliers.routes.ts | 11 ++ src/app/features/services/address.service.ts | 59 ++++++++ .../layout/sidebar/sidebar.component.html | 9 ++ 6 files changed, 235 insertions(+), 23 deletions(-) create mode 100644 src/app/features/components/suppliers/suppliers.routes.ts create mode 100644 src/app/features/services/address.service.ts diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 0ad4627..afd2120 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -95,6 +95,13 @@ export const routes: Routes = [ './features/components/shop-info/shop-info.routes' ).then((r) => r.SHOP_INFO_ROUTES), }, + { + path: 'supplier-list', + loadChildren: () => + import( + './features/components/suppliers/suppliers.routes' + ).then((r) => r.SUPPLIERS_ROUTES), + }, ], }, { 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 index 374f425..41af2e9 100644 --- a/src/app/features/components/suppliers/supplier-list/supplier-list.component.html +++ b/src/app/features/components/suppliers/supplier-list/supplier-list.component.html @@ -5,14 +5,29 @@

{{ selectedSupplierId ? "Lieferant bearbeiten" : "Neuer Lieferant" }}

- - - - + +
+ Lieferanten-Daten +
+
+
+
+
+
+ + +
+ Adresse (optional) +
+
+
+
+
+
+ + +
+ @@ -26,9 +41,9 @@

Bestehende Lieferanten

- + \ No newline at end of file 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 index c8bd402..520d42d 100644 --- a/src/app/features/components/suppliers/supplier-list/supplier-list.component.ts +++ b/src/app/features/components/suppliers/supplier-list/supplier-list.component.ts @@ -1,9 +1,27 @@ 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 { + FormBuilder, + FormGroup, + ReactiveFormsModule, + Validators, +} from '@angular/forms'; +import { Observable, of } from 'rxjs'; +import { switchMap, map } from 'rxjs/operators'; // <-- KORREKTUR: 'map' importiert + +// Models import { Supplier } from '../../../../core/models/supplier.model'; +import { + Address, + CreateAddress, + UpdateAddress, +} from '../../../../core/models/address.model'; + +// Services import { SupplierService } from '../../../services/supplier.service'; +import { AddressService } from '../../../services/address.service'; +// HINWEIS: Du hast den CustomerAddressService nicht mehr gebraucht, daher habe ich ihn entfernt. +// Falls du ihn doch an anderer Stelle brauchst, füge den Import wieder hinzu. @Component({ selector: 'app-supplier-list', @@ -13,9 +31,12 @@ import { SupplierService } from '../../../services/supplier.service'; }) export class SupplierListComponent implements OnInit { private supplierService = inject(SupplierService); + private addressService = inject(AddressService); // Korrekten Service verwenden private fb = inject(FormBuilder); suppliers$!: Observable; + // Das Dropdown für Adressen wird nicht mehr benötigt + // addresses$!: Observable; supplierForm: FormGroup; selectedSupplierId: string | null = null; @@ -24,16 +45,50 @@ export class SupplierListComponent implements OnInit { name: ['', Validators.required], contactPerson: [''], email: ['', Validators.email], - phoneNumber: [''] + phoneNumber: [''], + addressId: [null], + notes: [''], + address: this.fb.group({ + street: [''], + houseNumber: [''], + city: [''], + postalCode: [''], + country: [''], + }), }); } - ngOnInit(): void { this.loadSuppliers(); } - loadSuppliers(): void { this.suppliers$ = this.supplierService.getAll(); } + get addressForm(): FormGroup { + return this.supplierForm.get('address') as FormGroup; + } + + private isAddressFormDirty(): boolean { + const address = this.addressForm.value; + return Object.values(address).some((value) => !!value); + } + + ngOnInit(): void { + this.loadSuppliers(); + // this.addresses$ = this.adminAddressService.getAllUnlinkedAddresses(); // Lade ungebundene Adressen + } + + loadSuppliers(): void { + this.suppliers$ = this.supplierService.getAll(); + } selectSupplier(supplier: Supplier): void { this.selectedSupplierId = supplier.id; + // Reset address form before patching to avoid leftover values + this.addressForm.reset(); this.supplierForm.patchValue(supplier); + + if (supplier.addressId) { + this.addressService + .getAddressById(supplier.addressId) + .subscribe((address) => { + this.addressForm.patchValue(address); + }); + } } clearSelection(): void { @@ -43,24 +98,80 @@ export class SupplierListComponent implements OnInit { 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()); + const addressIdToSave$ = this.isAddressFormDirty() + ? this.saveAddress() + : of(this.supplierForm.value.addressId || null); + + addressIdToSave$ + .pipe( + switchMap((addressId: string | null) => { + const supplierData: Supplier = { + ...this.supplierForm.value, + id: this.selectedSupplierId || undefined, + addressId: addressId, + }; + + if (this.selectedSupplierId) { + return this.supplierService.update( + this.selectedSupplierId, + supplierData + ); + } else { + return this.supplierService.create(supplierData); + } + }) + ) + .subscribe(() => this.reset()); + } + + private saveAddress(): Observable { + const supplierName = this.supplierForm.get('name')?.value || 'Lieferant'; + const contactPerson = this.supplierForm + .get('contactPerson') + ?.value.split(' ') || ['']; + const firstName = contactPerson[0] || supplierName; + const lastName = contactPerson.slice(1).join(' ') || '(Lieferant)'; + + const addressData = { + ...this.addressForm.value, + firstName, + lastName, + type: 'Billing', + }; + + const existingAddressId = this.supplierForm.get('addressId')?.value; + + if (existingAddressId) { + const updateData: UpdateAddress = { + ...addressData, + id: existingAddressId, + }; + return this.addressService + .updateAddress(existingAddressId, updateData) + .pipe( + map(() => existingAddressId) // Gibt die bestehende ID zurück + ); } else { - this.supplierService.create(dataToSend).subscribe(() => this.reset()); + const createData: CreateAddress = addressData; + return this.addressService.createAddress(createData).pipe( + map((createdAddress: Address) => createdAddress.id) // Gibt die neue ID zurück + ); } } onDelete(id: string): void { - if (confirm('Lieferant wirklich löschen?')) { + if ( + confirm( + 'Lieferant wirklich löschen? (Zugehörige Adresse wird nicht gelöscht)' + ) + ) { 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/suppliers/suppliers.routes.ts b/src/app/features/components/suppliers/suppliers.routes.ts new file mode 100644 index 0000000..c2a5f06 --- /dev/null +++ b/src/app/features/components/suppliers/suppliers.routes.ts @@ -0,0 +1,11 @@ +import { Routes } from '@angular/router'; +import { SupplierListComponent } from './supplier-list/supplier-list.component'; + + +export const SUPPLIERS_ROUTES: Routes = [ + { + path: '', + component: SupplierListComponent, + title: '', + }, +]; diff --git a/src/app/features/services/address.service.ts b/src/app/features/services/address.service.ts new file mode 100644 index 0000000..019b23d --- /dev/null +++ b/src/app/features/services/address.service.ts @@ -0,0 +1,59 @@ +import { Injectable, inject } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { API_URL } from '../../core/tokens/api-url.token'; +import { Address, CreateAddress, UpdateAddress } from '../../core/models/address.model'; + +@Injectable({ + providedIn: 'root' +}) +export class AddressService { + private http = inject(HttpClient); + private apiUrl = inject(API_URL); + private readonly endpoint = '/admin/AdminAddresses'; + + /** + * Retrieves all addresses that are not linked to a customer (e.g., for suppliers). + * @returns An Observable array of Address objects. + */ + getAllUnlinkedAddresses(): Observable { + return this.http.get(`${this.apiUrl}${this.endpoint}`); + } + + /** + * Retrieves a single unlinked address by its ID. + * @param id The unique identifier of the address. + * @returns An Observable of a single Address object. + */ + getAddressById(id: string): Observable
{ + return this.http.get
(`${this.apiUrl}${this.endpoint}/${id}`); + } + + /** + * Creates a new unlinked address. + * @param data The data for the new address. + * @returns An Observable of the newly created Address object. + */ + createAddress(data: CreateAddress): Observable
{ + return this.http.post
(`${this.apiUrl}${this.endpoint}`, data); + } + + /** + * Updates an existing unlinked address. + * @param id The unique identifier of the address to update. + * @param data The updated address data. + * @returns An Observable that completes when the update is successful. + */ + updateAddress(id: string, data: UpdateAddress): Observable { + return this.http.put(`${this.apiUrl}${this.endpoint}/${id}`, data); + } + + /** + * Deletes an unlinked address by its ID. + * @param id The unique identifier of the address to delete. + * @returns An Observable that completes when the deletion is successful. + */ + deleteAddress(id: string): Observable { + return this.http.delete(`${this.apiUrl}${this.endpoint}/${id}`); + } +} \ No newline at end of file diff --git a/src/app/shared/components/layout/sidebar/sidebar.component.html b/src/app/shared/components/layout/sidebar/sidebar.component.html index 20cabb7..cd933ee 100644 --- a/src/app/shared/components/layout/sidebar/sidebar.component.html +++ b/src/app/shared/components/layout/sidebar/sidebar.component.html @@ -89,5 +89,14 @@ shop-info +