Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
43 changes: 23 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
# 🚀 Project: Complex NASA API

### Goal: Use NASA's API to return all of their facility locations (~400). Display the name of the facility, its location, and the weather at the facility currently.

### How to submit your code for review:

- Fork and clone this repo
- Create a new branch called answer
- Checkout answer branch
- Push to your fork
- Issue a pull request
- Your pull request description should contain the following:
- (1 to 5 no 3) I completed the challenge
- (1 to 5 no 3) I feel good about my code
- Anything specific on which you want feedback!

Example:
```
I completed the challenge: 5
I feel good about my code: 4
I'm not sure if my constructors are setup cleanly...
```
_Goal: Use NASA's API to return all of their facility locations (~400). Display the name of the facility, its location, and the weather at the facility currently._

<hr>

## Tech Used

HTML, CSS, JavaScript, Openweather and Nasa APIs.

<hr>

<img src="./Screenshot 2025-11-10 at 6.26.19 PM.png">

<hr>

[Rendered project here](https://godwinkamau.github.io/complex-nasa/)

<hr>

## Lessons Learned

- Sometimes, APIs just don't work. That's when you use a cors proxy to work around the obstacles and keep on trucking.
- Using fetch api to process large amounts of information effectively
- Using promises to control the flow of the behavior.
Binary file added Screenshot 2025-11-10 at 6.26.19 PM.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added css/pexels-spacex-60126.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 95 additions & 0 deletions css/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

.banner {
width:100%;
height:300px;
background: rgb(0, 0, 166);
color:white;
text-align: center;
display: flex;
flex-direction: column;
gap: 15px;
align-items: center;
justify-content: center;
padding:0 15px;
}

.words {
max-width:80%;
text-shadow: 1px 1px 1px black;
}

button {
padding:12px;
background-color: azure;
}

.banner p{
font-size: 2rem;
}

table {
margin:10px auto;
background-color: rgba(255,255,255,.5);
border-collapse: collapse;
}

td{
padding:10px;
border:1px solid black;
}

img {
position: fixed;
top:0;
left:0;
z-index: -1;
object-fit: cover;
}
21 changes: 21 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nasa Facility Info</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<section class="banner">
<section class="words">
<p>Here at NASA, we know, in order to succeed, we must conquer our greatest enemy, the sky. Thus, we keep up to date information on how this menace is plaguing our centres 24/7. Click the button below to find the latest information on our areas.</p>
</section>
<button>Press to Update</button>
</section>

<img src="css/pexels-spacex-60126.jpg" alt="picture of a rocket,probably spaceX">

<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
145 changes: 145 additions & 0 deletions js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
///////// INTRO TO MY ISSUE: I've made this object in the doxxNasa function, but I'm having trouble calling the weather list after I pass it to the next function. I've put a console.log so you can see the object after its made.

const apiKey = 'ae194c9fd4f9c372a84ee9d9568b0d6f'

document.querySelector('button').addEventListener('click',doxxNasa)

//making the object
function doxxNasa() {
let centers = {}
fetch('https://corsproxy.io/?url=https://data.nasa.gov/docs/legacy/gvk9-iz74.json')
.then(res => res.json())
.then(data => {
// organize the data received into an object, minimizing the amount of calls later on


data.forEach(point => {
////consolidate the facilities into their respective centers
// initialize new key value pair if the center is not in object
if (!Object.keys(centers).includes(point.center)){

// add the location and facilities list upon initialization(courtesy of Michael Kazin)
centers[point.center] = {facilities : [],location:point.location}
centers[point.center].facilities.push(point.facility)


} else {

// add facility to the list of facilities in the specific location
centers[point.center].facilities.push(point.facility)

}
})
findWeather(centers)


// makeTable(centers)
})
.catch(err=>console.log(err))

}

function findWeather(centers) {
//Had to cave in to chatGPT to learn about promises, I needed that information to properly form the object without running into undefined errors
// Create an array of promises
const weatherPromises = Object.values(centers).map(value => {
return fetch(`https://api.openweathermap.org/data/2.5/weather?lat=${value.location.latitude}&lon=${value.location.longitude}&units=imperial&appid=${apiKey}`)
.then(res => res.json())
.then(data => {
value.location.city = data.name;
value.location.temp = data.main.temp;
value.location.weather = data.weather[0].description;
})
.catch(err => console.log(err));
});

// Wait for all weather fetches to complete
Promise.all(weatherPromises)
.then(() => {
makeTable(centers);
});
}


function makeTable(centers) {
console.log(centers['Kennedy Space Center'].location.city)
// console.log('Centers',centers)
//// THIS IS WHERE MY TROUBLE STARTS /////////
//I'm trying to call the weather object's list, but I keep getting undefined
if (document.getElementById('table')) {
let deleteTable = document.getElementById('table')
deleteTable.parentNode.removeChild(deleteTable)
}

let table = document.createElement('table')
table.id = 'table'


for (const[key,value] of Object.entries(centers)) {
// console.log([key,value])
value.facilities.forEach(facility => {
// console.log(facility)
let row = table.insertRow()

for (let i = 0; i<5 ; i++) {
const newCell = row.insertCell()
if (i==0){
newCell.textContent = facility
} else if(i===1) {
newCell.textContent = key
} else if (i ===2) {
newCell.textContent = value.location.city
} else if (i === 3) {
newCell.textContent = value.location.weather
} else if (i === 4) {
newCell.textContent = value.location.temp
}
}


}
)

}
document.body.appendChild(table);
}

// centers['test1']= 'boo'
// fetch(`https://api.openweathermap.org/data/2.5/weather?lat=${centers[point.center].location.latitude}&lon=${centers[point.center].location.longitude}&units=imperial&appid=${apiKey}`)
// .then (res => res.json())
// .then(data => {
// // place location, temperature, and weather in the same center object
// centers['test2']='oob'
// centers[point.center].weather = {'city location' : data.name, 'temp' :data.main.temp , 'weather' : data.weather[0].description}
// })
// .catch(err => console.log(err))

// const nasaUrl = `https://corsproxy.io/?url=https://data.nasa.gov/docs/legacy/gvk9-iz74.json`

// const facilities = document.querySelector('#facilities')
// const loc = document.querySelector('#location')

// // i did have trouble using async syntax and for loops, so i applied hector's strategy of using the basic fetch syntax

// fetch(nasaUrl)
// .then(res =&gt; res.json()) // parse response as JSON
// .then(nasaData =&gt; {
// nasaData.forEach((x, i) =&gt; {
// const lat = nasaData[i].location.latitude
// const lon = nasaData[i].location.longitude
// const weatherUrl = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&amp;lon=${lon}&amp;APPID=0e904a2a7aacc8772e00052c29bf80c8`;
// fetch(weatherUrl)
// .then(res =&gt; res.json()) // parse response as JSON
// .then(weatherData =&gt; {

// facilities.innerHTML += ` ${nasaData[i].facility} || ${lat} ${lon} || Temp: ${(((weatherData.main.temp - 273.15) * 1.8) + 32).toFixed(1)} F | Humidity: ${weatherData.main.humidity} | Sky: ${weatherData.weather[0].description}`

// })
// .catch(err =&gt; {
// console.log(`error ${err}`)
// });
// })
// })
// .catch(err =&gt; {
// console.log(`error ${err}`)
// });