feat: surface automation option details

This commit is contained in:
TopherMayor
2026-04-30 11:07:26 -07:00
parent 899c9cb30b
commit b7a4386e00
4 changed files with 257 additions and 4 deletions

View File

@@ -63,6 +63,32 @@ function normalizeKey(value) {
.replace(/^-+|-+$/g, '');
}
function toTextList(value) {
const items = Array.isArray(value) ? value : value == null ? [] : [value];
return [...new Set(items.flatMap((item) => {
if (Array.isArray(item)) {
return item;
}
if (item && typeof item === 'object') {
return [
item.label,
item.name,
item.text,
item.title,
item.value,
item.summary,
item.description,
].filter(Boolean);
}
return [item];
})
.map((item) => String(item).trim())
.filter(Boolean))];
}
function readJsonLines(filePath) {
if (!fs.existsSync(filePath)) return [];
@@ -162,6 +188,13 @@ function loadPriceHistoryState() {
source: point.source || null,
sourceUrl: point.sourceUrl || point.url || null,
note: point.note || point.description || null,
availability: point.availability || point.status || null,
decisionNote: point.decisionNote || point.note || point.description || null,
highlights: toTextList(point.highlights || point.summaryBullets || point.bullets),
features: toTextList(point.features || point.featureHighlights || point.featureLabels),
amenities: toTextList(point.amenities || point.amenityHighlights || point.amenityLabels),
inclusions: toTextList(point.inclusions || point.includes || point.perks),
limitations: toTextList(point.limitations || point.tradeoffs || point.caveats),
};
if (!seriesByKey.has(key)) seriesByKey.set(key, []);
@@ -196,12 +229,41 @@ function getPriceHistoryForOption(option, priceHistoryState) {
function decorateOptionWithPriceHistory(option, priceHistoryState) {
const priceHistory = getPriceHistoryForOption(option, priceHistoryState);
const latestPricePoint = priceHistory.at(-1) || null;
const optionDetails = toTextList(option.details);
const automationHighlights = toTextList(latestPricePoint?.highlights);
const automationFeatures = toTextList(latestPricePoint?.features);
const automationAmenities = toTextList(latestPricePoint?.amenities);
const automationInclusions = toTextList(latestPricePoint?.inclusions);
const automationLimitations = toTextList(latestPricePoint?.limitations);
const decisionDetails = [
...optionDetails,
...automationHighlights,
...automationFeatures,
...automationAmenities,
...automationInclusions,
...automationLimitations,
];
return {
...option,
priceHistory,
latestPricePoint,
currentPrice: latestPricePoint?.price ?? null,
decisionDetails: [...new Set(decisionDetails)],
automationInsights: latestPricePoint ? {
currentPrice: latestPricePoint.price,
currency: latestPricePoint.currency || 'USD',
displayPrice: latestPricePoint.displayPrice || null,
source: latestPricePoint.source || null,
sourceUrl: latestPricePoint.sourceUrl || null,
availability: latestPricePoint.availability || null,
decisionNote: latestPricePoint.decisionNote || null,
highlights: automationHighlights,
features: automationFeatures,
amenities: automationAmenities,
inclusions: automationInclusions,
limitations: automationLimitations,
} : null,
};
}