Finish implementation of Hazard list so it can handle when hazards end
This commit is contained in:
parent
ab0b915249
commit
92822e2ddc
3 changed files with 21 additions and 11 deletions
|
|
@ -307,17 +307,17 @@ if (!process.env?.STATIC) {
|
||||||
|
|
||||||
app.post('/api/hazard-history', async (req, res) => {
|
app.post('/api/hazard-history', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { location, hazards } = req.body;
|
const { location, locationKey, hazards } = req.body;
|
||||||
|
|
||||||
if (!location || !Array.isArray(hazards)) {
|
if (!location || !locationKey || !Array.isArray(hazards)) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Missing or invalid location/hazards',
|
error: 'Missing or invalid location/locationKey/hazards',
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const history = await updateHistory({ location, hazards });
|
const history = await updateHistory({ location, locationKey, hazards });
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
history,
|
history,
|
||||||
|
|
|
||||||
|
|
@ -274,9 +274,12 @@ class Hazards extends WeatherDisplay {
|
||||||
if (!this.weatherParameters) return;
|
if (!this.weatherParameters) return;
|
||||||
|
|
||||||
// Format location
|
// Format location
|
||||||
const { city, state, country, countryCode } = this.weatherParameters;
|
const { city, state, country, countryCode, latitude, longitude } = this.weatherParameters;
|
||||||
const location = this.formatLocationLabel(city, state, country, countryCode);
|
const location = this.formatLocationLabel(city, state, country, countryCode);
|
||||||
|
|
||||||
|
// Create stable location key from lat/lon (rounded to 3 decimal places ~111m precision)
|
||||||
|
const locationKey = `${parseFloat(latitude).toFixed(3)},${parseFloat(longitude).toFixed(3)}`;
|
||||||
|
|
||||||
// Normalize hazards for the API
|
// Normalize hazards for the API
|
||||||
const hazards = (this.data || []).map((hazard) => ({
|
const hazards = (this.data || []).map((hazard) => ({
|
||||||
id: hazard.id,
|
id: hazard.id,
|
||||||
|
|
@ -291,7 +294,7 @@ class Hazards extends WeatherDisplay {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ location, hazards }),
|
body: JSON.stringify({ location, locationKey, hazards }),
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Silently fail - hazard history is non-critical
|
// Silently fail - hazard history is non-critical
|
||||||
|
|
|
||||||
|
|
@ -83,28 +83,34 @@ const formatLocation = (city, state, country, countryCode) => {
|
||||||
/**
|
/**
|
||||||
* Update hazard history with current active hazards for a location
|
* Update hazard history with current active hazards for a location
|
||||||
* @param {Object} payload - Request payload
|
* @param {Object} payload - Request payload
|
||||||
* @param {string} payload.location - Formatted location label
|
* @param {string} payload.location - Formatted location label (for display)
|
||||||
|
* @param {string} payload.locationKey - Stable location key from lat/lon (for matching)
|
||||||
* @param {Array} payload.hazards - Array of active hazards
|
* @param {Array} payload.hazards - Array of active hazards
|
||||||
* @returns {Array} Updated history
|
* @returns {Array} Updated history
|
||||||
*/
|
*/
|
||||||
const updateHistory = async (payload) => {
|
const updateHistory = async (payload) => {
|
||||||
const { location, hazards = [] } = payload;
|
const { location, locationKey, hazards = [] } = payload;
|
||||||
|
|
||||||
// Load existing history
|
// Load existing history
|
||||||
let history = await loadHistory();
|
let history = await loadHistory();
|
||||||
const now = new Date().toISOString();
|
const now = new Date().toISOString();
|
||||||
|
|
||||||
|
// Use locationKey for matching if provided, fall back to location for backward compatibility
|
||||||
|
const matchKey = locationKey || location;
|
||||||
|
|
||||||
// Create a set of active hazard keys for this location
|
// Create a set of active hazard keys for this location
|
||||||
const activeKeys = new Set();
|
const activeKeys = new Set();
|
||||||
hazards.forEach((hazard) => {
|
hazards.forEach((hazard) => {
|
||||||
const key = generateKey(location, hazard.id);
|
const key = generateKey(matchKey, hazard.id);
|
||||||
activeKeys.add(key);
|
activeKeys.add(key);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mark previously ongoing hazards for this location as ended if no longer active
|
// Mark previously ongoing hazards for this location as ended if no longer active
|
||||||
history = history.map((entry) => {
|
history = history.map((entry) => {
|
||||||
// Only process entries for this location
|
// Only process entries for this location
|
||||||
if (entry.location !== location) return entry;
|
// Use locationKey for matching if available, fall back to location for backward compatibility
|
||||||
|
const entryMatchKey = entry.locationKey || entry.location;
|
||||||
|
if (entryMatchKey !== matchKey) return entry;
|
||||||
|
|
||||||
// If this entry is ongoing but not in the current active set, mark it as ended
|
// If this entry is ongoing but not in the current active set, mark it as ended
|
||||||
if (entry.ongoing && !activeKeys.has(entry.key)) {
|
if (entry.ongoing && !activeKeys.has(entry.key)) {
|
||||||
|
|
@ -119,7 +125,7 @@ const updateHistory = async (payload) => {
|
||||||
|
|
||||||
// Add or update active hazards
|
// Add or update active hazards
|
||||||
hazards.forEach((hazard) => {
|
hazards.forEach((hazard) => {
|
||||||
const key = generateKey(location, hazard.id);
|
const key = generateKey(matchKey, hazard.id);
|
||||||
const existingIndex = history.findIndex((entry) => entry.key === key);
|
const existingIndex = history.findIndex((entry) => entry.key === key);
|
||||||
|
|
||||||
if (existingIndex >= 0) {
|
if (existingIndex >= 0) {
|
||||||
|
|
@ -136,6 +142,7 @@ const updateHistory = async (payload) => {
|
||||||
history.push({
|
history.push({
|
||||||
key,
|
key,
|
||||||
location,
|
location,
|
||||||
|
locationKey: matchKey,
|
||||||
hazardType: hazard.hazardType,
|
hazardType: hazard.hazardType,
|
||||||
encounteredAt: now,
|
encounteredAt: now,
|
||||||
lastSeenAt: now,
|
lastSeenAt: now,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue