diff --git a/apps/shopify-app/app/features/delivery/route-tracking.js b/apps/shopify-app/app/features/delivery/route-tracking.js
index 98dff86..4e2ea50 100644
--- a/apps/shopify-app/app/features/delivery/route-tracking.js
+++ b/apps/shopify-app/app/features/delivery/route-tracking.js
@@ -285,7 +285,7 @@ function mergeRouteTrackingSnapshot(currentSnapshot, serverSnapshot) {
const mergedBase = normalizeRouteTrackingSnapshot({
...historyBase,
policy: incomingSnapshot.policy ?? current.policy,
- progress: incomingSnapshot.progress,
+ progress: mergeTrackingProgressSnapshot(current.progress, incomingSnapshot.progress),
roadMatchedPath: getNewestRoadMatchedPath(current.roadMatchedPath, incomingSnapshot.roadMatchedPath),
routePlanId: incomingSnapshot.routePlanId ?? current.routePlanId,
schemaVersion: incomingSnapshot.schemaVersion,
@@ -317,6 +317,48 @@ function mergeRouteTrackingSnapshot(currentSnapshot, serverSnapshot) {
return mergedSnapshot;
}
+function mergeTrackingProgressSnapshot(currentProgress, incomingProgress) {
+ const currentLatestEvent = currentProgress?.latestEvent ?? null;
+ const incomingLatestEvent = incomingProgress?.latestEvent ?? null;
+ const currentLatestTimestamp = getPositionTimestamp(currentLatestEvent);
+ const incomingLatestTimestamp = getPositionTimestamp(incomingLatestEvent);
+ const latestEvent = incomingLatestEvent && incomingLatestTimestamp >= currentLatestTimestamp
+ ? incomingLatestEvent
+ : currentLatestEvent;
+ const completedStopIds = new Set(currentProgress?.completedStopIds ?? []);
+ const failedStopIds = new Set(currentProgress?.failedStopIds ?? []);
+
+ for (const deliveryStopId of incomingProgress?.completedStopIds ?? []) {
+ completedStopIds.add(deliveryStopId);
+ failedStopIds.delete(deliveryStopId);
+ }
+ for (const deliveryStopId of incomingProgress?.failedStopIds ?? []) {
+ failedStopIds.add(deliveryStopId);
+ completedStopIds.delete(deliveryStopId);
+ }
+
+ if (latestEvent?.deliveryStopId && latestEvent.eventType === "STOP_DELIVERED") {
+ completedStopIds.add(latestEvent.deliveryStopId);
+ failedStopIds.delete(latestEvent.deliveryStopId);
+ }
+ if (latestEvent?.deliveryStopId && latestEvent.eventType === "STOP_FAILED") {
+ failedStopIds.add(latestEvent.deliveryStopId);
+ completedStopIds.delete(latestEvent.deliveryStopId);
+ }
+
+ return {
+ completedStopIds: [...completedStopIds],
+ currentStage: latestEvent
+ ? getProgressStage(latestEvent.eventType)
+ : incomingProgress?.currentStage ?? currentProgress?.currentStage ?? "READY",
+ currentStopId: latestEvent
+ ? latestEvent.eventType === "STOP_ARRIVED" ? latestEvent.deliveryStopId : null
+ : incomingProgress?.currentStopId ?? currentProgress?.currentStopId ?? null,
+ failedStopIds: [...failedStopIds],
+ latestEvent,
+ };
+}
+
function mergeTrackingStopArrivals(currentArrivals, incomingArrivals) {
const arrivalsByEventId = new Map();
for (const arrival of currentArrivals) arrivalsByEventId.set(arrival.eventId, arrival);
diff --git a/apps/shopify-app/app/features/orders/orders-page.jsx b/apps/shopify-app/app/features/orders/orders-page.jsx
index 1ecceff..769fc4b 100644
--- a/apps/shopify-app/app/features/orders/orders-page.jsx
+++ b/apps/shopify-app/app/features/orders/orders-page.jsx
@@ -1273,17 +1273,28 @@ const noteCardStyle = {
padding: "8px 10px",
};
-const noteListStyle = {
- margin: 0,
- paddingLeft: "18px",
+const noteStackStyle = {
+ display: "grid",
+ gap: "8px",
+};
+
+const noteLabelStyle = {
+ color: "#657080",
+ fontSize: "10px",
+ fontWeight: 700,
+ letterSpacing: "0.06em",
+ marginBottom: "4px",
+ textAlign: "left",
+ textTransform: "uppercase",
};
-const noteListItemStyle = {
+const noteTextStyle = {
color: "#303030",
fontSize: "12px",
lineHeight: 1.4,
overflowWrap: "anywhere",
textAlign: "left",
+ whiteSpace: "pre-wrap",
};
const itemPopoverTitleStyle = {
@@ -5168,12 +5179,20 @@ function OrdersPageContent({ loaderData }) {
width: `${Math.round(notePopoverPosition.width)}px`,
}}
>
-
Order Note
-
-
- {orderNote ? - {orderNote}
: null}
- {customerNote ? - {customerNote}
: null}
-
+
Notes
+
+ {orderNote ? (
+
+
Order Note
+
{orderNote}
+
+ ) : null}
+ {customerNote ? (
+
+
Customer Note
+
{customerNote}
+
+ ) : null}
, document.body) : null}
diff --git a/apps/shopify-app/tests/orders-page.test.mjs b/apps/shopify-app/tests/orders-page.test.mjs
index df97a21..0280a65 100644
--- a/apps/shopify-app/tests/orders-page.test.mjs
+++ b/apps/shopify-app/tests/orders-page.test.mjs
@@ -424,12 +424,17 @@ test("Orders ID stays centered while Note uses a separate headerless column", ()
assert.match(ordersPageSource, /createPortal\([\s\S]*?ref=\{notePopoverRef\}[\s\S]*?notePopoverPosition\.left/);
assert.match(ordersPageSource, /data-order-notes-popover-root="true"/);
assert.match(ordersPageSource, /Notes);
assert.match(ordersPageSource, />Order Note);
+ assert.match(ordersPageSource, />Customer Note);
assert.match(ordersPageSource, /const noteCardStyle = \{/);
- assert.match(ordersPageSource, /const noteListStyle = \{/);
- assert.match(ordersPageSource, //);
- assert.match(ordersPageSource, /- \{orderNote\}<\/li>/);
- assert.match(ordersPageSource, /
- \{customerNote\}<\/li>/);
+ assert.match(ordersPageSource, /const noteStackStyle = \{/);
+ assert.match(ordersPageSource, /const noteLabelStyle = \{/);
+ assert.match(ordersPageSource, /const noteTextStyle = \{/);
+ assert.match(ordersPageSource, /\{orderNote \? \([\s\S]*?
Order Note<\/div>[\s\S]*?
\{orderNote\}<\/div>/);
+ assert.match(ordersPageSource, /\{customerNote \? \([\s\S]*?
Customer Note<\/div>[\s\S]*?
\{customerNote\}<\/div>/);
+ assert.doesNotMatch(ordersPageSource, /const noteListStyle = \{/);
+ assert.doesNotMatch(ordersPageSource, /
/);
});
test("Ordered pill exposes order timing and delivery-cycle sequence on hover", () => {
diff --git a/apps/shopify-app/tests/route-tracking-contract.test.mjs b/apps/shopify-app/tests/route-tracking-contract.test.mjs
index 3755535..ad81cd4 100644
--- a/apps/shopify-app/tests/route-tracking-contract.test.mjs
+++ b/apps/shopify-app/tests/route-tracking-contract.test.mjs
@@ -665,6 +665,56 @@ test("tracking progress keeps the current driver stage and completed stop ids",
assert.deepEqual(delivered.progress.completedStopIds, ["stop-1", "stop-2"]);
});
+test("reconnect snapshots without latest events cannot regress newer live progress", () => {
+ const liveSnapshot = normalizeRouteTrackingSnapshot({
+ policy,
+ progress: {
+ completedStopIds: ["stop-live-earlier", "stop-durable-failed"],
+ currentStage: "DRIVING",
+ currentStopId: null,
+ failedStopIds: ["stop-live-failed", "stop-durable-completed"],
+ latestEvent: {
+ deliveryStopId: "stop-live-delivered",
+ driverId: "driver-1",
+ eventId: "progress-live-delivered",
+ eventType: "STOP_DELIVERED",
+ occurredAt: "2026-07-20T04:05:00.000Z",
+ receivedAt: "2026-07-20T04:05:01.000Z",
+ routePlanId: "route-1",
+ },
+ },
+ recentPositions: [],
+ routePlanId: "route-1",
+ });
+ const reconnectSnapshot = {
+ policy,
+ progress: {
+ completedStopIds: ["stop-durable-completed"],
+ currentStage: "READY",
+ currentStopId: null,
+ failedStopIds: ["stop-durable-failed"],
+ latestEvent: null,
+ },
+ recentPositions: [],
+ routePlanId: "route-1",
+ status: "NO_DATA",
+ };
+
+ const merged = mergeRouteTrackingSnapshot(liveSnapshot, reconnectSnapshot);
+
+ assert.equal(merged.progress.currentStage, "DRIVING");
+ assert.equal(merged.progress.latestEvent.eventId, "progress-live-delivered");
+ assert.deepEqual(new Set(merged.progress.completedStopIds), new Set([
+ "stop-durable-completed",
+ "stop-live-delivered",
+ "stop-live-earlier",
+ ]));
+ assert.deepEqual(new Set(merged.progress.failedStopIds), new Set([
+ "stop-durable-failed",
+ "stop-live-failed",
+ ]));
+});
+
test("tracking proxy forwards authentication and streams the upstream body without buffering", async () => {
const abortController = new AbortController();
const request = new Request("https://app.test/app/route-tracking/route-1", {