import {CommonModule} from '@angular/common'; import {AfterViewInit, Component, inject, Input, OnDestroy, OnInit, ViewChild} from '@angular/core'; import {FormBuilder, ReactiveFormsModule, Validators} from '@angular/forms'; import { MatCell, MatCellDef, MatColumnDef, MatHeaderCell, MatHeaderCellDef, MatHeaderRow, MatHeaderRowDef, MatNoDataRow, MatRow, MatRowDef, MatTable, MatTableDataSource } from '@angular/material/table'; import {MatSort, MatSortModule} from '@angular/material/sort'; import {MatPaginator, MatPaginatorModule} from '@angular/material/paginator'; 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 {PrestashopService} from '../../services/prestashop.serivce'; import {debounceTime, Observable, Subject, takeUntil} from 'rxjs'; import {PsItem} from '../../interfaces/ps-item'; import {PsItemDialogComponent} from '../ps-item-dialog/ps-item-dialog.component'; import {MatDialog} from '@angular/material/dialog'; type Resource = 'categories' | 'manufacturers' | 'suppliers'; @Component({ selector: 'app-ps-admin-crud', standalone: true, templateUrl: './ps-admin-crud.component.html', styleUrls: ['./ps-admin-crud.component.css'], imports: [ CommonModule, ReactiveFormsModule, MatTable, MatColumnDef, MatHeaderCell, MatHeaderCellDef, MatCell, MatCellDef, MatHeaderRow, MatHeaderRowDef, MatRow, MatRowDef, MatSortModule, MatPaginatorModule, MatFormField, MatLabel, MatInput, MatButton, MatIconButton, MatIcon, MatNoDataRow ] }) export class PsAdminCrudComponent implements OnInit, AfterViewInit, OnDestroy { @Input({required: true}) resource!: Resource; @Input({required: true}) label!: string; private readonly fb = inject(FormBuilder); private readonly ps = inject(PrestashopService); private readonly dialog = inject(MatDialog); private readonly destroy$ = new Subject(); dataSource = new MatTableDataSource([]); displayedColumns: string[] = ['id', 'name', 'actions']; form = this.fb.group({name: ['', Validators.required]}); editId: number | null = null; @ViewChild(MatPaginator) paginator!: MatPaginator; @ViewChild(MatSort) sort!: MatSort; @ViewChild(MatTable) table!: MatTable; private readonly filter$: Subject = new Subject(); ngOnInit(): void { this.dataSource.filterPredicate = (row, filter) => { const f = filter.trim().toLowerCase(); return ( String(row.id).toLowerCase().includes(f) || String(row.name ?? '').toLowerCase().includes(f) ); }; this.filter$.pipe(debounceTime(150), takeUntil(this.destroy$)) .subscribe(v => { this.dataSource.filter = (v ?? '').trim().toLowerCase(); if (this.paginator) this.paginator.firstPage(); }); this.reload(); } ngAfterViewInit(): void { this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; } ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); } reload(): void { this.ps.list(this.resource).subscribe({ next: items => { this.dataSource.data = items; // rafraîchir le rendu si nécessaire this.table?.renderRows?.(); }, error: e => alert('Erreur de chargement: ' + (e?.message || e)) }); } createNew() { const ref = this.dialog.open(PsItemDialogComponent, { width: '400px', data: {label: this.label, title: `Créer ${this.label}`} }); ref.afterClosed().subscribe((name: string | null) => { if (!name) return; this.ps.create(this.resource, name).subscribe({ next: () => this.reload(), error: e => alert('Erreur: ' + (e?.message || e)) }); }); } startEdit(row: PsItem) { const ref = this.dialog.open(PsItemDialogComponent, { width: '400px', data: {label: this.label, name: row.name, title: `Modifier ${this.label} #${row.id}`} }); ref.afterClosed().subscribe((name: string | null) => { if (!name) return; this.ps.update(this.resource, row.id, name).subscribe({ next: () => this.reload(), error: e => alert('Erreur: ' + (e?.message || e)) }); }); } cancelEdit() { this.editId = null; this.form.reset({name: ''}); } onSubmit() { const name = (this.form.value.name ?? '').trim(); if (!name) return; const req$: Observable = this.editId ? this.ps.update(this.resource, this.editId, name) as Observable : this.ps.create(this.resource, name) as Observable; req$.subscribe({ next: () => { this.cancelEdit(); this.reload(); }, error: (e: unknown) => alert('Erreur: ' + (e instanceof Error ? e.message : String(e))) }); } remove(row: PsItem) { if (!confirm(`Supprimer ${this.label.toLowerCase()} "#${row.id} ${row.name} ?`)) return; this.ps.delete(this.resource, row.id).subscribe({ next: () => this.reload(), error: e => alert('Erreur: ' + (e?.message || e)) }); } applyFilter(value: string) { this.filter$.next(value); } }