├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt └── src ├── App.css ├── App.js ├── App.test.js ├── apiKeys.js ├── currentLocation.js ├── forcast.js ├── images ├── WeatherIcons.gif ├── background.jpg ├── background1.jpg ├── city.jpg ├── city1.jpg └── forecast.png ├── index.css ├── index.js ├── logo.svg ├── serviceWorker.js └── setupTests.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Gaurav Ghai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |

6 | View Complete Installation details. 7 |

8 |

9 | View Live demo. 10 |

11 | 12 | ## Setup 13 | 14 | ``` 15 | npm i && npm start 16 | ``` 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weather", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "axios": "^0.19.2", 10 | "react": "^16.13.1", 11 | "react-animated-weather": "^4.0.1", 12 | "react-dom": "^16.13.1", 13 | "react-geolocated": "^3.0.1", 14 | "react-live-clock": "^4.0.5", 15 | "react-scripts": "3.4.1", 16 | "react-skycons": "^0.7.0", 17 | "skycons": "^1.0.0" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": "react-app" 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.2%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravghai/weatherApp-Reactjs/7915d8b4dd2fd8b80f55e72098870f38e3607362/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Live weather app built by using React.js 28 | 29 | 33 | 42 | 43 | 44 | 45 |
46 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravghai/weatherApp-Reactjs/7915d8b4dd2fd8b80f55e72098870f38e3607362/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravghai/weatherApp-Reactjs/7915d8b4dd2fd8b80f55e72098870f38e3607362/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | /*-- 2 | Author: W3layouts 3 | Author URL: http://w3layouts.com 4 | License: Creative Commons Attribution 3.0 Unported 5 | License URL: http://creativecommons.org/licenses/by/3.0/ 6 | --*/ 7 | 8 | /*-- Reset Code --*/ 9 | 10 | html, 11 | body, 12 | div, 13 | span, 14 | applet, 15 | object, 16 | iframe, 17 | h1, 18 | h2, 19 | h3, 20 | h4, 21 | h5, 22 | h6, 23 | p, 24 | blockquote, 25 | pre, 26 | a, 27 | abbr, 28 | acronym, 29 | address, 30 | big, 31 | cite, 32 | code, 33 | del, 34 | dfn, 35 | em, 36 | img, 37 | ins, 38 | kbd, 39 | q, 40 | s, 41 | samp, 42 | small, 43 | strike, 44 | strong, 45 | sub, 46 | sup, 47 | tt, 48 | var, 49 | b, 50 | u, 51 | i, 52 | dl, 53 | dt, 54 | dd, 55 | ol, 56 | nav ul, 57 | nav li, 58 | fieldset, 59 | form, 60 | label, 61 | legend, 62 | table, 63 | caption, 64 | tbody, 65 | tfoot, 66 | thead, 67 | tr, 68 | th, 69 | td, 70 | article, 71 | aside, 72 | canvas, 73 | details, 74 | embed, 75 | figure, 76 | figcaption, 77 | footer, 78 | header, 79 | hgroup, 80 | menu, 81 | nav, 82 | output, 83 | ruby, 84 | section, 85 | summary, 86 | time, 87 | mark, 88 | audio, 89 | video { 90 | margin: 0; 91 | padding: 0; 92 | border: 0; 93 | font-size: 100%; 94 | font: inherit; 95 | vertical-align: baseline; 96 | } 97 | article, 98 | aside, 99 | details, 100 | figcaption, 101 | figure, 102 | footer, 103 | header, 104 | hgroup, 105 | menu, 106 | nav, 107 | section { 108 | display: block; 109 | } 110 | ol, 111 | ul { 112 | list-style: none; 113 | padding: 0; 114 | margin: 0; 115 | } 116 | blockquote, 117 | q { 118 | quotes: none; 119 | } 120 | blockquote:before, 121 | blockquote:after, 122 | q:before, 123 | q:after { 124 | content: ""; 125 | content: none; 126 | } 127 | table { 128 | border-collapse: collapse; 129 | border-spacing: 0; 130 | } 131 | /* start editing from here */ 132 | a { 133 | text-decoration: none; 134 | } 135 | .txt-rt { 136 | text-align: right; 137 | } /* text align right */ 138 | .txt-lt { 139 | text-align: left; 140 | } /* text align left */ 141 | .txt-center { 142 | text-align: center; 143 | } /* text align center */ 144 | .float-rt { 145 | float: right; 146 | } /* float right */ 147 | .float-lt { 148 | float: left; 149 | } /* float left */ 150 | .clear { 151 | clear: both; 152 | } /* clear float */ 153 | .pos-relative { 154 | position: relative; 155 | } /* Position Relative */ 156 | .pos-absolute { 157 | position: absolute; 158 | } /* Position Absolute */ 159 | .vertical-base { 160 | vertical-align: baseline; 161 | } /* vertical align baseline */ 162 | .vertical-top { 163 | vertical-align: top; 164 | } /* vertical align top */ 165 | .underline { 166 | padding-bottom: 5px; 167 | border-bottom: 1px solid #eee; 168 | margin: 0 0 20px 0; 169 | } /* Add 5px bottom padding and a underline */ 170 | nav.vertical ul li { 171 | display: block; 172 | } /* vertical menu */ 173 | nav.horizontal ul li { 174 | display: inline-block; 175 | } /* horizontal menu */ 176 | img { 177 | max-width: 100%; 178 | } 179 | .current-time { 180 | font-size: 35px; 181 | font-weight: 100; 182 | margin-bottom: 10px; 183 | letter-spacing: 1px; 184 | } 185 | .current-date { 186 | font-size: 18px; 187 | font-weight: 100; 188 | letter-spacing: 1px; 189 | } 190 | 191 | /*-- //Reset Code --*/ 192 | 193 | /*-- Index-Page-Styling --*/ 194 | 195 | body { 196 | background: url("./images/background.jpg"); 197 | background-repeat: no-repeat; 198 | background-attachment: fixed; 199 | background-position: center; 200 | background-size: cover; 201 | -webkit-background-size: cover; 202 | -moz-background-size: cover; 203 | -o-background-size: cover; 204 | font-family: "Open Sans", sans-serif; 205 | text-align: center; 206 | } 207 | 208 | body a { 209 | transition: 0.5s all; 210 | -webkit-transition: 0.5s all; 211 | -moz-transition: 0.5s all; 212 | -o-transition: 0.5s all; 213 | -ms-transition: 0.5s all; 214 | text-decoration: none; 215 | } 216 | 217 | h1 { 218 | font-size: 50px; 219 | font-weight: 400; 220 | color: #f9f9f9; 221 | font-family: "Oxygen", sans-serif; 222 | letter-spacing: 7px; 223 | margin-top: 50px; 224 | } 225 | 226 | .container { 227 | width: 65%; 228 | height: 80vh; 229 | margin: 50px auto; 230 | background-color: rgba(0, 0, 0, 0.73); 231 | } 232 | 233 | .city { 234 | width: 60%; 235 | height: 100%; 236 | float: left; 237 | background: url("./images/city.jpg"); 238 | background-repeat: no-repeat; 239 | background-size: cover; 240 | -webkit-background-size: cover; 241 | -moz-background-size: cover; 242 | -o-background-size: cover; 243 | min-height: 500px; 244 | position: relative; 245 | background-position-x: -30px; 246 | } 247 | 248 | .title { 249 | float: right; 250 | font-family: "Oxygen", sans-serif; 251 | padding: 30px 30px 0 0; 252 | } 253 | 254 | .title h2 { 255 | color: #fff; 256 | font-size: 30px; 257 | font-weight: bold; 258 | } 259 | 260 | .title h3 { 261 | font-size: 25px; 262 | font-weight: bold; 263 | color: #eee; 264 | margin-top: 0px; 265 | text-align: right; 266 | } 267 | 268 | .date-time { 269 | position: absolute; 270 | bottom: 0; 271 | color: #fff; 272 | width: 90%; 273 | padding: 0 30px 10px 30px; 274 | font-family: "Oxygen", sans-serif; 275 | } 276 | 277 | div#txt { 278 | font-size: 35px; 279 | font-weight: 100; 280 | margin-bottom: 10px; 281 | letter-spacing: 1px; 282 | } 283 | 284 | .dmy { 285 | float: left; 286 | text-align: left; 287 | position: absolute; 288 | } 289 | 290 | .temperature { 291 | width: 50%; 292 | float: right; 293 | position: relative; 294 | left: 10px; 295 | } 296 | 297 | .temperature p { 298 | font-family: "Raleway", sans-serif; 299 | font-size: 80px; 300 | font-weight: 100; 301 | margin: 0 40px; 302 | } 303 | 304 | .temperature p span { 305 | font-size: 50px; 306 | font-weight: 200; 307 | } 308 | 309 | .forecast { 310 | width: 40%; 311 | float: left; 312 | height: 100%; 313 | } 314 | 315 | .forecast-icon { 316 | padding: 25px 0; 317 | /* background: white; */ 318 | } 319 | 320 | .today-weather h3 { 321 | text-transform: capitalize; 322 | font-size: 50px; 323 | color: #fff; 324 | width: 80%; 325 | margin: 0 auto 10px; 326 | padding-bottom: 10px; 327 | border-width: thin; 328 | border-bottom: 1px solid #eee; 329 | } 330 | 331 | .today-weather ul li { 332 | width: 74%; 333 | margin: 0 auto; 334 | line-height: 39px; 335 | border-width: thin; 336 | border-bottom: 1px solid #777; 337 | color: #eee; 338 | font-weight: 600; 339 | text-align: left; 340 | padding-left: 20px; 341 | } 342 | 343 | .today-weather ul li span { 344 | float: right; 345 | padding-right: 10px; 346 | } 347 | 348 | .today-weather ul li:nth-child(5) { 349 | border-bottom: none; 350 | } 351 | 352 | .footer { 353 | padding-bottom: 20px; 354 | } 355 | 356 | .copyright p { 357 | color: #fff; 358 | } 359 | 360 | .copyright p a { 361 | color: #fff; 362 | } 363 | /*--w3layouts--*/ 364 | /*--agileits--*/ 365 | .copyright p a:hover { 366 | color: #ffeb3b; 367 | } 368 | 369 | /*-- //Index-Page-Styling --*/ 370 | 371 | /*-- Responsive Code --*/ 372 | 373 | @media screen and (max-width: 1920px) { 374 | .container { 375 | width: 50%; 376 | } 377 | } 378 | 379 | @media screen and (max-width: 1440px) { 380 | .container { 381 | width: 55%; 382 | } 383 | } 384 | 385 | @media screen and (max-width: 1280px) { 386 | .container { 387 | width: 60%; 388 | } 389 | } 390 | 391 | @media screen and (max-width: 1024px) { 392 | .container { 393 | width: 75%; 394 | } 395 | } 396 | 397 | @media screen and (max-width: 966px) { 398 | .container { 399 | width: 90%; 400 | } 401 | } 402 | 403 | @media screen and (max-width: 853px) { 404 | h1 { 405 | font-size: 45px; 406 | } 407 | /*--w3layouts--*/ 408 | /*--agileits--*/ 409 | } 410 | 411 | @media screen and (max-width: 800px) { 412 | h1 { 413 | font-size: 35px; 414 | } 415 | .temperature p { 416 | font-size: 100px; 417 | } 418 | .dmy { 419 | padding-top: 25px; 420 | } 421 | } 422 | 423 | @media screen and (max-width: 736px) { 424 | .temperature p { 425 | font-size: 80px; 426 | } 427 | .dmy { 428 | padding-top: 10px; 429 | } 430 | div#txt { 431 | font-size: 30px; 432 | } 433 | .forecast-icon img { 434 | width: 110px; 435 | } 436 | } 437 | 438 | @media screen and (max-width: 667px) { 439 | h1 { 440 | font-size: 40px; 441 | margin-top: 30px; 442 | } 443 | .container { 444 | width: 95%; 445 | margin-top: 30px; 446 | } 447 | } 448 | 449 | @media screen and (max-width: 640px) { 450 | h1 { 451 | font-size: 30px; 452 | margin-top: 45px; 453 | } 454 | div#txt { 455 | font-size: 25px; 456 | } 457 | /*--w3layouts--*/ 458 | /*--agileits--*/ 459 | .dmy { 460 | padding-top: 17px; 461 | } 462 | .temperature p { 463 | padding-bottom: 10px; 464 | } 465 | } 466 | 467 | @media screen and (max-width: 603px) { 468 | h1 { 469 | font-size: 35px; 470 | } 471 | .city { 472 | width: 100%; 473 | min-height: 300px; 474 | } 475 | .temperature { 476 | text-align: right; 477 | } 478 | .temperature p { 479 | font-size: 100px; 480 | } 481 | .dmy { 482 | padding-top: 35px; 483 | } 484 | .forecast-icon { 485 | margin: 10px 0; 486 | } 487 | .forecast { 488 | width: 100%; 489 | padding-bottom: 30px; 490 | } 491 | .copyright { 492 | padding-bottom: 20px; 493 | } 494 | .copyright p { 495 | line-height: 30px; 496 | font-size: 14px; 497 | } 498 | } 499 | 500 | @media screen and (max-width: 533px) { 501 | h1 { 502 | font-size: 33px; 503 | } 504 | } 505 | 506 | @media screen and (max-width: 480px) { 507 | /*--w3layouts--*/ 508 | /*--agileits--*/ 509 | h1 { 510 | font-size: 28px; 511 | letter-spacing: 2px; 512 | } 513 | .container { 514 | margin-bottom: 20px; 515 | } 516 | .forecast-icon { 517 | margin: 40px 0 10px; 518 | } 519 | .forecast-icon img { 520 | width: 100px; 521 | } 522 | .today-weather h3 { 523 | font-size: 40px; 524 | } 525 | .city { 526 | min-height: 450px; 527 | } 528 | .title h2 { 529 | font-size: 25px; 530 | } 531 | .title h3 { 532 | font-size: 14px; 533 | } 534 | .date-time { 535 | width: 100%; 536 | padding: 0; 537 | } 538 | .dmy { 539 | padding: 0; 540 | margin-bottom: 35px; 541 | text-align: center; 542 | width: 100%; 543 | } 544 | div#txt { 545 | font-size: 30px; 546 | } 547 | .date { 548 | font-size: 22px; 549 | } 550 | .temperature { 551 | text-align: center; 552 | width: 100%; 553 | } 554 | .copyright { 555 | padding: 20px; 556 | } 557 | .temperature p { 558 | font-size: 60px; 559 | padding-bottom: 15px; 560 | } 561 | .forecast-icon img { 562 | width: 65px; 563 | } 564 | .today-weather h3 { 565 | font-size: 30px; 566 | } 567 | .copyright p { 568 | line-height: 25px; 569 | font-size: 13px; 570 | } 571 | .container { 572 | height: 60vh; 573 | margin-top: 60px; 574 | } 575 | .mb-icon { 576 | top: 20% !important; 577 | display: block !important; 578 | } 579 | .forecast-icon, 580 | .today-weather h3 { 581 | display: none; 582 | } 583 | .today-weather { 584 | background-color: rgba(0, 0, 0, 0.73); 585 | margin-top: 22px; 586 | padding: 25px 0px; 587 | } 588 | } 589 | 590 | @media screen and (max-width: 375px) { 591 | h1 { 592 | font-size: 26px; 593 | line-height: 1.5em; 594 | letter-spacing: 0; 595 | } 596 | .city { 597 | min-height: 315px; 598 | } 599 | .dmy { 600 | margin-bottom: 30px; 601 | } 602 | .date { 603 | font-size: 18px; 604 | } 605 | .temperature p { 606 | padding-bottom: 15px; 607 | } 608 | } 609 | 610 | /*-- //Responsive Code --*/ 611 | .cityHead { 612 | display: flex; 613 | align-items: center; 614 | justify-content: center; 615 | } 616 | .search-box { 617 | display: flex; 618 | align-items: center; 619 | justify-content: center; 620 | margin-bottom: 15px; 621 | position: relative; 622 | z-index: 2; 623 | } 624 | .search-box .img-box { 625 | background: rgb(255, 255, 255, 0.2); 626 | border-radius: 50%; 627 | height: 32px; 628 | width: 35px; 629 | display: flex; 630 | align-items: center; 631 | justify-content: center; 632 | padding: 2px; 633 | } 634 | .search-box img { 635 | width: 60%; 636 | cursor: pointer; 637 | } 638 | .search-box .search-bar { 639 | border: none; 640 | padding: 10px 11px; 641 | background: transparent; 642 | color: white; 643 | border-bottom: 1px solid; 644 | font-size: 16px; 645 | } 646 | .search-box .search-bar::placeholder { 647 | color: white; 648 | } 649 | .search-bar:focus { 650 | outline: none; 651 | border-bottom: 1px solid gray; 652 | transition: all 1s ease-in-out; 653 | } 654 | .mb-icon { 655 | height: 100%; 656 | position: absolute; 657 | top: 34%; 658 | left: 36%; 659 | z-index: 1; 660 | display: none; 661 | } 662 | .mb-icon p { 663 | color: white; 664 | width: fit-content; 665 | position: relative; 666 | left: 24%; 667 | top: 2%; 668 | font-size: 25px; 669 | } 670 | .footer-info { 671 | color: white; 672 | } 673 | .footer-info a { 674 | color: floralwhite; 675 | font-weight: bold; 676 | } 677 | .hh_button { 678 | display: inline-block; 679 | text-decoration: none; 680 | background: linear-gradient(to right, #ff8a00, #da1b60); 681 | border: none; 682 | color: white; 683 | padding: 10px 25px; 684 | font-size: 1rem; 685 | border-radius: 3px; 686 | cursor: pointer; 687 | font-family: "Roboto", sans-serif; 688 | position: relative; 689 | margin-top: 30px; 690 | margin: 0px; 691 | position: absolute; 692 | right: 20px; 693 | top: 1.5%; 694 | } 695 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import CurrentLocation from "./currentLocation"; 3 | import "./App.css"; 4 | 5 | function App() { 6 | return ( 7 | 8 |
9 | 10 |
11 |
12 | 13 | Download Source Code 14 | {" "} 15 | | Developed by{" "} 16 | 17 | Gaurav Ghai 18 | {" "} 19 | | Powered by{" "} 20 | 21 | HTML HINTS 22 | 23 |
24 |
25 | ); 26 | } 27 | 28 | export default App; 29 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /src/apiKeys.js: -------------------------------------------------------------------------------- 1 | // Visit https://api.openweathermap.org & then signup to get our API keys for free 2 | module.exports = { 3 | key: "{Your API Key Here}", 4 | base: "https://api.openweathermap.org/data/2.5/", 5 | }; 6 | -------------------------------------------------------------------------------- /src/currentLocation.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import apiKeys from "./apiKeys"; 3 | import Clock from "react-live-clock"; 4 | import Forcast from "./forcast"; 5 | import loader from "./images/WeatherIcons.gif"; 6 | import ReactAnimatedWeather from "react-animated-weather"; 7 | const dateBuilder = (d) => { 8 | let months = [ 9 | "January", 10 | "February", 11 | "March", 12 | "April", 13 | "May", 14 | "June", 15 | "July", 16 | "August", 17 | "September", 18 | "October", 19 | "November", 20 | "December", 21 | ]; 22 | let days = [ 23 | "Sunday", 24 | "Monday", 25 | "Tuesday", 26 | "Wednesday", 27 | "Thursday", 28 | "Friday", 29 | "Saturday", 30 | ]; 31 | 32 | let day = days[d.getDay()]; 33 | let date = d.getDate(); 34 | let month = months[d.getMonth()]; 35 | let year = d.getFullYear(); 36 | 37 | return `${day}, ${date} ${month} ${year}`; 38 | }; 39 | const defaults = { 40 | color: "white", 41 | size: 112, 42 | animate: true, 43 | }; 44 | class Weather extends React.Component { 45 | state = { 46 | lat: undefined, 47 | lon: undefined, 48 | errorMessage: undefined, 49 | temperatureC: undefined, 50 | temperatureF: undefined, 51 | city: undefined, 52 | country: undefined, 53 | humidity: undefined, 54 | description: undefined, 55 | icon: "CLEAR_DAY", 56 | sunrise: undefined, 57 | sunset: undefined, 58 | errorMsg: undefined, 59 | }; 60 | 61 | componentDidMount() { 62 | if (navigator.geolocation) { 63 | this.getPosition() 64 | //If user allow location service then will fetch data & send it to get-weather function. 65 | .then((position) => { 66 | this.getWeather(position.coords.latitude, position.coords.longitude); 67 | }) 68 | .catch((err) => { 69 | //If user denied location service then standard location weather will le shown on basis of latitude & latitude. 70 | this.getWeather(28.67, 77.22); 71 | alert( 72 | "You have disabled location service. Allow 'This APP' to access your location. Your current location will be used for calculating Real time weather." 73 | ); 74 | }); 75 | } else { 76 | alert("Geolocation not available"); 77 | } 78 | 79 | this.timerID = setInterval( 80 | () => this.getWeather(this.state.lat, this.state.lon), 81 | 600000 82 | ); 83 | } 84 | 85 | componentWillUnmount() { 86 | clearInterval(this.timerID); 87 | } 88 | 89 | // tick = () => { 90 | // this.getPosition() 91 | // .then((position) => { 92 | // this.getWeather(position.coords.latitude, position.coords.longitude) 93 | // }) 94 | // .catch((err) => { 95 | // this.setState({ errorMessage: err.message }); 96 | // }); 97 | // } 98 | 99 | getPosition = (options) => { 100 | return new Promise(function (resolve, reject) { 101 | navigator.geolocation.getCurrentPosition(resolve, reject, options); 102 | }); 103 | }; 104 | getWeather = async (lat, lon) => { 105 | const api_call = await fetch( 106 | `${apiKeys.base}weather?lat=${lat}&lon=${lon}&units=metric&APPID=${apiKeys.key}` 107 | ); 108 | const data = await api_call.json(); 109 | this.setState({ 110 | lat: lat, 111 | lon: lon, 112 | city: data.name, 113 | temperatureC: Math.round(data.main.temp), 114 | temperatureF: Math.round(data.main.temp * 1.8 + 32), 115 | humidity: data.main.humidity, 116 | main: data.weather[0].main, 117 | country: data.sys.country, 118 | // sunrise: this.getTimeFromUnixTimeStamp(data.sys.sunrise), 119 | 120 | // sunset: this.getTimeFromUnixTimeStamp(data.sys.sunset), 121 | }); 122 | switch (this.state.main) { 123 | case "Haze": 124 | this.setState({ icon: "CLEAR_DAY" }); 125 | break; 126 | case "Clouds": 127 | this.setState({ icon: "CLOUDY" }); 128 | break; 129 | case "Rain": 130 | this.setState({ icon: "RAIN" }); 131 | break; 132 | case "Snow": 133 | this.setState({ icon: "SNOW" }); 134 | break; 135 | case "Dust": 136 | this.setState({ icon: "WIND" }); 137 | break; 138 | case "Drizzle": 139 | this.setState({ icon: "SLEET" }); 140 | break; 141 | case "Fog": 142 | this.setState({ icon: "FOG" }); 143 | break; 144 | case "Smoke": 145 | this.setState({ icon: "FOG" }); 146 | break; 147 | case "Tornado": 148 | this.setState({ icon: "WIND" }); 149 | break; 150 | default: 151 | this.setState({ icon: "CLEAR_DAY" }); 152 | } 153 | }; 154 | 155 | render() { 156 | if (this.state.temperatureC) { 157 | return ( 158 | 159 |
160 |
161 |

