PredictionScreen.tsx
Purpose
This module renders the Prediction tab, which is the primary interface for active heat risk monitoring. It manages the session lifecycle, triggers core temperature inference, displays the result on an animated arc gauge, and persists each prediction to the history database.
Its responsibilities include:
- Starting and stopping background monitoring sessions
- Triggering heat risk predictions on session start and on each background prediction event
- Requesting heart rate data from the watch integration before each prediction run
- Rendering a color-zoned SVG arc gauge showing the current estimated core temperature
- Displaying a localized status banner mapped to the current heat-stress state
- Persisting each successful prediction to
sensorHistoryDbfor dashboard consumption - Logging full WBGT and core temperature model inputs on each prediction for debugging
- Allowing the user to update their
daysActive14activity field with inline persistence - Requesting notification permissions on first mount
Invariants
Session Toggle Atomicity
Starting and stopping a session are gated behind sessionLoading state.
The toggle button is disabled while a session state change is in progress, preventing double-taps from creating inconsistent session state.
Prediction on Session Start
A prediction run is triggered immediately when a session is started, without waiting for the first background event.
When a session is stopped, the last prediction result is cleared from state.
Core Temp Persistence
Every successful prediction result has its coreTempC value written to sensorHistoryDb via recordCoreTemp.
Persistence failures are silently swallowed (.catch(() => {})) to avoid surfacing storage errors in the prediction UI.
Notification Permission on Mount
requestNotificationPermissions() is called once on component mount via useEffect.
This is fire-and-forget; the result does not gate any UI behavior.
Activity Days Persistence
daysActive14 is saved to the profile store on TextInput blur.
The value is clamped to [0, 14] before saving. The field is non-editable while a session is active.
ONNX Runtime Awareness
isOnnxRuntimeAvailable() is called at render time and its result is available in the component scope.
This allows the prediction service to select the appropriate model variant (baseline vs ONNX) without UI-level gating in this component.
Variants
Session States
The primary button renders one of four labels depending on session and loading state:
| Condition | Label |
|---|---|
| Not active, not loading | startSession |
| Starting (loading) | starting |
| Active, not loading | stopSession |
| Stopping (loading) | stopping |
When active, the button uses the secondary variant with a danger-colored border.
Prediction Result States
The result area renders one of three states:
- Value present — gauge and status banner are rendered
- Session active, no value yet — “working on it” hint text is shown
- Error — an error card is shown with the error message (only when not session-active)
Gauge Rendering
The CoreTempGauge component renders an SVG arc gauge with:
- Four colored zone segments mapped to temperature ranges
[36, 41]°C - Three threshold tick marks at 38.0, 38.5, and 40.0 °C
- A center circle showing the numeric value, unit, and state label
adjustsFontSizeToFiton all text within the circle to prevent overflow at any font scale
The gauge spans 242° to 298° (a 56° arc through the bottom of the circle).
Heat-Risk Zones
| Zone | Min temp (°C) | Color |
|---|---|---|
| Safe | — | #22C55E |
| Watch | 38.0 | #EAB308 |
| Caution | 38.5 | #F97316 |
| Danger | 40.0 | #EF4444 |
| Critical | 40.5 | #7F1D1D |
The status banner label and body are resolved from i18n keys of the form prediction.status.<key>.label and prediction.status.<key>.body.
Exports
PredictionScreen (default)
export default function PredictionScreen(): JSX.Element
Renders the prediction tab with session controls, core temperature gauge, status banner, and activity settings.
Has no props. Reads profile and session state from their respective services on mount and focus.