Weather Project - Max Iriye, Natasha Razmadze#4
Weather Project - Max Iriye, Natasha Razmadze#4NataliaRaz wants to merge 10 commits intoAda-C23:mainfrom
Conversation
yangashley
left a comment
There was a problem hiding this comment.
Nice job on weather-report, team!
| <span id="increaseTempControl">⬆️</span> | ||
| <span class="red" id="tempValue">80</span> | ||
| <span id="decreaseTempControl">⬇️</span> |
There was a problem hiding this comment.
I've seen a couple other examples of folks using span tags for these buttons. Did we provide an example with this kind of syntax? I'm guessing we did...
Personally, I'd prefer the more semantic button elements here for accessibility purposes since span is kind of 'meaningless'.
| @@ -0,0 +1,109 @@ | |||
| const API_KEY = 'http://localhost:5000'; | |||
There was a problem hiding this comment.
Nice job using a constant variable to reference a string which makes your code more readable and also in the long run more maintainable because we can look at the top of the file for the variable to update the string (like for example, if the port number changes and we have to update the endpoint). Then we could avoid combing through lots of code to make a small update.
Technically, the string referred to by this variable is not an API key, but an base endpoint.
| const API_KEY = 'http://localhost:5000'; | |
| const BASE_URL = 'http://localhost:5000'; |
| const increaseTemp = () => { | ||
| const tempElement = document.querySelector('#tempValue'); | ||
| let currentTemp = Number(tempElement.innerHTML); | ||
| currentTemp++; | ||
| tempElement.innerHTML = currentTemp; | ||
| setTempColor(currentTemp); | ||
| setLandscape(currentTemp); | ||
| }; | ||
|
|
||
| const decreaseTemp = () => { | ||
| const tempElement = document.querySelector('#tempValue'); | ||
| let currentTemp = Number(tempElement.innerHTML); | ||
| currentTemp--; | ||
| tempElement.innerHTML = currentTemp; | ||
| setTempColor(currentTemp); | ||
| setLandscape(currentTemp) | ||
| }; |
There was a problem hiding this comment.
The logic between these 2 methods are pretty similar. Consider combining them into one method and having some logic to determine if you need to increment or decrement the weather.
| if (currentTemp >= 80) { | ||
| landscapeElement.innerHTML = '🌵__🐍_🦂_🌵🌵__🐍_🏜_🦂'; | ||
| } else if (currentTemp >= 70) { | ||
| landscapeElement.innerHTML = '🌸🌿🌼__🌷🌻🌿_☘️🌱_🌻🌷'; | ||
| } else if (currentTemp >= 60) { | ||
| landscapeElement.innerHTML = '🌾🌾_🍃_🪨__🛤_🌾🌾🌾_🍃'; | ||
| } else { | ||
| landscapeElement.innerHTML = '🌲🌲⛄️🌲⛄️🍂🌲🍁🌲🌲⛄️🍂🌲'; | ||
| } |
There was a problem hiding this comment.
You could create an object that has color data, landscape data, etc for each temperature. Then you could use a loop to go through the object instead of having if/else if/else, which would make the function more concise and look something like:
const TEMP_DATA = {
90: {
color: 'red',
landscape: '🌵__🐍_🦂_🌵🌵__🐍_🏜_🦂'
},
70: { // other data, etc...}
}
for (const [temp, values] of Object.entries(TEMP_DATA)) {
if (currentTemp >= temp) { // this condition needs refactoring, but you get the idea
state.temp.className = value.color;
state.landscape.textContent = value.icon;
}
}Then you can move away from having a brittle implementation that can be tricky to make changes to.
| const setTempColor = (currentTemp) => { | ||
| const tempElement = document.querySelector('#tempValue'); | ||
| tempElement.classList.remove('red', 'orange', 'yellow', 'green', 'teal'); | ||
|
|
||
| if (currentTemp >= 80) { | ||
| tempElement.classList.add('red'); | ||
| } else if (currentTemp >= 70) { | ||
| tempElement.classList.add('orange'); | ||
| } else if (currentTemp >= 60) { | ||
| tempElement.classList.add('yellow'); | ||
| } else if (currentTemp >= 50) { | ||
| tempElement.classList.add('green'); | ||
| } else { | ||
| tempElement.classList.add('teal'); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Like my comment above, what if you looped over an object with data so you could move away from using if/else if/else?
| const skyElement = document.querySelector('#sky'); | ||
| const skyOptions = ["☁️ ☁️ ☁️ ☀️ ☁️ ☁️", "☁️☁️ ☁️ ☁️☁️ ☁️ 🌤 ☁️ ☁️☁️", "🌧🌈⛈🌧🌧💧⛈🌧🌦🌧💧🌧🌧", "🌨❄️🌨🌨❄️❄️🌨❄️🌨❄️❄️🌨🌨"] | ||
| skyElement.innerHTML = skyOptions[event.target.value] |
There was a problem hiding this comment.
Nice job using a data structure to get the value instead of using if/else if/else!
| setTempColor(cityTempFaren); | ||
| setLandscape(cityTempFaren); |
There was a problem hiding this comment.
There are 3 other places that repeat setTempColor and setLandscape. You could create a helper like setDisplayForTemperature that invokes these 2 methods. It's simple enough logic that I think it's ok as is, but also introducing setDisplayForTemperature would make the code a little more self-documenting.
| const cityElement = document.querySelector('#headerCityName'); | ||
| const cityName = cityElement.innerHTML; | ||
|
|
||
| const cityLocationInfo = await axios.get(`${API_KEY}/location?q=${cityName}`); | ||
|
|
||
| const tempElement = document.querySelector('#tempValue'); | ||
| const cityLat = cityLocationInfo.data[0].lat; | ||
| const cityLon = cityLocationInfo.data[0].lon; | ||
|
|
||
| const cityTempInfo = await axios.get(`${API_KEY}/weather?lat=${cityLat}&lon=${cityLon}`) | ||
|
|
||
| const cityTempKelvin = cityTempInfo.data.main.temp; | ||
| const cityTempFaren = Math.round((cityTempKelvin * 1.8) - 459.67); | ||
|
|
||
| tempElement.innerHTML = cityTempFaren; |
There was a problem hiding this comment.
Could also separate these 2 chunks of logic so you have a helper function getCityLatLon and getTempFromLatLon.
This does work, but imagine the logic for getting live temperature changes. Instead of digging through one larger function, it would be easier to refactor a single-responsibility helper function.
| const increaseButton = document.querySelector('#increaseTempControl'); | ||
| increaseButton.addEventListener('click', increaseTemp); | ||
|
|
||
| const decreaseButton = document.querySelector('#decreaseTempControl'); | ||
| decreaseButton.addEventListener('click', decreaseTemp); | ||
|
|
||
| const cityField = document.querySelector('#cityNameInput'); | ||
| cityField.addEventListener('change', cityInput); | ||
|
|
||
| const getTempButton = document.querySelector('#currentTempButton'); | ||
| getTempButton.addEventListener('click', setTempFromCity) | ||
|
|
||
| const skyElement = document.querySelector('#skySelect'); | ||
| skyElement.addEventListener("change", setSky) | ||
|
|
||
| const cityReset = document.querySelector('#cityNameReset'); | ||
| cityReset.addEventListener('click', resetCity); No newline at end of file |
There was a problem hiding this comment.
Nice job putting all the event handler registration logic in one place, this makes it easier to follow along and I know I only need to look in one place to find something related to registering a handler.
I'd prefer that the logic on lines 93-109 be put in a helper function, like registerEventHandlers and then you create an onLoaded helper function that executes all the code that needs to happen on page load.
The below example makes it easier to understand that there is code that should execute when the page first loads.
const registerEventHandlers = () => {
const increaseButton = document.querySelector('#increaseTempControl');
increaseButton.addEventListener('click', increaseTemp);
const decreaseButton = document.querySelector('#decreaseTempControl');
decreaseButton.addEventListener('click', decreaseTemp);
const cityField = document.querySelector('#cityNameInput');
cityField.addEventListener('change', cityInput);
const getTempButton = document.querySelector('#currentTempButton');
getTempButton.addEventListener('click', setTempFromCity)
const skyElement = document.querySelector('#skySelect');
skyElement.addEventListener("change", setSky)
const cityReset = document.querySelector('#cityNameReset');
cityReset.addEventListener('click', resetCity);
};
const onLoaded = () => {
registerEventHandlers();
};
onLoaded();| const cityField = document.querySelector('#cityNameInput'); | ||
| cityField.value = ''; | ||
|
|
||
| const cityElement = document.querySelector('#headerCityName'); |
There was a problem hiding this comment.
document.querySelector('#headerCityName'); appears in your code 3 times. While it's not a ton of repetition, it still is three function calls and these calls aren't complex, time intensive operations.
However, each time we type it, we could introduce a bug.
I'd prefer a global variable that can be referenced throughout the file or create an object with all the elements you'll need, like we did in our livecode: https://github.com/Ada-Activities/Pick-Me-Up-Pup/blob/c23-solution/src/index.js#L4-L10
No description provided.