added suppr and edit modal for supplier price

This commit is contained in:
2025-12-01 12:41:40 +01:00
parent c42c29a9fd
commit cdcdaaa25e
5 changed files with 170 additions and 58 deletions

View File

@@ -0,0 +1,13 @@
<form nz-form nzLayout="horizontal" [formGroup]="priceForm">
<nz-form-item nz-flex>
<nz-form-label nzSpan="9">
Prix
</nz-form-label>
<nz-form-control nzSpan="12">
<input nz-input type="number" placeholder="€€€" formControlName="price">
</nz-form-control>
</nz-form-item>
</form>

View File

@@ -0,0 +1,40 @@
import {Component, effect, input} from '@angular/core';
import {FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators} from "@angular/forms";
import {NzColDirective} from "ng-zorro-antd/grid";
import {NzFlexDirective} from "ng-zorro-antd/flex";
import {NzFormControlComponent, NzFormDirective, NzFormItemComponent, NzFormLabelComponent} from "ng-zorro-antd/form";
import {NzInputDirective} from "ng-zorro-antd/input";
import {GetPriceDto, GetSupplierDto} from "../../services/api";
@Component({
selector: 'app-price-form',
imports: [
FormsModule,
NzColDirective,
NzFlexDirective,
NzFormControlComponent,
NzFormDirective,
NzFormItemComponent,
NzFormLabelComponent,
NzInputDirective,
ReactiveFormsModule
],
templateUrl: './price-form.html',
styleUrl: './price-form.css',
})
export class PriceForm {
priceForm: FormGroup = new FormGroup({
price: new FormControl<string>(null, [Validators.required]),
})
price= input<GetPriceDto>();
constructor() {
effect(() => {
if (this.price()) {
this.priceForm.patchValue({
price: this.price().sellingPrice
});
}
});
}
}

View File

@@ -25,22 +25,32 @@
<td>{{ supplier.city }}</td>
<td>{{ supplier.deliveryDelay }} jours</td>
<td>
<app-modal-button type="link" [name]="'Voir les produits'" size="40%">
<nz-table [nzData]="suppliers()"
[nzFrontPagination]="false">
<app-modal-button type="link" [name]="'Voir les produits'" size="45%">
<nz-table [nzData]="suppliers()" [nzFrontPagination]="false">
<thead>
<tr style="text-align: center">
<tr class="text-center">
<th>Produit</th>
<th>Référence</th>
<th>Prix</th>
<th>Action</th>
</tr>
</thead>
<tbody style="text-align: center">
<tbody class="text-center">
@for (product of supplier.prices; track product.id) {
<tr>
<td>{{ product.productName }}</td>
<td>{{ product.productReferences }}</td>
<td>{{ product.sellingPrice }}€</td>
<td>
<div class="flex items-center justify-center space-x-2">
<nz-icon nzType="edit" nzTheme="outline"
class="cursor-pointer text-gray-600 hover:text-gray-900"
(click)="openEditProductModal(product)"></nz-icon>
<nz-divider nzType="vertical"></nz-divider>
<nz-icon nzType="delete" nzTheme="outline" class="cursor-pointer text-red-600 hover:text-red-800"
(click)="deleteProduct(product.productId, product.supplierId)"></nz-icon>
</div>
</td>
</tr>
}
</tbody>
@@ -49,9 +59,11 @@
</td>
<td>
<div style="display: flex; align-items: center;">
<nz-icon nzType="edit" nzTheme="outline" class="cursor-pointer" (click)="openEditModal(supplier)"></nz-icon>
<nz-icon nzType="edit" nzTheme="outline" class="cursor-pointer"
(click)="openEditModal(supplier)"></nz-icon>
<nz-divider nzType="vertical"></nz-divider>
<nz-icon nzType="delete" nzTheme="outline" (click)="delete(supplier.id)" class="text-red-600 cursor-pointer"></nz-icon>
<nz-icon nzType="delete" nzTheme="outline" (click)="delete(supplier.id)"
class="text-red-600 cursor-pointer"></nz-icon>
</div>
</td>
</tr>
@@ -60,7 +72,17 @@
</nz-table>
<div class="hidden">
<app-modal-nav #modalNav nameIcon="edit" [name]="'Modifier'" (ok)="onModalOk(selectedSupplier.id, supplierForm, modalNav)" (cancel)="onModalCancel(modalNav)">
<app-modal-nav #supplierModal nameIcon="edit" [name]="'Modifier'"
(ok)="onModalOk(selectedSupplier?.id, supplierForm, supplierModal)"
(cancel)="onModalCancel(supplierModal)">
<app-supplier-form #supplierForm [supplier]="selectedSupplier"></app-supplier-form>
</app-modal-nav>
</div>
<div class="hidden">
<app-modal-nav #productModal nameIcon="edit" [name]="'Modifier les prix des fournisseurs'"
(ok)="onModalProductOk(selectedProduct?.id, selectedSupplier?.id, priceForm, productModal)"
(cancel)="onModalCancel(productModal)">
<app-price-form #priceForm [price]="selectedProduct"></app-price-form>
</app-modal-nav>
</div>

