๐Ÿ“ฆ rparrett / weather_dashboard

๐Ÿ“„ main.tera ยท 92 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="apple-mobile-web-app-title" content="AZ Weather">
        <title>Arizona Weather Dashboard</title>
        <link href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMl8U/zpsIv8+cyz/PXEp/zFdHf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaQZv8+div/QXsx/0B6MP83ax3/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7dib/QX0x/0WEPf9Egzv/O3Um/zhtIP83bR//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQIEw/0aKQP9Jjkb/SI1F/0CBMP9BhDP/QYUz/0icbf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALVQP/0WOPf9LlUn/TZlO/0yYTf9FjT3/S5pL/0uaS/9Lmkv/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQIAv/z58Kv9KmUv/T59S/1GhVf9QoFT/SphK/1SlVv9UpVb/UqJU/wAAAAAAAAAAAAAAAAAAAAAAAAAAM2Ah/0eTQ/9GkUD/T6BW/zJfIP9XrGv/VKZd/zRiI/8AAAAAUodP/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEuaS/9KmEn/SZdI/1SnYf9YqmX/Wqxm/1uwb/9TpmD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRoVL/UKBR/0+eT/9iuof/ZLNx/2W0cf9ls3D/YK5u/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWKpa/1aoWf9Vp1f/cbp+/2+7fv9wu3z/cLt8/z9xM/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABap1r/AAAAAHC7ev9vu3n/cL15/2+7ef8yXR//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB4fCwAAAABmtmn/Z7dr/2i4bP9fqmD/ZbRo/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY7Vl/2W2Z/9mt2n/Zrdo/02PT/8YGiAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABltmf/Zrdp/2a3aP8AAAAAJCctAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAPwfAAD8HwAA/AcAAPwDAAD4AwAA8AMAAOAXAADgHwAA4B8AAOAfAAD0HwAA/B8AAPwfAAD+PwAA//8AAA==" rel="icon" type="image/x-icon" />
        <link rel="apple-touch-icon" href="/static/apple-touch-icon.png" />
        <link rel="stylesheet" type="text/css" href="/static/main.css">
        <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
        <script>
            const updated_at = {{ updated_at | json_encode() | safe }};
            async function checkFreshness(backoff = 1000) {
                const nextBackoff = Math.min(backoff * 2, 60000);

                try {
                    const res = await fetch('/is_data_fresh');
                    if (!res.ok) throw new Error(`HTTP ${res.status}`);

                    const fresh = await res.json();
                    if (fresh) {
                        location.reload();
                    } else {
                        setTimeout(() => checkFreshness(nextBackoff), backoff);
                    }
                } catch (err) {
                    console.error('Fetch error:', err);
                    setTimeout(() => checkFreshness(nextBackoff), backoff);
                }
            }
        </script>
    </head>
    <body>
        <div class="header sticky">
            <a class="github" href="https://www.github.com/rparrett/weather_dashboard"><svg aria-labelledby="simpleicons-github-icon" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title id="simpleicons-github-icon">GitHub icon</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"></path></svg></a>
            <div>
                Powered By <a href="https://pirateweather.net/en/latest/">Pirate Weather</a><br/>
                Last updated <strong class="updated_at">{{ updated_at | time_ago }}</strong> ago.
                {% if needs_update %}
                    <noscript>
                        Please refresh the page to get fresh data.
                    </noscript>
                    <span id="freshening" class="animated-ellipsis">Freshening</span>
                    <script>
                        document.getElementById("freshening").style.display = 'inline';
                        checkFreshness();
                    </script>
                {% endif %}
            </div>
        </div>
        {% for forecast in forecasts %}
        <div class="location sticky">
            <strong>{{forecast.location.name}}</strong>&nbsp;
            {% if forecast.location.link %}[<a href="{{forecast.location.link}}">mp</a>]&nbsp;{% endif %}
            [<a href="https://merrysky.net/forecast/{{forecast.location.latitude}},{{forecast.location.longitude}}/us">merry</a>]&nbsp;
            [<a href="https://forecast.weather.gov/MapClick.php?lat={{forecast.location.latitude}}&lon={{forecast.location.longitude}}">nws</a>]
        </div>
        <div class="days">
            {% for day in forecast.days %}
            <div class="day {% if day.is_weekend %} weekend{% endif %}">
                <div class="time">
                    <div>{{day.week_day}}</div>
                    <div>{{day.date}}</div>
                </div>
                <hr>
                <div class="temps">
                    <div class="temp-label"><strong>H</strong></div>
                    <div class="temp {{day.temperature_high | temperature_class}}">{{day.temperature_high | round}}</div>
                    <div class="temp-label"><strong>fl</strong></div>
                    <div class="temp"><span class="{{day.temperature_high | temperature_class}}">{{day.apparent_temperature_high | round}}</span></div>
                </div>
                <div class="temps">
                    <div class="temp-label">L</div>
                    <div class="temp {{day.temperature_low | temperature_class}}">{{day.temperature_low | round}}</div>
                    <div class="temp-label">fl</div>
                    <div class="temp"><span class="{{day.temperature_low | temperature_class}}">{{day.apparent_temperature_low | round}}</span></div>
                </div>
                <div class="temps">
                    <div class="temp-label">P</div>
                    <div class="temp {{day.precip_probability | precip_class}}">{{day.precip_probability | probability }}</div>
                    <div class="temp-label">W</div>
                    <div class="temp">{{day.wind_speed | round }}</div>
                </div>
                <hr>
                <div class="summary-cell"><span>{{day.summary}}</span></div>
            </div>
            {% endfor %}
        </div>
        {% endfor %}
    </body>
</html>