165 lines
5.2 KiB
TypeScript
165 lines
5.2 KiB
TypeScript
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<void>();
|
|
|
|
dataSource = new MatTableDataSource<PsItem>([]);
|
|
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<PsItem>;
|
|
|
|
private readonly filter$: Subject<string> = new Subject<string>();
|
|
|
|
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<unknown> = this.editId
|
|
? this.ps.update(this.resource, this.editId, name) as Observable<unknown>
|
|
: this.ps.create(this.resource, name) as Observable<unknown>;
|
|
|
|
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);
|
|
}
|
|
}
|