import { AsyncPipe, CurrencyPipe } from '@angular/common'; import { Component, OnInit, inject } from '@angular/core'; import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, RouterModule } from '@angular/router'; import { BehaviorSubject } from 'rxjs'; import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; import { MenuCategory } from '../../core/menu-category'; import { ToCsvService } from '../../shared/to-csv.service'; import { Bundle } from '../bundle'; import { BundleListDataSource } from './bundle-list-datasource'; @Component({ selector: 'app-bundle-list', templateUrl: './bundle-list.component.html', styleUrls: ['./bundle-list.component.css'], imports: [ AsyncPipe, CurrencyPipe, MatButtonModule, MatFormFieldModule, MatIconModule, MatInputModule, MatOptionModule, MatSelectModule, MatTableModule, ReactiveFormsModule, RouterModule, ], }) export class BundleListComponent implements OnInit { private route = inject(ActivatedRoute); private toCsv = inject(ToCsvService); searchFilter = new BehaviorSubject(''); menuCategoryFilter = new BehaviorSubject(''); data: BehaviorSubject = new BehaviorSubject([]); dataSource: BundleListDataSource = new BundleListDataSource(this.searchFilter, this.menuCategoryFilter, this.data); form: FormGroup<{ menuCategory: FormControl; filter: FormControl; }>; list: Bundle[] = []; menuCategories: MenuCategory[] = []; displayedColumns: string[] = ['name', 'price', 'menuCategory', 'info', 'items']; constructor() { this.form = new FormGroup({ menuCategory: new FormControl(''), filter: new FormControl('', { nonNullable: true }), }); this.data.subscribe((data: Bundle[]) => { this.list = data; }); this.form.controls.filter.valueChanges.pipe(debounceTime(150), distinctUntilChanged()).subscribe((value) => { this.searchFilter.next(value ?? ''); }); } filterOn(val: string) { this.menuCategoryFilter.next(val); } ngOnInit() { this.dataSource = new BundleListDataSource(this.searchFilter, this.menuCategoryFilter, this.data); this.route.data.subscribe((value) => { const data = value as { list: Bundle[]; menuCategories: MenuCategory[] }; this.loadData(data.list, data.menuCategories); }); } loadData(list: Bundle[], menuCategories: MenuCategory[]) { this.menuCategories = menuCategories; this.data.next(list); } exportCsv() { const headers = { Name: 'name', Units: 'units', Price: 'salePrice', MenuCategory: 'menuCategory', Items: 'items', }; // Map items to count for csv (simple) const csvList = this.dataSource.filteredData.map((b) => ({ ...b, menuCategory: b.menuCategory?.name ?? '', items: (b.items ?? []) .map((i) => `${i.name}${i.quantity && i.quantity !== 1 ? ` x${i.quantity}` : ''}`) .join(' | '), })); const csvData = new Blob([this.toCsv.toCsv(headers, csvList as unknown as Bundle[])], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); link.href = window.URL.createObjectURL(csvData); link.setAttribute('download', 'bundles.csv'); document.body.appendChild(link); link.click(); document.body.removeChild(link); } }