home page table filtering

This commit is contained in:
Cyril Joseph 2026-01-12 21:56:49 -04:00
parent cf6fdb6489
commit 587f532663
3 changed files with 142 additions and 5 deletions

View File

@ -19,6 +19,33 @@
</div> </div>
<div class="table-actions"> <div class="table-actions">
<div class="filter-controls" *ngIf="dataSource.data.length > 0">
<!-- Column Selection Dropdown -->
<mat-form-field appearance="outline" class="filter-field">
<mat-label>Filter By</mat-label>
<mat-select [(value)]="selectedColumn" (selectionChange)="onColumnChange()">
<mat-option value=""></mat-option>
<mat-option *ngFor="let column of filterableColumns" [value]="column.value">
{{column.displayName}}
</mat-option>
</mat-select>
</mat-form-field>
<!-- Search Input -->
<mat-form-field appearance="outline" class="filter-field">
<mat-label>Search Value</mat-label>
<input matInput [(ngModel)]="filterValue" (keyup)="applyFilter()"
placeholder="Enter search term...">
<mat-icon matSuffix>search</mat-icon>
</mat-form-field>
<!-- Clear Filter Button -->
<button mat-raised-button type="button" (click)="clearFilter()"
[disabled]="!selectedColumn && !filterValue">
<mat-icon>clear_all</mat-icon>
Clear Filter
</button>
</div>
<button mat-raised-button color="accent" (click)="exportData()" *ngIf="dataSource.data.length > 0" <button mat-raised-button color="accent" (click)="exportData()" *ngIf="dataSource.data.length > 0"
matTooltip="Export to Excel" [disabled]="dataSource.data.length === 0"> matTooltip="Export to Excel" [disabled]="dataSource.data.length === 0">
<mat-icon>download</mat-icon> Export <mat-icon>download</mat-icon> Export

View File

@ -12,10 +12,13 @@
.table-actions { .table-actions {
display: flex; display: flex;
justify-content: end; justify-content: space-between;
margin-bottom: 16px;
button { .filter-controls {
margin-bottom: 16px; display: flex;
gap: 16px;
align-items: center;
} }
} }

View File

