supplier und address
This commit is contained in:
@@ -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),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -5,14 +5,29 @@
|
||||
<h3>
|
||||
{{ selectedSupplierId ? "Lieferant bearbeiten" : "Neuer Lieferant" }}
|
||||
</h3>
|
||||
<input type="text" formControlName="name" placeholder="Name" />
|
||||
<input
|
||||
type="text"
|
||||
formControlName="contactPerson"
|
||||
placeholder="Ansprechpartner"
|
||||
/>
|
||||
<input type="email" formControlName="email" placeholder="E-Mail" />
|
||||
<input type="tel" formControlName="phoneNumber" placeholder="Telefon" />
|
||||
|
||||
<fieldset>
|
||||
<legend>Lieferanten-Daten</legend>
|
||||
<div><label>Name:</label><input type="text" formControlName="name" /></div>
|
||||
<div><label>Ansprechpartner:</label><input type="text" formControlName="contactPerson" /></div>
|
||||
<div><label>E-Mail:</label><input type="email" formControlName="email" /></div>
|
||||
<div><label>Telefon:</label><input type="tel" formControlName="phoneNumber" /></div>
|
||||
<div><label>Notizen:</label><textarea formControlName="notes"></textarea></div>
|
||||
</fieldset>
|
||||
|
||||
<!-- +++ NEUES ADRESS-FORMULAR +++ -->
|
||||
<fieldset formGroupName="address">
|
||||
<legend>Adresse (optional)</legend>
|
||||
<div><label>Straße:</label><input type="text" formControlName="street" /></div>
|
||||
<div><label>Hausnummer:</label><input type="text" formControlName="houseNumber" /></div>
|
||||
<div><label>Stadt:</label><input type="text" formControlName="city" /></div>
|
||||
<div><label>PLZ:</label><input type="text" formControlName="postalCode" /></div>
|
||||
<div><label>Land:</label><input type="text" formControlName="country" /></div>
|
||||
</fieldset>
|
||||
<!-- +++ ENDE NEU +++ -->
|
||||
|
||||
<br>
|
||||
|
||||
<button type="submit" [disabled]="supplierForm.invalid">
|
||||
{{ selectedSupplierId ? "Aktualisieren" : "Erstellen" }}
|
||||
</button>
|
||||
@@ -26,7 +41,7 @@
|
||||
<h2>Bestehende Lieferanten</h2>
|
||||
<ul>
|
||||
<li *ngFor="let supplier of suppliers$ | async">
|
||||
{{ supplier.name }} ({{ supplier.contactPerson }})
|
||||
{{ supplier.name }} ({{ supplier.contactPerson || 'Kein Ansprechpartner' }})
|
||||
<button (click)="selectSupplier(supplier)">Bearbeiten</button>
|
||||
<button (click)="onDelete(supplier.id)">Löschen</button>
|
||||
</li>
|
||||
|
||||
@@ -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<Supplier[]>;
|
||||
// Das Dropdown für Adressen wird nicht mehr benötigt
|
||||
// addresses$!: Observable<Address[]>;
|
||||
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 {
|
||||
@@ -44,17 +99,73 @@ export class SupplierListComponent implements OnInit {
|
||||
onSubmit(): void {
|
||||
if (this.supplierForm.invalid) return;
|
||||
|
||||
const dataToSend = { ...this.supplierForm.value, id: this.selectedSupplierId || '0' };
|
||||
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) {
|
||||
this.supplierService.update(this.selectedSupplierId, dataToSend).subscribe(() => this.reset());
|
||||
return this.supplierService.update(
|
||||
this.selectedSupplierId,
|
||||
supplierData
|
||||
);
|
||||
} else {
|
||||
this.supplierService.create(dataToSend).subscribe(() => this.reset());
|
||||
return this.supplierService.create(supplierData);
|
||||
}
|
||||
})
|
||||
)
|
||||
.subscribe(() => this.reset());
|
||||
}
|
||||
|
||||
private saveAddress(): Observable<string | null> {
|
||||
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 {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
11
src/app/features/components/suppliers/suppliers.routes.ts
Normal file
11
src/app/features/components/suppliers/suppliers.routes.ts
Normal file
@@ -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: '',
|
||||
},
|
||||
];
|
||||
59
src/app/features/services/address.service.ts
Normal file
59
src/app/features/services/address.service.ts
Normal file
@@ -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<Address[]> {
|
||||
return this.http.get<Address[]>(`${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<Address> {
|
||||
return this.http.get<Address>(`${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<Address> {
|
||||
return this.http.post<Address>(`${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<void> {
|
||||
return this.http.put<void>(`${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<void> {
|
||||
return this.http.delete<void>(`${this.apiUrl}${this.endpoint}/${id}`);
|
||||
}
|
||||
}
|
||||
@@ -89,5 +89,14 @@
|
||||
|
||||
<span>shop-info</span>
|
||||
</div>
|
||||
<div
|
||||
class="nav-item"
|
||||
[class.active]="activeRoute === 'supplier-list'"
|
||||
(click)="setActive('supplier-list')"
|
||||
>
|
||||
<app-icon [iconName]="'placeholder'" [svgColor]="'#8e44ad'"></app-icon>
|
||||
|
||||
<span>supplier-list</span>
|
||||
</div>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
Reference in New Issue
Block a user