feat(hail-recon): Hail Recon integration — storm intel panel, hail history, auto storm mode, address monitoring
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 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 };
|
||||
}
|
||||
Reference in New Issue
Block a user