@ -19,10 +19,11 @@ import { ConfirmDialogComponent } from '../shared/components/confirm-dialog/conf
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { StorageService } from '../core/services/common/storage.service'; import { StorageService } from '../core/services/common/storage.service';
import { CarnetService } from '../core/services/carnet/carnet.service'; import { CarnetService } from '../core/services/carnet/carnet.service';
import { FormsModule } from '@angular/forms';
@Component({ @Component({
selector: 'app-home', selector: 'app-home',
imports: [AngularMaterialModule, ChartComponent, CommonModule], imports: [AngularMaterialModule, ChartComponent, CommonModule, FormsModule],
templateUrl: './home.component.html', templateUrl: './home.component.html',
styleUrl: './home.component.scss', styleUrl: './home.component.scss',
providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }], providers: [{ provide: MatPaginatorIntl, useClass: CustomPaginator }],
@ -34,6 +35,23 @@ export class HomeComponent {
userPreferences: UserPreferences; userPreferences: UserPreferences;
carnetStatuses: CarnetStatus[] = []; carnetStatuses: CarnetStatus[] = [];
// table filter variables
selectedColumn: string = '';
filterValue: string = '';
filterableColumns: any[] = [
{ value: 'applicationName', displayName: 'Application Name' },
{ value: 'holderName', displayName: 'Holder Name' },
{ value: 'carnetNumber', displayName: 'Carnet Number' },
{ value: 'usSets', displayName: 'US Sets' },
{ value: 'foreignSets', displayName: 'Foreign Sets' },
{ value: 'transitSets', displayName: 'Transit Sets' },
{ value: 'carnetValue', displayName: 'Carnet Value' },
{ value: 'issueDate', displayName: 'Issue Date' },
{ value: 'expiryDate', displayName: 'Expiry Date' },
{ value: 'orderType', displayName: 'Order Type' },
{ value: 'carnetStatus', displayName: 'Carnet Status' }
];
dataSource = new MatTableDataSource<any>(); dataSource = new MatTableDataSource<any>();
@ViewChild(MatPaginator, { static: false }) @ViewChild(MatPaginator, { static: false })
@ -95,6 +113,10 @@ export class HomeComponent {
onCarnetStatusClick(event: any): void { onCarnetStatusClick(event: any): void {
this.isLoading = true; this.isLoading = true;
this.showTable = false; this.showTable = false;
// Clear any existing filters when loading new data
this.clearFilter();
this.homeService.getCarnetDataByStatus(event.spid, event.carnetStatus).subscribe({ this.homeService.getCarnetDataByStatus(event.spid, event.carnetStatus).subscribe({
next: (carnetDetails) => { next: (carnetDetails) => {
this.isLoading = false; this.isLoading = false;
@ -102,6 +124,9 @@ export class HomeComponent {
this.dataSource.data = carnetDetails; this.dataSource.data = carnetDetails;
this.dataSource.paginator = this.paginator; this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort; this.dataSource.sort = this.sort;
// Reset filter after new data is loaded
this.dataSource.filter = '';
}, },
error: (error) => { error: (error) => {
let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load carnet data for the selected status'); let errorMessage = this.errorHandler.handleApiError(error, 'Failed to load carnet data for the selected status');
@ -353,6 +378,88 @@ export class HomeComponent {
this.navigationService.navigate(route, extras); this.navigationService.navigate(route, extras);
} }
applyFilter(): void {
if (!this.dataSource) return;
if (this.selectedColumn && this.filterValue) {
this.dataSource.filterPredicate = (data: any, filter: string) => {
const columnValue = data[this.selectedColumn];
const searchTerm = filter.toLowerCase().trim();
// Handle different column types
switch (this.selectedColumn) {
case 'issueDate':
case 'expiryDate':
// Filter by date
if (columnValue) {
const formattedDate = this.formatDateForDisplay(columnValue);
return formattedDate.toLowerCase().includes(searchTerm);
}
return false;
case 'carnetStatus':
// Filter by status label instead of value
const statusLabel = this.getCarnetStatusLabel(columnValue);
return statusLabel.toLowerCase().includes(searchTerm);
default:
// Default string/number filter
if (typeof columnValue === 'string') {
return columnValue.toLowerCase().includes(searchTerm);
} else if (typeof columnValue === 'number') {
return columnValue.toString().includes(searchTerm);
}
return false;
}
};
this.dataSource.filter = this.filterValue.trim();
} else if (!this.filterValue) {
this.clearFilterData();
}
}
onColumnChange(): void {
this.clearFilterData();
}
clearFilter(): void {
this.selectedColumn = '';
this.clearFilterData();
}
clearFilterData(): void {
this.filterValue = '';
if (this.dataSource) {
this.dataSource.filter = '';
}
}
private formatDateForDisplay(dateValue: any): string {
if (!dateValue) return '';
try {
const date = new Date(dateValue);
// Return in multiple formats for better filtering
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const fullMonthNames = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'];
const month = monthNames[date.getUTCMonth()];
const fullMonth = fullMonthNames[date.getUTCMonth()];
const day = date.getUTCDate();
const year = date.getUTCFullYear();
const monthNumber = date.getUTCMonth() + 1;
// Return multiple formats separated by delimiter for filtering
return `${month} ${day}, ${year}|${fullMonth} ${day}, ${year}|${monthNumber}/${day}/${year}|${year}-${monthNumber.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
} catch (error) {
return '';
}
}
private saveFile(blob: Blob, filename: string): void { private saveFile(blob: Blob, filename: string): void {
const url = window.URL.createObjectURL(blob); const url = window.URL.createObjectURL(blob);
const a = document.createElement('a'); const a = document.createElement('a');