import { ChangeDetectionStrategy, Component, signal, computed } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import {
MagarySidebar,
MagaryTable,
MagarySelect,
MagaryOverlayPanel,
MagaryDialog,
MagaryTag,
MagaryToast,
MagaryButton,
MessageService,
} from 'ng-magary';
import { Shipment, ShipmentAction, OperationModule } from './logistics.models';
@Component({
selector: 'app-logistics-page',
standalone: true,
imports: [
CommonModule,
FormsModule,
MagarySidebar,
MagaryTable,
MagarySelect,
MagaryOverlayPanel,
MagaryDialog,
MagaryTag,
MagaryToast,
MagaryButton,
],
providers: [MessageService],
templateUrl: './logistics.page.html',
styleUrls: ['./logistics.page.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LogisticsPage {
constructor(private messageService: MessageService) {}
// Sidebar state
readonly sidebarVisible = signal(true);
readonly selectedModule = signal('shipments');
// Shipment data
readonly allShipments = signal<Shipment[]>([
{
id: 'SH-001',
trackingNumber: 'TRK-2026-001234',
origin: 'New York, NY',
destination: 'Los Angeles, CA',
status: 'IN_TRANSIT',
eta: '2026-03-06T14:00:00',
priority: 'HIGH',
carrier: 'FastShip Express',
weight: 125.5,
customer: 'Acme Corporation',
notes: 'Handle with care - fragile items',
},
{
id: 'SH-002',
trackingNumber: 'TRK-2026-001235',
origin: 'Chicago, IL',
destination: 'Miami, FL',
status: 'PENDING',
eta: '2026-03-08T10:00:00',
priority: 'MEDIUM',
carrier: 'Global Logistics',
weight: 85.2,
customer: 'TechStart Inc',
},
{
id: 'SH-003',
trackingNumber: 'TRK-2026-001236',
origin: 'Seattle, WA',
destination: 'Boston, MA',
status: 'BLOCKED',
eta: '2026-03-05T16:00:00',
priority: 'HIGH',
carrier: 'FastShip Express',
weight: 210.8,
customer: 'MegaMart',
notes: 'Weather delay - awaiting clearance',
},
{
id: 'SH-004',
trackingNumber: 'TRK-2026-001237',
origin: 'Houston, TX',
destination: 'Denver, CO',
status: 'DELIVERED',
eta: '2026-03-03T12:00:00',
priority: 'LOW',
carrier: 'Budget Freight',
weight: 45.0,
customer: 'Small Business LLC',
},
{
id: 'SH-005',
trackingNumber: 'TRK-2026-001238',
origin: 'Phoenix, AZ',
destination: 'Portland, OR',
status: 'IN_TRANSIT',
eta: '2026-03-07T09:00:00',
priority: 'MEDIUM',
carrier: 'Global Logistics',
weight: 152.3,
customer: 'Northwest Supplies',
},
]);
// Filters
readonly statusFilter = signal<Shipment['status'] | null>(null);
readonly priorityFilter = signal<Shipment['priority'] | null>(null);
// Filtered shipments
readonly filteredShipments = computed(() => {
let shipments = this.allShipments();
const status = this.statusFilter();
if (status) {
shipments = shipments.filter(s => s.status === status);
}
const priority = this.priorityFilter();
if (priority) {
shipments = shipments.filter(s => s.priority === priority);
}
return shipments;
});
// Selected shipment
readonly selectedShipmentId = signal<string | null>(null);
readonly selectedShipment = computed(() => {
const id = this.selectedShipmentId();
return this.allShipments().find(s => s.id === id) || null;
});
// Dialog state
readonly actionDialogVisible = signal(false);
readonly pendingAction = signal<ShipmentAction | null>(null);
// Navigation modules
readonly modules: OperationModule[] = [
{ id: 'shipments', label: 'Shipments', icon: 'pi pi-box', route: '/logistics/shipments' },
{ id: 'tracking', label: 'Live Tracking', icon: 'pi pi-map-marker', route: '/logistics/tracking' },
{ id: 'fleet', label: 'Fleet Management', icon: 'pi pi-car', route: '/logistics/fleet' },
{ id: 'analytics', label: 'Analytics', icon: 'pi pi-chart-line', route: '/logistics/analytics' },
{ id: 'settings', label: 'Settings', icon: 'pi pi-cog', route: '/logistics/settings' },
];
// Filter options
readonly statusOptions = [
{ label: 'All Statuses', value: null },
{ label: 'Pending', value: 'PENDING' },
{ label: 'In Transit', value: 'IN_TRANSIT' },
{ label: 'Delivered', value: 'DELIVERED' },
{ label: 'Blocked', value: 'BLOCKED' },
];
readonly priorityOptions = [
{ label: 'All Priorities', value: null },
{ label: 'Low', value: 'LOW' },
{ label: 'Medium', value: 'MEDIUM' },
{ label: 'High', value: 'HIGH' },
];
selectShipment(shipment: Shipment): void {
this.selectedShipmentId.set(shipment.id);
}
initiateAction(type: ShipmentAction['type'], shipment: Shipment): void {
this.pendingAction.set({
type,
shipmentId: shipment.id,
timestamp: new Date().toISOString(),
});
this.actionDialogVisible.set(true);
}
confirmAction(): void {
const action = this.pendingAction();
if (!action) return;
// Simulate API call
const shipments = this.allShipments();
const shipment = shipments.find(s => s.id === action.shipmentId);
if (shipment) {
// Update shipment status based on action
switch (action.type) {
case 'DISPATCH':
shipment.status = 'IN_TRANSIT';
break;
case 'HOLD':
shipment.status = 'BLOCKED';
break;
case 'RELEASE':
shipment.status = 'IN_TRANSIT';
break;
case 'MARK_DELIVERED':
shipment.status = 'DELIVERED';
break;
}
this.allShipments.set([...shipments]);
this.messageService.add({
severity: 'success',
summary: 'Action Completed',
detail: `${action.type.replace('_', ' ')} action completed for ${shipment.trackingNumber}`,
});
}
this.actionDialogVisible.set(false);
this.pendingAction.set(null);
}
getStatusSeverity(status: Shipment['status']): string {
switch (status) {
case 'PENDING': return 'info';
case 'IN_TRANSIT': return 'warning';
case 'DELIVERED': return 'success';
case 'BLOCKED': return 'danger';
}
}
getStatusLabel(status: Shipment['status']): string {
return status.replace('_', ' ');
}
getPrioritySeverity(priority: Shipment['priority']): string {
switch (priority) {
case 'LOW': return 'secondary';
case 'MEDIUM': return 'info';
case 'HIGH': return 'danger';
}
}
formatETA(eta: string): string {
const date = new Date(eta);
return date.toLocaleString('en-US', {
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
});
}
getAvailableActions(shipment: Shipment): ShipmentAction['type'][] {
switch (shipment.status) {
case 'PENDING': return ['DISPATCH', 'HOLD'];
case 'IN_TRANSIT': return ['MARK_DELIVERED', 'HOLD'];
case 'BLOCKED': return ['RELEASE'];
case 'DELIVERED': return [];
default: return [];
}
}
}