Skip to content

Commit

Permalink
Bring over front end from weather repo for separation of concerns and…
Browse files Browse the repository at this point in the history
… easier deployment
  • Loading branch information
Van-Nice committed Jun 20, 2024
0 parents commit b11cafc
Show file tree
Hide file tree
Showing 51 changed files with 941 additions and 0 deletions.
60 changes: 60 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wilsons Weather</title>
<link rel="stylesheet" href="styles.css">
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
<script type="module" src="scripts/script.js" defer></script>
</head>
<body>
<div class="grid-main">
<!-- Navbar -->
<div class="navbar glass-effect"></div>
<div class="navbar-content">
<div class="logo">
<img src="public/weather-day/partly-sunny-day.png" alt="">
<h1 class="title-text">Wilson's Weather</h1>
</div>
<form id="search-form">
<input type="text" id="location-search" placeholder="Search location">
</form>
</div>
<!-- Current Weather -->
<div class="current glass-effect">
<div class="current-header header">
Current Weather
<div id="currentTime"></div>
</div>
<div class="current-body">
<!-- Current weather goes here -->
</div>
</div>
<!-- Hourly Weather -->
<div class="hourly glass-effect">
<div class="blur-effect">
<div class="header">
Hourly Forecast
<div id="currentDate"></div>
</div>
<div class="hourly-body">
<!-- Hourly forecast goes here -->
</div>
</div>
</div>
<!-- Weekly Forecast -->
<div class="weekly glass-effect">
<div class="header">
Weekly Forecast
<div id="currentWeek"></div>
</div>
<div class="weekly-body body-text">
<!-- Weekly forecast goes here -->
</div>
</div>
</div>
<script src="/client/scripts/mobile.js"></script>
</body>
</html>
Binary file added public/weather-both/cloudy-both.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 public/weather-both/cold-both.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 public/weather-both/dreary-both.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 public/weather-both/flurries-both.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 public/weather-both/fog-both.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 public/weather-both/freezing-rain-both.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 public/weather-both/hot-both.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 public/weather-both/ice-both.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 public/weather-both/rain-and-snow-both.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 public/weather-both/rain-both.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 public/weather-both/showers-both.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 public/weather-both/sleet-both.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 public/weather-both/snow-both.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 public/weather-both/thunder-storm-both.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 public/weather-both/windy-both.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 public/weather-day/hazy-sunshine-day.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 public/weather-day/intermitten-clouds-day.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 public/weather-day/mostly-cloudy-day.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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 public/weather-day/mostly-sunny-day.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 public/weather-day/partly-sunny-day.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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 public/weather-day/sun-day.png
Binary file added public/weather-night/clear-night.png
Binary file added public/weather-night/hazy-moonlight-night.png
Binary file added public/weather-night/intermitten-clouds-night.png
Binary file added public/weather-night/mostly-clear-night.png
Binary file added public/weather-night/mostly-cloudy-night.png
Binary file added public/weather-night/partly-cloudy-night.png
6 changes: 6 additions & 0 deletions scripts/getIp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export async function getIp() {
return await fetch('https://api.ipify.org?format=json')
.then(response => response.json())
.then(data => console.log(data.ip))
.catch(error => console.log('Unable to get IP address', error));
}
Empty file added scripts/mobile.js
Empty file.
131 changes: 131 additions & 0 deletions scripts/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { updateWeather } from './weather.js';
import { getIp } from './getIp.js';
import { updateTime } from './timeDate.js';
import { updateCurrent } from './updateCurrent.js';

// This is unsecure fix at some point!!!
const API_BASE_URL = 'https://weather-app-server-d5459d7e5648.herokuapp.com'

async function startWeather(latitude, longitude) {
const response = await fetch(`${API_BASE_URL}/?coords=${latitude},${longitude}`);
const weatherData = await response.json()
console.log(weatherData);
return weatherData;
}

// Create get ip function
async function getIP() {
return await fetch(`${API_BASE_URL}/get-ip`);
}

async function ipWeather(ip) {
const response = await fetch(`${API_BASE_URL}/ip-weather-data?ip=${ip}`);
const weatherData = await response.json();
return weatherData;
}

// Ask for location, if not get ip
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
async function(position) {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
const weatherData = await startWeather(latitude, longitude);
updateWeather(weatherData, 'Your Location');
updateTime(weatherData);
},
async function(error) {
// This function is called when an error occurs, such as when the user denies the location permission
console.log("Geolocation permission denied.");
try {
const ip = await getIp();
const weatherData = await ipWeather(ip);
updateWeather(weatherData, 'Your Location');
updateTime(weatherData);
} catch (error) {
console.error('Error:', error);
}
}
);
} else {
console.log("Geolocation is not supported by this browser.");
(async () => {
try {
const ip = await getIp();
const weatherData = await ipWeather(ip);
updateWeather(weatherData, 'Your Location');
updateTime(weatherData);
} catch (error) {
console.error('Error:', error);
}
})();
}

// Get the form
const searchForm = document.getElementById('search-form');

// Get the search bar
const searchBar = document.getElementById('location-search');

