"That Is So Fetch": Weather API Webapp
Tags: api, webdev, javascript, learning
Published: 2023-04-07 08:11:35

![Map of the world from Pixabay][Photo by Pixabay](Photo by Pixabay: https://www.pexels.com/photo/black-textile-41949/) [The fetch quote is a reference to the 90s movie "Mean Girls" said by the Gretchen Wieners character]

## Getting Started
Hello, internet. This article will detail my process through building a "simple" API fetch web app for the first time. I struggled through not only the CSS not centering due to parent issues, but also JavaScript fetch issues. As I go through my process, I will try to provide ways I could have done this in a more efficient way. I had a project partner but will be talking in the first person the entire article. (Assume "I" and "We" is interchangeable. Both of us take credit equally and could explain it) (TLDR: Here is a weather app built using vanilla js, html, css (https://jstellmacher.github.io/Weatherboys/))
**FORWARNING**
I am new to javascript as of a month ago so please do not use this as a reference for your code. It may not work for you due to my lack of experience. I will strive to learn and grow though! (I changed some of the variable names just so it cannot be copied and pasted)

To begin, we created the repository as seen below. 

![Github new repo in top right](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m0lcx9nb2ve8fp09009w.png)

From there, we named it "Weatherboys". We added an automatic ReadMe just incase we wanted to add specific instructions on the app or things that we learned during the process. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nie6ea9nwv6n821u3qru.png)

After setting up the repository, we cloned the actual repository so we would both have it on our Githubs. (This was an issue) Below are two diagrams created in Draw.io that displays the current progression (top) and the second is best practices.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vqwe7lkj5i15z6j6y6he.png)

The second diagram is the correct way to do it because it makes less merge conflicts as well as cuts down the need to continuously git push to two different repositories.
***

## Choose an API
Finding an API was easy. Pick an idea of what you want to do, and you will most likely find an API for it. We found a compilation of APIs on a GitHub repository linked [HERE](https://github.com/toddmotto/public-apis) Shout out to Todd, Thanks! All of these are public APIs. If you cannot find what you are looking for here, just Google it.

For my first project, I wanted to have an intermediate challenge. (That is definitely what I got) Weather Apps may not seem difficult, but this one has been a struggle. Our criteria for the class was have 3 or more js event listeners, fetch from an API, and incorporate current best practices. 

The very abbreviated steps are outlined below:
1. Boiler plate (normie jargon: boiler plate = template) HTML, CSS Here is a link to FreeCodeCamp (https://www.freecodecamp.org/news/whats-boilerplate-and-why-do-we-use-it-let-s-check-out-the-coding-style-guide-ac2b6c814ee7/) (Which is an amazing resource btw)
2. Make nav, body, footer and start building out buttons, forms, and div boxes to interact with using your js later
3. Git add . , git commit -m "updates css", git push (Just do it often. You do not want to lose your code)
4. Wireframe / Outline how your app will function (Ours is ^ right before this list)
5. Build out the js: Fetch - Is your data console logging?
   ```
   const fetchWeather = (lat, long) => {
     fetch(
       `https://api.open-meteo.com/v1/forecast? 
latitude=${lat}&longitude=${long}&daily=temperature_2m_max,temperature_2m_min,sunrise,sunset,precipitation_sum,windspeed_10m_max&temperature_unit=fahrenheit&windspeed_unit=mph&precipitation_unit=inch&forecast_days=1&timezone=America%2FDenver`
     )
       .then((r) => r.json())
       .then(displayData);
     // .then(console.log("hello"));
   };
   ```
6\. Take a break from your struggles with js and make your app look pretty using CSS (Below is code that will help you have overall conformity in your app. Shove this in your style.css)
   ```
*{
margin:0;
padding:0;
font-family;
}
/* This is how you comment out a line also below is a good way to build a normal div box that centers the text */
div{
margin: auto;
width: 2vw;
border: 2px solid black;
padding: 10px;
}
/* The div above will center things vertically and horizontally but sometimes it will get messed up due to a parent div so watch out for that! The width has a vw. This means view width, it is a measurement that I like because it uses your screen's size to determine its size. The number before it is 2 which means 2% of the view width! */
   ```
7\. Back to js: Now that you can fetch data, and your app looks prettier, lets make event listeners!
```
const variable = document.addEventListener("click", () => {
  const submitClick = document.querySelector("submitBtn");
});
//You need to communicate with the DOM in order to create events in the variable above, we are telling it to listen for clicks to the submitBtn. Next we are going to make it do something after you click it
const variable2 = document.addEventListener("submit", (e) => {
e.preventDefault();
  const submitForm = document.querySelector("submit");
});
//This variable2 will submit a form. It is passing "e" as a parameter. After that we are preventing the default of the browser from occurring. This will prevent the page from reloading and losing the End User's data in the form. 
```
8\. Now, we need an event listener that tracks your mouse hovering over a div. The goal is to show extra fun weather detail.
```
const variable3 = document.addEventListener("onmouseenter", () => {
  const hover = document.querySelector("moreData");
hover.nextThing.otherThing = hover.
});
const variable4 = document.addEventListener("onmouseleave", () => {
  const disappear = document.querySelector("moreData");
});
```
9\. Now that I have 3 events and my data loads, I need to tackle the zip code and convert it to latitude and longitude. The API I am using requires latitude and longitude to find the weather data so I want to be able to allow the End User to simply put in a zip code and get the weather data from that location they put in. If I wanted it to be simple, I would make the user search their own latitude and longitude to input. Some ways to make this work is by using Google geolocation API and fetch from it anytime someone puts it in my form. Then I would have it linked to my getlocation function which in turn triggers the correct data to show up. 
10\. Lastly, make sure that your app loads and looks pretty.
---
Below is a picture of the process of the app.
![barebones app many hues of blue](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/whz02d3ql4pr7i5jer4u.png)
---
##Updates
I have now completed the app according to the rules of my assignment. In order for end users to find the weather they want, I needed to figure out how to convert zip code to latitude and longitude. What I ended up doing was using Google's location API. It is pretty useful. Here is the link [Google API Documentation](https://developers.google.com/maps/documentation/geocoding/get-api-key)

The code to do this was not too complicated but it felt like many steps. What I started with was an eventlistener for a "submit". When someone put their zipcode or city in the input area, I wanted something to happen. Next, I used `search.addEventListener("submit", (e) => {
  e.preventDefault();
  console.log(e.target[0].value);`

```
fetch(
    "https://maps.googleapis.com/maps/api/geocode/json?address=" +
      e.target[0].value +
      "&key=" +
      "INSERT YOUR API KEY HERE"
  )
```
In the code above, I am using a fetch within my event listener. It grabs any value inputted from the user. In my case in accordance with my code, it is the "e.target[0].value" that allowed me to "pinpoint" the information I needed to fetch from the API. 

I followed that with an If Else statement because if someone misspelled an address or the database did not have the information, I wanted them to get an error. This can be seen by the code below.

```
.then((response) => response.json())
    .then((data) => {
      // debugger;
      if (data.results.length === 0){
        alert("Please Use Different Location")
      } else {
        const latitude = data.results[0].geometry.location.lat;
        const longitude = data.results[0].geometry.location.lng;
        // console.log({ latitude, longitude });
        error.textContent = `Latitude:  
        ${latitude}
        
        Longitude:  
        ${longitude}`;
}
e.target[0].value = "";
    })
});
```
At the beginning, my API was not working. The reason for that was because I did not read Google's documentation well enough and also did not look at their DOM elements closely. For example, in the code above, I created a variable of latitude and what it equals is "data.results[0].geometry.location.lat" This was messed up because I was not specifying where in their array the code was. ie.) "results[0]" It was in the zeroth place in the array.

I ran into other issues such as making the app responsive because I did not format the CSS correctly. The best way to do that is make most of your sizing units the same. I will use 'vh' and 'vw'. These stand for view height and view width, respectively. Not only using those, but also using the following code, it will help the app be more responsive. Just make sure that you further customize it. 

```
[class*="col-"] {
  width: 100%;
}

@media only screen and (min-width: 600px) {
  /* For tablets: */
  .col-s-1 {width: 8.33%;}
  .col-s-2 {width: 16.66%;}
  .col-s-3 {width: 25%;}
  .col-s-4 {width: 33.33%;}
  .col-s-5 {width: 41.66%;}
  .col-s-6 {width: 50%;}
  .col-s-7 {width: 58.33%;}
  .col-s-8 {width: 66.66%;}
  .col-s-9 {width: 75%;}
  .col-s-10 {width: 83.33%;}
  .col-s-11 {width: 91.66%;}
  .col-s-12 {width: 100%;}
}
@media only screen and (min-width: 768px) {
  /* For desktop: */
  .col-1 {width: 8.33%;}
  .col-2 {width: 16.66%;}
  .col-3 {width: 25%;}
  .col-4 {width: 33.33%;}
  .col-5 {width: 41.66%;}
  .col-6 {width: 50%;}
  .col-7 {width: 58.33%;}
  .col-8 {width: 66.66%;}
  .col-9 {width: 75%;}
  .col-10 {width: 83.33%;}
  .col-11 {width: 91.66%;}
  .col-12 {width: 100%;}
}
```
[Thank you https://www.w3schools.com/ for allowing me to use this for educational purposes]

In our current society, mobile design first and pc design second is a current trend. Many users will open sites on their mobile before even thinking about opening it on a larger computer. In my project, I do not use all of the columns like the example above. I also do not use percentages. I think I as I continue to learn software development, I will update all of the weather app. I may re-create it using React. [TBD]

<hr>

## Final Thoughts

For a first project, I am proud of myself. I am very thankful for my instructor for guiding me through a few of the rough parts. This app looks incredibly choppy right now and functions that way but I will add to it a lot. I am learning now that the documentation needs a lot of work (this article included) but the whole point of this is to have a good starting base to compare to as I grow!

I will go more in-depth on the event listeners and converting the zip code to longitude and latitude as I update the app.  Thank you for reading! Hope to see you again. - J