Add the shipment progress card to the tracking page
Angular · Angular · advanced · modification
Replaces the raw status code on the tracking page with a proper progress card: a five-step progress bar, a friendly step label, and the ETA. The card takes the shipment as a signal input from the polling page and maps the status to a fill percentage and label. Checked all five statuses against seeded shipments and the bar and label match the mapping table.
Customer-facing order tracking. Shipments move through statuses over hours; customers leave the page open and the 15-second poll exists so the card advances without a reload. The shipments API answers in tens of milliseconds, so 15-second polls never overlap. The Shipment interface (code, status, eta) lives in ./shipment.
Requirements
- The tracking page polls the shipment record from `GET /api/shipments/{id}` every 15 seconds (existing behavior, unchanged) and passes the latest record into the new progress card.
- This PR adds the ShipmentProgress card: a progress bar filled per status (created 10%, picked_up 35%, in_transit 65%, out_for_delivery 85%, delivered 100%), a human step label (Order created / Picked up by carrier / In transit / Out for delivery / Delivered), and an estimated-arrival line from the record's `eta`.
- The card must always reflect the latest record passed in: when a poll delivers a new status, the bar width, the step label, and the ETA must all update. The card stays mounted across updates — the page does not re-create it per poll.
- Use signal inputs and derived values per the codebase conventions.
Files touched
- src/app/shipments/shipment-progress.component.ts
- src/app/shipments/tracking-page.component.ts
--- src/app/shipments/shipment-progress.component.ts
+import { Component, OnInit, input } from '@angular/core';
+import { Shipment, ShipmentStatus } from './shipment';
+
+const STEP_PERCENT: Record<ShipmentStatus, number> = {
+ created: 10,
+ picked_up: 35,
+ in_transit: 65,
+ out_for_delivery: 85,
+ delivered: 100,
+};
+
+const STEP_LABEL: Record<ShipmentStatus, string> = {
+ created: 'Order created',
+ picked_up: 'Picked up by carrier',
+ in_transit: 'In transit',
+ out_for_delivery: 'Out for delivery',
+ delivered: 'Delivered',
+};
+
+/**
+ * Progress card for one shipment. The parent polls the shipment and passes
+ * the latest record in; the card renders the current step and ETA.
+ */
+@Component({
+ selector: 'app-shipment-progress',
+ standalone: true,
+ template: `
+ <article class="shipment-progress">
+ <div