marek 1 lună în urmă
părinte
comite
844fd0e38a

+ 24 - 1
assets/css/style.css

@@ -40,7 +40,7 @@ body {
 }
 
 #mainStats .stats .values {
-    background-color: #dddddd;
+    background-color: rgba(0, 0, 0, 0.1);
     padding: 0.5rem 2rem;
     border-radius: 1rem;
     width: 10em;
@@ -60,4 +60,27 @@ header {
     align-items: center;
     flex-wrap: wrap;
     gap: 0 1em;
+}
+
+.icon {
+    display: inline-block;
+    width: 1em;
+    height: 1em;
+}
+
+header .middle {
+    font-size: 1.2em;
+    display: flex;
+    gap: 1em;
+    align-items: center;
+    justify-content: center;
+    flex-wrap: wrap;
+}
+
+[role="button"], button {
+    background-color: rgba(0, 0, 0, 0.1);
+    border-radius: 0.5em;
+    padding: 0.3em 1em;
+    text-decoration: none;
+    color: initial;
 }

+ 106 - 42
templates/en/index.eta

@@ -1,46 +1,110 @@
 <% layout("/en/layout") %>
 
-<%~ include("/en/partials/navbar") %>
-
-<% if (it.data?.[0]) { %>
-<div class="stats">
-    <div class="indoor">
-        <h3>indoor</h3>
-        <p>temp: <%= it.data?.[0].indoorTemp / 100 %> °C</p>
-        <p>pressure: <%= it.data?.[0].indoorPressure / 100 %> hPa</p>
-        <p>humidity: <%= it.data?.[0].indoorHumidity / 100 %>%</p>
-        <p>altitude: <%= it.data?.[0].indoorAltitude / 100 %>m</p>
-    </div>
-    <div class="outdoor">
-        <h3>outdoor</h3>
-        <p>connected: <%= it.data?.[0].outdoorConnected %></p>
-        <p>temp: <%= it.data?.[0].outdoorTemp / 100 %> °C</p>
-        <p>pressure: <%= it.data?.[0].outdoorPressure / 100 %> hPa</p>
-        <p>humidity: <%= it.data?.[0].outdoorHumidity / 100 %>%</p>
-        <p>altitude: <%= it.data?.[0].outdoorAltitude / 100 %>m</p>
+<%~ include("/en/partials/topbar") %>
+
+<% const tickIcon = `
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+        <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
+            <circle cx="12" cy="12" r="10" />
+            <path d="m9 12l2 2l4-4" />
+        </g>
+    </svg>
+` %>
+
+<% const xIcon = `
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+        <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
+            <circle cx="12" cy="12" r="10" />
+            <path d="m15 9l-6 6m0-6l6 6" />
+        </g>
+    </svg>
+` %>
+
+<% const tempIcon = `
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+        <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 4v10.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0" />
+    </svg>
+` %>
+
+<% const pressureIcon = `
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+        <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m12 14l4-4M3.34 19a10 10 0 1 1 17.32 0" />
+    </svg>
+` %>
+
+<% const humidityIcon = `
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+        <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5S5 13 5 15a7 7 0 0 0 7 7" />
+    </svg>
+` %>
+
+<% const altitudeIcon = `
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+        <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
+            <circle cx="12" cy="12" r="10" />
+            <path d="m16 12l-4-4l-4 4m4 4V8" />
+        </g>
+    </svg>
+` %>
+
+<div id="mainStats">
+    <% /* <div class="message">
+        <p>oops</p>
+    </div> */ %>
+
+    <div class="stats">
+        <div class="wrapper">
+            <h3>indoor</h3>
+            <div class="values indoor">
+                <p><%~ tempIcon %> <span id="indoorTemp"><%= it.data?.[0]?.indoorTemp / 100 %></span> °C</p>
+                <p><%~ pressureIcon %> <span id="indoorPressure"><%= it.data?.[0]?.indoorPressure / 100 %></span> hPa</p>
+                <p><%~ humidityIcon %> <span id="indoorHumidity"><%= it.data?.[0]?.indoorHumidity / 100 %></span> %</p>
+                <p><%~ altitudeIcon %> <span id="indoorAltitude"><%= it.data?.[0]?.indoorAltitude / 100 %></span> m</p>
+            </div>
+        </div>
+
+        <div class="wrapper">
+            <h3>outdoor</h3>
+            <div class="values outdoor">
+                <p id="outdoorConnected"><%~ it.data?.[0]?.outdoorConnected ? `${tickIcon} connected` : `${xIcon} disconnected` %></p>
+                <p><%~ tempIcon %> <span id="outdoorTemp"><%= it.data?.[0]?.outdoorTemp / 100 %></span> °C</p>
+                <p><%~ pressureIcon %> <span id="outdoorPressure"><%= it.data?.[0]?.outdoorPressure / 100 %></span> hPa</p>
+                <p><%~ humidityIcon %> <span id="outdoorHumidity"><%= it.data?.[0]?.outdoorHumidity / 100 %></span> %</p>
+                <p><%~ altitudeIcon %> <span id="outdoorAltitude"><%= it.data?.[0]?.outdoorAltitude / 100 %></span> m</p>
+            </div>
+        </div>
     </div>
 </div>
-<% } %>
-
-<h3>data</h3>
-
-<% if (it.data?.length) { %>
-    <div>
-        <table>
-            <tr>
-                <th>time</th>
-                <th>indoor</th>
-                <th>outdoor</th>
-            </tr>
-            <% for (const item of it.data) { %>
-                <tr>
-                    <td><%= item.timestamp %></td>
-                    <td><strong>temp:</strong> <%= item.indoorTemp / 100 %> °C, <strong>pressure:</strong> <%= item.indoorPressure / 100 %> hPa, <strong>humidity:</strong> <%= item.indoorHumidity / 100 %>%, <strong>altitude:</strong> <%= item.indoorAltitude / 100 %>m</td>
-                    <td><strong>connected:</strong> <%= item.outdoorConnected %>, <strong>temp:</strong> <%= item.outdoorTemp / 100 %> °C, <strong>pressure:</strong> <%= item.outdoorPressure  / 100%>hPa, <strong>humidity:</strong> <%= item.outdoorHumidity / 100 %>%, <strong>altitude:</strong> <%= item.outdoorAltitude / 100 %>m</td>
-                </tr>
-            <% } %>
-        </table>
-    </div>
-<% } else { %>
-    <p>no data yet. :(</p>
-<% } %>
+
+<script defer>
+    setInterval(async () => {
+        const response = await fetch('/currentData')
+        const data = await response.json()
+
+        const indoorTemp = document.querySelector(`#indoorTemp`)
+        const indoorPressure = document.querySelector(`#indoorPressure`)
+        const indoorHumidity = document.querySelector(`#indoorHumidity`)
+        const indoorAltitude = document.querySelector(`#indoorAltitude`)
+
+        const outdoorConnected = document.querySelector(`#outdoorConnected`)
+        const outdoorTemp = document.querySelector(`#outdoorTemp`)
+        const outdoorPressure = document.querySelector(`#outdoorPressure`)
+        const outdoorHumidity = document.querySelector(`#outdoorHumidity`)
+        const outdoorAltitude = document.querySelector(`#outdoorAltitude`)
+
+        indoorTemp.textContent = data?.indoorTemp / 100
+        indoorPressure.textContent = data?.indoorPressure / 100
+        indoorHumidity.textContent = data?.indoorHumidity / 100
+        indoorAltitude.textContent = data?.indoorAltitude / 100
+
+        const tickIcon = `<%~ tickIcon %>`
+
+        const xIcon = `<%~ xIcon %>`
+
+        outdoorConnected.innerHTML = data?.outdoorConnected ? `${tickIcon} connected` : `${xIcon} disconnected`
+        outdoorTemp.textContent = data?.outdoorTemp / 100
+        outdoorPressure.textContent = data?.outdoorPressure / 100
+        outdoorHumidity.textContent = data?.outdoorHumidity / 100
+        outdoorAltitude.textContent = data?.outdoorAltitude / 100
+    }, 10000)
+</script>

+ 0 - 7
templates/en/partials/navbar.eta

@@ -1,7 +0,0 @@
-<nav>
-    <h2>meteostanica</h2>
-
-    <ul>
-        <li><a href="/">⛰️⛰️⛰️🇸🇰🇸🇰🇸🇰</a></li>
-    </ul>
-</nav>

+ 75 - 0
templates/en/partials/topbar.eta

@@ -0,0 +1,75 @@
+<% const timeIcon = `
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+        <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
+            <circle cx="12" cy="12" r="10" />
+            <path d="M12 6v6l4 2" />
+        </g>
+    </svg>
+` %>
+
+<% const dateIcon = `
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+        <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
+            <path d="M8 2v4m8-4v4" />
+            <rect width="18" height="18" x="3" y="4" rx="2" />
+            <path d="M3 10h18M8 14h.01M12 14h.01M16 14h.01M8 18h.01M12 18h.01M16 18h.01" />
+        </g>
+    </svg>
+` %>
+
+<% const skFlag = `
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512">
+        <mask id="SVGuywqVbel">
+            <circle cx="256" cy="256" r="256" fill="#fff" />
+        </mask>
+        <g mask="url(#SVGuywqVbel)">
+            <path fill="#0052b4" d="m0 160l256-32l256 32v192l-256 32L0 352z" />
+            <path fill="#eee" d="M0 0h512v160H0z" />
+            <path fill="#d80027" d="M0 352h512v160H0z" />
+            <path fill="#eee" d="M64 63v217c0 104 144 137 144 137s144-33 144-137V63z" />
+            <path fill="#d80027" d="M96 95v185a83 78 0 0 0 9 34h206a83 77 0 0 0 9-34V95z" />
+            <path fill="#eee" d="M288 224h-64v-32h32v-32h-32v-32h-32v32h-32v32h32v32h-64v32h64v32h32v-32h64z" />
+            <path fill="#0052b4" d="M152 359a247 231 0 0 0 56 24c12-3 34-11 56-24a123 115 0 0 0 47-45a60 56 0 0 0-34-10l-14 2a60 56 0 0 0-110 0a60 56 0 0 0-14-2c-12 0-24 4-34 10a123 115 0 0 0 47 45" />
+        </g>
+    </svg>
+` %>
+
+<% const settingsIcon = `
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+        <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
+            <path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0a2.34 2.34 0 0 0 3.319 1.915a2.34 2.34 0 0 1 2.33 4.033a2.34 2.34 0 0 0 0 3.831a2.34 2.34 0 0 1-2.33 4.033a2.34 2.34 0 0 0-3.319 1.915a2.34 2.34 0 0 1-4.659 0a2.34 2.34 0 0 0-3.32-1.915a2.34 2.34 0 0 1-2.33-4.033a2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" />
+            <circle cx="12" cy="12" r="3" />
+        </g>
+    </svg>
+` %>
+
+<% const date = new Date() %>
+
+<header>
+    <p><%~ timeIcon %> <span id="topbarTime"><%= date.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: true }) %></span></p>
+    
+    <div class="middle">
+        <a role="button" href="/"><%~ skFlag %></a>
+        <a role="button" href="/en/settings"><%~ settingsIcon %></a>
+    </div>
+    
+    <p><%~ dateIcon %> <span id="topbarDate"><%= date.toLocaleDateString('en-US', { weekday: "long", year: "numeric", month: "long", day: "numeric" }) %></span></p>
+
+    <script defer>
+        setInterval(() => {
+            const topbarTime = document.querySelector("#topbarTime")
+            const topbarDate = document.querySelector("#topbarDate")
+
+            const date = new Date()
+
+            const timeString = date.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: true })
+            const dateString = date.toLocaleDateString('en-US', { weekday: "long", year: "numeric", month: "long", day: "numeric" })
+
+            topbarTime.textContent = timeString
+            
+            if (topbarDate.textContent !== dateString) {
+                topbarDate.textContent = dateString
+            }
+        }, 1000)
+    </script>
+</header>

