This is a solution to the Weather app challenge on Frontend Mentor. Frontend Mentor challenges help you improve your coding skills by building realistic projects.
Users should be able to:
- Search for weather information by entering a location in the search bar
- View current weather conditions including temperature, weather icon, and location details
- See additional weather metrics like "feels like" temperature, humidity percentage, wind speed, and precipitation amounts
- Browse a 7-day weather forecast with daily high/low temperatures and weather icons
- View an hourly forecast showing temperature changes throughout the day
- Switch between different days of the week using the day selector in the hourly forecast section
- Toggle between Imperial and Metric measurement units via the units dropdown
- View the optimal layout for the interface depending on their device's screen size
- See hover
and focus(I used the default focus states) states for all interactive elements on the page -
Switch between specific temperature units (Celsius and Fahrenheit) and measurement units for wind speed (km/h and mph) and precipitation (millimeters) via the units dropdownI decided to not implement this feature because it would complicate the code base and (almost) the same functionality can be achieved using the imperial-metric toggle.
- URL: https://florianstancioiu.github.io/weather-app/
- Storybook URL: https://florianstancioiu.github.io/weather-app/storybook/
- Frontend Mentor URL: https://www.frontendmentor.io/solutions/weather-app-with-react-and-typescript-p4BuSm6GJ7
- Semantic HTML5 markup
- Accessibility features
- CSS custom properties
- Flexbox
- CSS Grid
- Mobile-first workflow
- React - JS library
- TypeScript - JavaScript with types
- Storybook - Build, test & document components
- React Testing Library - For testing
- TailwindCSS - For styles
- Vite - Build tool
- I learned how to generate the test coverage report using Vitest and Istanbul
- I learned stuff about making websites keyboard and visually accessible (though I don't think I used the best approach when making the app keyboard accessible, it works, but the code is not the best it can be)
- I learned how to create custom hooks in React (I kinda knew this one already but I'm glad I practiced it in this project)
- I learned that storybook can test for accessibility issues
- I learned to use the Geolocation Web API in order to get the current location of the user
- I learned how to add storybook to Github pages using a custom deploy.yml workflow
- I learned that you can mock/fake a function in Vitest so that the actual function is not triggered directly (fetch)
- I learned (but not actually used in this project) how to create github secret keys
The main challenge I encountered was something to do with the Index.test.tsx file, I tried to make an assertion on the HourlyForecastItem temperature values and they matched correctly on local but failed to do so in Github Actions and the deploy failed, I still haven't managed to fix it, I removed the assertions, I now believe it has something to do with the fact that the API values are wrapped in a Float32Array.
I would also add storybook to this project, I don't know if I will have time until the Frontendmentor Hackathon time runs out, but I think I will add it nonetheless. I added storybook.
- React JS close dropdown using onBlur function - This helped me create a custom hook that I used to close the dropdowns when the user clicks outside of the dropdowns
- Destructuring nullable objects - This helped me solve a TS issue with destructuring nullable objects
- Get all unique values in a JavaScript array (remove duplicates) [duplicate] - This helped me make an array with unique values
- How do you display JavaScript datetime in 12 hour AM/PM format? - This helped me display hours in AM/PM format
- Scroll back to the top of scrollable div - This helped me reset the scroll to the top of the hourly forecast section when selecting a different day
- The Only Accessibility Video You Will Ever Need - Youtube - This helped me understand accessibility for web pages
Geoapify Location Platform: Maps, Geocoding, Routing, and APIs - This helped me do a reverse geocode (turn latitude and longitude into an address) when using the Geolocation Web APII ended up not using this- Bug: too hard to fix "Cannot update a component from inside the function body of a different component." - I keep on seeing this bug when I'm trying to set the data of the UnitsDropdown as a prop instead of a state call, more specifically when I'm trying to update the state that is passed as a prop, it might prove useful to read about it in the future.
- TypeScript: Remove a Property from an Object - This helped me remove a property from an object in Typescript
- useId - This helped me create ids for making the custom dropdowns more accessible
- Wrap stories with extra markup - This helped me pass accessibility for single list elements in Storybook
- How to set classes? - This helped me add custom classes to the body tag in storybook
- What's the best way to convert a number to a string in JavaScript? - This helped turn a number variable to string
- Pressing enter to submit form in react-testing-library does not work - This helped me change the text of an input element in tests
- fireEvent.keyDown not working as expected on my Jest + React Testing Library test - This helped fire an enter key in a input in tests
- Dynamic attribute in ReactJS - This helped me add a dynamic attribute in JSX
- How to make a test that will wait 5 seconds before check element appearance (React testing lib) - This helped me wait for a timer in test files
- Mocking Fetch And Network Requests With Vitest - This helped me mock fetch
- How to "mock" navigator.geolocation in a React Jest Test - This helped me mock navigator.geolocation
- Using secrets in GitHub Actions - I learned how to use secret keys in Github Actions
- Frontend Mentor - @florianstancioiu
- Threads - @florianstancioiu01
- LinkedIn - florianstancioiu
- freeCodeCamp - florianstancioiu
- September 8th, 2025: I created the github repo and I reused the contents of my calculator app solution because setting up React Testing Library to work correctly with Typescript is quite a pain. I created the component structure for the project and I also started working on the mobile version of the design.
- September 9th, 2025: I worked on the mobile version of the app, I picked up from where I left the design yesterday and I made my way through the app from top to bottom. I avoided implementing the functionality of the dropdowns or the search component, I just made them look like in the design.
- September 10th, 2025: I implemented the UnitsDropdown and DaysDropdown components, I don't think this will be their final version, meaning I will have to update them further to actually use them correctly but this is a first step. I'm happy with how DaysDropdown turned out and relatively happy with the UnitsDropdown - I think there's room for improvement here. I also started working on the desktop version - I created a first rough version, I made the mistake of creating a new breakpoint for desktop called
dsktp, even though it's descriptive, the name is too long and might bother me in the future. I also added a screenshot which will also be replaced, on top of that I added some Open Graph tags so that people can see what they click on in posts on social media. - September 12th, 2025: I added a
isLoadingprop for every single component that needed one, I also began work on implementing the API fetch calls. - September 14th, 2025: I made the existing HTML code more accessible and I also implemented the Search functionality for the Main area (I still have to work on displaying the Feels Like, Humidity, Wind and Precipitation sections)
- September 15th, 2025: I completed the functionality for today's weather section, the daily forecast section and the hourly forecast section. I still have some doubts about the hourly forecast section, it has been by far the trickiest of them all.
- September 16th, 2025: I implemented the no search results and the API error screens, I worked on the tablet version of the app and I also completed some TODOs that were left in the code base. I extracted all the fetch logic from the App.tsx into a custom hook named useMeteoData, also, I updated the said hook with the Geolocation API so that users can allow for their position to be read and used in fetch requests.
- September 17th, 2025: I removed the reversedGeocoding function - the one that turned lat and long into human readable addresses. I fixed a problem with the HourlyForecast component, on the initial load it was showing the wrong data, it was showing data for Sunday instead of the current day. I also started to work on the UnitsDropdown component but it's still not done, I wanted to make it as dynamic as possible but I think that's a bad idea and I should focus on other stuff in the next couple of days, like, on testing the components.
- September 18th, 2025: I added a debounce hook, I implemented the metric/imperial switch, I made the dropdowns keyboard accessible, I used chatgpt to create a github actions workflow that builds the app to the
rootdir of github pages, and the storybook build is placed in theroot/storybookdir, also, I wrote a few *.stories.tsx files for my components. - September 19th, 2025: I fixed a bug that occured when the user allows the page to retrieve the current location and then he/she switches to imperial units - the request to the API was not made - it is fixed now. I also added
*.stories.tsxfiles to each and every single component, I still have to create some dummy data for DailyForecast and HourlyForecast stories, I leave that for another day (I tried to create the dummy data and it's more difficult to create than I initially thought). - September 21th, 2025: I added the search dropdown, a dropdown that contains all previous searches that you can select from (the data is limited to 4 values and is stored using localStorage). I added the dummy data to HourlyForecast and DailyForecast stories, I also added the index page (App.tsx) in storybook.
- September 24th, 2025: I made the deploy.yml script run the tests when building the app on Github Pages. I improved how the app behaves when allowing (or blocking) the Geolocation Web API. I added tests to all the components in the
src/componentsdir (I still haven't added a test file for App.tsx). - September 25th, 2025: I tried to write tests for the
Index.tsxpage - the main page, I spent most of the time figuring out how to create the dummy data... I also updated the README.md a bit. - September 26th, 2025: I reached 80% test coverage, I struggled to write the tests for the Index page - I still have a lot to learn about testing components. I fixed a HourlyForecast bug that showed the hourly items for the current day in the wrong order, it was starting from 3 AM, it should start from 12 AM. I also removed some unnecessary dirs and files from the repo.
- September 27th, 2025: I tried to solve the CI error caused by one particular Index.test.tsx test case, I didn't manage to solve it so I removed that check that was causing problems (basically what happened was: the tests passed locally but failed in Github Actions). I spent too much time on it and I was going nowhere so doing something else was the right choice. I made sure all dropdowns close when pressing the
Escapekey. I also posted my solution to Frontend Mentor.
