From e355d48da42b3243ed757dfc0ae9a95d1895a85a Mon Sep 17 00:00:00 2001 From: jtricerolph Date: Mon, 31 Aug 2026 12:07:43 +0000 Subject: [PATCH] =?UTF-8?q?Add=20a=20sun=20cream=20tip=20for=20hot=20days?= =?UTF-8?q?=20(high=20>=2026=C2=B0C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Temp-based stand-in for the UV-index idea from earlier -- neither provider is currently fetched for UV, so this reuses the same highTemp value already computed for the jacket tip, just the other direction. Mutually exclusive with jacket (a high can't be both <12 and >26). Co-Authored-By: Claude Sonnet 5 --- backend/src/lib/summary.js | 8 +++++++- frontend/src/pages/Display.tsx | 3 ++- frontend/src/types.ts | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/backend/src/lib/summary.js b/backend/src/lib/summary.js index 5f0fb77..37eef7c 100644 --- a/backend/src/lib/summary.js +++ b/backend/src/lib/summary.js @@ -14,6 +14,9 @@ const SNOW_ICONS = new Set(['snow-light', 'snow-heavy']) // 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 +const SUN_HIGH_TEMP_C = 26 // today's forecast high above this -> sun cream tip + // (a temp-based stand-in for a proper UV index, + // which neither provider is currently fetched for) // summarizeToday(points, nowHour) — `points` is today's hourly forecast_points rows // (already icon-normalized), `nowHour` is 0-23 in Europe/London. Returns null if @@ -97,9 +100,12 @@ export function summarizeToday(points, nowHour) { } // Jacket: keyed off today's forecast high, not "right now" -- same framing - // as the big temp above it. + // as the big temp above it. Mutually exclusive with the sun tip below (never + // both -- one high temp can't be both below 12 and above 26). if (highPoint.temp_c < JACKET_HIGH_TEMP_C) { tips.push({ key: 'jacket', text: "Don't forget your jacket" }) + } else if (highPoint.temp_c > SUN_HIGH_TEMP_C) { + tips.push({ key: 'sun', text: "Don't forget your sun cream" }) } return { diff --git a/frontend/src/pages/Display.tsx b/frontend/src/pages/Display.tsx index cc85f14..6e2a8f1 100644 --- a/frontend/src/pages/Display.tsx +++ b/frontend/src/pages/Display.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'react' -import { CloudOff, Umbrella, Shirt } from 'lucide-react' +import { CloudOff, Umbrella, Shirt, Sun } from 'lucide-react' import { fetchForecast, fetchDisplayConfig } from '../api' import { WeatherIcon } from '../lib/icons' import { PointMeta } from '../components/PointMeta' @@ -14,6 +14,7 @@ const TIP_ICONS: Record = { umbrella: Umbrella, 'umbrella-soft': Umbrella, jacket: Shirt, + sun: Sun, } const POLL_MS = 5 * 60 * 1000 // client polls more often than the server's hourly diff --git a/frontend/src/types.ts b/frontend/src/types.ts index c7d9899..18b6421 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -23,7 +23,7 @@ export interface Astro { sunset: string | null } -export type TipKey = 'umbrella' | 'umbrella-soft' | 'jacket' +export type TipKey = 'umbrella' | 'umbrella-soft' | 'jacket' | 'sun' export interface Summary { headline: string // "Scattered showers today", "Rain likely later", ...