@metron-labs/quote-react 0.1.55 → 0.1.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,10 @@ import ScheduleResultsStage from "./stages/ScheduleResultsStage";
11
11
  import BasketStage from "./stages/BasketStage";
12
12
  import { CartProvider, useCart } from "../lib/cart/CartContext";
13
13
  const SAVED_QUOTE_KEY = "metron-quick-quote";
14
+ // A tab left open for days shouldn't come back with old matches and old prices.
15
+ // ponytail: counts from the last edit, not from matching. Stamp the match time instead if
16
+ // prices move faster than people edit.
17
+ const SAVED_QUOTE_TTL_MS = 24 * 60 * 60 * 1000;
14
18
  // Its own provider, separate from the estimating tools' - a quote in progress and a set
15
19
  // of calculator results are different baskets.
16
20
  export default function QuickQuote(props) {
@@ -54,6 +58,10 @@ function QuickQuoteInner({ fullPage = false, hideHeader = false, internal = fals
54
58
  saved = JSON.parse(window.sessionStorage.getItem(SAVED_QUOTE_KEY) ?? "null");
55
59
  }
56
60
  catch { }
61
+ // Older than the TTL (or saved before there was a stamp): start fresh. The save effect
62
+ // below then removes it, as scheduleResult stays null.
63
+ if (saved && !(Date.now() - (saved.savedAt ?? 0) < SAVED_QUOTE_TTL_MS))
64
+ saved = null;
57
65
  if (saved?.scheduleResult) {
58
66
  setEntryMode("schedule");
59
67
  setScheduleResult(saved.scheduleResult);
@@ -81,7 +89,7 @@ function QuickQuoteInner({ fullPage = false, hideHeader = false, internal = fals
81
89
  if (!scheduleResult)
82
90
  window.sessionStorage.removeItem(SAVED_QUOTE_KEY);
83
91
  else
84
- window.sessionStorage.setItem(SAVED_QUOTE_KEY, JSON.stringify({ scheduleResult, reviewGateComplete: scheduleReviewGateComplete, cartSeeded, cart }));
92
+ window.sessionStorage.setItem(SAVED_QUOTE_KEY, JSON.stringify({ savedAt: Date.now(), scheduleResult, reviewGateComplete: scheduleReviewGateComplete, cartSeeded, cart }));
85
93
  }
86
94
  catch { }
87
95
  }, [restored, scheduleResult, scheduleReviewGateComplete, cartSeeded, cart]);
@@ -197,9 +197,9 @@ function LinkedGroupPill({ meta }) {
197
197
  function curatedCandidates(candidates, result, selectedProductId) {
198
198
  const recommendedIds = result?.rerank?.recommendedCandidateIds ?? [];
199
199
  if (recommendedIds.length === 0) {
200
- const top5 = candidates.slice(0, 5);
201
- const pinnedSelected = !top5.some((candidate) => candidate.product_id === selectedProductId) ? candidates.find((candidate) => candidate.product_id === selectedProductId) : undefined;
202
- return pinnedSelected ? [...top5, pinnedSelected] : top5;
200
+ const topCandidates = candidates.slice(0, 6);
201
+ const pinnedSelected = !topCandidates.some((candidate) => candidate.product_id === selectedProductId) ? candidates.find((candidate) => candidate.product_id === selectedProductId) : undefined;
202
+ return pinnedSelected ? [...topCandidates, pinnedSelected] : topCandidates;
203
203
  }
204
204
  const byId = new Map(candidates.map((candidate) => [candidate.product_id, candidate]));
205
205
  const shown = recommendedIds.map((candidateId) => byId.get(candidateId)).filter((candidate) => candidate != null);
@@ -209,7 +209,7 @@ function curatedCandidates(candidates, result, selectedProductId) {
209
209
  shown.unshift(selected);
210
210
  }
211
211
  }
212
- return [...new Map(shown.map((candidate) => [candidate.product_id, candidate])).values()].slice(0, 5);
212
+ return [...new Map(shown.map((candidate) => [candidate.product_id, candidate])).values()].slice(0, 6);
213
213
  }
214
214
  function recommendedCandidates(result) {
215
215
  const recommendedIds = result?.rerank?.recommendedCandidateIds ?? [];
@@ -682,7 +682,7 @@ export default function ScheduleResultsStage({ scheduleResult, onStartOver, cart
682
682
  const savedSearchCandidate = activeReviewRow ? savedSearchCandidates[activeReviewRow.item.line_id] : undefined;
683
683
  const reviewDisplayCandidates = !reviewQuery && savedSearchCandidate && !reviewCandidates.some((candidate) => candidate.product_id === savedSearchCandidate.product_id) ? [...reviewCandidates, savedSearchCandidate] : reviewCandidates;
684
684
  const reviewOptionCandidates = (() => {
685
- const topCandidates = reviewDisplayCandidates.slice(0, reviewQuery ? 12 : 3);
685
+ const topCandidates = reviewDisplayCandidates.slice(0, reviewQuery ? 12 : 6);
686
686
  if (reviewQuery || !savedSearchCandidate || topCandidates.some((candidate) => candidate.product_id === savedSearchCandidate.product_id))
687
687
  return topCandidates;
688
688
  return [...topCandidates, savedSearchCandidate];