Bigger tip chip(s), soft umbrella tier, and a jacket tip

- Umbrella tip now bigger (larger padding/font/icon) and there can be
  more than one chip shown at once (e.g. cold + rainy).
- Added a softer 'You might want an umbrella' tier: shown when the
  existing strong threshold isn't met but any remaining hour today
  still has a real (>10%) rain chance -- previously that case showed
  nothing at all.
- Added a jacket tip: shown when today's forecast high is below 12°C.
  Both new thresholds are named constants at the top of summary.js,
  easy to retune without touching the logic.

summary.js's umbrella boolean is replaced by a tips[] array so future
nudges (e.g. a UV/sun-cream tip, if we add UV index data) slot in the
same way without another one-off boolean + span.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-08-31 12:05:11 +00:00
parent 335e6e31a8
commit b4f1e81eed
4 changed files with 69 additions and 16 deletions

View file

@ -10,6 +10,11 @@
const RAIN_ICONS = new Set(['drizzle', 'rain-light', 'rain-heavy', 'sleet', 'hail'])
const SNOW_ICONS = new Set(['snow-light', 'snow-heavy'])
// Tunable thresholds for the "now" panel's tip chips — all easy to adjust here
// without touching the logic that uses them.
const UMBRELLA_SOFT_PRECIP_PCT = 10 // any remaining hour above this -> "might want"
const JACKET_HIGH_TEMP_C = 12 // today's forecast high below this -> jacket tip
// summarizeToday(points, nowHour) — `points` is today's hourly forecast_points rows
// (already icon-normalized), `nowHour` is 0-23 in Europe/London. Returns null if
// there's nothing to summarize (no data yet).
@ -73,16 +78,37 @@ export function summarizeToday(points, nowHour) {
? 'Thunderstorms possible'
: null
// Umbrella nudge: real rain chance either right now or coming up later today.
const umbrella = laterWetFraction > 0.25 || rainFraction > 0.25
// Tip chips — small, actionable nudges under the headline. Each is
// independent (a cold rainy day can show both), ordered by how likely
// reception actually wants a guest to see it.
const tips = []
// Umbrella: the existing "real rain chance" threshold gets the strong
// wording; falling short of that but with a real (if lesser) chance
// still on the cards for later today gets a softer nudge instead of
// nothing at all.
const umbrellaStrong = laterWetFraction > 0.25 || rainFraction > 0.25
const umbrellaSoft = !umbrellaStrong &&
laterPoints.some(p => p.precip_prob != null && p.precip_prob > UMBRELLA_SOFT_PRECIP_PCT)
if (umbrellaStrong) {
tips.push({ key: 'umbrella', text: "Don't forget your umbrella" })
} else if (umbrellaSoft) {
tips.push({ key: 'umbrella-soft', text: 'You might want an umbrella' })
}
// Jacket: keyed off today's forecast high, not "right now" -- same framing
// as the big temp above it.
if (highPoint.temp_c < JACKET_HIGH_TEMP_C) {
tips.push({ key: 'jacket', text: "Don't forget your jacket" })
}
return {
headline,
note,
umbrella,
highTemp: highPoint.temp_c,
highFeelsLike: highPoint.feels_like_c,
rainChance: rainPeakPoint ? { prob: rainPeakPoint.precip_prob, ts: rainPeakPoint.ts } : null,
tips,
}
}