├── .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 | ![image](https://s8.uupload.ir/files/weather-app-cover_48xr.jpg) 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 | 127 | 130 | 133 | 476 | 477 |
478 | 481 | 484 |
486 | 487 | Loading... 488 |
489 | 492 | 495 |
496 |
497 | 500 | 503 |
505 | 508 | 509 |
511 | 512 |
514 |
515 |
516 |
517 | 518 |
519 |
520 | 521 |
522 | 526 | 527 | 530 |
531 | 532 | 533 |
534 | 538 | 539 | 542 |
543 | 544 | 545 |
546 | 550 | 551 | 554 |
555 | 556 |
557 |
558 | 559 |
560 | 561 |
562 | 563 | 564 | 567 |
569 | 570 |
572 | 573 |
574 | 575 | Back 576 |
577 |
578 | 579 | 582 | 583 | 584 | 585 | 586 | 587 | Management of cities 588 |
589 | 590 | 591 |
592 | 593 |
595 | 596 |
Change your city
597 |
598 | 599 |
601 | 602 |
Add second city
603 |
604 |
605 | 606 |
607 | 608 |
609 | 612 | 615 |
618 |
620 | 621 |
622 | 623 | Back 624 |
625 |
626 | 627 | 630 | 631 | 632 | 633 | 634 | 635 | Management of cities 636 |
637 | 638 |
639 |
640 | 641 | 643 |
644 | 650 |
651 | 652 | 665 |
666 | 668 |
669 | 670 |
672 | 673 | Loading... 674 |
675 | 676 |
677 |
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 | 2 | 3 | 4 | 5 | 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 | --------------------------------------------------------------------------------