Files
Extrudex/frontend/src/app/components/inventory-summary/inventory-summary.component.ts

82 lines
2.7 KiB
TypeScript
Raw Normal View History

import {
ChangeDetectionStrategy,
Component,
computed,
inject,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatIconModule } from '@angular/material/icon';
import { MatTooltipModule } from '@angular/material/tooltip';
import { FilamentService } from '../../services/filament.service';
import { classifyStockLevel } from '../../models/filament.model';
/**
* InventorySummaryComponent dashboard summary for filament inventory metrics.
*
* Displays three key metrics driven by FilamentService:
* - Total filament count (active spools)
* - Low stock count (spools classified as 'low' or 'critical')
* - Estimated total filament value (sum of purchase prices for active spools)
*
* All values update dynamically whenever FilamentService data changes.
*/
@Component({
selector: 'app-inventory-summary',
standalone: true,
imports: [
CommonModule,
MatIconModule,
MatTooltipModule,
],
templateUrl: './inventory-summary.component.html',
styleUrl: './inventory-summary.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class InventorySummaryComponent {
private readonly filamentService = inject(FilamentService);
/** Computed: total number of active filament spools */
readonly totalFilamentCount = computed(() =>
this.filamentService.filaments().filter((f) => f.isActive).length
);
/** Computed: count of spools at low or critical stock levels */
readonly lowStockCount = computed(() =>
this.filamentService.filaments().filter((f) => {
const level = classifyStockLevel(f);
return level === 'low' || level === 'critical';
}).length
);
/** Computed: count of spools at critical stock level only */
readonly criticalStockCount = computed(() =>
this.filamentService.filaments().filter(
(f) => classifyStockLevel(f) === 'critical'
).length
);
/** Computed: estimated total value of all active spools with a recorded price */
readonly estimatedTotalValue = computed(() =>
this.filamentService
.filaments()
.filter((f) => f.isActive && f.purchasePrice !== null)
.reduce((sum, f) => sum + (f.purchasePrice ?? 0), 0)
);
/** Computed: whether there are low-stock spools to highlight */
readonly hasLowStock = computed(() => this.lowStockCount() > 0);
/** Computed: whether there are critical-stock spools */
readonly hasCriticalStock = computed(() => this.criticalStockCount() > 0);
/** Format a currency value for display */
formatCurrency(value: number): string {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 0,
maximumFractionDigits: 2,
}).format(value);
}
}