82 lines
2.7 KiB
TypeScript
82 lines
2.7 KiB
TypeScript
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);
|
|
}
|
|
}
|