View File

@@ -5,9 +5,10 @@ import {NzIconDirective} from "ng-zorro-antd/icon";
import {NzTableComponent} from "ng-zorro-antd/table";
import {ModalButton} from "../modal-button/modal-button";
import {SupplierForm} from "../supplier-form/supplier-form";
import {GetPriceDto, GetSupplierDto, SuppliersService} from "../../services/api";
import {GetPriceDto, GetSupplierDto, PricesService, SuppliersService} from "../../services/api";
import {NzNotificationService} from "ng-zorro-antd/notification";
import {firstValueFrom} from "rxjs";
import {PriceForm} from "../price-form/price-form";
@Component({
selector: 'app-supplier-table',
@@ -18,6 +19,7 @@ import {firstValueFrom} from "rxjs";
NzTableComponent,
ModalButton,
SupplierForm,
PriceForm,
],
templateUrl: './supplier-table.html',
styleUrl: './supplier-table.css',
@@ -25,82 +27,68 @@ import {firstValueFrom} from "rxjs";
export class SupplierTable implements OnInit {
private suppliersService = inject(SuppliersService);
private notificationService = inject(NzNotificationService)
private pricesService = inject(PricesService);
private notificationService = inject(NzNotificationService);
suppliers = signal<GetSupplierDto[]>([]);
suppliersLoading = signal<boolean>(false);
updateSupplier = viewChild.required<SupplierForm>('supplierForm');
modal = viewChild.required<ModalNav>('modalNav');
supplierModal = viewChild.required<ModalNav>('supplierModal');
productModal = viewChild.required<ModalNav>('productModal');
selectedSupplier: GetSupplierDto | null = null;
selectedProduct: GetPriceDto | null = null;
async ngOnInit() {
await this.fetchSuppliers();
}
async fetchSuppliers() {
this.suppliersLoading.set(true)
this.suppliersLoading.set(true);
try {
const suppliers = await firstValueFrom(this.suppliersService.getAllSuppliersEndpoint())
const suppliers = await firstValueFrom(this.suppliersService.getAllSuppliersEndpoint());
this.suppliers.set(suppliers);
} catch (e) {
this.notificationService.error(
'Erreur',
'Erreur de communication avec l\'API'
)
this.notificationService.error('Erreur', 'Erreur de communication avec l\'API');
}
this.suppliersLoading.set(false)
}
async delete(supplier:number) {
try {
await firstValueFrom(this.suppliersService.deleteSupplierEndpoint(supplier))
this.notificationService.success(
'Success',
'Suppression effectuée'
)
} catch (e) {
this.notificationService.error(
'Erreur',
'Impossible de supprimer la ligne'
)
}
await this.fetchSuppliers();
this.suppliersLoading.set(false);
}
async edit(id: number, updateSupplierComponent: SupplierForm) {
if (updateSupplierComponent.supplierForm.invalid) {
this.notificationService.error(
'Erreur',
'Erreur d\'écriture dans le formulaire'
)
this.notificationService.error('Erreur', 'Erreur d\'écriture dans le formulaire');
return;
}
try {
const suppliers = updateSupplierComponent.supplierForm.getRawValue();
await firstValueFrom(this.suppliersService.updateSupplierEndpoint(id, suppliers))
this.notificationService.success(
'Success',
'Fournisseur modifié'
)
await firstValueFrom(this.suppliersService.updateSupplierEndpoint(id, suppliers));
this.notificationService.success('Success', 'Fournisseur modifié');
} catch (e) {
console.error(e);
this.notificationService.error(
'Erreur',
'Erreur lors de la modification'
)
this.notificationService.error('Erreur', 'Erreur lors de la modification');
}
}
selectedSupplier: GetSupplierDto | null = null;
openEditModal(supplier: GetSupplierDto) {
this.selectedSupplier = { ...supplier };
this.modal().showModal();
async delete(supplier: number) {
try {
await firstValueFrom(this.suppliersService.deleteSupplierEndpoint(supplier));
this.notificationService.success('Succès', 'Suppression effectuée');
await this.fetchSuppliers();
} catch (e) {
this.notificationService.error('Erreur', 'Impossible de supprimer la ligne');
}
}
async onModalOk(supplierId: number, updateSupplierComponent: SupplierForm, modal: ModalNav) {
if (!this.selectedSupplier) return;
openEditModal(supplier: GetSupplierDto) {
this.selectedSupplier = { ...supplier };
this.supplierModal().showModal();
}
openEditProductModal(product: GetPriceDto) {
this.selectedProduct = { ...product };
this.productModal().showModal();
}
async onModalOk(supplierId: number | undefined, updateSupplierComponent: SupplierForm, modal: ModalNav) {
if (!supplierId || !this.selectedSupplier) return;
await this.edit(supplierId, updateSupplierComponent);
updateSupplierComponent.supplierForm.reset();
@@ -108,7 +96,56 @@ export class SupplierTable implements OnInit {
await this.fetchSuppliers();
}
async onModalProductOk(
productId: number | undefined,
supplierId: number | undefined,
updateProductComponent: PriceForm,
modal: ModalNav
) {
if (!productId || !supplierId || !this.selectedProduct) return;
await this.editPrice(productId, supplierId, updateProductComponent);
updateProductComponent.priceForm.reset();
modal.isVisible = false;
await this.fetchSuppliers();
}
onModalCancel(modal: ModalNav) {
modal.isVisible = false;
}
async editPrice(productId: number, supplierId: number, updateProductComponent: PriceForm) {
if (updateProductComponent.priceForm.invalid) {
this.notificationService.error('Erreur', 'Erreur d\'écriture dans le formulaire');
return;
}
try {
const formValue = updateProductComponent.priceForm.getRawValue();
const body = {
productId,
supplierId,
sellingPrice: Number(formValue.price),
};
console.log('PATCH body =>', body);
await firstValueFrom(this.pricesService.patchPriceEndpoint(productId, supplierId, body));
this.notificationService.success('Success', 'Prix modifié');
} catch (e) {
console.error(e);
this.notificationService.error('Erreur', 'Erreur lors de la modification');
}
}
async deleteProduct(idProduct: number, idSupplier: number) {
try {
await firstValueFrom(this.pricesService.deletePriceEndpoint(idProduct, idSupplier));
this.notificationService.success('Succès', 'Produit supprimé');
await this.fetchSuppliers();
} catch (e) {
this.notificationService.error('Erreur', 'Impossible de supprimer le produit');
}
}
}