From f11b1c9dcff418a2995a1089fa91fd9e44d6fe8b Mon Sep 17 00:00:00 2001
From: Bastien Wirtz <bastien.wirtz@gmail.com>
Date: Mon, 13 Sep 2021 23:13:26 +0200
Subject: Weather service refactoring

---
 src/components/services/OpenWeather.vue | 133 +++++++++++++-------------------
 1 file changed, 52 insertions(+), 81 deletions(-)

(limited to 'src/components/services/OpenWeather.vue')

diff --git a/src/components/services/OpenWeather.vue b/src/components/services/OpenWeather.vue
index 0fc1fe5..09ff76a 100644
--- a/src/components/services/OpenWeather.vue
+++ b/src/components/services/OpenWeather.vue
@@ -1,41 +1,30 @@
 <template>
   <div>
     <div class="card" :class="item.class">
-      <a :href="`https://openweathermap.org/city/` + locationId" :target="item.target" rel="noreferrer">
+      <a
+        :href="`https://openweathermap.org/city/${id}`"
+        :target="item.target"
+        rel="noreferrer"
+      >
         <div class="card-content">
           <div class="media">
-            <div v-if="image" class="media-left" :class="item.background">
+            <div v-if="icon" class="media-left" :class="item.background">
               <figure class="image is-48x48">
                 <img
-                  :src="`http://openweathermap.org/img/wn/` + image + `@2x.png`"
+                  :src="`https://openweathermap.org/img/wn/${icon}@2x.png`"
                   :alt="conditions"
                   :title="conditions"
                 />
               </figure>
             </div>
-            <div v-if="item.icon" class="media-left">
-              <figure class="image is-48x48">
-                <i style="font-size: 35px" :class="['fa-fw', item.icon]"></i>
-              </figure>
-            </div>
             <div class="media-content">
-              <p class="title is-4">{{ locationName }}</p>
-              <p class="subtitle is-6">
-                <template v-if="item.subtitle">
-                  {{ item.subtitle }}
-                </template>
-                <template v-else-if="api">
-                  <template v-if="temp !== ''">
-                    {{ temp }}
-                    <span v-if="this.item.units === 'metric'">&deg;C</span>
-                    <span v-else-if="this.item.units === 'imperial'">&deg;F</span>
-                    <span v-else>K</span>
-                  </template>
-                  <template v-else> 
-                    <span class="error">Data could not be retrieved</span>                      
-                  </template>
-                </template>
-              </p>
+              <p v-if="error" class="error">Data could not be retrieved</p>
+              <div v-else>
+                <p class="title is-4">{{ name }}</p>
+                <p class="subtitle is-6">
+                  {{ temp | tempSuffix(this.item.units) }}
+                </p>
+              </div>
             </div>
           </div>
           <div class="tag" :class="item.tagstyle" v-if="item.tag">
@@ -54,63 +43,21 @@ export default {
     item: Object,
   },
   data: () => ({
+    id: null,
+    icon: null,
+    name: null,
+    temp: null,
+    conditions: null,
     error: false,
-    api: {
-      id: "",
-      name: "",
-      weather: [
-        {
-          main: "",
-          description: "",
-          icon: "",
-        },
-      ],
-      main: {
-        temp: "",
-        humidity: "",
-      },
-    },
   }),
-  computed: {
-    locationId: function () {
-      if (this.api) {
-        return this.api.id;
-      }
-      return "";
-    },
-    locationName: function () {
-      if (this.api) {
-        return this.api.name;
-      }
-      return "";
-    },
-    temp: function () {
-      if (this.api && this.api.main.temp !== "") {
-        return parseInt(this.api.main.temp).toFixed(1);
-      }
-      return "";
-    },
-    image: function () {
-      if (this.api) {
-        return this.api.weather[0].icon;
-      }
-      return "";
-    },
-    conditions: function () {
-      if (this.api) {
-        return this.api.weather[0].description;
-      }
-      return "";
-    },
-  },
   created() {
-    this.fetchStatus();
+    this.fetchWeather();
   },
   methods: {
-    fetchStatus: async function () {
+    fetchWeather: async function () {
       let locationQuery;
 
-      // If a specific location ID was specified, use it. Otherwise retrieve value from location (name).
+      // Use location ID if specified, otherwise retrieve value from location (name).
       if (this.item.locationId) {
         locationQuery = `id=${this.item.locationId}`;
       } else {
@@ -118,19 +65,43 @@ export default {
       }
 
       const url = `https://api.openweathermap.org/data/2.5/weather?${locationQuery}&appid=${this.item.apiKey}&units=${this.item.units}`;
-      this.api = await fetch(url)
-        .then((response) => response.json())
-        .catch((e) => { 
-          this.error = true; 
-          console.log(e) 
+      fetch(url)
+        .then((response) => {
+          if (!response.ok) {
+            throw Error(response.statusText);
+          }
+          return response.json();
+        })
+        .then((weather) => {
+          this.id = weather.id;
+          this.name = weather.name;
+          this.temp = parseInt(weather.main.temp).toFixed(1);
+          this.icon = weather.weather[0].icon;
+          this.conditions = weather.weather[0].description;
+        })
+        .catch((e) => {
+          console.log(e);
+          this.error = true;
         });
     },
   },
+  filters: {
+    tempSuffix: function (value, type) {
+      if (!value) return "";
+
+      let unit = "K";
+      if (type === "metric") {
+        unit = "°C";
+      } else if (type === "imperial") {
+        unit = "°F";
+      }
+      return `${value} ${unit}`;
+    },
+  },
 };
 </script>
 
 <style scoped lang="scss">
-
 // Add a border around the weather image.
 // Otherwise the image is not always distinguishable.
 .media-left {
-- 
cgit v1.2.3

