refactor: reorganize component files and update import paths; add PsItem and PsProduct interfaces
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
import {Component, inject, OnInit, ViewChild} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {
|
||||
MatCell, MatCellDef, MatColumnDef, MatHeaderCell, MatHeaderCellDef,
|
||||
MatHeaderRow, MatHeaderRowDef, MatNoDataRow, MatRow, MatRowDef,
|
||||
MatTable, MatTableDataSource
|
||||
} from '@angular/material/table';
|
||||
import {MatPaginator, MatPaginatorModule} from '@angular/material/paginator';
|
||||
import {MatSort, MatSortModule} from '@angular/material/sort';
|
||||
import {MatFormField, MatLabel} from '@angular/material/form-field';
|
||||
import {MatInput} from '@angular/material/input';
|
||||
import {MatButton, MatIconButton} from '@angular/material/button';
|
||||
import {MatIcon} from '@angular/material/icon';
|
||||
import {FormBuilder, ReactiveFormsModule} from '@angular/forms';
|
||||
import {MatDialog, MatDialogModule} from '@angular/material/dialog';
|
||||
|
||||
import {PsItem} from '../../interfaces/ps-item';
|
||||
import {ProductListItem} from '../../interfaces/product-list-item';
|
||||
import {PrestashopService} from '../../services/prestashop.serivce';
|
||||
import {ProductDialogData, PsProductDialogComponent} from '../ps-product-dialog/ps-product-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-ps-product-crud',
|
||||
standalone: true,
|
||||
templateUrl: './ps-product-crud.component.html',
|
||||
styleUrls: ['./ps-product-crud.component.css'],
|
||||
imports: [
|
||||
CommonModule, ReactiveFormsModule,
|
||||
MatTable, MatColumnDef, MatHeaderRow, MatHeaderRowDef, MatRow, MatRowDef,
|
||||
MatHeaderCell, MatHeaderCellDef, MatCell, MatCellDef, MatNoDataRow,
|
||||
MatSortModule, MatPaginatorModule,
|
||||
MatFormField, MatLabel, MatInput,
|
||||
MatButton, MatIconButton, MatIcon,
|
||||
MatDialogModule
|
||||
]
|
||||
})
|
||||
export class PsProductCrudComponent implements OnInit {
|
||||
private readonly fb = inject(FormBuilder);
|
||||
private readonly ps = inject(PrestashopService);
|
||||
private readonly dialog = inject(MatDialog);
|
||||
|
||||
// référentiels
|
||||
categories: PsItem[] = [];
|
||||
manufacturers: PsItem[] = [];
|
||||
suppliers: PsItem[] = [];
|
||||
|
||||
// maps d’affichage
|
||||
private catMap = new Map<number, string>();
|
||||
private manMap = new Map<number, string>();
|
||||
private supMap = new Map<number, string>();
|
||||
|
||||
// table
|
||||
displayed: string[] = ['id', 'name', 'category', 'manufacturer', 'supplier', 'priceTtc', 'actions'];
|
||||
dataSource = new MatTableDataSource<any>([]);
|
||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
@ViewChild(MatSort) sort!: MatSort;
|
||||
@ViewChild(MatTable) table!: MatTable<any>;
|
||||
|
||||
// filtre
|
||||
filterCtrl = this.fb.control<string>('');
|
||||
|
||||
ngOnInit(): void {
|
||||
// charger référentiels en parallèle
|
||||
Promise.all([
|
||||
this.ps.list('categories').toPromise(),
|
||||
this.ps.list('manufacturers').toPromise(),
|
||||
this.ps.list('suppliers').toPromise()
|
||||
]).then(([cats, mans, sups]) => {
|
||||
this.categories = cats ?? [];
|
||||
this.catMap = new Map(this.categories.map(x => [x.id, x.name]));
|
||||
this.manufacturers = mans ?? [];
|
||||
this.manMap = new Map(this.manufacturers.map(x => [x.id, x.name]));
|
||||
this.suppliers = sups ?? [];
|
||||
this.supMap = new Map(this.suppliers.map(x => [x.id, x.name]));
|
||||
this.reload();
|
||||
});
|
||||
|
||||
// filtre client
|
||||
this.filterCtrl.valueChanges.subscribe(v => {
|
||||
this.dataSource.filter = (v ?? '').toString().trim().toLowerCase();
|
||||
if (this.paginator) this.paginator.firstPage();
|
||||
});
|
||||
this.dataSource.filterPredicate = (row: any, f: string) =>
|
||||
row.name?.toLowerCase().includes(f) ||
|
||||
String(row.id).includes(f) ||
|
||||
(row.categoryName?.toLowerCase().includes(f)) ||
|
||||
(row.manufacturerName?.toLowerCase().includes(f)) ||
|
||||
(row.supplierName?.toLowerCase().includes(f));
|
||||
}
|
||||
|
||||
private toTtc(ht: number, vat: number) {
|
||||
return Math.round(((ht * (1 + vat)) + Number.EPSILON) * 100) / 100;
|
||||
}
|
||||
|
||||
private attachSortingAccessors() {
|
||||
this.dataSource.sortingDataAccessor = (item: any, property: string) => {
|
||||
switch (property) {
|
||||
case 'category':
|
||||
return (item.categoryName ?? '').toLowerCase();
|
||||
case 'manufacturer':
|
||||
return (item.manufacturerName ?? '').toLowerCase();
|
||||
case 'supplier':
|
||||
return (item.supplierName ?? '').toLowerCase();
|
||||
case 'priceTtc':
|
||||
return Number(item.priceTtc ?? 0);
|
||||
case 'name':
|
||||
return (item.name ?? '').toLowerCase();
|
||||
default:
|
||||
return item[property];
|
||||
}
|
||||
};
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
}
|
||||
|
||||
private bindProducts(p: (ProductListItem & { priceHt?: number })[]) {
|
||||
const vat = 0.20; // valeur fixe utilisée pour calcul TTC en liste
|
||||
this.dataSource.data = p.map(x => ({
|
||||
...x,
|
||||
categoryName: x.id_category_default ? (this.catMap.get(x.id_category_default) ?? '') : '',
|
||||
manufacturerName: x.id_manufacturer ? (this.manMap.get(x.id_manufacturer) ?? '') : '',
|
||||
supplierName: x.id_supplier ? (this.supMap.get(x.id_supplier) ?? '') : '',
|
||||
priceTtc: this.toTtc(x.priceHt ?? 0, vat)
|
||||
}));
|
||||
this.attachSortingAccessors();
|
||||
this.table?.renderRows?.();
|
||||
}
|
||||
|
||||
reload() {
|
||||
this.ps.listProducts().subscribe(p => this.bindProducts(p));
|
||||
}
|
||||
|
||||
create() {
|
||||
const data: ProductDialogData = {
|
||||
mode: 'create',
|
||||
refs: {
|
||||
categories: this.categories,
|
||||
manufacturers: this.manufacturers,
|
||||
suppliers: this.suppliers
|
||||
}
|
||||
};
|
||||
this.dialog.open(PsProductDialogComponent, {width: '900px', data}).afterClosed().subscribe(ok => {
|
||||
if (ok) this.reload();
|
||||
});
|
||||
}
|
||||
|
||||
edit(row: ProductListItem & { priceHt?: number }) {
|
||||
const data: ProductDialogData = {
|
||||
mode: 'edit',
|
||||
productRow: row,
|
||||
refs: {
|
||||
categories: this.categories,
|
||||
manufacturers: this.manufacturers,
|
||||
suppliers: this.suppliers
|
||||
}
|
||||
};
|
||||
this.dialog.open(PsProductDialogComponent, {width: '900px', data}).afterClosed().subscribe(ok => {
|
||||
if (ok) this.reload();
|
||||
});
|
||||
}
|
||||
|
||||
remove(row: ProductListItem) {
|
||||
if (!confirm(`Supprimer le produit "${row.name}" (#${row.id}) ?`)) return;
|
||||
this.ps.deleteProduct(row.id).subscribe({
|
||||
next: () => this.reload(),
|
||||
error: (e: unknown) => alert('Erreur: ' + (e instanceof Error ? e.message : String(e)))
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user