Outdoor options
This commit is contained in:
fraxle
2026-05-15 11:23:57 +01:00
parent c48721703e
commit c896decea7
+40 -2
View File
@@ -152,6 +152,12 @@ export function UTCIForecast() {
icon: '🌾', icon: '🌾',
cols: { hour: true, air: true, rh: true, dew: true, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: true, uvA: false, uvB: false, burn: false, utciP: false, precip: true, soilT: true, soilT6: true, soilM: true, concreteT: false, vehicleT: false, indoorT: false, managedT: false }, cols: { hour: true, air: true, rh: true, dew: true, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: true, uvA: false, uvB: false, burn: false, utciP: false, precip: true, soilT: true, soilT6: true, soilM: true, concreteT: false, vehicleT: false, indoorT: false, managedT: false },
}, },
outdoors: {
label: 'Outdoors',
icon: '🌤️',
// Default cols match the first variant (beach). Switching variant updates visibleCols.
cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: false, burn: true, utciP: true, precip: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false },
},
alltemps: { alltemps: {
label: 'All Temps', label: 'All Temps',
icon: '🌡️', icon: '🌡️',
@@ -164,6 +170,16 @@ export function UTCIForecast() {
}, },
}; };
// Outdoors sub-variants — each has its own column set.
// Selecting a variant applies its cols to visibleCols.
const OUTDOORS_VARIANTS = {
beach: { name: 'Beach', cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: true, burn: true, utciP: true, precip: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false } },
festival: { name: 'Festival', cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: false, burn: true, utciP: true, precip: true, soilT: false, soilT6: false, soilM: true, concreteT: false, vehicleT: false, indoorT: false, managedT: false } },
events: { name: 'Events', cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: false, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: false, burn: true, utciP: true, precip: true, soilT: false, soilT6: false, soilM: false, concreteT: true, vehicleT: false, indoorT: false, managedT: false } },
naturist: { name: 'Naturist', cols: { hour: true, air: true, rh: false, dew: true, wind: true, dir: false, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: true, uvA: true, uvB: true, burn: true, utciP: true, precip: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false } },
wintersports: { name: 'Winter Sports', cols: { hour: true, air: true, rh: false, dew: false, wind: true, dir: true, cloud: true, sun: true, direct: false, diffuse: false, tmrt: false, delta: false, utci: false, uvA: true, uvB: true, burn: true, utciP: true, precip: true, soilT: false, soilT6: false, soilM: false, concreteT: false, vehicleT: false, indoorT: false, managedT: false } },
};
// Current active filter profile // Current active filter profile
const [activeProfile, setActiveProfile] = useState('basic'); const [activeProfile, setActiveProfile] = useState('basic');
@@ -179,6 +195,9 @@ export function UTCIForecast() {
// Vehicle type for the cabin heat column. 'car' is the default preset. // Vehicle type for the cabin heat column. 'car' is the default preset.
const [vehicleType, setVehicleType] = useState('car'); const [vehicleType, setVehicleType] = useState('car');
// Outdoors profile sub-variant (beach / festival / events / naturist)
const [outdoorsVariant, setOutdoorsVariant] = useState('beach');
// Vehicle ventilation — true = windows open (high convective loss). // Vehicle ventilation — true = windows open (high convective loss).
const [vehicleVent, setVehicleVent] = useState(false); const [vehicleVent, setVehicleVent] = useState(false);
@@ -966,7 +985,12 @@ export function UTCIForecast() {
return; return;
} }
setActiveProfile(key); setActiveProfile(key);
if (key !== 'custom') setVisibleCols({ ...profile.cols }); if (key === 'outdoors') {
// Apply the current variant's cols (default: beach on first switch)
setVisibleCols({ ...OUTDOORS_VARIANTS[outdoorsVariant].cols });
} else if (key !== 'custom') {
setVisibleCols({ ...profile.cols });
}
// Auto-enable indoor column for profiles that include it; // Auto-enable indoor column for profiles that include it;
// reset to off for profiles that don't. // reset to off for profiles that don't.
if (key !== 'custom') { if (key !== 'custom') {
@@ -977,6 +1001,7 @@ export function UTCIForecast() {
}} }}
>${profile.icon} ${profile.label}${locked ? ' 🔒' : ''}</button>`; >${profile.icon} ${profile.label}${locked ? ' 🔒' : ''}</button>`;
})} })}
</div> </div>
<!-- <!--
@@ -985,10 +1010,23 @@ export function UTCIForecast() {
Burn + Vehicle dropdowns always shown (free + pro). Burn + Vehicle dropdowns always shown (free + pro).
Pro users see all toggles; free users see profile-filtered subset. Pro users see all toggles; free users see profile-filtered subset.
--> -->
${(isPro || FILTER_PROFILES[activeProfile]?.cols['burn'] || FILTER_PROFILES[activeProfile]?.cols['vehicleT'] || FILTER_PROFILES[activeProfile]?.cols['indoorT'] || FILTER_PROFILES[activeProfile]?.cols['managedT']) && html` ${(isPro || activeProfile === 'outdoors' || FILTER_PROFILES[activeProfile]?.cols['burn'] || FILTER_PROFILES[activeProfile]?.cols['vehicleT'] || FILTER_PROFILES[activeProfile]?.cols['indoorT'] || FILTER_PROFILES[activeProfile]?.cols['managedT']) && html`
<div class="col-toggles"> <div class="col-toggles">
<span class="col-toggles-label">Columns:</span> <span class="col-toggles-label">Columns:</span>
${activeProfile === 'outdoors' && html`
<select
class=${`col-toggle burn-select on`}
value=${outdoorsVariant}
onChange=${(e) => {
const v = e.target.value;
setOutdoorsVariant(v);
setVisibleCols({ ...OUTDOORS_VARIANTS[v].cols });
}}>
${Object.entries(OUTDOORS_VARIANTS).map(([k, v]) => html`
<option key=${k} value=${k}>${v.name}</option>`)}
</select>`}
${isPro && (activeProfile === 'custom' || FILTER_PROFILES[activeProfile].cols['air']) && html`<button class=${`col-toggle${visibleCols.air ? ' on' : ''}`} onClick=${() => toggleCol('air')}>Air</button>`} ${isPro && (activeProfile === 'custom' || FILTER_PROFILES[activeProfile].cols['air']) && html`<button class=${`col-toggle${visibleCols.air ? ' on' : ''}`} onClick=${() => toggleCol('air')}>Air</button>`}
${isPro && (activeProfile === 'custom' || FILTER_PROFILES[activeProfile].cols['rh']) && html`<button class=${`col-toggle${visibleCols.rh ? ' on' : ''}`} onClick=${() => toggleCol('rh')}>RH</button>`} ${isPro && (activeProfile === 'custom' || FILTER_PROFILES[activeProfile].cols['rh']) && html`<button class=${`col-toggle${visibleCols.rh ? ' on' : ''}`} onClick=${() => toggleCol('rh')}>RH</button>`}
${isPro && (activeProfile === 'custom' || FILTER_PROFILES[activeProfile].cols['dew']) && html`<button class=${`col-toggle${visibleCols.dew ? ' on' : ''}`} onClick=${() => toggleCol('dew')}>Dew</button>`} ${isPro && (activeProfile === 'custom' || FILTER_PROFILES[activeProfile].cols['dew']) && html`<button class=${`col-toggle${visibleCols.dew ? ' on' : ''}`} onClick=${() => toggleCol('dew')}>Dew</button>`}