Files
hub/docs/extensions/weather.html
T
nmemmertandClaude Sonnet 5.5 efd17f4263 Extensions: hub bridge for tasks, contacts and calendar (asked of the person once), Sites in My Store, and four example extensions
- hub.tasks / hub.contacts / hub.calendar in the extension sandbox; each kind of access is approved by the person and remembered per extension
- My Store: Sites kind (any web link, optionally shown inside the hub)
- Examples: notes and checklists, habit tracker, kitchen converter and scaler, weather and verse of the day

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-26 09:25:39 -04:00

25 lines
4.0 KiB
HTML

<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Today</title>
<style>
:root{--bg:#fff;--fg:#1b1e24;--mut:#6b7280;--line:#e0e3e9;--acc:#3d6bf0;--card:#f4f5f8}@media(prefers-color-scheme:dark){:root{--bg:#181b21;--fg:#eceef2;--mut:#8b93a3;--line:#2a2f38;--acc:#6a8cff;--card:#20242c}}
*{box-sizing:border-box}body{margin:0;padding:14px;font:15px system-ui,sans-serif;background:var(--bg);color:var(--fg);max-width:720px}
input,button{font:inherit;color:inherit;background:var(--card);border:1px solid var(--line);border-radius:8px;padding:8px}button{cursor:pointer}
.c{background:var(--card);border-radius:12px;padding:14px;margin:0 0 12px}.big{font-size:40px;font-weight:600}.d{display:flex;gap:8px;overflow:auto}.d div{min-width:78px;text-align:center;background:var(--bg);border-radius:10px;padding:8px}.m{color:var(--mut);font-size:13px}blockquote{margin:0;font-size:17px;line-height:1.5}
</style></head><body>
<div class="c"><form id="f" style="display:flex;gap:6px"><input id="city" placeholder="City (for example Lynchburg)" style="flex:1"><button>Set</button></form><div id="w" class="m" style="margin-top:10px">Pick a city for the weather.</div></div>
<div class="c"><div class="m">Verse of the day</div><blockquote id="verse">Loading…</blockquote><div class="m" id="ref" style="margin-top:6px"></div></div>
<script>
var CODES={0:'Clear',1:'Mostly clear',2:'Partly cloudy',3:'Overcast',45:'Fog',48:'Fog',51:'Light drizzle',53:'Drizzle',55:'Heavy drizzle',61:'Light rain',63:'Rain',65:'Heavy rain',71:'Light snow',73:'Snow',75:'Heavy snow',80:'Showers',81:'Showers',82:'Heavy showers',95:'Thunderstorm',96:'Thunderstorm',99:'Thunderstorm'};
function esc(s){return String(s).replace(/[&<>"]/g,function(c){return{'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]})}
function today(){var d=new Date();return d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate()}
function weather(p){document.getElementById('w').textContent='Loading…';
fetch('https://api.open-meteo.com/v1/forecast?latitude='+p.lat+'&longitude='+p.lon+'&current=temperature_2m,weather_code,wind_speed_10m&daily=weather_code,temperature_2m_max,temperature_2m_min&temperature_unit=fahrenheit&wind_speed_unit=mph&timezone=auto&forecast_days=6').then(function(r){return r.json()}).then(function(j){
var c=j.current,d=j.daily;document.getElementById('w').innerHTML='<div class="m">'+esc(p.name)+'</div><div class="big">'+Math.round(c.temperature_2m)+'&deg;F</div><div>'+(CODES[c.weather_code]||'')+', wind '+Math.round(c.wind_speed_10m)+' mph</div><div class="d" style="margin-top:10px">'+d.time.map(function(t,i){return '<div><div class="m">'+(i?new Date(t+'T12:00').toLocaleDateString([], {weekday:'short'}):'Today')+'</div><div>'+Math.round(d.temperature_2m_max[i])+'&deg;</div><div class="m">'+Math.round(d.temperature_2m_min[i])+'&deg;</div></div>'}).join('')+'</div>'}).catch(function(){document.getElementById('w').textContent='Could not load the weather.'})}
document.getElementById('f').onsubmit=function(e){e.preventDefault();var q=document.getElementById('city').value.trim();if(!q)return;
fetch('https://geocoding-api.open-meteo.com/v1/search?count=1&name='+encodeURIComponent(q)).then(function(r){return r.json()}).then(function(j){var g=j.results&&j.results[0];if(!g){document.getElementById('w').textContent='City not found.';return}
var p={name:g.name+(g.admin1?', '+g.admin1:''),lat:g.latitude,lon:g.longitude};hub.storage.set('place',p);weather(p)})};
hub.storage.get('place').then(function(p){if(p)weather(p)});
hub.storage.get('verse').then(function(v){if(v&&v.day===today()){showV(v);return}
fetch('https://bible-api.com/?random=verse').then(function(r){return r.json()}).then(function(j){var n={day:today(),text:String(j.text||'').trim(),ref:j.reference||''};hub.storage.set('verse',n);showV(n)}).catch(function(){document.getElementById('verse').textContent='Could not load a verse today.'})});
function showV(v){document.getElementById('verse').textContent=v.text;document.getElementById('ref').textContent=v.ref}
</script></body></html>