Add a sun cream tip for hot days (high > 26°C)

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 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-08-31 12:07:43 +00:00
parent b4f1e81eed
commit e355d48da4
3 changed files with 10 additions and 3 deletions

View file

@ -14,6 +14,9 @@ const SNOW_ICONS = new Set(['snow-light', 'snow-heavy'])
// without touching the logic that uses them. // without touching the logic that uses them.
const UMBRELLA_SOFT_PRECIP_PCT = 10 // any remaining hour above this -> "might want" 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 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 // summarizeToday(points, nowHour) — `points` is today's hourly forecast_points rows
// (already icon-normalized), `nowHour` is 0-23 in Europe/London. Returns null if // (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 // 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) { if (highPoint.temp_c < JACKET_HIGH_TEMP_C) {
tips.push({ key: 'jacket', text: "Don't forget your jacket" }) 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 { return {

View file

@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from 'react' 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 { fetchForecast, fetchDisplayConfig } from '../api'
import { WeatherIcon } from '../lib/icons' import { WeatherIcon } from '../lib/icons'
import { PointMeta } from '../components/PointMeta' import { PointMeta } from '../components/PointMeta'
@ -14,6 +14,7 @@ const TIP_ICONS: Record<TipKey, typeof Umbrella> = {
umbrella: Umbrella, umbrella: Umbrella,
'umbrella-soft': Umbrella, 'umbrella-soft': Umbrella,
jacket: Shirt, jacket: Shirt,
sun: Sun,
} }
const POLL_MS = 5 * 60 * 1000 // client polls more often than the server's hourly const POLL_MS = 5 * 60 * 1000 // client polls more often than the server's hourly

View file

@ -23,7 +23,7 @@ export interface Astro {
sunset: string | null sunset: string | null
} }
export type TipKey = 'umbrella' | 'umbrella-soft' | 'jacket' export type TipKey = 'umbrella' | 'umbrella-soft' | 'jacket' | 'sun'
export interface Summary { export interface Summary {
headline: string // "Scattered showers today", "Rain likely later", ... headline: string // "Scattered showers today", "Rain likely later", ...