{this.state.city}

162 |

{this.state.country}

163 |
164 |
165 | {" "} 166 | 172 |

{this.state.main}

173 |
174 |
175 |
176 |
177 |
178 | 179 |
180 |
{dateBuilder(new Date())}
181 |
182 |
183 |

184 | {this.state.temperatureC}°C 185 |

186 | {/* / 187 | {this.state.temperatureF} °F */} 188 |
189 |
190 |
191 | 192 |
193 | ); 194 | } else { 195 | return ( 196 | 197 | 198 |

199 | Detecting your location 200 |

201 |

202 | Your current location wil be displayed on the App

& used 203 | for calculating Real time weather. 204 |

205 |
206 | ); 207 | } 208 | } 209 | } 210 | 211 | export default Weather; 212 | -------------------------------------------------------------------------------- /src/forcast.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, Component } from "react"; 2 | import axios from "axios"; 3 | import apiKeys from "./apiKeys"; 4 | import ReactAnimatedWeather from "react-animated-weather"; 5 | 6 | function Forcast(props) { 7 | const [query, setQuery] = useState(""); 8 | const [error, setError] = useState(""); 9 | const [weather, setWeather] = useState({}); 10 | 11 | const search = (city) => { 12 | axios 13 | .get( 14 | `${apiKeys.base}weather?q=${ 15 | city != "[object Object]" ? city : query 16 | }&units=metric&APPID=${apiKeys.key}` 17 | ) 18 | .then((response) => { 19 | setWeather(response.data); 20 | setQuery(""); 21 | }) 22 | .catch(function (error) { 23 | console.log(error); 24 | setWeather(""); 25 | setQuery(""); 26 | setError({ message: "Not Found", query: query }); 27 | }); 28 | }; 29 | function checkTime(i) { 30 | if (i < 10) { 31 | i = "0" + i; 32 | } // add zero in front of numbers < 10 33 | return i; 34 | } 35 | 36 | const defaults = { 37 | color: "white", 38 | size: 112, 39 | animate: true, 40 | }; 41 | 42 | useEffect(() => { 43 | search("Delhi"); 44 | }, []); 45 | 46 | return ( 47 |
48 |
49 | 55 |
56 |
57 |

{props.weather}

58 |
59 | setQuery(e.target.value)} 64 | value={query} 65 | /> 66 |
67 | {" "} 68 | 72 |
73 |
74 |
    75 | {typeof weather.main != "undefined" ? ( 76 |
    77 | {" "} 78 |
  • 79 |

    80 | {weather.name}, {weather.sys.country} 81 |

    82 | 86 |
  • 87 |
  • 88 | Temperature{" "} 89 | 90 | {Math.round(weather.main.temp)}°c ({weather.weather[0].main}) 91 | 92 |
  • 93 |
  • 94 | Humidity{" "} 95 | 96 | {Math.round(weather.main.humidity)}% 97 | 98 |
  • 99 |
  • 100 | Visibility{" "} 101 | 102 | {Math.round(weather.visibility)} mi 103 | 104 |
  • 105 |
  • 106 | Wind Speed{" "} 107 | 108 | {Math.round(weather.wind.speed)} Km/h 109 | 110 |
  • 111 |
    112 | ) : ( 113 |
  • 114 | {error.query} {error.message} 115 |
  • 116 | )} 117 |
118 |
119 |
120 | ); 121 | } 122 | export default Forcast; 123 | -------------------------------------------------------------------------------- /src/images/WeatherIcons.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravghai/weatherApp-Reactjs/7915d8b4dd2fd8b80f55e72098870f38e3607362/src/images/WeatherIcons.gif -------------------------------------------------------------------------------- /src/images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravghai/weatherApp-Reactjs/7915d8b4dd2fd8b80f55e72098870f38e3607362/src/images/background.jpg -------------------------------------------------------------------------------- /src/images/background1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravghai/weatherApp-Reactjs/7915d8b4dd2fd8b80f55e72098870f38e3607362/src/images/background1.jpg -------------------------------------------------------------------------------- /src/images/city.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravghai/weatherApp-Reactjs/7915d8b4dd2fd8b80f55e72098870f38e3607362/src/images/city.jpg -------------------------------------------------------------------------------- /src/images/city1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravghai/weatherApp-Reactjs/7915d8b4dd2fd8b80f55e72098870f38e3607362/src/images/city1.jpg -------------------------------------------------------------------------------- /src/images/forecast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gauravghai/weatherApp-Reactjs/7915d8b4dd2fd8b80f55e72098870f38e3607362/src/images/forecast.png -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want your app to work offline and load faster, you can change 15 | // unregister() to register() below. Note this comes with some pitfalls. 16 | // Learn more about service workers: https://bit.ly/CRA-PWA 17 | serviceWorker.unregister(); 18 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' }, 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready 134 | .then(registration => { 135 | registration.unregister(); 136 | }) 137 | .catch(error => { 138 | console.error(error.message); 139 | }); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | --------------------------------------------------------------------------------