+ 6 - 6
templates/sk/index.eta

@@ -3,7 +3,7 @@
 <%~ include("/sk/partials/topbar") %>
 
 <% const tickIcon = `
-    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
         <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
             <circle cx="12" cy="12" r="10" />
             <path d="m9 12l2 2l4-4" />
@@ -12,7 +12,7 @@
 ` %>
 
 <% const xIcon = `
-    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
         <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
             <circle cx="12" cy="12" r="10" />
             <path d="m15 9l-6 6m0-6l6 6" />
@@ -21,25 +21,25 @@
 ` %>
 
 <% const tempIcon = `
-    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
         <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 4v10.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0" />
     </svg>
 ` %>
 
 <% const pressureIcon = `
-    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
         <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m12 14l4-4M3.34 19a10 10 0 1 1 17.32 0" />
     </svg>
 ` %>
 
 <% const humidityIcon = `
-    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
         <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5S5 13 5 15a7 7 0 0 0 7 7" />
     </svg>
 ` %>
 
 <% const altitudeIcon = `
-    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
         <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
             <circle cx="12" cy="12" r="10" />
             <path d="m16 12l-4-4l-4 4m4 4V8" />

+ 35 - 6
templates/sk/partials/topbar.eta

@@ -1,5 +1,5 @@
 <% const timeIcon = `
