]> git.immae.eu Git - github/bastienwirtz/homer.git/blob - src/components/services/OpenWeather.vue
Fix openweather service
[github/bastienwirtz/homer.git] / src / components / services / OpenWeather.vue
1 <template>
2 <div>
3 <div class="card" :class="item.class">
4 <a
5 :href="`https://openweathermap.org/city/${id}`"
6 :target="item.target"
7 rel="noreferrer"
8 >
9 <div class="card-content">
10 <div class="media">
11 <div v-if="icon" class="media-left" :class="item.background">
12 <figure class="image is-48x48">
13 <img
14 :src="`https://openweathermap.org/img/wn/${icon}@2x.png`"
15 :alt="conditions"
16 :title="conditions"
17 />
18 </figure>
19 </div>
20 <div class="media-content">
21 <p v-if="error" class="error">Data could not be retrieved</p>
22 <div v-else>
23 <p class="title is-4">{{ name }}</p>
24 <p class="subtitle is-6">
25 <span>
26 {{ temperature }}
27 </span>
28 <span class="location-time">
29 {{ locationTime }}
30 </span>
31 </p>
32 </div>
33 </div>
34 </div>
35 <div class="tag" :class="item.tagstyle" v-if="item.tag">
36 <strong class="tag-text">#{{ item.tag }}</strong>
37 </div>
38 </div>
39 </a>
40 </div>
41 </div>
42 </template>
43
44 <script>
45 export default {
46 name: "OpenWeather",
47 props: {
48 item: Object,
49 },
50 data: () => ({
51 id: null,
52 icon: null,
53 name: null,
54 temp: null,
55 conditions: null,
56 error: false,
57 timezoneOffset: 0,
58 }),
59 computed: {
60 temperature: function () {
61 if (!this.temp) return "";
62
63 let unit = "K";
64 if (this.item.units === "metric") {
65 unit = "°C";
66 } else if (this.item.units === "imperial") {
67 unit = "°F";
68 }
69 return `${this.temp} ${unit}`;
70 },
71 locationTime: function () {
72 return this.calcTime(this.timezoneOffset);
73 },
74 },
75 created() {
76 this.fetchWeather();
77 },
78 methods: {
79 fetchWeather: async function () {
80 let locationQuery;
81
82 // Use location ID if specified, otherwise retrieve value from location (name).
83 if (this.item.locationId) {
84 locationQuery = `id=${this.item.locationId}`;
85 } else {
86 locationQuery = `q=${this.item.location}`;
87 }
88
89 const apiKey = this.item.apikey || this.item.apiKey;
90
91 let url = `https://api.openweathermap.org/data/2.5/weather?${locationQuery}&appid=${apiKey}&units=${this.item.units}`;
92 if (this.item.endpoint) {
93 url = this.item.endpoint;
94 }
95 fetch(url)
96 .then((response) => {
97 if (!response.ok) {
98 throw Error(response.statusText);
99 }
100 return response.json();
101 })
102 .then((weather) => {
103 this.id = weather.id;
104 this.name = weather.name;
105 this.temp = parseInt(weather.main.temp).toFixed(1);
106 this.icon = weather.weather[0].icon;
107 this.conditions = weather.weather[0].description;
108 this.timezoneOffset = weather.timezone;
109 })
110 .catch((e) => {
111 console.log(e);
112 this.error = true;
113 });
114 },
115 calcTime: (offset) => {
116 const localTime = new Date();
117 const utcTime =
118 localTime.getTime() + localTime.getTimezoneOffset() * 60000;
119 const calculatedTime = new Date(utcTime + 1000 * offset);
120 return calculatedTime.toLocaleString([], {
121 hour: "2-digit",
122 minute: "2-digit",
123 });
124 },
125 },
126 };
127 </script>
128
129 <style scoped lang="scss">
130 // Add a border around the weather image.
131 // Otherwise the image is not always distinguishable.
132 .media-left {
133 &.circle,
134 &.square {
135 background-color: #e4e4e4;
136 }
137
138 &.circle {
139 border-radius: 90%;
140 }
141
142 img {
143 max-height: 100%;
144 }
145 }
146
147 .error {
148 color: #de0000;
149 }
150
151 // Change background color in dark mode.
152 .is-dark {
153 .media-left {
154 &.circle,
155 &.square {
156 background-color: #909090;
157 }
158 }
159 }
160
161 //Location Time
162 .location-time {
163 margin-left: 20px;
164 }
165 </style>