74 lines
2.5 KiB
JavaScript
74 lines
2.5 KiB
JavaScript
/**
|
|
* Polls /api/hail-status every 60 seconds.
|
|
* Auto-triggers stormMode when a real hail event is detected.
|
|
*
|
|
* In mock mode: simulates a storm event arriving after MOCK_TRIGGER_DELAY ms
|
|
* so the full auto-trigger flow can be tested locally without a real webhook.
|
|
*
|
|
* Usage:
|
|
* const { stormActive, stormEvent, lastChecked } = useStormStatus(setStormMode);
|
|
*/
|
|
|
|
import { useState, useEffect, useRef } from 'react';
|
|
|
|
const POLL_INTERVAL_MS = 60_000;
|
|
const MOCK_TRIGGER_DELAY = 0; // set > 0 (e.g. 30000) to simulate auto-trigger in dev
|
|
|
|
export function useStormStatus(onStormDetected) {
|
|
const [stormActive, setStormActive] = useState(false);
|
|
const [stormEvent, setStormEvent] = useState(null);
|
|
const [lastChecked, setLastChecked] = useState(null);
|
|
const prevActive = useRef(false);
|
|
|
|
const checkStatus = async () => {
|
|
try {
|
|
const res = await fetch('/api/hail-status');
|
|
if (!res.ok) return;
|
|
const data = await res.json();
|
|
|
|
setStormActive(data.stormActive ?? false);
|
|
setStormEvent(data.event ?? null);
|
|
setLastChecked(Date.now());
|
|
|
|
if (data.stormActive && !prevActive.current) {
|
|
onStormDetected?.(data.event);
|
|
}
|
|
prevActive.current = data.stormActive ?? false;
|
|
} catch {
|
|
// Network error or KV unavailable — silently ignore, don't disrupt UI
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
// Mock trigger for local testing
|
|
if (MOCK_TRIGGER_DELAY > 0) {
|
|
const t = setTimeout(() => {
|
|
const mockEvent = {
|
|
address: '4817 Shady Brook Ln',
|
|
city: 'Plano',
|
|
state: 'TX',
|
|
zip: '75093',
|
|
hailSize: 1.75,
|
|
stormDate: new Date().toISOString(),
|
|
receivedAt: Date.now(),
|
|
};
|
|
setStormActive(true);
|
|
setStormEvent(mockEvent);
|
|
setLastChecked(Date.now());
|
|
if (!prevActive.current) {
|
|
onStormDetected?.(mockEvent);
|
|
prevActive.current = true;
|
|
}
|
|
}, MOCK_TRIGGER_DELAY);
|
|
return () => clearTimeout(t);
|
|
}
|
|
|
|
// Real polling
|
|
checkStatus();
|
|
const interval = setInterval(checkStatus, POLL_INTERVAL_MS);
|
|
return () => clearInterval(interval);
|
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
return { stormActive, stormEvent, lastChecked };
|
|
}
|