diff --git a/README.md b/README.md
index 4638c655..3ef599c7 100644
--- a/README.md
+++ b/README.md
@@ -3,3 +3,7 @@
This project has been created by a student at Parsity, an online software engineering course. The work in this repository is wholly of the student based on a sample starter project that can be accessed by looking at the repository that this project forks.
If you have any questions about this project or the program in general, visit [parsity.io](https://parsity.io/) or email hello@parsity.io.
+
+This is a simple weather application which will display the current weather and a five-day forecast for any geographic location based on an input of City, State (if applicable) and Country. The application will begin with the user's current location as a default.
+
+Data is taken from Open Weather API: https://openweathermap.org/api.
diff --git a/index.html b/index.html
new file mode 100644
index 00000000..679ab8ac
--- /dev/null
+++ b/index.html
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/main.js b/main.js
new file mode 100644
index 00000000..d188bf75
--- /dev/null
+++ b/main.js
@@ -0,0 +1,285 @@
+const apiKey = "6427275c4ee8b157888fdf144b2fc5ca";
+const units = "imperial";
+
+// Fetch current cocation to display default weather forecast.This returns an object in the form of {lat:____, lon:____}
+const getCurrentLocation = () => {
+ const options = {
+ enableHighAccuracy: true,
+ maximumAge: 0,
+ };
+
+ return new Promise((resolve, reject) => {
+ navigator.geolocation.getCurrentPosition(
+ (position) => {
+ resolve({
+ lon: position.coords.longitude,
+ lat: position.coords.latitude,
+ });
+ },
+ (error) => reject(console.warn(`ERROR(${error.code}): ${error.message}`)),
+ options
+ );
+ });
+};
+
+// Using the current location, fetch the appropriate weather data from OpenWeather API
+const fetchCurrentLocationData = async (location) => {
+ const url = `https://api.openweathermap.org/data/2.5/weather?lat=${location.lat}&lon=${location.lon}&appid=${apiKey}&units=${units}`;
+
+ const fetchedData = await fetch(url, {
+ method: "GET",
+ data: "json",
+ });
+
+ const currentLocationData = await fetchedData.json();
+
+ return currentLocationData;
+};
+
+// Update HTML with current/default location weather data
+const addCurrentLocation = async () => {
+ try {
+ const location = await getCurrentLocation();
+ const locationData = await fetchCurrentLocationData(location);
+ addNow(locationData);
+
+ const fiveDayData = await fetchFiveDayData(location);
+ const processedData = await processFiveDayData(fiveDayData);
+ addFiveDay(processedData);
+ } catch (error) {
+ console.error("Error processing data:", error);
+ }
+};
+
+addCurrentLocation();
+
+// Use fetchNow() and addNow() functions to update the current weather forecast section of the HTML from a given locaiton query
+const getNow = async () => {
+ try {
+ const nowData = await fetchNow();
+ addNow(nowData);
+ } catch (error) {
+ console.error("Error processing data:", error);
+ }
+};
+
+// Fetch current weatehr data for the location queried
+const fetchNow = async () => {
+ const query = document.querySelector("#query").value.replace(/\s+/g, "%20");
+
+ const url = `https://api.openweathermap.org/data/2.5/weather?q=${query}$&limit=1&appid=${apiKey}&units=${units}`;
+
+ const fetchedData = await fetch(url, {
+ method: "Get",
+ dataType: "json",
+ });
+
+ const nowData = await fetchedData.json();
+
+ return nowData;
+};
+
+// Use template to update HTML for the current weather forecast based on data from the queried location
+const addNow = async (data) => {
+ const nowSection = document.querySelector("#now");
+ nowSection.replaceChildren();
+
+ const template = `
+
+
+
${data.main.temp.toFixed(1)}°
+ ${data.name}
+ ${data.weather[0].main}
+
+
+

+
+
+ `;
+
+ nowSection.insertAdjacentHTML("beforeend", template);
+};
+
+// Use a series of functions to populate the 5-day forecast section of the HTML
+const getFiveDay = async () => {
+ try {
+ const coordinates = await fetchCoordinates();
+ const fiveDayData = await fetchFiveDayData(coordinates);
+ const processedData = await processFiveDayData(fiveDayData);
+ addFiveDay(processedData);
+ } catch (error) {
+ console.error("Error processing data:", error);
+ }
+};
+
+// Use Open Weather Geolocation API to return data, {lat:____, lon:___}, for the queried location
+const fetchCoordinates = async () => {
+ const query = document.querySelector("#query").value.replace(/\s+/g, "%20");
+
+ const coordinatesCall = await fetch(
+ `https://api.openweathermap.org/geo/1.0/direct?q=${query}&limit=1&appid=${apiKey}
+ `,
+ {
+ method: "GET",
+ dataType: "json",
+ }
+ );
+
+ const coordinatesArray = await coordinatesCall.json();
+ const coordinates = coordinatesArray[0];
+
+ return coordinates;
+};
+
+// Given an object with {lat:___, lon:___} syntax, fetch five-day weather information. This returns 40 instances of data which must be divided into 5 sets of 8.
+const fetchFiveDayData = async (coordinates) => {
+ const fiveDayURL = `https://api.openweathermap.org/data/2.5/forecast?lat=${coordinates.lat}&lon=${coordinates.lon}&appid=${apiKey}&units=${units}`;
+
+ const fetchFiveDay = await fetch(fiveDayURL, {
+ method: "GET",
+ dataType: "json",
+ });
+
+ const fiveDayData = await fetchFiveDay.json();
+
+ return fiveDayData;
+};
+
+// Colate data from each day in the five-day forecast.
+const processFiveDayData = async (data) => {
+ const dividedDayData = [];
+
+ const processDayData = (day) => {
+ const indexRange = [(day - 1) * 8, day * 8 - 1];
+
+ const getAvgTemp = () => {
+ let acc = 0;
+ let timeIndex = 0;
+
+ for (let i = indexRange[0]; i <= indexRange[1]; i++) {
+ const currentTemp = data.list[i].main.temp;
+ acc += (currentTemp - acc) / (timeIndex + 1);
+ timeIndex++;
+ }
+
+ return acc.toFixed(1);
+ };
+
+ const getSummaryIcon = () => {
+ let icons = {};
+
+ for (let i = indexRange[0]; i <= indexRange[1]; i++) {
+ const icon = data.list[i].weather[0].icon;
+
+ if (icons.hasOwnProperty(icon)) {
+ icons[icon]++;
+ } else {
+ icons[icon] = 1;
+ }
+ }
+
+ let iconMaxCount = 0;
+ let iconSummary = "";
+
+ for (let key in icons) {
+ if (icons[key] > iconMaxCount) {
+ iconMaxCount = icons[key];
+ iconSummary = key;
+ }
+ }
+ return iconSummary;
+ };
+
+ const getDayName = () => {
+ const dt_txt = new Date(data.list[indexRange[0]].dt_txt);
+
+ const dateFormatter = new Intl.DateTimeFormat("en-US", {
+ weekday: "long",
+ });
+
+ return dateFormatter.format(dt_txt);
+ };
+
+ const getSummaryWeatherDescription = () => {
+ let dayData = {};
+ let weatherDescriptions = {};
+
+ for (let i = indexRange[0]; i <= indexRange[1]; i++) {
+ const weatherDescription = data.list[i].weather[0].main;
+
+ if (weatherDescriptions.hasOwnProperty(weatherDescription)) {
+ weatherDescriptions[weatherDescription]++;
+ } else {
+ weatherDescriptions[weatherDescription] = 1;
+ }
+ }
+
+ let weatherDescriptionsMaxCount = 0;
+ let summaryDescription = "";
+
+ for (let key in weatherDescriptions) {
+ if (weatherDescriptions[key] > weatherDescriptionsMaxCount) {
+ weatherDescriptionsMaxCount = weatherDescriptions[key];
+ summaryDescription = key;
+ }
+ }
+ return summaryDescription;
+ };
+
+ return {
+ avgTemp: getAvgTemp(),
+ iconSummary: getSummaryIcon(),
+ weatherSummary: getSummaryWeatherDescription(),
+ dayName: getDayName(),
+ };
+ };
+
+ // Iterate through each day to colate all summary data
+ for (let i = 1; i <= 5; i++) {
+ dividedDayData.push(processDayData(i));
+ }
+
+ return dividedDayData;
+};
+
+// Update HTML with data given in the form returned by the processFiveDayData function
+const addFiveDay = (summaryData) => {
+ const fiveDaySection = document.querySelector(".forecast-5-day");
+ fiveDaySection.replaceChildren();
+
+ const dayTemplate = (summaryItem) => `
+
+
+
${summaryItem.weatherSummary}
+
+
${summaryItem.avgTemp}°
+
+

+
${summaryItem.dayName}
+
+
+ `;
+
+ const allDaysTemplate = `
+
+
Five Day Forecast
+
+
+
+ ${summaryData.map((summaryItem) => dayTemplate(summaryItem)).join("")}
+
+ `;
+
+ fiveDaySection.insertAdjacentHTML("beforeend", allDaysTemplate);
+};
+
+const searchButton = document.querySelector(".search");
+searchButton.addEventListener("click", () => {
+ getNow();
+ getFiveDay();
+ document.querySelector("#query").value = "";
+});