3.3.1
Updated At A Glance - re-order and add category colour shades Pets image
This commit is contained in:
+39
-15
@@ -479,6 +479,7 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: 'Lightning risk',
|
||||
value: `${lightningRisk} at ${hhmm(peakLightningRow.iso)}`,
|
||||
alert: peakLightning >= 5,
|
||||
grp: 'precip',
|
||||
}] : [];
|
||||
|
||||
const moistureLabel = (v) => {
|
||||
@@ -513,22 +514,20 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
if (taVals.length === 0) return [];
|
||||
const dayHigh = Math.max(...taVals);
|
||||
const dayMean = taVals.reduce((a, b) => a + b, 0) / taVals.length;
|
||||
const fmt = (anom) => {
|
||||
const mag = Math.abs(anom);
|
||||
return mag < 0.5
|
||||
? 'About average'
|
||||
: `${anom >= 0 ? '+' : '−'}${mag.toFixed(1)}° ${anom >= 0 ? 'warmer' : 'cooler'}`;
|
||||
};
|
||||
const out = [];
|
||||
const nHigh = normals.high?.[doy];
|
||||
if (nHigh != null) {
|
||||
const a = dayHigh - nHigh;
|
||||
out.push({ icon: '🌡', label: '1991-2020 High', value: fmt(a), alert: a >= 5 });
|
||||
if (Math.abs(a) >= 3) {
|
||||
out.push({ icon: '🌡', label: '1991-2020 High', value: `${a >= 0 ? '+' : '−'}${Math.abs(a).toFixed(1)}° ${a >= 0 ? 'warmer' : 'cooler'}`, alert: a >= 5, grp: 'ambient' });
|
||||
}
|
||||
}
|
||||
const nMean = normals.mean?.[doy];
|
||||
if (nMean != null) {
|
||||
const a = dayMean - nMean;
|
||||
out.push({ icon: '🌡', label: '1991-2020 Average', value: fmt(a), alert: a >= 5 });
|
||||
if (Math.abs(a) >= 3) {
|
||||
out.push({ icon: '🌡', label: '1991-2020 Average', value: `${a >= 0 ? '+' : '−'}${Math.abs(a).toFixed(1)}° ${a >= 0 ? 'warmer' : 'cooler'}`, alert: a >= 5, grp: 'ambient' });
|
||||
}
|
||||
}
|
||||
return out;
|
||||
})();
|
||||
@@ -557,6 +556,7 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: 'Good driving time',
|
||||
value: formatWindows(drivingWins) ?? 'Drive with care',
|
||||
alert: drivingWins.length === 0,
|
||||
grp: 'felt',
|
||||
};
|
||||
|
||||
// ── Farming ────────────────────────────────────────────────────────────
|
||||
@@ -575,12 +575,14 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: 'Best field work',
|
||||
value: formatWindows(fieldWins) ?? 'No suitable window',
|
||||
alert: fieldWins.length === 0,
|
||||
grp: 'surface',
|
||||
},
|
||||
...(show('soilT') ? [{
|
||||
icon: '🌱',
|
||||
label: 'Soil warms to 10°C by',
|
||||
value: soilWarmRow ? (hhmm(soilWarmRow.iso) === '00:00' ? 'All Day' : hhmm(soilWarmRow.iso)) : 'Not today',
|
||||
alert: !soilWarmRow,
|
||||
grp: 'surface',
|
||||
}] : []),
|
||||
...(show('precipProb') ? [rainItem] : []),
|
||||
...lightningItem,
|
||||
@@ -589,6 +591,7 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: 'Soil moisture',
|
||||
value: moistureLabel(soilM) ?? '-',
|
||||
alert: soilM != null && (soilM < 0.10 || soilM > 0.50),
|
||||
grp: 'surface',
|
||||
}] : []),
|
||||
...(weekDays ? computeCropAdvice(weekDays, lat) : []),
|
||||
...(show('pollen') && maxPollen >= 10 ? [{
|
||||
@@ -596,6 +599,7 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: 'Grass pollen',
|
||||
value: pollenLabel(maxPollen),
|
||||
alert: maxPollen >= 50,
|
||||
grp: 'airqual',
|
||||
}] : []),
|
||||
];
|
||||
}
|
||||
@@ -612,11 +616,13 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: 'Peak cabin temp',
|
||||
value: peakCabin ? `${Math.round(peakCabin.vehicleT)}° at ${hhmm(peakCabin.iso)}` : '-',
|
||||
alert: !!(peakCabin && peakCabin.vehicleT > 31.5),
|
||||
grp: 'felt',
|
||||
}, {
|
||||
icon: '🧒',
|
||||
label: 'Children/pets in car',
|
||||
value: dangerFrom ? `Unsafe from ${hhmm(dangerFrom.iso)}` : 'Safe all day',
|
||||
alert: !!dangerFrom,
|
||||
grp: 'felt',
|
||||
}] : []),
|
||||
...(show('precipProb') ? [rainItem] : []),
|
||||
...lightningItem,
|
||||
@@ -630,6 +636,7 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
return best ? `${hhmm(best.iso)} (${Math.round(best.utciAdj)}° felt)` : '-';
|
||||
})(),
|
||||
alert: false,
|
||||
grp: 'felt',
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -651,18 +658,21 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: 'Peak indoor (unmanaged)',
|
||||
value: peakIndoor ? `${Math.round(peakIndoor.indoorT)}° at ${hhmm(peakIndoor.iso)}` : '-',
|
||||
alert: !!(peakIndoor && peakIndoor.indoorT >= 28),
|
||||
grp: 'felt',
|
||||
}] : []),
|
||||
...(show('managedT') ? [{
|
||||
icon: '🌡',
|
||||
label: 'Peak indoor (managed)',
|
||||
value: peakManaged ? `${Math.round(peakManaged.managedT)}°` : '-',
|
||||
alert: !!(peakManaged && peakManaged.managedT >= 28),
|
||||
grp: 'felt',
|
||||
}] : []),
|
||||
...(show('indoorT') ? [{
|
||||
icon: '🪟',
|
||||
label: 'Open windows',
|
||||
value: formatWindows(ventWins) ?? 'Keep closed',
|
||||
alert: false,
|
||||
grp: 'felt',
|
||||
}] : []),
|
||||
...lightningItem,
|
||||
...(show('aqi') ? [{
|
||||
@@ -676,6 +686,7 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: 'Pollen',
|
||||
value: pollenLabel(maxPollen),
|
||||
alert: maxPollen >= 50,
|
||||
grp: 'airqual',
|
||||
}] : []),
|
||||
];
|
||||
}
|
||||
@@ -695,24 +706,28 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: 'Sunsoak for pet',
|
||||
value: peakFur ? `${Math.round(peakFur.furSurfaceT)}° at ${hhmm(peakFur.iso)}` : '-',
|
||||
alert: !!(peakFur && peakFur.furSurfaceT >= 45),
|
||||
grp: 'surface',
|
||||
}] : []),
|
||||
...(show('petShadeT') ? [{
|
||||
icon: '🌳',
|
||||
label: 'Shade for pet',
|
||||
value: peakShade ? `${Math.round(peakShade.shadeT)}° at ${hhmm(peakShade.iso)}` : '-',
|
||||
alert: !!(peakShade && peakShade.shadeT >= 26),
|
||||
grp: 'ambient',
|
||||
}] : []),
|
||||
...(show('petHomeT') ? [{
|
||||
icon: '🏠',
|
||||
label: 'Pet at home',
|
||||
value: peakIndoor ? `${Math.round(peakIndoor.indoorT)}° at ${hhmm(peakIndoor.iso)}` : '-',
|
||||
alert: !!(peakIndoor && peakIndoor.indoorT >= 26),
|
||||
grp: 'felt',
|
||||
}] : []),
|
||||
...(show('vehicleT') ? [{
|
||||
icon: '🧒',
|
||||
label: 'Kids/pets in car',
|
||||
value: carDanger ? `Unsafe from ${hhmm(carDanger.iso)}` : 'Safe all day',
|
||||
alert: !!carDanger,
|
||||
grp: 'felt',
|
||||
}] : []),
|
||||
...lightningItem,
|
||||
...(show('aqi') ? [{
|
||||
@@ -720,12 +735,14 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: 'Air quality',
|
||||
value: peakAqi > 0 ? aqiLabel(peakAqi) : '-',
|
||||
alert: peakAqi >= 60,
|
||||
grp: 'airqual',
|
||||
}] : []),
|
||||
...(show('pollen') && maxPollen >= 10 ? [{
|
||||
icon: '🌼',
|
||||
label: 'Pollen',
|
||||
value: pollenLabel(maxPollen),
|
||||
alert: maxPollen >= 50,
|
||||
grp: 'airqual',
|
||||
}] : []),
|
||||
];
|
||||
}
|
||||
@@ -749,6 +766,7 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: `Best ${variant} window`,
|
||||
value: formatWindows(coolWins) ?? 'No cool window today',
|
||||
alert: coolWins.length === 0,
|
||||
grp: 'felt',
|
||||
},
|
||||
...(show('precipProb') ? [rainItem] : []),
|
||||
...lightningItem,
|
||||
@@ -757,6 +775,7 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: 'UV burn time (peak)',
|
||||
value: burnMins,
|
||||
alert: !!(peakUvRow && peakUvRow.uv >= 6),
|
||||
grp: 'solar',
|
||||
}] : []),
|
||||
...(show('aqi') ? [{
|
||||
icon: '💨',
|
||||
@@ -793,18 +812,21 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
label: 'Comfortable window',
|
||||
value: formatWindows(comfortWins) ?? 'No comfortable window',
|
||||
alert: comfortWins.length === 0,
|
||||
grp: 'felt',
|
||||
},
|
||||
{
|
||||
icon: '🌡',
|
||||
label: 'Peak felt temp',
|
||||
value: peakFelt ? `${Math.round(peakFelt.utciAdj)}° at ${hhmm(peakFelt.iso)}` : '-',
|
||||
alert: !!(peakFelt && (peakFelt.utciAdj >= 32 || peakFelt.utciAdj < 0)),
|
||||
grp: 'felt',
|
||||
},
|
||||
...((show('burn') || show('uvA')) && burnMins ? [{
|
||||
icon: '☀',
|
||||
label: 'UV burn time (peak)',
|
||||
value: burnMins,
|
||||
alert: !!(peakUvRow && peakUvRow.uv >= 6),
|
||||
grp: 'solar',
|
||||
}] : []),
|
||||
...(show('precipProb') ? [rainItem] : []),
|
||||
...lightningItem,
|
||||
@@ -812,13 +834,15 @@ export function computeGlanceSummary(todayRows, profile, variant, skinType, cols
|
||||
icon: '💨',
|
||||
label: 'Air quality',
|
||||
value: peakAqi > 0 ? aqiLabel(peakAqi) : '-',
|
||||
alert: peakAqi >= 60,
|
||||
}] : []),
|
||||
...(show('pollen') && maxPollen >= 10 ? [{
|
||||
alert: peakAqi >= 60,
|
||||
grp: 'airqual',
|
||||
}] : []),
|
||||
...(show('pollen') && maxPollen >= 10 ? [{
|
||||
icon: '🌿',
|
||||
label: 'Pollen',
|
||||
value: pollenLabel(maxPollen),
|
||||
alert: maxPollen >= 50,
|
||||
grp: 'airqual',
|
||||
}] : []),
|
||||
];
|
||||
}
|
||||
@@ -894,11 +918,11 @@ export function computeCropAdvice(weekDays, lat) {
|
||||
const ready = sowSeason.filter(c =>
|
||||
weekSoilT != null && weekSoilT >= c.sow.minSoilT && !groundWet);
|
||||
out.push(ready.length ? {
|
||||
icon: '🌱', label: 'Good to sow', value: listCrops(ready), alert: false,
|
||||
icon: '🌱', label: 'Good to sow', value: listCrops(ready), alert: false, grp: 'surface',
|
||||
} : {
|
||||
icon: '🌱', label: 'Good to sow',
|
||||
value: groundWet ? 'Hold off — ground too wet' : 'Hold off — soil still cold',
|
||||
alert: true,
|
||||
alert: true, grp: 'surface',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -911,10 +935,10 @@ export function computeCropAdvice(weekDays, lat) {
|
||||
out.push(ready.length ? {
|
||||
icon: '🌾', label: 'Good to harvest',
|
||||
value: dryDriven ? `${listCrops(ready)} (${dryRange()})` : listCrops(ready),
|
||||
alert: false,
|
||||
alert: false, grp: 'surface',
|
||||
} : {
|
||||
icon: '🌾', label: 'Good to harvest',
|
||||
value: 'Hold — too wet to harvest grain', alert: true,
|
||||
value: 'Hold — too wet to harvest grain', alert: true, grp: 'surface',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user