├── .gitignore
├── LICENSE
├── README.md
├── index.html
├── package-lock.json
├── package.json
├── src
├── assets
│ ├── animated-svg
│ │ ├── moonrise.svg
│ │ ├── raindrop-measure.svg
│ │ ├── sunrise.svg
│ │ ├── thermometer-colder.svg
│ │ ├── thermometer-warmer.svg
│ │ └── wind.svg
│ ├── fonts
│ │ ├── Font-icons
│ │ │ ├── iconly.css
│ │ │ ├── iconly.eot
│ │ │ ├── iconly.min.css
│ │ │ ├── iconly.svg
│ │ │ ├── iconly.ttf
│ │ │ ├── iconly.woff
│ │ │ └── iconly.woff2
│ │ └── Poppins
│ │ │ ├── Poppins-Black.ttf
│ │ │ ├── Poppins-BlackItalic.ttf
│ │ │ ├── Poppins-Bold.ttf
│ │ │ ├── Poppins-BoldItalic.ttf
│ │ │ ├── Poppins-ExtraBold.ttf
│ │ │ ├── Poppins-ExtraBoldItalic.ttf
│ │ │ ├── Poppins-ExtraLight.ttf
│ │ │ ├── Poppins-ExtraLightItalic.ttf
│ │ │ ├── Poppins-Italic.ttf
│ │ │ ├── Poppins-Light.ttf
│ │ │ ├── Poppins-LightItalic.ttf
│ │ │ ├── Poppins-Medium.ttf
│ │ │ ├── Poppins-MediumItalic.ttf
│ │ │ ├── Poppins-Regular.ttf
│ │ │ ├── Poppins-SemiBold.ttf
│ │ │ ├── Poppins-SemiBoldItalic.ttf
│ │ │ ├── Poppins-Thin.ttf
│ │ │ └── Poppins-ThinItalic.ttf
│ ├── images
│ │ ├── favicon.ico
│ │ ├── first page
│ │ │ ├── 27.webp
│ │ │ ├── location-pin.webp
│ │ │ └── map-pin.svg
│ │ └── weather
│ │ │ ├── atmosphere_day.webp
│ │ │ ├── atmosphere_night.webp
│ │ │ ├── clear_day.webp
│ │ │ ├── clear_night.webp
│ │ │ ├── clouds_day.webp
│ │ │ ├── clouds_night.webp
│ │ │ ├── drizzle_day.webp
│ │ │ ├── drizzle_night.webp
│ │ │ ├── rain_day.webp
│ │ │ ├── rain_night.webp
│ │ │ ├── snow_day.webp
│ │ │ ├── snow_night.webp
│ │ │ ├── thunderstorm_day.webp
│ │ │ └── thunderstorm_night.webp
│ └── swiperjs
│ │ ├── slider-config.js
│ │ ├── swiper-bundle.min.js.map
│ │ ├── swiper-min.css
│ │ └── swiper-min.js
├── js
│ ├── animaitons.js
│ ├── app.js
│ ├── dom.js
│ ├── getApis.js
│ ├── json
│ │ ├── forecast.json
│ │ └── weather_icons.json
│ ├── theme.js
│ ├── userCity.js
│ └── weatherApp.js
└── styles
│ ├── css-reset.css
│ ├── css
│ ├── animations.css
│ └── animations.css.map
│ ├── sass
│ ├── _mixins.scss
│ └── animations.scss
│ ├── tailwind.css
│ └── tailwind_output.css
└── tailwind.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Alireza Hoseyni
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 | ### Hello🤚
5 | With this web application, you can get information about the weather of your city and region🌦️
6 | I implemented this project to learn and master the use of APIs in JavaScript and front-end
7 |
8 | [Live Demo](https://new-weather-appp.vercel.app/)
9 |
10 | ### Backend and APIs
11 | I used this interesting and practical web
12 | service to develop the project.
13 | Complete information, dedicated icon for day
14 | and night is one of its features
15 |
16 |
17 | [🧩 Open source weather back-end ](https://openweathermap.org/api)
18 |
19 |
20 | ### Features
21 |
22 |
23 | - 🌱 Minimal design
24 |
25 | - ⚡User interface designed with tailwind css
26 |
27 | - 🌨️ Weather for a full day
28 |
29 | - 🕰️ The local time of the selected city
30 |
31 | - 🌍 Finding user location with IPv6 by [IP Geolocation web service](https://ipgeolocation.io)
32 |
33 | - ✌️Simultaneous access to the information of two cities
34 |
35 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Weather App
19 |
20 |
21 |
22 |
23 |
26 |
27 |
28 |
30 |

32 |
33 |
34 | Discover the Weather in Your City
35 |
36 |
37 | Get to know your Weather maps and radar precipitation forecast
38 |
39 |
43 |
44 |
45 |
46 |
47 |
49 |
54 |

56 |
58 | Select your City
59 |
60 |
61 |
62 |
63 |
64 |
67 |
68 |
69 |
74 |
79 |
80 |
81 |
82 |
83 |
85 |
86 |
87 |
100 |
101 |
102 |
103 |
104 |
106 |
107 | or
108 |
109 |
110 |
111 |
112 |
113 |
114 |
116 |
117 |
118 |
119 |
124 |
125 |
126 |
127 |
130 |
133 |
134 |
135 |
155 |
156 |
157 |
158 |
159 |
160 |
162 |
165 |
166 |
167 |
168 |
169 |

170 |
171 |
172 |
173 |
174 |
175 | Los Angeles
176 |
177 |
178 | CLear sky
179 |
180 |
181 |
182 |
183 |
185 | 14
186 |
187 |
189 | °
190 |
191 |
192 |
193 |
194 |
195 |
196 |
199 |
200 |
201 |
202 |
204 |
205 |
206 |
207 |
208 |
209 |

210 |
211 |
212 | Wind :
213 | 2.8
214 | km/h
215 |
216 |
217 |
218 |
219 |
220 |
221 |

222 |
223 |
224 | Humidity :
225 | 35
226 | %
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |

238 |
239 |
240 | Min temp :
241 | ...
242 |
243 |
244 |
245 |
246 |
247 |
248 |

249 |
250 |
251 | Max temp :
252 | ...
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
264 |
265 | 20:35:42
266 |
267 |
268 | sat / 2022,18,25
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 | Today
279 |
280 |
281 |
282 |
283 |
284 |
286 |
Clear Sky
287 |
288 |
289 |
290 |
09:00
291 |
292 |
293 |
294 |
296 |
Clear Sky
297 |
298 |
299 |
300 |
09:00
301 |
302 |
303 |
304 |
306 |
Clear Sky
307 |
308 |
309 |
310 |
09:00
311 |
312 |
313 |
314 |
316 |
Clear Sky
317 |
318 |
319 |
320 |
09:00
321 |
322 |
323 |
324 |
326 |
Clear Sky
327 |
328 |
329 |
330 |
09:00
331 |
332 |
333 |
334 |
336 |
Clear Sky
337 |
338 |
339 |
340 |
09:00
341 |
342 |
343 |
344 |
346 |
Clear Sky
347 |
348 |
349 |
350 |
09:00
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
367 |
368 |
369 |
371 |
372 |
374 |
375 |

376 |
377 |
378 |
379 |
380 |
381 | Los Angeles
382 |
383 |
384 | CLear sky
385 |
386 |
387 |
388 |
390 | 14
391 |
392 |
394 | °
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |

409 |
410 |
411 | Wind :
412 | 2.8
413 | km/h
414 |
415 |
416 |
417 |
418 |
419 |
420 |

421 |
422 |
423 | Humidity :
424 | 35
425 | %
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |

437 |
438 |
439 | Min temp :
440 | ...
441 |
442 |
443 |
444 |
445 |
446 |
447 |

448 |
449 |
450 | Max temp :
451 | ...
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
Made with Love
471 |
472 | Alireza hosseini
473 |
474 |
475 |
476 |
477 |
478 |
481 |
484 |
486 |
487 | Loading...
488 |
489 |
492 |
495 |
496 |
497 |
500 |
503 |
505 |
508 |
509 |
562 |
563 |
564 |
567 |
609 |
612 |
615 |
678 |
681 |
684 |
686 |
688 |
689 |
690 | Please turn on your VPN
691 |
692 | Without
694 | VPN, we cannot receive information from the server
695 |
699 |
700 |
701 |
704 |
705 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "weather_app",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "sass" : "sass --watch src/styles/sass:src/styles/css",
8 | "tailwind" : "npx tailwindcss -i ./src/styles/tailwind.css -o ./src/styles/tailwind_output.css --watch",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "author": "alireza hosseini",
12 | "license": "MIT",
13 | "devDependencies": {
14 | "tailwindcss": "^3.1.8"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/assets/animated-svg/moonrise.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/animated-svg/raindrop-measure.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/animated-svg/sunrise.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/animated-svg/thermometer-colder.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/animated-svg/thermometer-warmer.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/animated-svg/wind.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/fonts/Font-icons/iconly.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * ti-light-v2 icon font. Generated by Iconly: https://iconly.io/
3 | */
4 |
5 | @font-face {
6 | font-display: auto;
7 | font-family: "ti-light-v2";
8 | font-style: normal;
9 | font-weight: 400;
10 | src: url("./iconly.eot?1665430336564");
11 | src: url("./iconly.eot?#iefix") format("embedded-opentype"), url("./iconly.woff2?1665430336564") format("woff2"), url("./iconly.woff?1665430336564") format("woff"), url("./iconly.ttf?1665430336564") format("truetype"), url("./iconly.svg?1665430336564#ti-light-v2") format("svg");
12 | }
13 |
14 | [class="icon"], [class^="icon-"], [class*=" icon-"] {
15 | display: inline-block;
16 | font-family: "ti-light-v2" !important;
17 | font-weight: 400;
18 | font-style: normal;
19 | font-variant: normal;
20 | text-rendering: auto;
21 | line-height: 1;
22 | -moz-osx-font-smoothing: grayscale;
23 | -webkit-font-smoothing: antialiased;
24 | }
25 |
26 | .icon-work:before {
27 | content: "\e000";
28 | }
29 |
30 | .icon-wifi:before {
31 | content: "\e001";
32 | }
33 |
34 | .icon-watch:before {
35 | content: "\e002";
36 | }
37 |
38 | .icon-wallet:before {
39 | content: "\e003";
40 | }
41 |
42 | .icon-volume-slash:before {
43 | content: "\e004";
44 | }
45 |
46 | .icon-volume-mute:before {
47 | content: "\e005";
48 | }
49 |
50 | .icon-volume-low:before {
51 | content: "\e006";
52 | }
53 |
54 | .icon-volume-high:before {
55 | content: "\e007";
56 | }
57 |
58 | .icon-volume-cross:before {
59 | content: "\e008";
60 | }
61 |
62 | .icon-video:before {
63 | content: "\e009";
64 | }
65 |
66 | .icon-unlock:before {
67 | content: "\e00a";
68 | }
69 |
70 | .icon-two-user:before {
71 | content: "\e00b";
72 | }
73 |
74 | .icon-tv:before {
75 | content: "\e00c";
76 | }
77 |
78 | .icon-turn-off:before {
79 | content: "\e00d";
80 | }
81 |
82 | .icon-trash-2:before {
83 | content: "\e00e";
84 | }
85 |
86 | .icon-trash-1:before {
87 | content: "\e00f";
88 | }
89 |
90 | .icon-torch:before {
91 | content: "\e010";
92 | }
93 |
94 | .icon-text:before {
95 | content: "\e011";
96 | }
97 |
98 | .icon-swap2:before {
99 | content: "\e012";
100 | }
101 |
102 | .icon-swap-1:before {
103 | content: "\e013";
104 | }
105 |
106 | .icon-sunrise:before {
107 | content: "\e014";
108 | }
109 |
110 | .icon-sun:before {
111 | content: "\e015";
112 | }
113 |
114 | .icon-submit:before {
115 | content: "\e016";
116 | }
117 |
118 | .icon-statistics:before {
119 | content: "\e017";
120 | }
121 |
122 | .icon-statistics-monitor:before {
123 | content: "\e018";
124 | }
125 |
126 | .icon-star:before {
127 | content: "\e019";
128 | }
129 |
130 | .icon-speker:before {
131 | content: "\e01a";
132 | }
133 |
134 | .icon-signal:before {
135 | content: "\e01b";
136 | }
137 |
138 | .icon-shield:before {
139 | content: "\e01c";
140 | }
141 |
142 | .icon-shield-faild:before {
143 | content: "\e01d";
144 | }
145 |
146 | .icon-shield-done:before {
147 | content: "\e01e";
148 | }
149 |
150 | .icon-settings:before {
151 | content: "\e01f";
152 | }
153 |
154 | .icon-settings-2:before {
155 | content: "\e020";
156 | }
157 |
158 | .icon-send:before {
159 | content: "\e021";
160 | }
161 |
162 | .icon-send-up:before {
163 | content: "\e022";
164 | }
165 |
166 | .icon-send-right:before {
167 | content: "\e023";
168 | }
169 |
170 | .icon-search:before {
171 | content: "\e024";
172 | }
173 |
174 | .icon-scan:before {
175 | content: "\e025";
176 | }
177 |
178 | .icon-rotate-right:before {
179 | content: "\e026";
180 | }
181 |
182 | .icon-rotate-right-1:before {
183 | content: "\e027";
184 | }
185 |
186 | .icon-reserve:before {
187 | content: "\e028";
188 | }
189 |
190 | .icon-received:before {
191 | content: "\e029";
192 | }
193 |
194 | .icon-qustion:before {
195 | content: "\e02a";
196 | }
197 |
198 | .icon-puse:before {
199 | content: "\e02b";
200 | }
201 |
202 | .icon-programming:before {
203 | content: "\e02c";
204 | }
205 |
206 | .icon-profile:before {
207 | content: "\e02d";
208 | }
209 |
210 | .icon-plus:before {
211 | content: "\e02e";
212 | }
213 |
214 | .icon-play:before {
215 | content: "\e02f";
216 | }
217 |
218 | .icon-play-square:before {
219 | content: "\e030";
220 | }
221 |
222 | .icon-note:before {
223 | content: "\e031";
224 | }
225 |
226 | .icon-note-up:before {
227 | content: "\e032";
228 | }
229 |
230 | .icon-note-plus:before {
231 | content: "\e033";
232 | }
233 |
234 | .icon-note-minus:before {
235 | content: "\e034";
236 | }
237 |
238 | .icon-note-failed:before {
239 | content: "\e035";
240 | }
241 |
242 | .icon-note-down:before {
243 | content: "\e036";
244 | }
245 |
246 | .icon-note-accept:before {
247 | content: "\e037";
248 | }
249 |
250 | .icon-night:before {
251 | content: "\e038";
252 | }
253 |
254 | .icon-next-track:before {
255 | content: "\e039";
256 | }
257 |
258 | .icon-next-track-2:before {
259 | content: "\e03a";
260 | }
261 |
262 | .icon-mouse:before {
263 | content: "\e03b";
264 | }
265 |
266 | .icon-more:before {
267 | content: "\e03c";
268 | }
269 |
270 | .icon-monitor:before {
271 | content: "\e03d";
272 | }
273 |
274 | .icon-mobile:before {
275 | content: "\e03e";
276 | }
277 |
278 | .icon-microphon-2:before {
279 | content: "\e03f";
280 | }
281 |
282 | .icon-microphon-1:before {
283 | content: "\e040";
284 | }
285 |
286 | .icon-message:before {
287 | content: "\e041";
288 | }
289 |
290 | .icon-menu:before {
291 | content: "\e042";
292 | }
293 |
294 | .icon-menu-1:before {
295 | content: "\e043";
296 | }
297 |
298 | .icon-megaphone:before {
299 | content: "\e044";
300 | }
301 |
302 | .icon-mask:before {
303 | content: "\e045";
304 | }
305 |
306 | .icon-logout:before {
307 | content: "\e046";
308 | }
309 |
310 | .icon-login:before {
311 | content: "\e047";
312 | }
313 |
314 | .icon-lock:before {
315 | content: "\e048";
316 | }
317 |
318 | .icon-lock-1:before {
319 | content: "\e049";
320 | }
321 |
322 | .icon-location:before {
323 | content: "\e04a";
324 | }
325 |
326 | .icon-laptop:before {
327 | content: "\e04b";
328 | }
329 |
330 | .icon-key:before {
331 | content: "\e04c";
332 | }
333 |
334 | .icon-instagram:before {
335 | content: "\e04d";
336 | }
337 |
338 | .icon-info:before {
339 | content: "\e04e";
340 | }
341 |
342 | .icon-info-1:before {
343 | content: "\e04f";
344 | }
345 |
346 | .icon-in-progress:before {
347 | content: "\e050";
348 | }
349 |
350 | .icon-in-progress-square:before {
351 | content: "\e051";
352 | }
353 |
354 | .icon-image:before {
355 | content: "\e052";
356 | }
357 |
358 | .icon-image-4:before {
359 | content: "\e053";
360 | }
361 |
362 | .icon-image-3:before {
363 | content: "\e054";
364 | }
365 |
366 | .icon-image-2:before {
367 | content: "\e055";
368 | }
369 |
370 | .icon-home:before {
371 | content: "\e056";
372 | }
373 |
374 | .icon-home-2:before {
375 | content: "\e057";
376 | }
377 |
378 | .icon-hedphon:before {
379 | content: "\e058";
380 | }
381 |
382 | .icon-heart:before {
383 | content: "\e059";
384 | }
385 |
386 | .icon-grid:before {
387 | content: "\e05a";
388 | }
389 |
390 | .icon-graph:before {
391 | content: "\e05b";
392 | }
393 |
394 | .icon-gps-2:before {
395 | content: "\e05c";
396 | }
397 |
398 | .icon-gps-1:before {
399 | content: "\e05d";
400 | }
401 |
402 | .icon-game:before {
403 | content: "\e05e";
404 | }
405 |
406 | .icon-folder:before {
407 | content: "\e05f";
408 | }
409 |
410 | .icon-filter:before {
411 | content: "\e060";
412 | }
413 |
414 | .icon-filter-2:before {
415 | content: "\e061";
416 | }
417 |
418 | .icon-feedback-like:before {
419 | content: "\e062";
420 | }
421 |
422 | .icon-feedback-dislike:before {
423 | content: "\e063";
424 | }
425 |
426 | .icon-eye:before {
427 | content: "\e064";
428 | }
429 |
430 | .icon-eye-slash:before {
431 | content: "\e065";
432 | }
433 |
434 | .icon-export:before {
435 | content: "\e066";
436 | }
437 |
438 | .icon-edit:before {
439 | content: "\e067";
440 | }
441 |
442 | .icon-edit-square:before {
443 | content: "\e068";
444 | }
445 |
446 | .icon-edit-2:before {
447 | content: "\e069";
448 | }
449 |
450 | .icon-dollar:before {
451 | content: "\e06a";
452 | }
453 |
454 | .icon-document:before {
455 | content: "\e06b";
456 | }
457 |
458 | .icon-discovery:before {
459 | content: "\e06c";
460 | }
461 |
462 | .icon-discount:before {
463 | content: "\e06d";
464 | }
465 |
466 | .icon-discount-square:before {
467 | content: "\e06e";
468 | }
469 |
470 | .icon-decrease-cart:before {
471 | content: "\e06f";
472 | }
473 |
474 | .icon-danger:before {
475 | content: "\e070";
476 | }
477 |
478 | .icon-copy:before {
479 | content: "\e071";
480 | }
481 |
482 | .icon-collateral:before {
483 | content: "\e072";
484 | }
485 |
486 | .icon-cloud:before {
487 | content: "\e073";
488 | }
489 |
490 | .icon-cloud-received:before {
491 | content: "\e074";
492 | }
493 |
494 | .icon-cloud-exit:before {
495 | content: "\e075";
496 | }
497 |
498 | .icon-cloud-lightning:before {
499 | content: "\e076";
500 | }
501 |
502 | .icon-close-square:before {
503 | content: "\e077";
504 | }
505 |
506 | .icon-clock:before {
507 | content: "\e078";
508 | }
509 |
510 | .icon-checklist:before {
511 | content: "\e079";
512 | }
513 |
514 | .icon-chat:before {
515 | content: "\e07a";
516 | }
517 |
518 | .icon-charge:before {
519 | content: "\e07b";
520 | }
521 |
522 | .icon-census:before {
523 | content: "\e07c";
524 | }
525 |
526 | .icon-cart:before {
527 | content: "\e07d";
528 | }
529 |
530 | .icon-cart-2:before {
531 | content: "\e07e";
532 | }
533 |
534 | .icon-card:before {
535 | content: "\e07f";
536 | }
537 |
538 | .icon-camera:before {
539 | content: "\e080";
540 | }
541 |
542 | .icon-calling:before {
543 | content: "\e081";
544 | }
545 |
546 | .icon-call:before {
547 | content: "\e082";
548 | }
549 |
550 | .icon-call-disconnected:before {
551 | content: "\e083";
552 | }
553 |
554 | .icon-call-silent:before {
555 | content: "\e084";
556 | }
557 |
558 | .icon-calender:before {
559 | content: "\e085";
560 | }
561 |
562 | .icon-calender-3:before {
563 | content: "\e086";
564 | }
565 |
566 | .icon-calender-2:before {
567 | content: "\e087";
568 | }
569 |
570 | .icon-bookmark:before {
571 | content: "\e088";
572 | }
573 |
574 | .icon-bell:before {
575 | content: "\e089";
576 | }
577 |
578 | .icon-bell-2:before {
579 | content: "\e08a";
580 | }
581 |
582 | .icon-battery:before {
583 | content: "\e08b";
584 | }
585 |
586 | .icon-bag:before {
587 | content: "\e08c";
588 | }
589 |
590 | .icon-back-track:before {
591 | content: "\e08d";
592 | }
593 |
594 | .icon-back-track-2:before {
595 | content: "\e08e";
596 | }
597 |
598 | .icon-award:before {
599 | content: "\e08f";
600 | }
601 |
602 | .icon-arrow-up-square:before {
603 | content: "\e090";
604 | }
605 |
606 | .icon-arrow-up-square-3:before {
607 | content: "\e091";
608 | }
609 |
610 | .icon-arrow-up-square-2:before {
611 | content: "\e092";
612 | }
613 |
614 | .icon-arrow-up-circle:before {
615 | content: "\e093";
616 | }
617 |
618 | .icon-arrow-up-3:before {
619 | content: "\e094";
620 | }
621 |
622 | .icon-arrow-up-1:before {
623 | content: "\e095";
624 | }
625 |
626 | .icon-arrow-up-1-1:before {
627 | content: "\e096";
628 | }
629 |
630 | .icon-arrow-right-square:before {
631 | content: "\e097";
632 | }
633 |
634 | .icon-arrow-right-square-3:before {
635 | content: "\e098";
636 | }
637 |
638 | .icon-arrow-right-square-2:before {
639 | content: "\e099";
640 | }
641 |
642 | .icon-arrow-right-circle:before {
643 | content: "\e09a";
644 | }
645 |
646 | .icon-arrow-right-3:before {
647 | content: "\e09b";
648 | }
649 |
650 | .icon-arrow-right-2:before {
651 | content: "\e09c";
652 | }
653 |
654 | .icon-arrow-right-1:before {
655 | content: "\e09d";
656 | }
657 |
658 | .icon-arrow-left-square:before {
659 | content: "\e09e";
660 | }
661 |
662 | .icon-arrow-left-square-3:before {
663 | content: "\e09f";
664 | }
665 |
666 | .icon-arrow-left-square-2:before {
667 | content: "\e0a0";
668 | }
669 |
670 | .icon-arrow-left-circle:before {
671 | content: "\e0a1";
672 | }
673 |
674 | .icon-arrow-left-3:before {
675 | content: "\e0a2";
676 | }
677 |
678 | .icon-wind:before {
679 | content: "\e0a3";
680 | }
681 |
682 | .icon-arrow-left-1:before {
683 | content: "\e0a4";
684 | }
685 |
686 | .icon-arrow-down-square:before {
687 | content: "\e0a5";
688 | }
689 |
690 | .icon-arrow-down-square-3:before {
691 | content: "\e0a6";
692 | }
693 |
694 | .icon-arrow-down-square-2:before {
695 | content: "\e0a7";
696 | }
697 |
698 | .icon-arrow-down-circle:before {
699 | content: "\e0a8";
700 | }
701 |
702 | .icon-arrow-down-2:before {
703 | content: "\e0a9";
704 | }
705 |
706 | .icon-arrow-down-2-1:before {
707 | content: "\e0aa";
708 | }
709 |
710 | .icon-arrow-down-1:before {
711 | content: "\e0ab";
712 | }
713 |
714 | .icon-align-right:before {
715 | content: "\e0ac";
716 | }
717 |
718 | .icon-align-left:before {
719 | content: "\e0ad";
720 | }
721 |
722 | .icon-align-center:before {
723 | content: "\e0ae";
724 | }
725 |
726 | .icon-airpod:before {
727 | content: "\e0af";
728 | }
729 |
730 | .icon-airplane:before {
731 | content: "\e0b0";
732 | }
733 |
734 | .icon-add:before {
735 | content: "\e0b1";
736 | }
737 |
738 | .icon-add-1:before {
739 | content: "\e0b2";
740 | }
741 |
742 | .icon-add-user:before {
743 | content: "\e0b3";
744 | }
745 |
746 | .icon-add-cart:before {
747 | content: "\e0b4";
748 | }
749 |
750 | .icon-accept:before {
751 | content: "\e0b5";
752 | }
753 |
754 | .icon-3-user:before {
755 | content: "\e0b6";
756 | }
757 |
758 | .icon-2-user:before {
759 | content: "\e0b7";
760 | }
761 |
762 | .icon-thermometer-4:before {
763 | content: "\e0b8";
764 | }
765 |
766 | .icon-thermometer-2:before {
767 | content: "\e0b9";
768 | }
769 |
770 | .icon-sunset:before {
771 | content: "\e0ba";
772 | }
773 |
774 | .icon-sunrise-2:before {
775 | content: "\e0bb";
776 | }
777 |
778 | .icon-drops:before {
779 | content: "\e0bc";
780 | }
781 |
782 | .icon-drop-percentage:before {
783 | content: "\e0bd";
784 | }
785 |
--------------------------------------------------------------------------------
/src/assets/fonts/Font-icons/iconly.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Font-icons/iconly.eot
--------------------------------------------------------------------------------
/src/assets/fonts/Font-icons/iconly.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * ti-light-v2 icon font. Generated by Iconly: https://iconly.io/
3 | */
4 | @font-face{font-display:auto;font-family:"ti-light-v2";font-style:normal;font-weight:400;src:url(./iconly.eot?1665430336564);src:url(./iconly.eot?#iefix) format("embedded-opentype"),url(./iconly.woff2?1665430336564) format("woff2"),url(./iconly.woff?1665430336564) format("woff"),url(./iconly.ttf?1665430336564) format("truetype"),url(./iconly.svg?1665430336564#ti-light-v2) format("svg")}[class*=" icon-"],[class=icon],[class^=icon-]{display:inline-block;font-family:"ti-light-v2"!important;font-weight:400;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.icon-work:before{content:"\e000"}.icon-wifi:before{content:"\e001"}.icon-watch:before{content:"\e002"}.icon-wallet:before{content:"\e003"}.icon-volume-slash:before{content:"\e004"}.icon-volume-mute:before{content:"\e005"}.icon-volume-low:before{content:"\e006"}.icon-volume-high:before{content:"\e007"}.icon-volume-cross:before{content:"\e008"}.icon-video:before{content:"\e009"}.icon-unlock:before{content:"\e00a"}.icon-two-user:before{content:"\e00b"}.icon-tv:before{content:"\e00c"}.icon-turn-off:before{content:"\e00d"}.icon-trash-2:before{content:"\e00e"}.icon-trash-1:before{content:"\e00f"}.icon-torch:before{content:"\e010"}.icon-text:before{content:"\e011"}.icon-swap2:before{content:"\e012"}.icon-swap-1:before{content:"\e013"}.icon-sunrise:before{content:"\e014"}.icon-sun:before{content:"\e015"}.icon-submit:before{content:"\e016"}.icon-statistics:before{content:"\e017"}.icon-statistics-monitor:before{content:"\e018"}.icon-star:before{content:"\e019"}.icon-speker:before{content:"\e01a"}.icon-signal:before{content:"\e01b"}.icon-shield:before{content:"\e01c"}.icon-shield-faild:before{content:"\e01d"}.icon-shield-done:before{content:"\e01e"}.icon-settings:before{content:"\e01f"}.icon-settings-2:before{content:"\e020"}.icon-send:before{content:"\e021"}.icon-send-up:before{content:"\e022"}.icon-send-right:before{content:"\e023"}.icon-search:before{content:"\e024"}.icon-scan:before{content:"\e025"}.icon-rotate-right:before{content:"\e026"}.icon-rotate-right-1:before{content:"\e027"}.icon-reserve:before{content:"\e028"}.icon-received:before{content:"\e029"}.icon-qustion:before{content:"\e02a"}.icon-puse:before{content:"\e02b"}.icon-programming:before{content:"\e02c"}.icon-profile:before{content:"\e02d"}.icon-plus:before{content:"\e02e"}.icon-play:before{content:"\e02f"}.icon-play-square:before{content:"\e030"}.icon-note:before{content:"\e031"}.icon-note-up:before{content:"\e032"}.icon-note-plus:before{content:"\e033"}.icon-note-minus:before{content:"\e034"}.icon-note-failed:before{content:"\e035"}.icon-note-down:before{content:"\e036"}.icon-note-accept:before{content:"\e037"}.icon-night:before{content:"\e038"}.icon-next-track:before{content:"\e039"}.icon-next-track-2:before{content:"\e03a"}.icon-mouse:before{content:"\e03b"}.icon-more:before{content:"\e03c"}.icon-monitor:before{content:"\e03d"}.icon-mobile:before{content:"\e03e"}.icon-microphon-2:before{content:"\e03f"}.icon-microphon-1:before{content:"\e040"}.icon-message:before{content:"\e041"}.icon-menu:before{content:"\e042"}.icon-menu-1:before{content:"\e043"}.icon-megaphone:before{content:"\e044"}.icon-mask:before{content:"\e045"}.icon-logout:before{content:"\e046"}.icon-login:before{content:"\e047"}.icon-lock:before{content:"\e048"}.icon-lock-1:before{content:"\e049"}.icon-location:before{content:"\e04a"}.icon-laptop:before{content:"\e04b"}.icon-key:before{content:"\e04c"}.icon-instagram:before{content:"\e04d"}.icon-info:before{content:"\e04e"}.icon-info-1:before{content:"\e04f"}.icon-in-progress:before{content:"\e050"}.icon-in-progress-square:before{content:"\e051"}.icon-image:before{content:"\e052"}.icon-image-4:before{content:"\e053"}.icon-image-3:before{content:"\e054"}.icon-image-2:before{content:"\e055"}.icon-home:before{content:"\e056"}.icon-home-2:before{content:"\e057"}.icon-hedphon:before{content:"\e058"}.icon-heart:before{content:"\e059"}.icon-grid:before{content:"\e05a"}.icon-graph:before{content:"\e05b"}.icon-gps-2:before{content:"\e05c"}.icon-gps-1:before{content:"\e05d"}.icon-game:before{content:"\e05e"}.icon-folder:before{content:"\e05f"}.icon-filter:before{content:"\e060"}.icon-filter-2:before{content:"\e061"}.icon-feedback-like:before{content:"\e062"}.icon-feedback-dislike:before{content:"\e063"}.icon-eye:before{content:"\e064"}.icon-eye-slash:before{content:"\e065"}.icon-export:before{content:"\e066"}.icon-edit:before{content:"\e067"}.icon-edit-square:before{content:"\e068"}.icon-edit-2:before{content:"\e069"}.icon-dollar:before{content:"\e06a"}.icon-document:before{content:"\e06b"}.icon-discovery:before{content:"\e06c"}.icon-discount:before{content:"\e06d"}.icon-discount-square:before{content:"\e06e"}.icon-decrease-cart:before{content:"\e06f"}.icon-danger:before{content:"\e070"}.icon-copy:before{content:"\e071"}.icon-collateral:before{content:"\e072"}.icon-cloud:before{content:"\e073"}.icon-cloud-received:before{content:"\e074"}.icon-cloud-exit:before{content:"\e075"}.icon-cloud-lightning:before{content:"\e076"}.icon-close-square:before{content:"\e077"}.icon-clock:before{content:"\e078"}.icon-checklist:before{content:"\e079"}.icon-chat:before{content:"\e07a"}.icon-charge:before{content:"\e07b"}.icon-census:before{content:"\e07c"}.icon-cart:before{content:"\e07d"}.icon-cart-2:before{content:"\e07e"}.icon-card:before{content:"\e07f"}.icon-camera:before{content:"\e080"}.icon-calling:before{content:"\e081"}.icon-call:before{content:"\e082"}.icon-call-disconnected:before{content:"\e083"}.icon-call-silent:before{content:"\e084"}.icon-calender:before{content:"\e085"}.icon-calender-3:before{content:"\e086"}.icon-calender-2:before{content:"\e087"}.icon-bookmark:before{content:"\e088"}.icon-bell:before{content:"\e089"}.icon-bell-2:before{content:"\e08a"}.icon-battery:before{content:"\e08b"}.icon-bag:before{content:"\e08c"}.icon-back-track:before{content:"\e08d"}.icon-back-track-2:before{content:"\e08e"}.icon-award:before{content:"\e08f"}.icon-arrow-up-square:before{content:"\e090"}.icon-arrow-up-square-3:before{content:"\e091"}.icon-arrow-up-square-2:before{content:"\e092"}.icon-arrow-up-circle:before{content:"\e093"}.icon-arrow-up-3:before{content:"\e094"}.icon-arrow-up-1:before{content:"\e095"}.icon-arrow-up-1-1:before{content:"\e096"}.icon-arrow-right-square:before{content:"\e097"}.icon-arrow-right-square-3:before{content:"\e098"}.icon-arrow-right-square-2:before{content:"\e099"}.icon-arrow-right-circle:before{content:"\e09a"}.icon-arrow-right-3:before{content:"\e09b"}.icon-arrow-right-2:before{content:"\e09c"}.icon-arrow-right-1:before{content:"\e09d"}.icon-arrow-left-square:before{content:"\e09e"}.icon-arrow-left-square-3:before{content:"\e09f"}.icon-arrow-left-square-2:before{content:"\e0a0"}.icon-arrow-left-circle:before{content:"\e0a1"}.icon-arrow-left-3:before{content:"\e0a2"}.icon-wind:before{content:"\e0a3"}.icon-arrow-left-1:before{content:"\e0a4"}.icon-arrow-down-square:before{content:"\e0a5"}.icon-arrow-down-square-3:before{content:"\e0a6"}.icon-arrow-down-square-2:before{content:"\e0a7"}.icon-arrow-down-circle:before{content:"\e0a8"}.icon-arrow-down-2:before{content:"\e0a9"}.icon-arrow-down-2-1:before{content:"\e0aa"}.icon-arrow-down-1:before{content:"\e0ab"}.icon-align-right:before{content:"\e0ac"}.icon-align-left:before{content:"\e0ad"}.icon-align-center:before{content:"\e0ae"}.icon-airpod:before{content:"\e0af"}.icon-airplane:before{content:"\e0b0"}.icon-add:before{content:"\e0b1"}.icon-add-1:before{content:"\e0b2"}.icon-add-user:before{content:"\e0b3"}.icon-add-cart:before{content:"\e0b4"}.icon-accept:before{content:"\e0b5"}.icon-3-user:before{content:"\e0b6"}.icon-2-user:before{content:"\e0b7"}.icon-thermometer-4:before{content:"\e0b8"}.icon-thermometer-2:before{content:"\e0b9"}.icon-sunset:before{content:"\e0ba"}.icon-sunrise-2:before{content:"\e0bb"}.icon-drops:before{content:"\e0bc"}.icon-drop-percentage:before{content:"\e0bd"}
--------------------------------------------------------------------------------
/src/assets/fonts/Font-icons/iconly.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Font-icons/iconly.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Font-icons/iconly.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Font-icons/iconly.woff
--------------------------------------------------------------------------------
/src/assets/fonts/Font-icons/iconly.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Font-icons/iconly.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-Black.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-BlackItalic.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-Bold.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-BoldItalic.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-ExtraBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-ExtraBold.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-ExtraBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-ExtraBoldItalic.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-ExtraLight.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-ExtraLight.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-ExtraLightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-ExtraLightItalic.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-Italic.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-Light.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-LightItalic.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-Medium.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-MediumItalic.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-Regular.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-SemiBold.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-SemiBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-SemiBoldItalic.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-Thin.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Poppins/Poppins-ThinItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/fonts/Poppins/Poppins-ThinItalic.ttf
--------------------------------------------------------------------------------
/src/assets/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/favicon.ico
--------------------------------------------------------------------------------
/src/assets/images/first page/27.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/first page/27.webp
--------------------------------------------------------------------------------
/src/assets/images/first page/location-pin.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/first page/location-pin.webp
--------------------------------------------------------------------------------
/src/assets/images/first page/map-pin.svg:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/assets/images/weather/atmosphere_day.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/atmosphere_day.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/atmosphere_night.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/atmosphere_night.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/clear_day.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/clear_day.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/clear_night.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/clear_night.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/clouds_day.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/clouds_day.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/clouds_night.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/clouds_night.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/drizzle_day.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/drizzle_day.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/drizzle_night.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/drizzle_night.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/rain_day.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/rain_day.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/rain_night.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/rain_night.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/snow_day.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/snow_day.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/snow_night.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/snow_night.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/thunderstorm_day.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/thunderstorm_day.webp
--------------------------------------------------------------------------------
/src/assets/images/weather/thunderstorm_night.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alirezahoseini/Weather-App-JS/e88aef696b2e6a9a8ffc193fc3ad0ce74bfccc23/src/assets/images/weather/thunderstorm_night.webp
--------------------------------------------------------------------------------
/src/assets/swiperjs/slider-config.js:
--------------------------------------------------------------------------------
1 | var swiper = new Swiper(".nextHours", {
2 | slidesPerView: 3,
3 | spaceBetween: 10,
4 | breakpoints: {
5 | 100: {
6 | slidesPerView: 3.7,
7 | spaceBetween: 10,
8 | },
9 | 768: {
10 | slidesPerView: 4.5,
11 | spaceBetween: 15,
12 | },
13 | 991: {
14 | slidesPerView: 5.5,
15 | spaceBetween: 15,
16 | },
17 | 1280: {
18 | slidesPerView: 5.5,
19 | spaceBetween: 15,
20 | },
21 |
22 | },
23 | });
--------------------------------------------------------------------------------
/src/assets/swiperjs/swiper-min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Swiper 8.4.4
3 | * Most modern mobile touch slider and framework with hardware accelerated transitions
4 | * https://swiperjs.com
5 | *
6 | * Copyright 2014-2022 Vladimir Kharlampidi
7 | *
8 | * Released under the MIT License
9 | *
10 | * Released on: October 12, 2022
11 | */
12 |
13 | @font-face{font-family:swiper-icons;src:url('data:application/font-woff;charset=utf-8;base64, d09GRgABAAAAAAZgABAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAAGRAAAABoAAAAci6qHkUdERUYAAAWgAAAAIwAAACQAYABXR1BPUwAABhQAAAAuAAAANuAY7+xHU1VCAAAFxAAAAFAAAABm2fPczU9TLzIAAAHcAAAASgAAAGBP9V5RY21hcAAAAkQAAACIAAABYt6F0cBjdnQgAAACzAAAAAQAAAAEABEBRGdhc3AAAAWYAAAACAAAAAj//wADZ2x5ZgAAAywAAADMAAAD2MHtryVoZWFkAAABbAAAADAAAAA2E2+eoWhoZWEAAAGcAAAAHwAAACQC9gDzaG10eAAAAigAAAAZAAAArgJkABFsb2NhAAAC0AAAAFoAAABaFQAUGG1heHAAAAG8AAAAHwAAACAAcABAbmFtZQAAA/gAAAE5AAACXvFdBwlwb3N0AAAFNAAAAGIAAACE5s74hXjaY2BkYGAAYpf5Hu/j+W2+MnAzMYDAzaX6QjD6/4//Bxj5GA8AuRwMYGkAPywL13jaY2BkYGA88P8Agx4j+/8fQDYfA1AEBWgDAIB2BOoAeNpjYGRgYNBh4GdgYgABEMnIABJzYNADCQAACWgAsQB42mNgYfzCOIGBlYGB0YcxjYGBwR1Kf2WQZGhhYGBiYGVmgAFGBiQQkOaawtDAoMBQxXjg/wEGPcYDDA4wNUA2CCgwsAAAO4EL6gAAeNpj2M0gyAACqxgGNWBkZ2D4/wMA+xkDdgAAAHjaY2BgYGaAYBkGRgYQiAHyGMF8FgYHIM3DwMHABGQrMOgyWDLEM1T9/w8UBfEMgLzE////P/5//f/V/xv+r4eaAAeMbAxwIUYmIMHEgKYAYjUcsDAwsLKxc3BycfPw8jEQA/gZBASFhEVExcQlJKWkZWTl5BUUlZRVVNXUNTQZBgMAAMR+E+gAEQFEAAAAKgAqACoANAA+AEgAUgBcAGYAcAB6AIQAjgCYAKIArAC2AMAAygDUAN4A6ADyAPwBBgEQARoBJAEuATgBQgFMAVYBYAFqAXQBfgGIAZIBnAGmAbIBzgHsAAB42u2NMQ6CUAyGW568x9AneYYgm4MJbhKFaExIOAVX8ApewSt4Bic4AfeAid3VOBixDxfPYEza5O+Xfi04YADggiUIULCuEJK8VhO4bSvpdnktHI5QCYtdi2sl8ZnXaHlqUrNKzdKcT8cjlq+rwZSvIVczNiezsfnP/uznmfPFBNODM2K7MTQ45YEAZqGP81AmGGcF3iPqOop0r1SPTaTbVkfUe4HXj97wYE+yNwWYxwWu4v1ugWHgo3S1XdZEVqWM7ET0cfnLGxWfkgR42o2PvWrDMBSFj/IHLaF0zKjRgdiVMwScNRAoWUoH78Y2icB/yIY09An6AH2Bdu/UB+yxopYshQiEvnvu0dURgDt8QeC8PDw7Fpji3fEA4z/PEJ6YOB5hKh4dj3EvXhxPqH/SKUY3rJ7srZ4FZnh1PMAtPhwP6fl2PMJMPDgeQ4rY8YT6Gzao0eAEA409DuggmTnFnOcSCiEiLMgxCiTI6Cq5DZUd3Qmp10vO0LaLTd2cjN4fOumlc7lUYbSQcZFkutRG7g6JKZKy0RmdLY680CDnEJ+UMkpFFe1RN7nxdVpXrC4aTtnaurOnYercZg2YVmLN/d/gczfEimrE/fs/bOuq29Zmn8tloORaXgZgGa78yO9/cnXm2BpaGvq25Dv9S4E9+5SIc9PqupJKhYFSSl47+Qcr1mYNAAAAeNptw0cKwkAAAMDZJA8Q7OUJvkLsPfZ6zFVERPy8qHh2YER+3i/BP83vIBLLySsoKimrqKqpa2hp6+jq6RsYGhmbmJqZSy0sraxtbO3sHRydnEMU4uR6yx7JJXveP7WrDycAAAAAAAH//wACeNpjYGRgYOABYhkgZgJCZgZNBkYGLQZtIJsFLMYAAAw3ALgAeNolizEKgDAQBCchRbC2sFER0YD6qVQiBCv/H9ezGI6Z5XBAw8CBK/m5iQQVauVbXLnOrMZv2oLdKFa8Pjuru2hJzGabmOSLzNMzvutpB3N42mNgZGBg4GKQYzBhYMxJLMlj4GBgAYow/P/PAJJhLM6sSoWKfWCAAwDAjgbRAAB42mNgYGBkAIIbCZo5IPrmUn0hGA0AO8EFTQAA');font-weight:400;font-style:normal}:root{--swiper-theme-color:#007aff}.swiper{margin-left:auto;margin-right:auto;position:relative;overflow:hidden;list-style:none;padding:0;z-index:1}.swiper-vertical>.swiper-wrapper{flex-direction:column}.swiper-wrapper{position:relative;width:100%;height:100%;z-index:1;display:flex;transition-property:transform;box-sizing:content-box}.swiper-android .swiper-slide,.swiper-wrapper{transform:translate3d(0px,0,0)}.swiper-pointer-events{touch-action:pan-y}.swiper-pointer-events.swiper-vertical{touch-action:pan-x}.swiper-slide{flex-shrink:0;width:100%;height:100%;position:relative;transition-property:transform}.swiper-slide-invisible-blank{visibility:hidden}.swiper-autoheight,.swiper-autoheight .swiper-slide{height:auto}.swiper-autoheight .swiper-wrapper{align-items:flex-start;transition-property:transform,height}.swiper-backface-hidden .swiper-slide{transform:translateZ(0);-webkit-backface-visibility:hidden;backface-visibility:hidden}.swiper-3d,.swiper-3d.swiper-css-mode .swiper-wrapper{perspective:1200px}.swiper-3d .swiper-cube-shadow,.swiper-3d .swiper-slide,.swiper-3d .swiper-slide-shadow,.swiper-3d .swiper-slide-shadow-bottom,.swiper-3d .swiper-slide-shadow-left,.swiper-3d .swiper-slide-shadow-right,.swiper-3d .swiper-slide-shadow-top,.swiper-3d .swiper-wrapper{transform-style:preserve-3d}.swiper-3d .swiper-slide-shadow,.swiper-3d .swiper-slide-shadow-bottom,.swiper-3d .swiper-slide-shadow-left,.swiper-3d .swiper-slide-shadow-right,.swiper-3d .swiper-slide-shadow-top{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:10}.swiper-3d .swiper-slide-shadow{background:rgba(0,0,0,.15)}.swiper-3d .swiper-slide-shadow-left{background-image:linear-gradient(to left,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-3d .swiper-slide-shadow-right{background-image:linear-gradient(to right,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-3d .swiper-slide-shadow-top{background-image:linear-gradient(to top,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-3d .swiper-slide-shadow-bottom{background-image:linear-gradient(to bottom,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-css-mode>.swiper-wrapper{overflow:auto;scrollbar-width:none;-ms-overflow-style:none}.swiper-css-mode>.swiper-wrapper::-webkit-scrollbar{display:none}.swiper-css-mode>.swiper-wrapper>.swiper-slide{scroll-snap-align:start start}.swiper-horizontal.swiper-css-mode>.swiper-wrapper{scroll-snap-type:x mandatory}.swiper-vertical.swiper-css-mode>.swiper-wrapper{scroll-snap-type:y mandatory}.swiper-centered>.swiper-wrapper::before{content:'';flex-shrink:0;order:9999}.swiper-centered.swiper-horizontal>.swiper-wrapper>.swiper-slide:first-child{margin-inline-start:var(--swiper-centered-offset-before)}.swiper-centered.swiper-horizontal>.swiper-wrapper::before{height:100%;min-height:1px;width:var(--swiper-centered-offset-after)}.swiper-centered.swiper-vertical>.swiper-wrapper>.swiper-slide:first-child{margin-block-start:var(--swiper-centered-offset-before)}.swiper-centered.swiper-vertical>.swiper-wrapper::before{width:100%;min-width:1px;height:var(--swiper-centered-offset-after)}.swiper-centered>.swiper-wrapper>.swiper-slide{scroll-snap-align:center center}.swiper-virtual .swiper-slide{-webkit-backface-visibility:hidden;transform:translateZ(0)}.swiper-virtual.swiper-css-mode .swiper-wrapper::after{content:'';position:absolute;left:0;top:0;pointer-events:none}.swiper-virtual.swiper-css-mode.swiper-horizontal .swiper-wrapper::after{height:1px;width:var(--swiper-virtual-size)}.swiper-virtual.swiper-css-mode.swiper-vertical .swiper-wrapper::after{width:1px;height:var(--swiper-virtual-size)}:root{--swiper-navigation-size:44px}.swiper-button-next,.swiper-button-prev{position:absolute;top:50%;width:calc(var(--swiper-navigation-size)/ 44 * 27);height:var(--swiper-navigation-size);margin-top:calc(0px - (var(--swiper-navigation-size)/ 2));z-index:10;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--swiper-navigation-color,var(--swiper-theme-color))}.swiper-button-next.swiper-button-disabled,.swiper-button-prev.swiper-button-disabled{opacity:.35;cursor:auto;pointer-events:none}.swiper-button-next.swiper-button-hidden,.swiper-button-prev.swiper-button-hidden{opacity:0;cursor:auto;pointer-events:none}.swiper-navigation-disabled .swiper-button-next,.swiper-navigation-disabled .swiper-button-prev{display:none!important}.swiper-button-next:after,.swiper-button-prev:after{font-family:swiper-icons;font-size:var(--swiper-navigation-size);text-transform:none!important;letter-spacing:0;font-variant:initial;line-height:1}.swiper-button-prev,.swiper-rtl .swiper-button-next{left:10px;right:auto}.swiper-button-prev:after,.swiper-rtl .swiper-button-next:after{content:'prev'}.swiper-button-next,.swiper-rtl .swiper-button-prev{right:10px;left:auto}.swiper-button-next:after,.swiper-rtl .swiper-button-prev:after{content:'next'}.swiper-button-lock{display:none}.swiper-pagination{position:absolute;text-align:center;transition:.3s opacity;transform:translate3d(0,0,0);z-index:10}.swiper-pagination.swiper-pagination-hidden{opacity:0}.swiper-pagination-disabled>.swiper-pagination,.swiper-pagination.swiper-pagination-disabled{display:none!important}.swiper-horizontal>.swiper-pagination-bullets,.swiper-pagination-bullets.swiper-pagination-horizontal,.swiper-pagination-custom,.swiper-pagination-fraction{bottom:10px;left:0;width:100%}.swiper-pagination-bullets-dynamic{overflow:hidden;font-size:0}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet{transform:scale(.33);position:relative}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active{transform:scale(1)}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-main{transform:scale(1)}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-prev{transform:scale(.66)}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-prev-prev{transform:scale(.33)}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-next{transform:scale(.66)}.swiper-pagination-bullets-dynamic .swiper-pagination-bullet-active-next-next{transform:scale(.33)}.swiper-pagination-bullet{width:var(--swiper-pagination-bullet-width,var(--swiper-pagination-bullet-size,8px));height:var(--swiper-pagination-bullet-height,var(--swiper-pagination-bullet-size,8px));display:inline-block;border-radius:50%;background:var(--swiper-pagination-bullet-inactive-color,#000);opacity:var(--swiper-pagination-bullet-inactive-opacity, .2)}button.swiper-pagination-bullet{border:none;margin:0;padding:0;box-shadow:none;-webkit-appearance:none;appearance:none}.swiper-pagination-clickable .swiper-pagination-bullet{cursor:pointer}.swiper-pagination-bullet:only-child{display:none!important}.swiper-pagination-bullet-active{opacity:var(--swiper-pagination-bullet-opacity, 1);background:var(--swiper-pagination-color,var(--swiper-theme-color))}.swiper-pagination-vertical.swiper-pagination-bullets,.swiper-vertical>.swiper-pagination-bullets{right:10px;top:50%;transform:translate3d(0px,-50%,0)}.swiper-pagination-vertical.swiper-pagination-bullets .swiper-pagination-bullet,.swiper-vertical>.swiper-pagination-bullets .swiper-pagination-bullet{margin:var(--swiper-pagination-bullet-vertical-gap,6px) 0;display:block}.swiper-pagination-vertical.swiper-pagination-bullets.swiper-pagination-bullets-dynamic,.swiper-vertical>.swiper-pagination-bullets.swiper-pagination-bullets-dynamic{top:50%;transform:translateY(-50%);width:8px}.swiper-pagination-vertical.swiper-pagination-bullets.swiper-pagination-bullets-dynamic .swiper-pagination-bullet,.swiper-vertical>.swiper-pagination-bullets.swiper-pagination-bullets-dynamic .swiper-pagination-bullet{display:inline-block;transition:.2s transform,.2s top}.swiper-horizontal>.swiper-pagination-bullets .swiper-pagination-bullet,.swiper-pagination-horizontal.swiper-pagination-bullets .swiper-pagination-bullet{margin:0 var(--swiper-pagination-bullet-horizontal-gap,4px)}.swiper-horizontal>.swiper-pagination-bullets.swiper-pagination-bullets-dynamic,.swiper-pagination-horizontal.swiper-pagination-bullets.swiper-pagination-bullets-dynamic{left:50%;transform:translateX(-50%);white-space:nowrap}.swiper-horizontal>.swiper-pagination-bullets.swiper-pagination-bullets-dynamic .swiper-pagination-bullet,.swiper-pagination-horizontal.swiper-pagination-bullets.swiper-pagination-bullets-dynamic .swiper-pagination-bullet{transition:.2s transform,.2s left}.swiper-horizontal.swiper-rtl>.swiper-pagination-bullets-dynamic .swiper-pagination-bullet{transition:.2s transform,.2s right}.swiper-pagination-progressbar{background:rgba(0,0,0,.25);position:absolute}.swiper-pagination-progressbar .swiper-pagination-progressbar-fill{background:var(--swiper-pagination-color,var(--swiper-theme-color));position:absolute;left:0;top:0;width:100%;height:100%;transform:scale(0);transform-origin:left top}.swiper-rtl .swiper-pagination-progressbar .swiper-pagination-progressbar-fill{transform-origin:right top}.swiper-horizontal>.swiper-pagination-progressbar,.swiper-pagination-progressbar.swiper-pagination-horizontal,.swiper-pagination-progressbar.swiper-pagination-vertical.swiper-pagination-progressbar-opposite,.swiper-vertical>.swiper-pagination-progressbar.swiper-pagination-progressbar-opposite{width:100%;height:4px;left:0;top:0}.swiper-horizontal>.swiper-pagination-progressbar.swiper-pagination-progressbar-opposite,.swiper-pagination-progressbar.swiper-pagination-horizontal.swiper-pagination-progressbar-opposite,.swiper-pagination-progressbar.swiper-pagination-vertical,.swiper-vertical>.swiper-pagination-progressbar{width:4px;height:100%;left:0;top:0}.swiper-pagination-lock{display:none}.swiper-scrollbar{border-radius:10px;position:relative;-ms-touch-action:none;background:rgba(0,0,0,.1)}.swiper-scrollbar-disabled>.swiper-scrollbar,.swiper-scrollbar.swiper-scrollbar-disabled{display:none!important}.swiper-horizontal>.swiper-scrollbar,.swiper-scrollbar.swiper-scrollbar-horizontal{position:absolute;left:1%;bottom:3px;z-index:50;height:5px;width:98%}.swiper-scrollbar.swiper-scrollbar-vertical,.swiper-vertical>.swiper-scrollbar{position:absolute;right:3px;top:1%;z-index:50;width:5px;height:98%}.swiper-scrollbar-drag{height:100%;width:100%;position:relative;background:rgba(0,0,0,.5);border-radius:10px;left:0;top:0}.swiper-scrollbar-cursor-drag{cursor:move}.swiper-scrollbar-lock{display:none}.swiper-zoom-container{width:100%;height:100%;display:flex;justify-content:center;align-items:center;text-align:center}.swiper-zoom-container>canvas,.swiper-zoom-container>img,.swiper-zoom-container>svg{max-width:100%;max-height:100%;object-fit:contain}.swiper-slide-zoomed{cursor:move}.swiper-lazy-preloader{width:42px;height:42px;position:absolute;left:50%;top:50%;margin-left:-21px;margin-top:-21px;z-index:10;transform-origin:50%;box-sizing:border-box;border:4px solid var(--swiper-preloader-color,var(--swiper-theme-color));border-radius:50%;border-top-color:transparent}.swiper-watch-progress .swiper-slide-visible .swiper-lazy-preloader,.swiper:not(.swiper-watch-progress) .swiper-lazy-preloader{animation:swiper-preloader-spin 1s infinite linear}.swiper-lazy-preloader-white{--swiper-preloader-color:#fff}.swiper-lazy-preloader-black{--swiper-preloader-color:#000}@keyframes swiper-preloader-spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.swiper .swiper-notification{position:absolute;left:0;top:0;pointer-events:none;opacity:0;z-index:-1000}.swiper-free-mode>.swiper-wrapper{transition-timing-function:ease-out;margin:0 auto}.swiper-grid>.swiper-wrapper{flex-wrap:wrap}.swiper-grid-column>.swiper-wrapper{flex-wrap:wrap;flex-direction:column}.swiper-fade.swiper-free-mode .swiper-slide{transition-timing-function:ease-out}.swiper-fade .swiper-slide{pointer-events:none;transition-property:opacity}.swiper-fade .swiper-slide .swiper-slide{pointer-events:none}.swiper-fade .swiper-slide-active,.swiper-fade .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-cube{overflow:visible}.swiper-cube .swiper-slide{pointer-events:none;-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:1;visibility:hidden;transform-origin:0 0;width:100%;height:100%}.swiper-cube .swiper-slide .swiper-slide{pointer-events:none}.swiper-cube.swiper-rtl .swiper-slide{transform-origin:100% 0}.swiper-cube .swiper-slide-active,.swiper-cube .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-cube .swiper-slide-active,.swiper-cube .swiper-slide-next,.swiper-cube .swiper-slide-next+.swiper-slide,.swiper-cube .swiper-slide-prev{pointer-events:auto;visibility:visible}.swiper-cube .swiper-slide-shadow-bottom,.swiper-cube .swiper-slide-shadow-left,.swiper-cube .swiper-slide-shadow-right,.swiper-cube .swiper-slide-shadow-top{z-index:0;-webkit-backface-visibility:hidden;backface-visibility:hidden}.swiper-cube .swiper-cube-shadow{position:absolute;left:0;bottom:0px;width:100%;height:100%;opacity:.6;z-index:0}.swiper-cube .swiper-cube-shadow:before{content:'';background:#000;position:absolute;left:0;top:0;bottom:0;right:0;filter:blur(50px)}.swiper-flip{overflow:visible}.swiper-flip .swiper-slide{pointer-events:none;-webkit-backface-visibility:hidden;backface-visibility:hidden;z-index:1}.swiper-flip .swiper-slide .swiper-slide{pointer-events:none}.swiper-flip .swiper-slide-active,.swiper-flip .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-flip .swiper-slide-shadow-bottom,.swiper-flip .swiper-slide-shadow-left,.swiper-flip .swiper-slide-shadow-right,.swiper-flip .swiper-slide-shadow-top{z-index:0;-webkit-backface-visibility:hidden;backface-visibility:hidden}.swiper-creative .swiper-slide{-webkit-backface-visibility:hidden;backface-visibility:hidden;overflow:hidden;transition-property:transform,opacity,height}.swiper-cards{overflow:visible}.swiper-cards .swiper-slide{transform-origin:center bottom;-webkit-backface-visibility:hidden;backface-visibility:hidden;overflow:hidden}
--------------------------------------------------------------------------------
/src/js/animaitons.js:
--------------------------------------------------------------------------------
1 | import Dom from './dom.js'
2 | import UserCity from './userCity.js'
3 | // classes
4 | const dom = new Dom()
5 | const userCity = new UserCity()
6 |
7 |
8 | class Animations {
9 |
10 | /* -------------------
11 | first page select city
12 | -------------------- */
13 | firstPageSelectCity() {
14 | const userData = userCity.checkLocalStorage();
15 | if (userData === null) {
16 |
17 | dom.removeClassTimeOut(
18 | ".select_first_city--first_page",
19 | 200,
20 | "animate_bottom"
21 | );
22 | dom.removeClassTimeOut(
23 | ".select_first_city--first_page .body--image",
24 | 300,
25 | "animate_bottom"
26 | );
27 | dom.removeClassTimeOut(
28 | ".select_first_city--first_page .body--texts h1",
29 | 450,
30 | "animate_bottom"
31 | );
32 | dom.removeClassTimeOut(
33 | ".select_first_city--first_page .body--texts p",
34 | 650,
35 | "animate_bottom"
36 | );
37 | dom.removeClassTimeOut(
38 | ".select_first_city--first_page .body--texts button",
39 | 800,
40 | "animate_bottom"
41 | );
42 | }
43 | }
44 | /* -------------------
45 | Switch in First page and Select City Page
46 | -------------------- */
47 | switchFirstPageAndSelectCityPage() {
48 | // Hidden First Page
49 | dom.addClassTimeOut(
50 | ".select_first_city--first_page .body--image",
51 | 150,
52 | "animate_top"
53 | );
54 | dom.addClassTimeOut(
55 | ".select_first_city--first_page .body--texts h1",
56 | 300,
57 | "animate_top"
58 | );
59 | dom.addClassTimeOut(
60 | ".select_first_city--first_page .body--texts p",
61 | 350,
62 | "animate_top"
63 | );
64 | dom.addClassTimeOut(
65 | ".select_first_city--first_page .body--texts button",
66 | 450,
67 | "animate_top"
68 | );
69 | dom.addClassTimeOut(".select_first_city--first_page", 500, "animate_top");
70 | dom.addClassTimeOut(".select_first_city--first_page", 980, "hidden");
71 |
72 | // Show Select Cite Page
73 |
74 | dom.removeClassTimeOut(
75 | ".select_first_city--selectbox",
76 | 850,
77 | "animate_bottom"
78 | );
79 | dom.removeClassTimeOut(".select_first_city--selectbox", 800, "invisible");
80 | dom.removeClassTimeOut(
81 | ".select_first_city--selectbox .selectbox--image",
82 | 700,
83 | "animate_bottom"
84 | );
85 | dom.removeClassTimeOut(
86 | ".select_first_city--selectbox .selectbox--founded_city_with_ip",
87 | 850,
88 | "animate_bottom"
89 | );
90 | dom.removeClassTimeOut(
91 | ".select_first_city--selectbox .selectbox--founded_city_with_ip .buttons",
92 | 900,
93 | "animate_bottom"
94 | );
95 | }
96 | /* -------------------
97 | Open Select city options
98 | -------------------- */
99 | openSelectCityOptions() {
100 | // Hidde Automatic founded city with ip
101 | dom.addClass('.select_first_city--selectbox .selectbox--image', 'sm')
102 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--founded_city_with_ip', 50, "animate_top")
103 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--founded_city_with_ip', 50, "h-0")
104 |
105 | // Showing Select city options
106 | // default citeis
107 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--default_cities', 5, 'hidden')
108 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--default_cities', 5, 'h-0')
109 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--default_cities', 100, 'invisible')
110 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--default_cities', 150, 'animate_bottom')
111 | // line
112 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--line', 50, 'h-0')
113 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--line', 50, 'flex')
114 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--line', 55, 'hidden')
115 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--line', 200, 'invisible')
116 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--line', 250, 'animate_bottom')
117 | // custom city
118 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--custom_city', 100, 'h-0')
119 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--custom_city', 105, 'hidden')
120 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--custom_city', 300, 'invisible')
121 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--custom_city', 350, 'animate_bottom')
122 | // submit button
123 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--continue-btn', 150, 'h-0')
124 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--continue-btn', 155, 'hidden')
125 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--continue-btn', 350, 'invisible')
126 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--continue-btn', 450, 'animate_bottom')
127 | // back button
128 | dom.removeClassTimeOut('#first_city--back_btn', 150, 'invisible')
129 | dom.removeClassTimeOut('#first_city--back_btn', 155, 'animate_left')
130 | }
131 | /* -------------------
132 | Close Select city options
133 | -------------------- */
134 | closeSelectCityOptions() {
135 | // Show Automatic founded city with ip
136 | dom.removeClass('.select_first_city--selectbox .selectbox--image', 'sm')
137 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--founded_city_with_ip', 600, "animate_top")
138 | dom.removeClassTimeOut('.select_first_city--selectbox .selectbox--founded_city_with_ip', 620, "h-0");
139 |
140 | // Hidde Select city options
141 | // default citeis
142 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--default_cities', 250, 'animate_bottom')
143 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--default_cities', 650, 'invisible')
144 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--default_cities', 680, 'h-0')
145 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--default_cities', 690, 'hidden')
146 | // line
147 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--line', 200, 'animate_bottom')
148 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--line', 600, 'invisible')
149 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--line', 620, 'h-0')
150 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--line', 640, 'hidden')
151 | // custom city
152 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--custom_city', 100, 'animate_bottom')
153 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--custom_city', 500, 'invisible')
154 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--custom_city', 520, 'h-0')
155 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--custom_city', 545, 'hidden')
156 | // submit button
157 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--continue-btn', 1, 'animate_bottom')
158 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--continue-btn', 300, 'invisible')
159 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--continue-btn', 320, 'h-0')
160 | dom.addClassTimeOut('.select_first_city--selectbox .selectbox--continue-btn', 340, 'hidden')
161 | // back button
162 | dom.addClassTimeOut('#first_city--back_btn', 380, 'invisible')
163 | dom.addClassTimeOut('#first_city--back_btn', 1, 'animate_left')
164 | }
165 | /* -------------------
166 | Open Change First city Form
167 | -------------------- */
168 | }
169 |
170 |
171 |
172 |
173 |
174 | export default Animations
--------------------------------------------------------------------------------
/src/js/app.js:
--------------------------------------------------------------------------------
1 | import Dom from "./dom.js";
2 | import UserCity from "./userCity.js";
3 | import Animations from "./animaitons.js";
4 | import Theme from "./theme.js";
5 | // classes
6 | const dom = new Dom();
7 | const userCity = new UserCity();
8 | const theme = new Theme();
9 | const animations = new Animations();
10 |
11 | // Evenetlisteners
12 | document.addEventListener("DOMContentLoaded", eventlisteners);
13 | function eventlisteners() {
14 | // Run background hidden closer popups
15 | dom.backgroundHidden()
16 | // Run animations
17 | animations.firstPageSelectCity();
18 | // Switch first page to select city page
19 | document
20 | .querySelector(".select_first_city--first_page .body--texts button")
21 | .addEventListener("click", animations.switchFirstPageAndSelectCityPage);
22 | // Switch Theme Button ---- Dark and light
23 | document.querySelector('#switcher_btn').addEventListener('click', themeSwitcher)
24 | // Run change city
25 | document.querySelector('#change_city_popup_button').addEventListener('click', dom.openChangeCityPopup)
26 | // Run them switcher menu -- theme selector
27 | theme.themeChengerBtn();
28 | // Close change city popup with Back button
29 | document.querySelector('#change_city_popup .back-btn').addEventListener('click', dom.closeChangeCityPopup)
30 | // Close change city Form with Back button
31 | document.querySelector('#change_city_form .back-btn').addEventListener('click', () => {
32 | dom.closeChangeCityForm()
33 | dom.resetChangeCityForm()
34 | });
35 | // Submit change cityu form
36 | document.querySelector('#change_city_form #submit-form').addEventListener('click', (event) => userCity.submitChangeCityForm(event))
37 | //
38 | document.querySelector('#secondeCity .add-city-button').addEventListener('click', dom.openChangeCityPopup)
39 | }
40 |
41 | /*-------------------
42 | Functions
43 | -------------------*/
44 | // Automatic Show Pages
45 | showPages();
46 | function showPages() {
47 | const userCityData = userCity.checkLocalStorage();
48 | if (userCityData !== null) {
49 | dom.showApp();
50 | } else {
51 | userCity.accessUserCityWithIp();
52 | dom.showFirstPage();
53 | openSelectCity();
54 | userCity.setCityToloaclstorage();
55 | }
56 | }
57 |
58 |
59 | // Open select City And run select box
60 | function openSelectCity() {
61 | // variables
62 | const wrongBtn = document.querySelector("#wrong_btn"),
63 | trueBtn = document.querySelector("#true_btn"),
64 | backBtn = document.querySelector("#first_city--back_btn");
65 | // ***------*** Eventlisteners ***------***
66 | // Open Select options
67 | wrongBtn.addEventListener("click", () => {
68 | animations.openSelectCityOptions();
69 | // run select city form
70 | userCity.selectCity();
71 | });
72 | // Open App page
73 | trueBtn.addEventListener('click', () => {
74 | // set auto city to user city
75 | const autoCity = localStorage.getItem('autoUserCity');
76 | localStorage.setItem('userCity', autoCity)
77 | localStorage.removeItem('autoUserCity');
78 | // show and run app
79 | dom.removeClass('#loading', 'hidde')
80 | dom.showApp()
81 | })
82 | // Close Select options
83 | backBtn.addEventListener('click', () => animations.closeSelectCityOptions())
84 |
85 | }
86 |
87 |
88 | // Open Switch Theme Menu ---- just opn it
89 | function themeSwitcher() {
90 | const menu = document.querySelector('#switcher_menu'),
91 | bgSection = document.querySelector('#hidden_background_section'),
92 | app = document.querySelector('#app');
93 |
94 | // open themes menu
95 | menu.classList.add('active');
96 | bgSection.classList.add('active');
97 | app.classList.add('blur');
98 | }
99 |
100 |
101 | // change City popup -----
102 | (async function() {
103 | ///------- add eventlisteners on inner sections (open first and seconde forms)
104 | const changeFirstCityBtn = document.querySelector('#change-first-city-button'),
105 | changeSecondeCityBtn = document.querySelector('#change-seconde-city-button')
106 | changeFirstCityBtn.addEventListener('click', dom.openChangeFirstCityForm);
107 | changeSecondeCityBtn.addEventListener('click', dom.openChangeSecondeCityForm);
108 |
109 |
110 | ///------ validation and submit form
111 | const customCityInput = document.querySelector('#change_city_form #custom-city'),
112 | defaultCitiesInput = document.querySelector('#change_city_form #default-cities'),
113 | submitBtn = document.querySelector('#change_city_form #submit-form');
114 |
115 | // chack custom city
116 | customCityInput.addEventListener('input', () => {
117 | // text validation
118 | const isValidCoustomCity = dom.changeCityFormValidation(customCityInput.value);
119 | /// cleare default city input
120 | if(defaultCitiesInput.value !== 'null'){
121 | // clear default city value
122 | defaultCitiesInput.value = 'null';
123 | }
124 | // Active and deActive submit btn
125 | if(isValidCoustomCity == true && defaultCitiesInput.value == 'null'){
126 | activeSubmitButton()
127 | }else{
128 | deActivateSubmitButton()
129 | }
130 |
131 | })
132 |
133 | // chack default city
134 | defaultCitiesInput.addEventListener('change', () => {
135 | if(customCityInput.value === '' && defaultCitiesInput.value == 'null'){
136 | deActivateSubmitButton();
137 | }else if(customCityInput.value !== 'null'){
138 | customCityInput.value = '';
139 | activeSubmitButton();
140 | }
141 | });
142 |
143 | // Active submit button
144 | function activeSubmitButton(){
145 | submitBtn.classList.add('active');
146 | submitBtn.removeAttribute('disabled');
147 | }
148 |
149 | // deActivate submit button
150 | function deActivateSubmitButton(){
151 | submitBtn.classList.remove('active');
152 | submitBtn.setAttribute('disabled', true);
153 | }
154 | })()
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/src/js/dom.js:
--------------------------------------------------------------------------------
1 | import GetApis from "./getApis.js";
2 | import Theme from "./theme.js";
3 | import WeatherApp from "./weatherApp.js";
4 | const theme = new Theme();
5 | const weatherApp = new WeatherApp();
6 | const getApis = new GetApis();
7 |
8 |
9 | class Dom {
10 | removeClassTimeOut(elementId, time, classValue) {
11 | const selectedElement = document.querySelector(elementId);
12 | setTimeout(() => {
13 | selectedElement.classList.remove(classValue);
14 | }, time);
15 | }
16 | removeClass(elementId, classValue) {
17 | const selectedElement = document.querySelector(elementId);
18 | selectedElement.classList.remove(classValue);
19 | }
20 | addClassTimeOut(elementId, time, classValue) {
21 | const selectedElement = document.querySelector(elementId);
22 | setTimeout(() => {
23 | selectedElement.classList.add(classValue);
24 | }, time);
25 | }
26 | addClass(elementId, classValue) {
27 | const selectedElement = document.querySelector(elementId);
28 | selectedElement.classList.add(classValue);
29 | }
30 |
31 | // Show APP Page
32 | async showApp() {
33 | // show app page
34 | this.removeClassTimeOut("#app", 300, "hidden");
35 | // set theme
36 | theme.firstLoadSetTheme()
37 | // hidde loading
38 | this.addClassTimeOut("#loading", 500, "hidde");
39 | // hidde first select city page
40 | this.addClass("#select_first_city", "hidden");
41 |
42 | //---- Run first city
43 | // Access to user city from LS
44 | const userCityName = localStorage.getItem('userCity').toLowerCase();
45 | // check response error
46 | try {
47 | // access response
48 | const response = await getApis.getWeather(userCityName);
49 | this.runApp(response)
50 | this.addClassTimeOut("#select_first_city", 100, "hidden");
51 | } catch (error) {
52 | this.showVpnError()
53 | }
54 |
55 | //---- Run seconde city
56 | // Access to seconde city from LS
57 | const secondeCity = localStorage.getItem('secondeCity');
58 | if(secondeCity !== null){
59 | weatherApp.runSecondeCity()
60 | }else{
61 | this.removeClass('#add-city-button', 'hidden')
62 | }
63 |
64 | }
65 | // Show First page and select city
66 | showFirstPage() {
67 | this.addClassTimeOut("#loading", 300, "hidde");
68 | this.addClass("#select_first_city", "flex");
69 | this.removeClass("#select_first_city", "hidden");
70 | }
71 | // Show Message
72 | showMessage(message = "default message", icon = "info", colorClass = 'success') {
73 | // access message box
74 | const messageBox = document.querySelector("#message_box");
75 | // create message tag
76 | const messageTag = document.createElement('div');
77 | messageTag.classList = `message ${colorClass} duration-700 invisible animate_bottom`;
78 | messageTag.innerHTML = `
79 |
80 |
81 |
82 | ${message}
83 |
84 |
85 | `;
86 | // apeend and show message
87 | messageBox.appendChild(messageTag)
88 | messageTag.classList.remove('invisible')
89 | // slide on
90 | setTimeout(() => {
91 | messageTag.classList.remove('animate_bottom')
92 | }, 100);
93 | // slide out
94 | setTimeout(() => {
95 | messageTag.classList.add('animate_top')
96 | }, 5000);
97 | // romowe from DOM
98 | setTimeout(() => {
99 | messageTag.remove()
100 | }, 5500);
101 | }
102 | // Run and create app
103 | runApp(data) {
104 | localStorage.setItem('weather', JSON.stringify(data));
105 | weatherApp.setDateAndTime();
106 |
107 |
108 | // Access to the weather data
109 | const weatherData = data.list;
110 |
111 | weatherApp.setRealtimeWeather(weatherData[0]);
112 | weatherApp.nextHours(weatherData);
113 |
114 | // Remove loading frame classes
115 | weatherApp.removeLoadingFrame('main_weather');
116 | weatherApp.removeLoadingFrame('more_data_section');
117 | }
118 | // Background hiddden Closer popups
119 | backgroundHidden() {
120 | const bg = document.querySelector('#hidden_background_section');
121 | // access to elements for closeing
122 | const app = document.querySelector('#app'),
123 | themeSwitcherMenu = document.querySelector('#switcher_menu'),
124 | changeCityPopup = document.querySelector('#change_city_popup'),
125 | changeCityForm = document.querySelector('#change_city_form')
126 | bg.addEventListener('click', () => {
127 | // Close Theme Switcher
128 | if (themeSwitcherMenu.classList.contains('active')) {
129 | app.classList.remove('blur');
130 | themeSwitcherMenu.classList.remove('active');
131 | bg.classList.remove('active')
132 | } else if (changeCityPopup.classList.contains('active')) {
133 | app.classList.remove('blur');
134 | changeCityPopup.classList.remove('active');
135 | bg.classList.remove('active')
136 | } else if (changeCityForm.classList.contains('active')) {
137 | changeCityForm.classList.remove('active');
138 | changeCityPopup.classList.add('active')
139 | this.resetChangeCityForm()
140 | }
141 | })
142 | }
143 | // Show Vpn error
144 | showVpnError() {
145 | // access to the Elements
146 | const appElem = document.querySelector('#app'),
147 | selectFirstCityElem = document.querySelector('#select_first_city'),
148 | vpnErrorElem = document.querySelector('#vpn_error'),
149 | errorTextBox = vpnErrorElem.querySelector('#error-text');
150 |
151 | // Blur bg
152 | appElem.classList.add('blur');
153 | selectFirstCityElem.classList.add('blur');
154 |
155 | // Show error
156 | vpnErrorElem.classList.add('active');
157 | setTimeout(() => {
158 | errorTextBox.classList.remove('animate_bottom')
159 | }, 500);
160 | }
161 | /*---------------------------
162 | Chnage city Popup and form
163 | ---------------------------*/
164 | openChangeCityPopup() {
165 | // Access to the Elements
166 | const changeCityPopup = document.querySelector('#change_city_popup'),
167 | backgroundSection = document.querySelector('#hidden_background_section'),
168 | app = document.querySelector('#app');
169 |
170 | // Open it
171 | backgroundSection.classList.add('active')
172 | app.classList.add('blur');
173 | changeCityPopup.classList.add('active');
174 | }
175 | openChangeFirstCityForm() {
176 | // Access to Elements
177 | const form = document.querySelector('#change_city_form'),
178 | popup = document.querySelector('#change_city_popup'),
179 | title = form.querySelector('.title');
180 |
181 | // Open it
182 | form.classList.add('active')
183 | popup.classList.remove('active')
184 | title.children[0].classList.add('indigo')
185 | title.children[1].innerHTML = 'Change your city';
186 |
187 | // Set Form Status
188 | form.setAttribute('form-status', 'firstCity')
189 | }
190 | openChangeSecondeCityForm() {
191 | // Access to Elements
192 | const form = document.querySelector('#change_city_form'),
193 | popup = document.querySelector('#change_city_popup'),
194 | title = form.querySelector('.title');
195 |
196 | // Open it
197 | form.classList.add('active')
198 | popup.classList.remove('active')
199 | title.children[0].classList.add('purple')
200 | title.children[1].innerHTML = 'Add or change seconde city';
201 |
202 | // Set Form Status
203 | form.setAttribute('form-status', 'secondeCity')
204 | }
205 | closeChangeCityPopup() {
206 | // Access to Elements
207 | const changeCityPopup = document.querySelector('#change_city_popup'),
208 | backgroundSection = document.querySelector('#hidden_background_section'),
209 | app = document.querySelector('#app');
210 | // close it
211 | backgroundSection.classList.remove('active')
212 | app.classList.remove('blur');
213 | changeCityPopup.classList.remove('active')
214 | }
215 | closeChangeCityForm() {
216 | // Access to Elements
217 | const changeCityPopup = document.querySelector('#change_city_popup'),
218 | changeCityForm = document.querySelector('#change_city_form');
219 |
220 | // close it
221 | changeCityPopup.classList.add('active')
222 | changeCityForm.classList.remove('active')
223 | }
224 | resetChangeCityForm() {
225 | const formElement = document.querySelector('#change_city_form'),
226 | customCityInput = formElement.querySelector('#custom-city'),
227 | defaultCiteisInput = formElement.querySelector('#default-cities'),
228 | title = formElement.querySelector('.title'),
229 | submitBtn = document.querySelector('#change_city_form #submit-form');
230 |
231 |
232 | customCityInput.value = '';
233 | defaultCiteisInput.value = 'null';
234 | formElement.setAttribute('form-status', 'null');
235 | submitBtn.classList.remove('active');
236 | submitBtn.setAttribute('disabled', true);
237 |
238 | if (title.children[0].classList.contains('purple')) {
239 | title.children[0].classList.remove('purple')
240 | } else if (title.children[0].classList.contains('indigo')) {
241 | title.children[0].classList.remove('indigo')
242 | }
243 | }
244 | changeCityFormValidation(value){
245 | // create regEx Pattern
246 | const pattern = /\s|[1-9]|[!@#$%^&.*()_+]/g;
247 |
248 | // validation
249 | if(value.length < 3){
250 | return false
251 | }else if(value.match(pattern)){
252 | return false;
253 | }else{
254 | return true;
255 | }
256 | }
257 |
258 |
259 |
260 | }
261 |
262 | export default Dom;
263 |
--------------------------------------------------------------------------------
/src/js/getApis.js:
--------------------------------------------------------------------------------
1 | class GetApis{
2 | async findIcon(weather){
3 |
4 | // Access to time
5 | let currentHour = weather.dt_txt;
6 | currentHour = currentHour.split(' ')
7 | const time = currentHour[1].slice(0, 2);
8 |
9 | let currentStatus = '';
10 |
11 | // Gain status
12 | if(time >= '06' && time <= '19' ){
13 | currentStatus = 'day'
14 | }else {
15 | currentStatus = 'night'
16 | }
17 |
18 | // Create icon link
19 | let icon = weather.weather[0].main;
20 | icon = icon.toLowerCase()
21 | icon = `./src/assets/images/weather/${icon}_${currentStatus}.webp`;
22 |
23 | return icon;
24 | }
25 |
26 | async getTime(){
27 | // Access to user city
28 | const userCity = localStorage.getItem('userCity');
29 |
30 | // base url and api key
31 | const url = 'https://api.ipgeolocation.io/timezone?apiKey=';
32 | const key = '05eb684275634618a6ef2f613715aef8';
33 |
34 |
35 | // Get Date and time from Api
36 | const apiResponse = fetch(`${url}${key}&location=${userCity}`,{
37 | headers: { 'X-Api-Key': key},
38 | contentType: 'application/json',
39 | }).then(res => {
40 | return res.json()
41 | }).catch(error => {
42 | console.log(error);
43 | })
44 |
45 |
46 | // Extract time from api
47 | let timeData = await apiResponse;
48 | timeData = timeData.time_24;
49 |
50 | timeData = timeData.split(':')
51 | timeData = {
52 | hour: timeData[0],
53 | minute: timeData[1],
54 | second: timeData[2]
55 | }
56 |
57 |
58 | //Extract Date data from api
59 | ///// Day name
60 | let dayName = await apiResponse;
61 | dayName = dayNameFinder(dayName);
62 | function dayNameFinder(dayName){
63 | let name = dayName;
64 | name = name.date_time_txt;
65 | name = name.split(',');
66 | name = name[0];
67 | // return name;
68 | return name
69 | }
70 | ///// date
71 | let date = await apiResponse;
72 | date = date.date;
73 |
74 |
75 |
76 |
77 | const completeData = {
78 | watch : timeData ,
79 | dayName,
80 | date
81 | }
82 |
83 |
84 |
85 | return completeData ;
86 | }
87 |
88 | async chackingCoustomCity(city){
89 | const key = '72caee2eff37548de75d5d9674aa2510';
90 | // created url
91 | const url = `http://api.openweathermap.org/data/2.5/forecast?q=${city}&appid=${key}&units=metric`;
92 | // send request
93 | const request = await fetch(url).then((res) => res)
94 | .catch((error) => {
95 | dom.addClass("#loading", "hidde")
96 | console.log(error)
97 | })
98 | .catch((error) => {
99 | dom.addClass("#loading", "hidde")
100 | console.log(error)
101 | })
102 | // access response
103 | const response = await request.json();
104 |
105 | // check response error
106 | if (request.status === 200) {
107 | return true
108 | } else {
109 | return false
110 | }
111 | }
112 |
113 | async getWeather(city){
114 | const key = '72caee2eff37548de75d5d9674aa2510';
115 | // // created url
116 | const url = `http://api.openweathermap.org/data/2.5/forecast?q=${city}&appid=${key}&units=metric`;
117 | // send request
118 | const request = await fetch(url, {method: "GET"}).then((res) => res)
119 | .catch((error) => {
120 | dom.addClass("#loading", "hidde")
121 | console.log(error)
122 | })
123 | .catch((error) => {
124 | dom.addClass("#loading", "hidde")
125 | console.log(error)
126 | })
127 | // access response
128 | const response = await request.json();
129 |
130 | // check response error
131 | if (request.status === 200) {
132 | return response
133 | } else {
134 | return false
135 | }
136 | }
137 |
138 | }
139 |
140 | export default GetApis;
--------------------------------------------------------------------------------
/src/js/json/forecast.json:
--------------------------------------------------------------------------------
1 | {
2 | "cod": "200",
3 | "message": 0,
4 | "cnt": 40,
5 | "list": [
6 | { "dt": 1670619600, "main": { "temp": 5.31, "feels_like": 5.31, "temp_min": 5.31, "temp_max": 5.96, "pressure": 1024, "sea_level": 1024, "grnd_level": 889, "humidity": 63, "temp_kf": -0.65 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }], "clouds": { "all": 54 }, "wind": { "speed": 0.7, "deg": 151, "gust": 0.98 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-09 21:00:00" },
7 | { "dt": 1670630400, "main": { "temp": 5.3, "feels_like": 5.3, "temp_min": 5.3, "temp_max": 5.45, "pressure": 1025, "sea_level": 1025, "grnd_level": 888, "humidity": 61, "temp_kf": -0.15 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }], "clouds": { "all": 55 }, "wind": { "speed": 0.14, "deg": 91, "gust": 0.95 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-10 00:00:00" },
8 | { "dt": 1670641200, "main": { "temp": 5.09, "feels_like": 5.09, "temp_min": 5.09, "temp_max": 5.09, "pressure": 1025, "sea_level": 1025, "grnd_level": 889, "humidity": 59, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }], "clouds": { "all": 73 }, "wind": { "speed": 0.31, "deg": 272, "gust": 0.85 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-10 03:00:00" },
9 | { "dt": 1670652000, "main": { "temp": 5.58, "feels_like": 4.66, "temp_min": 5.58, "temp_max": 5.58, "pressure": 1026, "sea_level": 1026, "grnd_level": 890, "humidity": 59, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], "clouds": { "all": 83 }, "wind": { "speed": 1.46, "deg": 189, "gust": 1.33 }, "visibility": 10000, "pop": 0, "sys": { "pod": "d" }, "dt_txt": "2022-12-10 06:00:00" },
10 | { "dt": 1670662800, "main": { "temp": 6.93, "feels_like": 5.99, "temp_min": 6.93, "temp_max": 6.93, "pressure": 1024, "sea_level": 1024, "grnd_level": 888, "humidity": 52, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], "clouds": { "all": 82 }, "wind": { "speed": 1.64, "deg": 200, "gust": 1.27 }, "visibility": 10000, "pop": 0.02, "sys": { "pod": "d" }, "dt_txt": "2022-12-10 09:00:00" },
11 | { "dt": 1670673600, "main": { "temp": 7.62, "feels_like": 6.65, "temp_min": 7.62, "temp_max": 7.62, "pressure": 1022, "sea_level": 1022, "grnd_level": 887, "humidity": 48, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], "clouds": { "all": 67 }, "wind": { "speed": 1.76, "deg": 204, "gust": 1.16 }, "visibility": 10000, "pop": 0.02, "sys": { "pod": "d" }, "dt_txt": "2022-12-10 12:00:00" },
12 | { "dt": 1670684400, "main": { "temp": 6.89, "feels_like": 6.07, "temp_min": 6.89, "temp_max": 6.89, "pressure": 1023, "sea_level": 1023, "grnd_level": 888, "humidity": 51, "temp_kf": 0 }, "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03n" }], "clouds": { "all": 34 }, "wind": { "speed": 1.53, "deg": 208, "gust": 1.22 }, "visibility": 10000, "pop": 0.22, "sys": { "pod": "n" }, "dt_txt": "2022-12-10 15:00:00" },
13 | { "dt": 1670695200, "main": { "temp": 6.24, "feels_like": 6.24, "temp_min": 6.24, "temp_max": 6.24, "pressure": 1024, "sea_level": 1024, "grnd_level": 889, "humidity": 54, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }], "clouds": { "all": 60 }, "wind": { "speed": 1.01, "deg": 211, "gust": 1.12 }, "visibility": 10000, "pop": 0.15, "sys": { "pod": "n" }, "dt_txt": "2022-12-10 18:00:00" },
14 | { "dt": 1670706000, "main": { "temp": 5.74, "feels_like": 5.74, "temp_min": 5.74, "temp_max": 5.74, "pressure": 1025, "sea_level": 1025, "grnd_level": 889, "humidity": 56, "temp_kf": 0 }, "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], "clouds": { "all": 97 }, "wind": { "speed": 0.33, "deg": 249, "gust": 0.74 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-10 21:00:00" },
15 | { "dt": 1670716800, "main": { "temp": 5.32, "feels_like": 5.32, "temp_min": 5.32, "temp_max": 5.32, "pressure": 1025, "sea_level": 1025, "grnd_level": 888, "humidity": 56, "temp_kf": 0 }, "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], "clouds": { "all": 98 }, "wind": { "speed": 0.8, "deg": 250, "gust": 0.94 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-11 00:00:00" },
16 | { "dt": 1670727600, "main": { "temp": 4.9, "feels_like": 4.9, "temp_min": 4.9, "temp_max": 4.9, "pressure": 1025, "sea_level": 1025, "grnd_level": 889, "humidity": 57, "temp_kf": 0 }, "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], "clouds": { "all": 92 }, "wind": { "speed": 0.95, "deg": 288, "gust": 1.16 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-11 03:00:00" },
17 | { "dt": 1670738400, "main": { "temp": 5.88, "feels_like": 5.88, "temp_min": 5.88, "temp_max": 5.88, "pressure": 1026, "sea_level": 1026, "grnd_level": 890, "humidity": 54, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], "clouds": { "all": 67 }, "wind": { "speed": 0.97, "deg": 222, "gust": 0.93 }, "visibility": 10000, "pop": 0, "sys": { "pod": "d" }, "dt_txt": "2022-12-11 06:00:00" },
18 | { "dt": 1670749200, "main": { "temp": 7.19, "feels_like": 6.06, "temp_min": 7.19, "temp_max": 7.19, "pressure": 1024, "sea_level": 1024, "grnd_level": 889, "humidity": 49, "temp_kf": 0 }, "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03d" }], "clouds": { "all": 47 }, "wind": { "speed": 1.85, "deg": 221, "gust": 1.42 }, "visibility": 10000, "pop": 0, "sys": { "pod": "d" }, "dt_txt": "2022-12-11 09:00:00" },
19 | { "dt": 1670760000, "main": { "temp": 7.76, "feels_like": 6.59, "temp_min": 7.76, "temp_max": 7.76, "pressure": 1022, "sea_level": 1022, "grnd_level": 888, "humidity": 46, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], "clouds": { "all": 56 }, "wind": { "speed": 1.99, "deg": 229, "gust": 1.73 }, "visibility": 10000, "pop": 0.08, "sys": { "pod": "d" }, "dt_txt": "2022-12-11 12:00:00" },
20 | { "dt": 1670770800, "main": { "temp": 7.08, "feels_like": 6.31, "temp_min": 7.08, "temp_max": 7.08, "pressure": 1023, "sea_level": 1023, "grnd_level": 888, "humidity": 49, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }], "clouds": { "all": 53 }, "wind": { "speed": 1.51, "deg": 233, "gust": 1.56 }, "visibility": 10000, "pop": 0.19, "sys": { "pod": "n" }, "dt_txt": "2022-12-11 15:00:00" },
21 | { "dt": 1670781600, "main": { "temp": 6.45, "feels_like": 6.45, "temp_min": 6.45, "temp_max": 6.45, "pressure": 1023, "sea_level": 1023, "grnd_level": 888, "humidity": 52, "temp_kf": 0 }, "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03n" }], "clouds": { "all": 47 }, "wind": { "speed": 0.81, "deg": 230, "gust": 1.28 }, "visibility": 10000, "pop": 0.03, "sys": { "pod": "n" }, "dt_txt": "2022-12-11 18:00:00" },
22 | { "dt": 1670792400, "main": { "temp": 5.65, "feels_like": 5.65, "temp_min": 5.65, "temp_max": 5.65, "pressure": 1023, "sea_level": 1023, "grnd_level": 887, "humidity": 55, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }], "clouds": { "all": 52 }, "wind": { "speed": 0.61, "deg": 265, "gust": 1.34 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-11 21:00:00" },
23 | { "dt": 1670803200, "main": { "temp": 5.04, "feels_like": 5.04, "temp_min": 5.04, "temp_max": 5.04, "pressure": 1023, "sea_level": 1023, "grnd_level": 887, "humidity": 55, "temp_kf": 0 }, "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03n" }], "clouds": { "all": 49 }, "wind": { "speed": 0.76, "deg": 21, "gust": 0.76 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-12 00:00:00" },
24 | { "dt": 1670814000, "main": { "temp": 4.52, "feels_like": 4.52, "temp_min": 4.52, "temp_max": 4.52, "pressure": 1023, "sea_level": 1023, "grnd_level": 887, "humidity": 53, "temp_kf": 0 }, "weather": [{ "id": 801, "main": "Clouds", "description": "few clouds", "icon": "02n" }], "clouds": { "all": 16 }, "wind": { "speed": 0.75, "deg": 39, "gust": 0.97 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-12 03:00:00" },
25 | { "dt": 1670824800, "main": { "temp": 5.64, "feels_like": 5.64, "temp_min": 5.64, "temp_max": 5.64, "pressure": 1024, "sea_level": 1024, "grnd_level": 888, "humidity": 51, "temp_kf": 0 }, "weather": [{ "id": 801, "main": "Clouds", "description": "few clouds", "icon": "02d" }], "clouds": { "all": 11 }, "wind": { "speed": 1.14, "deg": 140, "gust": 0.91 }, "visibility": 10000, "pop": 0, "sys": { "pod": "d" }, "dt_txt": "2022-12-12 06:00:00" },
26 | { "dt": 1670835600, "main": { "temp": 7.04, "feels_like": 5.83, "temp_min": 7.04, "temp_max": 7.04, "pressure": 1021, "sea_level": 1021, "grnd_level": 886, "humidity": 47, "temp_kf": 0 }, "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03d" }], "clouds": { "all": 26 }, "wind": { "speed": 1.91, "deg": 191, "gust": 1.66 }, "visibility": 10000, "pop": 0, "sys": { "pod": "d" }, "dt_txt": "2022-12-12 09:00:00" },
27 | { "dt": 1670846400, "main": { "temp": 7.58, "feels_like": 6.67, "temp_min": 7.58, "temp_max": 7.58, "pressure": 1019, "sea_level": 1019, "grnd_level": 885, "humidity": 43, "temp_kf": 0 }, "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03d" }], "clouds": { "all": 31 }, "wind": { "speed": 1.7, "deg": 193, "gust": 1.49 }, "visibility": 10000, "pop": 0, "sys": { "pod": "d" }, "dt_txt": "2022-12-12 12:00:00" },
28 | { "dt": 1670857200, "main": { "temp": 6.76, "feels_like": 6.76, "temp_min": 6.76, "temp_max": 6.76, "pressure": 1020, "sea_level": 1020, "grnd_level": 885, "humidity": 47, "temp_kf": 0 }, "weather": [{ "id": 801, "main": "Clouds", "description": "few clouds", "icon": "02n" }], "clouds": { "all": 15 }, "wind": { "speed": 1.32, "deg": 162, "gust": 1.31 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-12 15:00:00" },
29 | { "dt": 1670868000, "main": { "temp": 6.28, "feels_like": 5.35, "temp_min": 6.28, "temp_max": 6.28, "pressure": 1020, "sea_level": 1020, "grnd_level": 885, "humidity": 49, "temp_kf": 0 }, "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03n" }], "clouds": { "all": 31 }, "wind": { "speed": 1.55, "deg": 91, "gust": 2.04 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-12 18:00:00" },
30 | { "dt": 1670878800, "main": { "temp": 5.7, "feels_like": 5.7, "temp_min": 5.7, "temp_max": 5.7, "pressure": 1020, "sea_level": 1020, "grnd_level": 885, "humidity": 49, "temp_kf": 0 }, "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03n" }], "clouds": { "all": 33 }, "wind": { "speed": 1.18, "deg": 71, "gust": 1.7 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-12 21:00:00" },
31 | { "dt": 1670889600, "main": { "temp": 5.92, "feels_like": 5.92, "temp_min": 5.92, "temp_max": 5.92, "pressure": 1020, "sea_level": 1020, "grnd_level": 885, "humidity": 47, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }], "clouds": { "all": 62 }, "wind": { "speed": 0.86, "deg": 41, "gust": 1.07 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-13 00:00:00" },
32 | { "dt": 1670900400, "main": { "temp": 5.46, "feels_like": 5.46, "temp_min": 5.46, "temp_max": 5.46, "pressure": 1021, "sea_level": 1021, "grnd_level": 885, "humidity": 52, "temp_kf": 0 }, "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], "clouds": { "all": 98 }, "wind": { "speed": 0.49, "deg": 285, "gust": 0.62 }, "visibility": 10000, "pop": 0.09, "sys": { "pod": "n" }, "dt_txt": "2022-12-13 03:00:00" },
33 | { "dt": 1670911200, "main": { "temp": 6.11, "feels_like": 6.11, "temp_min": 6.11, "temp_max": 6.11, "pressure": 1022, "sea_level": 1022, "grnd_level": 886, "humidity": 53, "temp_kf": 0 }, "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }], "clouds": { "all": 98 }, "wind": { "speed": 0.73, "deg": 120, "gust": 0.56 }, "visibility": 10000, "pop": 0.09, "sys": { "pod": "d" }, "dt_txt": "2022-12-13 06:00:00" },
34 | { "dt": 1670922000, "main": { "temp": 7.62, "feels_like": 7.13, "temp_min": 7.62, "temp_max": 7.62, "pressure": 1019, "sea_level": 1019, "grnd_level": 885, "humidity": 49, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], "clouds": { "all": 63 }, "wind": { "speed": 1.34, "deg": 211, "gust": 1.58 }, "visibility": 10000, "pop": 0.01, "sys": { "pod": "d" }, "dt_txt": "2022-12-13 09:00:00" },
35 | { "dt": 1670932800, "main": { "temp": 8.75, "feels_like": 7.9, "temp_min": 8.75, "temp_max": 8.75, "pressure": 1018, "sea_level": 1018, "grnd_level": 884, "humidity": 46, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }], "clouds": { "all": 56 }, "wind": { "speed": 1.82, "deg": 232, "gust": 2.15 }, "visibility": 10000, "pop": 0.01, "sys": { "pod": "d" }, "dt_txt": "2022-12-13 12:00:00" },
36 | { "dt": 1670943600, "main": { "temp": 8.12, "feels_like": 8.12, "temp_min": 8.12, "temp_max": 8.12, "pressure": 1019, "sea_level": 1019, "grnd_level": 885, "humidity": 48, "temp_kf": 0 }, "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03n" }], "clouds": { "all": 46 }, "wind": { "speed": 0.93, "deg": 235, "gust": 1.28 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-13 15:00:00" },
37 | { "dt": 1670954400, "main": { "temp": 7.73, "feels_like": 7.73, "temp_min": 7.73, "temp_max": 7.73, "pressure": 1020, "sea_level": 1020, "grnd_level": 885, "humidity": 49, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }], "clouds": { "all": 73 }, "wind": { "speed": 1.2, "deg": 227, "gust": 1.53 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-13 18:00:00" },
38 | { "dt": 1670965200, "main": { "temp": 7.29, "feels_like": 7.29, "temp_min": 7.29, "temp_max": 7.29, "pressure": 1020, "sea_level": 1020, "grnd_level": 885, "humidity": 49, "temp_kf": 0 }, "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }], "clouds": { "all": 100 }, "wind": { "speed": 0.83, "deg": 272, "gust": 1.01 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-13 21:00:00" },
39 | { "dt": 1670976000, "main": { "temp": 6.91, "feels_like": 6.91, "temp_min": 6.91, "temp_max": 6.91, "pressure": 1020, "sea_level": 1020, "grnd_level": 885, "humidity": 50, "temp_kf": 0 }, "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }], "clouds": { "all": 66 }, "wind": { "speed": 0.71, "deg": 316, "gust": 0.96 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-14 00:00:00" },
40 | { "dt": 1670986800, "main": { "temp": 6.73, "feels_like": 6.73, "temp_min": 6.73, "temp_max": 6.73, "pressure": 1020, "sea_level": 1020, "grnd_level": 885, "humidity": 51, "temp_kf": 0 }, "weather": [{ "id": 801, "main": "Clouds", "description": "few clouds", "icon": "02n" }], "clouds": { "all": 22 }, "wind": { "speed": 0.5, "deg": 7, "gust": 0.96 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-14 03:00:00" },
41 | { "dt": 1670997600, "main": { "temp": 8.3, "feels_like": 8.3, "temp_min": 8.3, "temp_max": 8.3, "pressure": 1021, "sea_level": 1021, "grnd_level": 887, "humidity": 46, "temp_kf": 0 }, "weather": [{ "id": 801, "main": "Clouds", "description": "few clouds", "icon": "02d" }], "clouds": { "all": 20 }, "wind": { "speed": 0.6, "deg": 156, "gust": 0.63 }, "visibility": 10000, "pop": 0, "sys": { "pod": "d" }, "dt_txt": "2022-12-14 06:00:00" },
42 | { "dt": 1671008400, "main": { "temp": 10.63, "feels_like": 8.82, "temp_min": 10.63, "temp_max": 10.63, "pressure": 1019, "sea_level": 1019, "grnd_level": 886, "humidity": 41, "temp_kf": 0 }, "weather": [{ "id": 801, "main": "Clouds", "description": "few clouds", "icon": "02d" }], "clouds": { "all": 15 }, "wind": { "speed": 1.44, "deg": 226, "gust": 1.74 }, "visibility": 10000, "pop": 0, "sys": { "pod": "d" }, "dt_txt": "2022-12-14 09:00:00" },
43 | { "dt": 1671019200, "main": { "temp": 11.84, "feels_like": 10.1, "temp_min": 11.84, "temp_max": 11.84, "pressure": 1018, "sea_level": 1018, "grnd_level": 886, "humidity": 39, "temp_kf": 0 }, "weather": [{ "id": 801, "main": "Clouds", "description": "few clouds", "icon": "02d" }], "clouds": { "all": 16 }, "wind": { "speed": 1.81, "deg": 231, "gust": 2.33 }, "visibility": 10000, "pop": 0, "sys": { "pod": "d" }, "dt_txt": "2022-12-14 12:00:00" },
44 | { "dt": 1671030000, "main": { "temp": 10.68, "feels_like": 8.93, "temp_min": 10.68, "temp_max": 10.68, "pressure": 1020, "sea_level": 1020, "grnd_level": 886, "humidity": 43, "temp_kf": 0 }, "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03n" }], "clouds": { "all": 36 }, "wind": { "speed": 0.24, "deg": 227, "gust": 1.1 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-14 15:00:00" },
45 | { "dt": 1671040800, "main": { "temp": 9.68, "feels_like": 9.68, "temp_min": 9.68, "temp_max": 9.68, "pressure": 1020, "sea_level": 1020, "grnd_level": 887, "humidity": 46, "temp_kf": 0 }, "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03n" }], "clouds": { "all": 29 }, "wind": { "speed": 0.33, "deg": 65, "gust": 1.15 }, "visibility": 10000, "pop": 0, "sys": { "pod": "n" }, "dt_txt": "2022-12-14 18:00:00" }
46 | ],
47 | "city": { "id": 112931, "name": "Tehran", "coord": { "lat": 35.6944, "lon": 51.4215 }, "country": "IR", "population": 7153309, "timezone": 12600, "sunrise": 1670556740, "sunset": 1670592060 }
48 | }
49 |
--------------------------------------------------------------------------------
/src/js/json/weather_icons.json:
--------------------------------------------------------------------------------
1 | {
2 | "broken_clouds" : {
3 | "day" : {
4 | "img" : "./src/assets/images/weather/broken_clouds/broken_clouds_day.webp"
5 | },
6 | "night" : {
7 | "img" : "./src/assets/images/weather/broken_clouds/borken_clouds_night.web"
8 | }
9 | },
10 | "clear_sky" : {
11 | "day" : {
12 | "img" : "./src/assets/images/weather/clear_sky/clear_sky_day.webp"
13 | },
14 | "night" : {
15 | "img" : "./src/assets/images/weather/clear_sky/clear_sky_night.webp"
16 | }
17 | },
18 | "few_clouds" : {
19 | "day" : {
20 | "img" : "./src/assets/images/weather/few_clouds/few_clouds_day.webp"
21 | },
22 | "night" : {
23 | "img" : "./src/assets/images/weather/few_clouds/few_clouds_night.webp"
24 | }
25 | },
26 | "mist" : {
27 | "day" : {
28 | "img" : "./src/assets/images/weather/mist/mist_day.webp"
29 | },
30 | "night" : {
31 | "img" : "./src/assets/images/weather/mist/mist_night.webp"
32 | }
33 | },
34 | "scattered_clouds" : {
35 | "day" : {
36 | "img" : "./src/assets/images/weather/scattered_clouds/scattered_clouds_day.webp"
37 | },
38 | "night" : {
39 | "img" : "./src/assets/images/weather/scattered_clouds/scattered_clouds_night.webp"
40 | }
41 | },
42 | "shower_rain" : {
43 | "day" : {
44 | "img" : "./src/assets/images/weather/shower_rain/shower_rain_day.webp"
45 | },
46 | "night" : {
47 | "img" : "./src/assets/images/weather/shower_rain/shower_rain_night.webp"
48 | }
49 | },
50 | "snow" : {
51 | "day" : {
52 | "img" : "./src/assets/images/weather/snow/snow.webp"
53 | },
54 | "night" : {
55 | "img" : "./src/assets/images/weather/snow/snow.webp"
56 | }
57 | },
58 | "thunderstorm" : {
59 | "day" : {
60 | "img" : "./src/assets/images/weather/thunderstorm/thunderstorm_day.webp"
61 | },
62 | "night" : {
63 | "img" : "./src/assets/images/weather/thunderstorm//thunderstorm_night.webp"
64 | }
65 | },
66 | "rain" : {
67 | "day" : {
68 | "img" : "./src/assets/images/weather/rain/rain.webp"
69 | },
70 | "night" : {
71 | "img" : "./src/assets/images/weather/rain/rain.webp"
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/src/js/theme.js:
--------------------------------------------------------------------------------
1 |
2 | class Theme {
3 | // Set app theme affter loading
4 | firstLoadSetTheme(){
5 | const theme = localStorage.getItem('theme');
6 | // First loaded
7 | if(theme === null){
8 | localStorage.setItem('theme', 'auto');
9 | this.setTheme('auto')
10 | }
11 |
12 | // set theme after other loaded
13 | if(theme === 'auto'){
14 | this.setTheme('auto')
15 | }if(theme === 'dark'){
16 | this.setTheme('dark')
17 | }if(theme === 'light'){
18 | this.setTheme('light')
19 | }
20 | }
21 |
22 | // Theme Seter
23 | setTheme(theme){
24 |
25 | if(theme === 'light'){
26 | // set theme to local storage
27 | localStorage.setItem('theme', 'light');
28 | // set theme on app
29 | setLight();
30 | }else if(theme === 'dark'){
31 | // set theme to local storage
32 | localStorage.setItem('theme', 'dark');
33 | // set theme on app
34 | setDark()
35 | }else if(theme === 'auto'){
36 | // set theme to local storage
37 | localStorage.setItem('theme', 'auto');
38 | // set theme on app
39 | const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
40 | if(isDark){
41 | setDark();
42 | }else{
43 | setLight();
44 | }
45 | }
46 | changeSwitcherBtn();
47 |
48 | // Set Light theme
49 | function setLight(){
50 | const body = document.querySelector('body');
51 | body.classList.remove('dark');
52 |
53 | }
54 | // Set Dark theme
55 | function setDark(){
56 | const body = document.querySelector('body');
57 | body.classList.add('dark');
58 | }
59 | // Change switcher btn icon and active current theme
60 | function changeSwitcherBtn () {
61 | const switcherBtn = document.querySelector('#switcher_btn i');
62 | const themeInputs = document.querySelectorAll('#switcher_menu input[name="theme"]');
63 |
64 | // Active input in switcher select menu
65 | if(theme === 'auto'){
66 | themeInputs[2].setAttribute('checked', 'true');
67 | // check auto theme
68 | const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
69 | if(isDark){
70 | switcherBtn.classList = 'icon-night';
71 | }else{
72 | switcherBtn.classList = 'icon-sun';
73 | }
74 | }else
75 | if(theme === 'dark'){
76 | themeInputs[0].setAttribute('checked', 'true');
77 | switcherBtn.classList = 'icon-night';
78 | }else if(theme === 'light'){
79 | themeInputs[1].setAttribute('checked', 'true');
80 | switcherBtn.classList = 'icon-sun';
81 | }
82 | }
83 | }
84 |
85 | // Theme Changer
86 | themeChengerBtn(){
87 | // Theme chenger Button -------------
88 | const menu = document.querySelector('#switcher_menu');
89 | const themeInputs = document.querySelectorAll('#switcher_menu input[name="theme"]');
90 |
91 | themeInputs.forEach((input) => {
92 | input.addEventListener('change', () => {
93 | this.setTheme(input.value);
94 | this.closePopups();
95 | })
96 | })
97 |
98 | // auto change theme
99 | const systemTheme = window.matchMedia("(prefers-color-scheme: dark)");
100 | systemTheme.addEventListener('change', () => {
101 | const themeFromLocal = localStorage.getItem('theme');
102 | if(themeFromLocal === 'auto'){
103 | this.setTheme('auto')
104 | }
105 | })
106 | }
107 |
108 | // Auto close popups
109 | closePopups(){
110 | // access to elements for closeing
111 | const bg = document.querySelector('#hidden_background_section');
112 | const app = document.querySelector('#app'),
113 | themeSwitcherMenu = document.querySelector('#switcher_menu');
114 |
115 | // ****** Close Theme Switcher
116 | if(themeSwitcherMenu.classList.contains('active')){
117 | app.classList.remove('blur');
118 | themeSwitcherMenu.classList.remove('active');
119 | bg.classList.remove('active')
120 | }
121 |
122 | }
123 | }
124 |
125 |
126 | export default Theme;
--------------------------------------------------------------------------------
/src/js/userCity.js:
--------------------------------------------------------------------------------
1 | import Dom from "./dom.js";
2 | import GetApis from "./getApis.js";
3 | const dom = new Dom();
4 | const getApis = new GetApis();
5 |
6 | class UserCity {
7 | // Checking localstorage for exist city
8 | checkLocalStorage() {
9 | const userCity = localStorage.getItem("userCity");
10 | return userCity;
11 | }
12 | // Send request to the api and access to user city with IP v2
13 | accessUserCityWithIp() {
14 | sendRequest();
15 | function sendRequest() {
16 | const url = "https://api.getgeoapi.com/v2/ip/check?api_key=";
17 | const key = "0508976ca8ebdfc96b4f8cffb1f16d4fca2ac41d";
18 | fetch(url + key, {
19 | method: "GET",
20 | })
21 | .then((res) => {
22 | // set result
23 | res.json().then((output) => setResult(output));
24 | clearTimeout(showError);
25 | })
26 | .catch((error) => {
27 | console.log(error);
28 | });
29 | }
30 |
31 | function setResult(data) {
32 | // set user city and Geographical coordinates to local storage and show to page
33 | localStorage.setItem("autoUserCity", data.city.name);
34 | document
35 | .querySelector("#city_with_ip")
36 | .setAttribute("value", `${data.city.name} / ${data.country.capital}`);
37 | }
38 | }
39 | // Select city Form Handler
40 | selectCity() {
41 | // access to the inputs
42 | const defaultCitiesInput = document.querySelector("#default_cities");
43 | const customCityInput = document.querySelector("#custom_city");
44 |
45 | defaultCitiesInput.addEventListener("change", (event) => {
46 | // clear custom city
47 | customCityInput.value = "";
48 | // inputs validation
49 | this.selectInputsValidation();
50 | });
51 | customCityInput.addEventListener("input", (event) => {
52 | // clear default cities
53 | defaultCitiesInput.value = null;
54 | // inputs validation
55 | this.selectInputsValidation();
56 | });
57 | }
58 | // Select city form validation
59 | selectInputsValidation() {
60 | // Ccess to the values
61 | const defaultCitiesValue = document.querySelector("#default_cities").value;
62 | const customCityValue = document.querySelector("#custom_city").value;
63 |
64 | const continueBtn = document.querySelector(".selectbox--continue-btn");
65 | // set tailwind classes
66 | const classes = ["opacity-50", "cursor-not-allowed"];
67 |
68 | // cheacking Default cities
69 | if (
70 | (defaultCitiesValue === "null" ||
71 | (defaultCitiesValue === null && customCityValue !== ""),
72 | customCityValue.length > 2)
73 | ) {
74 | continueBtn.classList.remove(...classes);
75 | continueBtn.removeAttribute("disabled");
76 | // cheacking Custom city
77 | } else if (
78 | customCityValue === "" &&
79 | defaultCitiesValue !== null &&
80 | defaultCitiesValue !== "null"
81 | ) {
82 | continueBtn.classList.remove(...classes);
83 | continueBtn.removeAttribute("disabled");
84 | } else {
85 | continueBtn.classList.add(...classes);
86 | continueBtn.setAttribute("disabled", "true");
87 | }
88 | }
89 | // Set Selected city to localstorage
90 | setCityToloaclstorage() {
91 | // access to elements
92 | const continueBtn = document.querySelector(".selectbox--continue-btn"),
93 | loading = document.querySelector("#loading");
94 |
95 | continueBtn.addEventListener("click", () => {
96 | let customCityValue = document.querySelector("#custom_city").value;
97 | customCityValue = customCityValue.toLowerCase();
98 | const defaultCitiesValue =
99 | document.querySelector("#default_cities").value;
100 |
101 | // Checking custom city
102 | if (customCityValue !== "") {
103 | // show loading
104 | loading.classList.remove("hidde");
105 | // checking
106 | this.checkingCustomCity(customCityValue);
107 | } else {
108 | // set Default city to local storage and go to app page
109 | localStorage.setItem("userCity", defaultCitiesValue);
110 | dom.removeClass("#loading", "hidde");
111 | dom.showApp();
112 | }
113 | });
114 | }
115 | // Checking custom city
116 | async checkingCustomCity(city) {
117 | // Access to user city from LS
118 | const key = "72caee2eff37548de75d5d9674aa2510";
119 | // created url
120 | const url = `http://api.openweathermap.org/data/2.5/forecast?q=${city}&appid=${key}&units=metric`;
121 | // send request
122 | const request = await fetch(url)
123 | .then((res) => res)
124 | .catch((error) => {
125 | dom.addClass("#loading", "hidde");
126 | dom.showVpnError()
127 | console.log(error);
128 | })
129 | .catch((error) => {
130 | dom.addClass("#loading", "hidde");
131 | console.log(error);
132 | });
133 | // access response
134 | const response = await request.json();
135 |
136 | // check response error
137 | if (request.status === 200) {
138 | // Go to app
139 | dom.addClass("#select_first_city", "hidden");
140 | localStorage.setItem("userCity", city);
141 | dom.showApp();
142 | } else {
143 | // Back to select City
144 | dom.addClass("#loading", "hidde");
145 | dom.showMessage("Your city Not Found, Try again ", "info", "danger");
146 | }
147 | }
148 | // Submit Change city form
149 | async submitChangeCityForm(event) {
150 | event.preventDefault();
151 |
152 | // Access to elments
153 | const form = document.querySelector("#change_city_form");
154 | const status = form.getAttribute("form-status"),
155 | customCityInput = document.querySelector(
156 | "#change_city_form #custom-city"
157 | ),
158 | defaultCitiesInput = document.querySelector(
159 | "#change_city_form #default-cities"
160 | ),
161 | loading = document.querySelector("#change_city_form #loading");
162 |
163 | let city = "";
164 |
165 | // Default city
166 | if (customCityInput.value === "" && defaultCitiesInput.value !== null) {
167 | city = defaultCitiesInput.value;
168 | // custom city
169 | } else if (
170 | defaultCitiesInput.value == "null" &&
171 | customCityInput.value !== ""
172 | ) {
173 | loading.classList.add("active");
174 | /// Chacking city with api
175 | const isValidCity = await getApis.chackingCoustomCity(
176 | customCityInput.value
177 | );
178 | // Show error
179 | if (isValidCity == false) {
180 | loading.classList.remove("active");
181 | dom.showMessage("Your city Not Found, Try again ", "info", "danger");
182 | } else {
183 | // Set city
184 | city = customCityInput.value;
185 | }
186 | }
187 |
188 | // chacking form status and set city to localStorage
189 | if (city !== "" && city !== null) {
190 | if (status === "firstCity") {
191 | // Set first city
192 | localStorage.setItem("userCity", city);
193 | window.location.reload();
194 | } else if (status === "secondeCity") {
195 | // set seconde city
196 | localStorage.setItem("secondeCity", city);
197 | window.location.reload();
198 | }
199 | }
200 | }
201 | }
202 |
203 | export default UserCity;
204 |
--------------------------------------------------------------------------------
/src/js/weatherApp.js:
--------------------------------------------------------------------------------
1 | import GetApis from "./getApis.js";
2 | const getApis = new GetApis();
3 | class WeatherApp {
4 | // Set Realtime Weather
5 | async setRealtimeWeather(weatherData) {
6 | // Set user City
7 | const userCity = localStorage.getItem("userCity");
8 | const userCityTag = document.querySelector("#realtime_weather .location");
9 | userCityTag.innerHTML = userCity;
10 |
11 | // Set description
12 | const descriptionTag = document.querySelector(
13 | "#realtime_weather .description"
14 | );
15 | descriptionTag.innerHTML = weatherData.weather[0].description;
16 |
17 | // Set weather temperature
18 | const tempTag = document.querySelector("#realtime_weather .temp");
19 | tempTag.innerHTML = Math.floor(weatherData.main.temp);
20 |
21 | // Set weather icon
22 | const weatherImgTag = document.querySelector(
23 | "#realtime_weather .real-img img"
24 | );
25 | weatherImgTag.src = await getApis.findIcon(weatherData);
26 |
27 | // Set More info ------- access to elements
28 | const moreInfo = document.querySelector("#more_data_section"),
29 | maxTempTag = moreInfo.querySelector("#max_temp h4"),
30 | minTempTag = moreInfo.querySelector("#min_temp h4"),
31 | humidityTag = moreInfo.querySelector("#humidity h4"),
32 | windTag = moreInfo.querySelector("#wind h4");
33 |
34 | maxTempTag.innerHTML = weatherData.main.temp_max + " °";
35 | minTempTag.innerHTML = weatherData.main.temp_min + " °";
36 | humidityTag.innerHTML = weatherData.main.humidity;
37 | windTag.innerHTML = weatherData.wind.speed;
38 | }
39 | // Next hours Weather
40 | async nextHours(weatherData) {
41 | /* -------------------------------
42 | Get time and find current hour
43 | ------------------------------- */
44 | let cityHour = await getApis.getTime();
45 | cityHour = cityHour.watch.hour;
46 |
47 | // access to the slider static childs
48 | const sliderChildes = document.querySelectorAll(".nextHours .swiper-slide");
49 |
50 | // access to the current hour in weather data
51 | let currentHour = "";
52 | for (let index = 0; index < weatherData.length; index++) {
53 | /// access to the weather hours
54 | let time = weatherData[index].dt_txt.split(" ")[1];
55 | time = time.slice(0, 2);
56 |
57 | // console.log(time)
58 | if (time === cityHour) {
59 | currentHour = index;
60 | break;
61 | }
62 | }
63 |
64 | // cuting finally items from weather data array
65 | const finallyItems = weatherData.slice(currentHour, currentHour + 7);
66 |
67 | // Set to day weather to local storage
68 | localStorage.setItem("toDayWeather", JSON.stringify(finallyItems));
69 |
70 | // Create next hours weathers in slider
71 | finallyItems.forEach(async (weather, index) => {
72 | // access to te time
73 | let time = weather.dt_txt.split(" ")[1];
74 | time = time.slice(0, 2);
75 |
76 | // access slide element
77 | const slideElement = sliderChildes[index];
78 | // access to tags
79 | const weatherInfo = slideElement.querySelector(".weather_info"),
80 | weatherIcon = slideElement.querySelector(".weather_icon"),
81 | weatherTime = slideElement.querySelector(".weather_time");
82 | // set data
83 | weatherInfo.innerHTML = weather.weather[0].main;
84 | weatherIcon.src = await getApis.findIcon(weather);
85 | weatherTime.innerHTML = time + ":00";
86 | slideElement.setAttribute("timeId", index);
87 |
88 | // active current time
89 | if (index == 0) {
90 | slideElement.classList.add("active");
91 | }
92 |
93 | // switching in times
94 | slideElement.addEventListener("click", () => this.activeThisTime(index));
95 | });
96 |
97 | // Remove loading frame on next hour
98 | this.removeLoadingFrame("nextHours");
99 | for (let index = 0; index <= 35; index++) {
100 | const weather = weatherData[index];
101 | // access slide element
102 | const slideElement = sliderChildes[index];
103 | const icon = await getApis.findIcon(weather);
104 | }
105 | }
106 |
107 | //
108 | activeThisTime(selectedTime) {
109 | // access to to day weather from local storage
110 | const weatherData = JSON.parse(localStorage.getItem("toDayWeather"));
111 | // Active time
112 | function run() {
113 | // access to the time slides
114 | const timeSlides = document.querySelectorAll(".nextHours .swiper-slide");
115 | // unActive last slide
116 | timeSlides.forEach((slide, index) => {
117 | if (slide.classList.contains("active")) {
118 | slide.classList.remove("active");
119 | }
120 | });
121 | // active new slide
122 | timeSlides.forEach((slide, index) => {
123 | if (index === selectedTime) {
124 | slide.classList.add("active");
125 | }
126 | });
127 | }
128 | run();
129 |
130 | this.setRealtimeWeather(weatherData[selectedTime]);
131 | }
132 | // Set Time and Date
133 | async setDateAndTime() {
134 | // Extract time from api
135 | const time = await getApis.getTime();
136 |
137 | // access to HTML elemnts
138 | const dateTag = document.querySelector("#time_and_date .date");
139 | const timeTag = document.querySelector("#time_and_date .time");
140 |
141 | dateTag.innerHTML = `${time.dayName} / ${time.date}`;
142 | timeTag.innerHTML = `${time.watch.hour}: ${time.watch.minute} : ${time.watch.second}`;
143 |
144 | // run clock
145 | this.runClock([time.watch.hour, time.watch.minute, time.watch.second]);
146 | }
147 | // Run clock
148 | runClock(timeData) {
149 | // access to the loading classes
150 | const loadingClasses = document.querySelectorAll(
151 | `#time_and_date .loading_frame`
152 | );
153 | // remove classes
154 | loadingClasses.forEach((currentElement) =>
155 | currentElement.classList.remove("loading_frame")
156 | );
157 | // access to the data
158 | let hour = Number(timeData[0]),
159 | minute = Number(timeData[1]),
160 | seconde = Number(timeData[2]);
161 |
162 | // show values
163 | let showSeconde = "";
164 | let showMinute = "";
165 | let showHour = "";
166 |
167 | // access to the Elements
168 | const timeTag = document.querySelector("#time_and_date .time");
169 |
170 | setInterval(() => {
171 | // seconde --------------
172 | seconde++;
173 | if (seconde > 59) {
174 | seconde = 1;
175 | }
176 | // seconde fixer
177 | if (seconde < 10) {
178 | showSeconde = `0${seconde}`;
179 | } else {
180 | showSeconde = seconde;
181 | }
182 |
183 | // minute ------------------
184 | if (seconde === 1) {
185 | minute++;
186 | }
187 | if (minute > 59) {
188 | minute = 1;
189 | }
190 | // minute fixer
191 | if (minute < 10) {
192 | showMinute = `0${minute}`;
193 | } else {
194 | showMinute = minute;
195 | }
196 |
197 | // hour ---------------
198 | if (minute === 1) {
199 | hour++;
200 | }
201 |
202 | // hour fixer
203 | if (hour < 10) {
204 | showHour = `0${hour}`;
205 | } else {
206 | showHour = hour;
207 | }
208 |
209 | timeTag.innerHTML = `${showHour} : ${showMinute} : ${showSeconde}`;
210 | }, 1000);
211 | }
212 | // Remove loading frame
213 | removeLoadingFrame(elementId) {
214 | // access to the loading classes
215 | const loadingClasses = document.querySelectorAll(
216 | `#${elementId} .loading_frame`
217 | );
218 | // remove classes
219 | loadingClasses.forEach((currentElement) =>
220 | currentElement.classList.remove("loading_frame")
221 | );
222 | }
223 | // Run seconde city
224 | async runSecondeCity() {
225 | // access to seconde city from local storage
226 | const userCity = localStorage.getItem("secondeCity").toLocaleLowerCase();
227 |
228 | // show seconde city section
229 | document
230 | .querySelector("#secondeCity .seconde-city-info")
231 | .classList.remove("hidden");
232 |
233 | // Access to seconde city weather
234 | let weather = await getApis.getWeather(userCity);
235 | this.removeLoadingFrame("secondeCity");
236 |
237 | // Set user City
238 | const userCityTag = document.querySelector("#secondeCity .location");
239 | userCityTag.innerHTML = userCity;
240 |
241 | // Set description
242 | const descriptionTag = document.querySelector("#secondeCity .description");
243 | descriptionTag.innerHTML = weather.list[0].weather[0].description;
244 |
245 | // Set weather temperature
246 | const tempTag = document.querySelector("#secondeCity .temp");
247 | tempTag.innerHTML = Math.floor(weather.list[0].main.temp);
248 |
249 | // Set weather icon
250 | const weatherImgTag = document.querySelector("#secondeCity .real-img img");
251 | weatherImgTag.src = await getApis.findIcon(weather.list[0]);
252 |
253 | // Set More info ------- access to elements
254 | const moreInfo = document.querySelector("#secondeCity .more-weather"),
255 | maxTempTag = moreInfo.querySelector("#max_temp h4"),
256 | minTempTag = moreInfo.querySelector("#min_temp h4"),
257 | humidityTag = moreInfo.querySelector("#humidity h4"),
258 | windTag = moreInfo.querySelector("#wind h4");
259 |
260 | maxTempTag.innerHTML = weather.list[0].main.temp_max + " °";
261 | minTempTag.innerHTML = weather.list[0].main.temp_min + " °";
262 | humidityTag.innerHTML = weather.list[0].main.humidity;
263 | windTag.innerHTML = weather.list[0].wind.speed;
264 | }
265 | }
266 |
267 | export default WeatherApp;
268 |
--------------------------------------------------------------------------------
/src/styles/css-reset.css:
--------------------------------------------------------------------------------
1 | html, body, div, span, applet, object, iframe,
2 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
3 | a, abbr, acronym, address, big, cite, code,
4 | del, dfn, em, img, ins, kbd, q, s, samp,
5 | small, strike, strong, sub, sup, tt, var,
6 | b, u, i, center,
7 | dl, dt, dd, ol, ul, li,
8 | fieldset, form, label, legend,
9 | table, caption, tbody, tfoot, thead, tr, th, td,
10 | article, aside, canvas, details, embed,
11 | figure, figcaption, footer, header, hgroup,
12 | menu, nav, output, ruby, section, summary,
13 | time, mark, audio, video {
14 | margin: 0;
15 | padding: 0;
16 | font-size: 100%;
17 | font: inherit;
18 | vertical-align: baseline;
19 | }
20 | /* HTML5 display-role reset for older browsers */
21 | article, aside, details, figcaption, figure,
22 | footer, header, hgroup, menu, nav, section {
23 | display: block;
24 | }
25 | body {
26 | line-height: 1;
27 | }
28 | ol, ul {
29 | list-style: none;
30 | }
31 | blockquote, q {
32 | quotes: none;
33 | }
34 | blockquote:before, blockquote:after,
35 | q:before, q:after {
36 | content: '';
37 | content: none;
38 | }
39 | table {
40 | border-collapse: collapse;
41 | border-spacing: 0;
42 | }
--------------------------------------------------------------------------------
/src/styles/css/animations.css:
--------------------------------------------------------------------------------
1 | .animate_right {
2 | transform: translateX(50px);
3 | -webkit-transform: translateX(50px);
4 | -moz-transform: translateX(50px);
5 | -ms-transform: translateX(50px);
6 | -o-transform: translateX(50px);
7 | opacity: 0;
8 | }
9 |
10 | .animate_left {
11 | transform: translateX(-50px);
12 | -webkit-transform: translateX(-50px);
13 | -moz-transform: translateX(-50px);
14 | -ms-transform: translateX(-50px);
15 | -o-transform: translateX(-50px);
16 | opacity: 0;
17 | }
18 |
19 | .animate_bottom {
20 | transform: translateY(50px);
21 | -webkit-transform: translateY(50px);
22 | -moz-transform: translateY(50px);
23 | -ms-transform: translateY(50px);
24 | -o-transform: translateY(50px);
25 | opacity: 0;
26 | }
27 |
28 | .animate_top {
29 | transform: translateY(-50px);
30 | -webkit-transform: translateY(-50px);
31 | -moz-transform: translateY(-50px);
32 | -ms-transform: translateY(-50px);
33 | -o-transform: translateY(-50px);
34 | opacity: 0;
35 | }
36 |
37 | /*# sourceMappingURL=animations.css.map */
38 |
--------------------------------------------------------------------------------
/src/styles/css/animations.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["../sass/animations.scss","../sass/_mixins.scss"],"names":[],"mappings":"AAIC;ECFC;EACA;EACA;EACA;EACA;EACA;;;ADAD;ECLC;EACA;EACA;EACA;EACA;EACA;;;ADGD;ECEC;EACA;EACA;EACA;EACA;EACA;;;ADJD;ECDC;EACA;EACA;EACA;EACA;EACA","file":"animations.css"}
--------------------------------------------------------------------------------
/src/styles/sass/_mixins.scss:
--------------------------------------------------------------------------------
1 | // ------------ Slide right --------- //
2 | @mixin slide_x($space) {
3 | transform: translateX($space);
4 | -webkit-transform: translateX($space);
5 | -moz-transform: translateX($space);
6 | -ms-transform: translateX($space);
7 | -o-transform: translateX($space);
8 | opacity: 0;
9 | }
10 |
11 | // ------------ Slide Bottom --------- //
12 | @mixin slide_y($space) {
13 | transform: translateY($space);
14 | -webkit-transform: translateY($space);
15 | -moz-transform: translateY($space);
16 | -ms-transform: translateY($space);
17 | -o-transform: translateY($space);
18 | opacity: 0;
19 | }
20 |
--------------------------------------------------------------------------------
/src/styles/sass/animations.scss:
--------------------------------------------------------------------------------
1 | @import './mixins';
2 |
3 |
4 |
5 | .animate_right{
6 | @include slide_x(50px)
7 | }
8 | .animate_left{
9 | @include slide_x(-50px)
10 | }
11 | .animate_bottom{
12 | @include slide_y(50px)
13 | }
14 | .animate_top{
15 | @include slide_y(-50px)
16 | }
--------------------------------------------------------------------------------
/src/styles/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 | body {
5 | font-family: 'Poppins', sans-serif;
6 | }
7 | * {
8 | transition: .1s;
9 | -webkit-tap-highlight-color: transparent;
10 | -webkit-transition: .1s;
11 | -moz-transition: .1s;
12 | -ms-transition: .1s;
13 | -o-transition: .1s;
14 | }
15 | .blur{
16 | filter: blur(10px);
17 | -webkit-filter: blur(10px);
18 | }
19 |
20 | /* font family */
21 |
22 | /* -----------------
23 | Start Select City
24 | ------------------ */
25 | .selectbox--default_cities select {
26 | -webkit-appearance: none;
27 | -moz-appearance: none;
28 | appearance: none;
29 | }
30 | .selectbox--default_cities .select i {
31 | top: 50%;
32 | transform: translateY(-50%);
33 | -webkit-transform: translateY(-50%);
34 | -moz-transform: translateY(-50%);
35 | -ms-transform: translateY(-50%);
36 | -o-transform: translateY(-50%);
37 | }
38 | .select_first_city--selectbox .selectbox--image{
39 | transition: .7s;
40 | max-width: calc(100% / 2);
41 | -webkit-transition: .7s;
42 | -moz-transition: .7s;
43 | -ms-transition: .7s;
44 | -o-transition: .7s;
45 | }
46 | .select_first_city--selectbox .selectbox--image.sm{
47 | max-width: calc(100% / 4);
48 | }
49 | /* -----------------
50 | End of Select City
51 | ------------------ */
52 |
53 | /* Start loading */
54 | #loading{
55 | transition: all .2s;
56 | -webkit-transition: all .2s;
57 | -moz-transition: all .2s;
58 | -ms-transition: all .2s;
59 | -o-transition: all .2s;
60 | }
61 | #loading.hidde{
62 | opacity: 0;
63 | visibility: hidden;
64 | pointer-events: none;
65 | }
66 | #loading i{
67 | animation-name: rotate;
68 | animation-duration: 1.5s;
69 | animation-fill-mode: both;
70 | animation-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
71 | animation-iteration-count: infinite;
72 | }
73 | @keyframes rotate {
74 | 0%{
75 | transform: rotate(0deg);
76 | -webkit-transform: rotate(0deg);
77 | -moz-transform: rotate(0deg);
78 | -ms-transform: rotate(0deg);
79 | -o-transform: rotate(0deg);
80 | } 100%{
81 | transform: rotate(360deg);
82 | -webkit-transform: rotate(360deg);
83 | -moz-transform: rotate(360deg);
84 | -ms-transform: rotate(360deg);
85 | -o-transform: rotate(360deg);
86 | }
87 | }
88 |
89 | /* End of loading */
90 |
91 |
92 | /* Dark mode Switcher menu and button styles */
93 | #switcher_menu .custom_radio_inputs label i{
94 | transition: .1s;
95 | -webkit-transition: .1s;
96 | -moz-transition: .1s;
97 | -ms-transition: .1s;
98 | -o-transition: .1s;
99 | }
100 | #switcher_menu .custom_radio_inputs input[type = 'radio']:checked ~ label i{
101 | background-color: #2563eb;
102 | }
103 | /* End of Dark mode Switcher menu and button styles */
104 |
105 | /* Realtime degree responseive font size */
106 | @media screen and (max-width: 767px) {
107 | .realtitle--degree{
108 | font-size: 25vw;
109 | }
110 | #secondeCity .temp{
111 | font-size: 15vw;
112 | }
113 | .realtitle--degree span{
114 | font-size: 15vw;
115 | }
116 | }
117 | /* End of Realtime degree responseive font size */
118 |
119 | /* Realtime weather image shadow */
120 | .real-img{
121 | filter: drop-shadow(-10px -5px 45px rgba(0, 0, 0, 0.226));
122 | -webkit-filter: drop-shadow(-10px -5px 45px rgba(0, 0, 0, 0.226));
123 | }
124 | /* End of Realtime weather image shadow */
125 |
126 | /* Start Switcher menu / dark and light theme */
127 | #switcher_menu{
128 | pointer-events: none;
129 | }
130 | #switcher_menu #main{
131 | transition: .3s;
132 | -webkit-transition: .3s;
133 | -moz-transition: .3s;
134 | -ms-transition: .3s;
135 | -o-transition: .3s;
136 | opacity: 0;
137 | visibility: hidden;
138 | pointer-events: all;
139 | }
140 | #switcher_menu.active #main{
141 | transform: translateY(0px);
142 | -webkit-transform: translateY(0px);
143 | -moz-transform: translateY(0px);
144 | -ms-transform: translateY(0px);
145 | -o-transform: translateY(0px);
146 | opacity: 1;
147 | visibility: visible;
148 | }
149 | /* End of Switcher menu / dark and light theme */
150 |
151 | /* Background hidden for close popups */
152 | #hidden_background_section{
153 | visibility: hidden;
154 | display: none;
155 | opacity: 0;
156 | }
157 | #hidden_background_section.active{
158 | visibility: visible;
159 | display: flex;
160 | opacity: .2;
161 | }
162 | /* End of Background hidden for close popups */
163 |
164 |
165 |
166 | /* Swiper js slider styles */
167 | .swiper-slide {
168 | height: auto !important;
169 | transition: .3s;
170 | -webkit-transition: .3s;
171 | -moz-transition: .3s;
172 | -ms-transition: .3s;
173 | -o-transition: .3s;
174 | }
175 | .swiper-slide.active{
176 | background: linear-gradient(rgb(86, 154, 255), rgb(0, 81, 255));
177 | color: white !important;
178 | }
179 | .swiper-slide .slide-image{
180 | max-height: 40%;
181 | }
182 | .swiper-slide .slide-image img{
183 | max-height: 100%;
184 | }
185 | .rounded-2xl{
186 | border-radius: 1rem;
187 | -webkit-border-radius: 1rem;
188 | -moz-border-radius: 1rem;
189 | -ms-border-radius: 1rem;
190 | -o-border-radius: 1rem;
191 | }
192 | /* End of Swiper js slider styles */
193 |
194 | /* Main weather */
195 | #more_data_section{
196 | font-size: .9em;
197 | }
198 | /* End of Main weather */
199 |
200 | /* Messsage bax Syles & notifications */
201 | #message_box{
202 | position: fixed;
203 | top: 0;
204 | right: 0;
205 | }
206 | #message_box .message{
207 | background: rgb(240, 240, 240);
208 | box-shadow: 2px 2px 15px rgba(37, 37, 37, 0.055);
209 | padding: 10px;
210 | border-radius: 10px;
211 | -webkit-border-radius: 10px;
212 | -moz-border-radius: 10px;
213 | -ms-border-radius: 10px;
214 | -o-border-radius: 10px;
215 | width: 100%;
216 | margin: 10px auto;
217 | }
218 | body.dark #message_box .message{
219 | background: rgb(28, 37, 53);
220 | color: white;
221 | }
222 | #message_box .message .message--body{
223 | display: flex;
224 | align-items: center;
225 | }
226 | .message .message--icon{
227 | font-size: xx-large;
228 | margin-right: 10px;
229 | padding: 5px;
230 | border-radius: 10px;
231 | -webkit-border-radius: 10px;
232 | -moz-border-radius: 10px;
233 | -ms-border-radius: 10px;
234 | -o-border-radius: 10px;
235 | }
236 | .message.danger .message--icon{
237 | background: rgb(255, 38, 0);
238 | color: rgb(255, 255, 255);
239 | }
240 | .message.info .message--icon{
241 | background: rgb(0, 68, 255);
242 | color: rgb(255, 255, 255);
243 | }
244 | .message.success .message--icon{
245 | background: rgb(0, 141, 19);
246 | color: rgb(255, 255, 255);
247 | }
248 | /* End of Messsage Syles & notification box */
249 |
250 |
251 |
252 | /* Loading frame */
253 | .loading_frame{
254 | background-color: rgb(238, 238, 238);
255 | color: rgb(0, 0, 0, 0);
256 | border-radius: 5px;
257 | -webkit-border-radius: 5px;
258 | -moz-border-radius: 5px;
259 | -ms-border-radius: 5px;
260 | -o-border-radius: 5px;
261 | position: relative;
262 | overflow: hidden;
263 | transition: .3s;
264 | -webkit-transition: .3s;
265 | -moz-transition: .3s;
266 | -ms-transition: .3s;
267 | -o-transition: .3s;
268 | margin-top: 3px;
269 | }
270 | .loading_frame *{
271 | opacity: 0;
272 | }
273 | span.loading_frame{
274 | color: rgba(255, 0, 0, 0) !important;
275 | }
276 | body.dark .loading_frame{
277 | background-color: #1c2535;
278 | }
279 | .loading_frame::after{
280 | content: '';
281 | position: absolute;
282 | top: 0;
283 | left: 0;
284 | width: 100%;
285 | height: 100%;
286 | background: -moz-linear-gradient(82deg, rgba(2,0,36,0) 0%, rgba(184,184,184,0.21052170868347342) 50%, rgba(184,184,184,0) 100%);
287 | background: -webkit-linear-gradient(82deg, rgba(2,0,36,0) 0%, rgba(184,184,184,0.21052170868347342) 50%, rgba(184,184,184,0) 100%);
288 | background: linear-gradient(82deg, rgba(2,0,36,0) 0%, rgba(184,184,184,0.21052170868347342) 50%, rgba(184,184,184,0) 100%);
289 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#020024",endColorstr="#b8b8b8",GradientType=1);
290 | display: block;
291 | animation-name: loadingFrame;
292 | animation-iteration-count: infinite;
293 | animation-duration: 2s;
294 | }
295 | @keyframes loadingFrame {
296 | 0%{
297 | left: -100%;
298 | }
299 | 100%{
300 | left: 100%;
301 | }
302 | }
303 |
304 | /* End of Loading frame */
305 |
306 | /* Show vpn error box */
307 | #vpn_error{
308 | visibility: hidden;
309 | pointer-events: none;
310 | opacity: 0;
311 | transition: .3s;
312 | -webkit-transition: .3s;
313 | -moz-transition: .3s;
314 | -ms-transition: .3s;
315 | -o-transition: .3s;
316 | }
317 | #vpn_error.active{
318 | visibility: visible;
319 | pointer-events: all;
320 | opacity: 1;
321 | }
322 | #error-text{
323 | transition: .3s;
324 | -webkit-transition: .3s;
325 | -moz-transition: .3s;
326 | -ms-transition: .3s;
327 | -o-transition: .3s;
328 | }
329 | /* End of Show vpn error box */
330 |
331 |
332 | /* Start change city popup */
333 | #change_city_popup{
334 | pointer-events: none;
335 | }
336 | #change_city_popup > #main{
337 | transition: .3s;
338 | -webkit-transition: .3s;
339 | -moz-transition: .3s;
340 | -ms-transition: .3s;
341 | -o-transition: .3s;
342 | opacity: 0;
343 | visibility: hidden;
344 | pointer-events: none;
345 | }
346 | #change_city_popup.active #main{
347 | transform: translateY(0px);
348 | -webkit-transform: translateY(0px);
349 | -moz-transform: translateY(0px);
350 | -ms-transform: translateY(0px);
351 | -o-transform: translateY(0px);
352 | opacity: 1;
353 | visibility: visible;
354 | pointer-events: all;
355 | }
356 | /* End of change city popup */
357 |
358 | /* ---------------------
359 | Start change city Form
360 | ---------------------- */
361 | .indigo{
362 | color: rgb(72, 130, 255) !important;
363 | }
364 | .purple{
365 | color: rgb(123, 46, 196) !important;
366 | }
367 | #change_city_form{
368 | pointer-events: none;
369 | }
370 | #change_city_form .main{
371 | pointer-events: all;
372 | visibility: hidden;
373 | transition: .3s;
374 | -webkit-transition: .3s;
375 | -moz-transition: .3s;
376 | -ms-transition: .3s;
377 | -o-transition: .3s;
378 | opacity: 0;
379 | }
380 | #change_city_form.active .main{
381 | visibility: visible;
382 | opacity: 1;
383 | transform: translateY(0);
384 | -webkit-transform: translateY(0);
385 | -moz-transform: translateY(0);
386 | -ms-transform: translateY(0);
387 | -o-transform: translateY(0);
388 | }
389 | #change_city_form #submit-form{
390 | opacity: .5;
391 | cursor: not-allowed;
392 | }
393 | #change_city_form #submit-form.active{
394 | opacity: 1;
395 | cursor: pointer;
396 | }
397 | #change_city_form #loading{
398 | visibility: hidden;
399 | opacity: 0;
400 | pointer-events: none;
401 | }
402 | #change_city_form #loading.active {
403 | opacity: 1;
404 | visibility: visible;
405 | pointer-events: all;
406 | }
407 | /* ---------------------
408 | End of change city Form
409 | ---------------------- */
410 |
411 |
412 | /* ---------------------
413 | Start Seconde city
414 | ---------------------- */
415 | body.dark .seconde-city-info .location.loading_frame{
416 | color: #2564eb00 !important;
417 | }
418 | body.dark .seconde-city-info .location{
419 | color: #f3f3f3 !important;
420 | }
421 | body.dark .seconde-city-info .description.loading_frame{
422 | color: #2564eb00 !important;
423 | }
424 | body.dark .seconde-city-info .description{
425 | color: #d8d8d8 !important;
426 | }
427 | body.dark .seconde-city-info .text.loading_frame{
428 | color: #d8d8d800 !important;
429 | }
430 | body.dark .seconde-city-info .text{
431 | color: #ececec !important;
432 | }
433 | /* ---------------------
434 | End of Seconde city
435 | ---------------------- */
436 |
437 |
438 | .seconde-city-info::after{
439 | content: 'Seconde city';
440 | position: absolute;
441 | rotate: 90deg;
442 | right: 0;
443 | top: 50%;
444 | opacity: .3;
445 | transform: translatey(-30px);
446 | -webkit-transform: translatey(-30px);
447 | -moz-transform: translatey(-30px);
448 | -ms-transform: translatey(-30px);
449 | -o-transform: translatey(-30px);
450 | }
451 | body.dark .seconde-city-info::after{
452 | color: white;
453 | }
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | content: ["./*.html"],
3 | darkMode: 'class',
4 | theme: {
5 | extend: {},
6 | },
7 | plugins: [],
8 | }
9 |
--------------------------------------------------------------------------------