// Create a dropdown for suggestions
const dropdown = document.createElement('div');
dropdown.setAttribute('id', 'dropdown');
searchBar.parentNode.appendChild(dropdown);

// Stop user from enter invalid address in search bar
searchBar.addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
event.preventDefault();
}
});

// Add event listener
searchBar.addEventListener('input', async function(event) {
const userInput = event.target.value;

if (userInput.length > 2) { // Trigger autocomplete after 2 char
try {
const response = await fetch(`${API_BASE_URL}/search-locations?input=${encodeURIComponent(userInput)}`);
const data = await response.json();
dropdown.innerHTML = ''; // Clear previous suggestions

data.predictions.forEach(item => {
const div = document.createElement('div');
div.innerHTML = item.description;
div.onclick = function() {
searchBar.value = item.description;
dropdown.innerHTML = ''; // Clear suggestions after selection

// Trigger form submission event manually
const event = new Event('submit');
searchForm.dispatchEvent(event);
};
dropdown.appendChild(div);
});
} catch (error) {
console.error('Error:', error);
}
}
});

searchForm.addEventListener('submit', async function(event) {
event.preventDefault();
// Get the user input from the search bar
const userSubmission = searchBar.value;
console.log('Form was submitted')
try {
// Clear the search bar
searchBar.value = '';

// Send a request to the server with the user input
const response = await fetch(`${API_BASE_URL}/weather-data?input=${encodeURIComponent(userSubmission)}`);
const weatherData = await response.json();

// Handle the response data here
updateWeather(weatherData, userSubmission);
updateTime(weatherData);
} catch (error) {
console.error('Error:', error);
}

});
46 changes: 46 additions & 0 deletions scripts/timeDate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
export function updateTime(weatherData) {
// Extract timezone and timestamp from weatherData
const timezone = weatherData.timezone;
const time = weatherData.current.dt;

// Get first day of the week
const firstDay = weatherData.daily[0].dt;
const lastDay = weatherData.daily[weatherData.daily.length - 1].dt;

const weekDateOptions = {
month: 'numeric',
day: 'numeric',
timeZone: timezone,
}

const firstDayDate = new Date(firstDay * 1000).toLocaleDateString('en-US', weekDateOptions);
const lastDayDate = new Date(lastDay * 1000).toLocaleDateString('en-US', weekDateOptions);

// Convert Unix timestamp to Date object
const currentDateTime = new Date(time * 1000);


// Date formatting options
const dateOptions = {
weekday: 'long',
month: 'long',
day: 'numeric',
timeZone: timezone // Set the timezone for formatting
};
// Format date
const formattedDate = currentDateTime.toLocaleDateString('en-US', dateOptions);

// Time formatting options
const timeOptions = {
hour: 'numeric',
minute: '2-digit',
timeZone: timezone // Set the timezone for formatting
};
// Format time
const formattedTime = currentDateTime.toLocaleTimeString('en-US', timeOptions);

// Example: Update date and time in HTML
document.getElementById('currentTime').textContent = formattedTime;
document.getElementById('currentDate').textContent = formattedDate;
document.getElementById('currentWeek').textContent = `${firstDayDate} - ${lastDayDate}`;
}
24 changes: 24 additions & 0 deletions scripts/unitConversions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export function kelvinToFahrenheit(kelvin) {
const fahrenheit = Math.round((kelvin - 273.15) * 9/5 + 32);
return fahrenheit;
}

export function kelvinToCelsius(kelvin) {
const celsius = Math.round(kelvin - 273.15);
return celsius;
}

export function capitalizeFirstLetterOfEachWord(str) {
// Split the string into words
const words = str.split(' ');

// Capitalize the first letter of each word
const capitalizedWords = words.map(word => {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
});

// Join the words back into a single string
const capitalizedStr = capitalizedWords.join(' ');

return capitalizedStr;
}
34 changes: 34 additions & 0 deletions scripts/updateCurrent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { kelvinToFahrenheit, kelvinToCelsius, capitalizeFirstLetterOfEachWord } from './unitConversions.js';

export function updateCurrent(weatherData, weatherCodeToImageMap, userInput) {
const current = weatherData.current;
const temperature = kelvinToFahrenheit(current.temp);
const description = capitalizeFirstLetterOfEachWord(current.weather[0].description);
const time = current.dt;
const sunrise = current.sunrise;
const sunset = current.sunset;
const id = current.weather[0].id;
let image = weatherCodeToImageMap[id];
if (typeof image !== 'string' && time > sunrise && time < sunset) {
image = image[0];
} else {
image = image[1];
}
const location = userInput.split(',');

// Get the town from userInput
// There's two possible scenarios for the userInput
// 1. A string from a verified google address
// 2. Your location
// For your location set userInput to false
let currentHTML = `
<div class="current-left body-text">
<div class="current-place">${location[0]}</div>
<div class="current-temp">${temperature}&deg</div>
<div class="current-description">${description}</div>
</div>
`;

const currentForecastDiv = document.querySelector('.current-body');
currentForecastDiv.innerHTML = currentHTML
}
Loading

0 comments on commit b11cafc

Please sign in to comment.