-    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
         <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
             <circle cx="12" cy="12" r="10" />
             <path d="M12 6v6l4 2" />
@@ -8,7 +8,7 @@
 ` %>
 
 <% const dateIcon = `
-    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
         <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
             <path d="M8 2v4m8-4v4" />
             <rect width="18" height="18" x="3" y="4" rx="2" />
@@ -17,11 +17,40 @@
     </svg>
 ` %>
 
+<% const usFlag = `
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512">
+        <mask id="SVGuywqVbel">
+            <circle cx="256" cy="256" r="256" fill="#fff" />
+        </mask>
+        <g mask="url(#SVGuywqVbel)">
+            <path fill="#eee" d="M256 0h256v64l-32 32l32 32v64l-32 32l32 32v64l-32 32l32 32v64l-256 32L0 448v-64l32-32l-32-32v-64z" />
+            <path fill="#d80027" d="M224 64h288v64H224Zm0 128h288v64H256ZM0 320h512v64H0Zm0 128h512v64H0Z" />
+            <path fill="#0052b4" d="M0 0h256v256H0Z" />
+            <path fill="#eee" d="m187 243l57-41h-70l57 41l-22-67zm-81 0l57-41H93l57 41l-22-67zm-81 0l57-41H12l57 41l-22-67zm162-81l57-41h-70l57 41l-22-67zm-81 0l57-41H93l57 41l-22-67zm-81 0l57-41H12l57 41l-22-67Zm162-82l57-41h-70l57 41l-22-67Zm-81 0l57-41H93l57 41l-22-67zm-81 0l57-41H12l57 41l-22-67Z" />
+        </g>
+    </svg>
+` %>
+
+<% const settingsIcon = `
+    <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+        <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
+            <path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0a2.34 2.34 0 0 0 3.319 1.915a2.34 2.34 0 0 1 2.33 4.033a2.34 2.34 0 0 0 0 3.831a2.34 2.34 0 0 1-2.33 4.033a2.34 2.34 0 0 0-3.319 1.915a2.34 2.34 0 0 1-4.659 0a2.34 2.34 0 0 0-3.32-1.915a2.34 2.34 0 0 1-2.33-4.033a2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" />
+            <circle cx="12" cy="12" r="3" />
+        </g>
+    </svg>
+` %>
+
 <% const date = new Date() %>
 
 <header>
-    <p><%~ timeIcon %> <span id="topbarTime"><%= date.getHours() %>:<%= date.getMinutes() %></span></p>
-    <p><span id="topbarDate"><%= date.getDate() %>. <%= date.getMonth() + 1 %>. <%= date.getFullYear() %></span> <%~ dateIcon %></p>
+    <p><%~ timeIcon %> <span id="topbarTime"><%= date.toLocaleString('sk-SK', { hour: 'numeric', minute: 'numeric', second: 'numeric' }) %></span></p>
+    
+    <div class="middle">
+        <a role="button" href="/en"><%~ usFlag %></a>
+        <a role="button" href="/settings"><%~ settingsIcon %></a>
+    </div>
+    
+    <p><%~ dateIcon %> <span id="topbarDate"><%= date.toLocaleDateString('sk-SK', { weekday: "long", year: "numeric", month: "long", day: "numeric" }) %></span></p>
 
     <script defer>
         setInterval(() => {
@@ -30,8 +59,8 @@
 
             const date = new Date()
 
-            const timeString = `${date.getHours().toString().padStart(2, `0`) }:${date.getMinutes().toString().padStart(2, `0`)}:${date.getSeconds().toString().padStart(2, `0`)}`
-            const dateString = `${date.getDate() }. ${date.getMonth() + 1 }. ${date.getFullYear()}`
+            const timeString = date.toLocaleString('sk-SK', { hour: 'numeric', minute: 'numeric', second: 'numeric' })
+            const dateString = date.toLocaleDateString('sk-SK', { weekday: "long", year: "numeric", month: "long", day: "numeric" })
 
             topbarTime.textContent = timeString