Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
chandler767 authored Oct 28, 2024
0 parents commit 1d969f2
Show file tree
Hide file tree
Showing 3 changed files with 286 additions and 0 deletions.
49 changes: 49 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Snowmaking Weather Dashboard</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="app">
<header>
<h1>Snowmaking Dashboard</h1>
<div class="location-input">
<input type="text" id="locationInput" placeholder="Enter location or use GPS">
<button id="locationBtn">Use GPS</button>
<ul id="suggestions"></ul>
<button id="submitBtn">Submit</button>
</div>
<div class="unit-switch">
<label>
<input type="checkbox" id="unitSwitch">
<span>°F / °C</span>
</label>
</div>
</header>

<main>
<section id="currentConditions" class="card">
<h2>Current Conditions</h2>
<p>Temperature: <span id="temp"></span></p>
<p>Humidity: <span id="humidity"></span></p>
<p>Wet Bulb: <span id="wetBulb"></span></p>
<div id="snowQualityGauge">
<p id="snowQuality">Snow Quality: <span id="quality"></span></p>
<div id="snowIndicator"></div>
</div>
</section>

<section id="forecast" class="card">
<h2>7-Day Snowmaking Forecast</h2>
<div id="forecastContainer">
<!-- Forecast days will be injected here by JavaScript -->
</div>
</section>
</main>
</div>
<script src="script.js"></script>
</body>
</html>
148 changes: 148 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
const API_KEY = '93884a8e001a81fd2dc1b978e4980a43'; // Replace with your OpenWeatherMap API key

document.getElementById('locationBtn').addEventListener('click', fetchWeatherByLocation);
document.getElementById('submitBtn').addEventListener('click', submitLocation);
document.getElementById('unitSwitch').addEventListener('change', toggleUnits);
document.getElementById('locationInput').addEventListener('input', fetchLocationSuggestions);

let isCelsius = false;

// Display an error message to the user
function displayError(message) {
const errorContainer = document.createElement('p');
errorContainer.textContent = message;
errorContainer.className = 'error-message';
document.body.prepend(errorContainer);
setTimeout(() => errorContainer.remove(), 5000);
}

// Fetch weather data based on GPS location
async function fetchWeatherByLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
async (position) => {
const lat = position.coords.latitude;
const lon = position.coords.longitude;
await fetchNearestCity(lat, lon);
await fetchWeatherData(lat, lon);
},
(error) => {
displayError("Unable to access GPS location.");
console.error("Geolocation error:", error);
}
);
} else {
displayError("Geolocation is not supported by this browser.");
}
}

// Fetch weather data based on location input
async function submitLocation() {
const location = document.getElementById('locationInput').value;
try {
const data = await fetchGeoLocation(location);
if (data.length > 0) {
const { lat, lon, name } = data[0];
document.getElementById('locationInput').value = name; // Autofill with selected location
await fetchWeatherData(lat, lon);
} else {
displayError("Location not found. Please enter a valid location.");
}
} catch (error) {
displayError("Failed to fetch location data. Please try again.");
console.error("Error fetching location data:", error);
}
}

// Fetch location suggestions for the input field
async function fetchLocationSuggestions() {
const query = document.getElementById('locationInput').value;
if (query.length < 3) return; // Only fetch if query is longer than 2 characters

try {
const data = await fetchGeoLocation(query);

const suggestionsList = document.getElementById('suggestions');
suggestionsList.innerHTML = '';
data.forEach(location => {
const suggestionItem = document.createElement('li');
suggestionItem.textContent = location.name;
suggestionItem.addEventListener('click', () => {
document.getElementById('locationInput').value = location.name;
suggestionsList.innerHTML = '';
});
suggestionsList.appendChild(suggestionItem);
});
} catch (error) {
displayError("Failed to fetch location suggestions.");
console.error("Error fetching location suggestions:", error);
}
}

// Fetch latitude and longitude based on a query using Geocoding API
async function fetchGeoLocation(query) {
const response = await fetch(`https://api.openweathermap.org/geo/1.0/direct?q=${query}&limit=5&appid=${API_KEY}`);

if (!response.ok) {
throw new Error(`Location fetch failed: ${response.status}`);
}
return await response.json();
}

// Fetch the nearest city name based on latitude and longitude
async function fetchNearestCity(lat, lon) {
try {
const response = await fetch(`https://api.openweathermap.org/geo/1.0/reverse?lat=${lat}&lon=${lon}&limit=1&appid=${API_KEY}`);

if (!response.ok) {
throw new Error(`Nearest city fetch failed: ${response.status}`);
}

const data = await response.json();
if (data.length > 0) {
document.getElementById('locationInput').value = data[0].name;
} else {
displayError("Unable to find nearest city.");
}
} catch (error) {
displayError("Failed to fetch nearest city.");
console.error("Error fetching nearest city:", error);
}
}

// Fetch weather data for a given latitude and longitude
async function fetchWeatherData(lat, lon) {
try {
const response = await fetch(`https://api.openweathermap.org/data/2.5/onecall?lat=${lat}&lon=${lon}&appid=${API_KEY}&units=${isCelsius ? 'metric' : 'imperial'}`);

if (!response.ok) {
throw new Error(`Weather data fetch failed: ${response.status}`);
}

const data = await response.json();

if (data.current) {
updateCurrentConditions(data.current);
} else {
displayError("Current weather data is unavailable.");
}

if (data.daily) {
updateForecast(data.daily);
} else {
displayError("Daily forecast data is unavailable.");
}
} catch (error) {
displayError("Failed to fetch weather data. Please try again.");
console.error("Error fetching weather data:", error);
}
}

// Toggle between Celsius and Fahrenheit
function toggleUnits() {
isCelsius = document.getElementById('unitSwitch').checked;
const location = document.getElementById('locationInput').value;
if (location) {
submitLocation(); // Re-fetch data for the current location
}
}
89 changes: 89 additions & 0 deletions styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
body {
font-family: Arial, sans-serif;
margin: 0;
background-color: white;
color: #333;
}

#app {
max-width: 600px;
margin: auto;
padding: 1em;
}

header {
display: flex;
flex-direction: column;
align-items: center;
gap: 1em;
}

.location-input {
position: relative;
display: flex;
gap: 0.5em;
}

#suggestions {
list-style: none;
padding: 0;
position: absolute;
top: 100%;
left: 0;
width: 100%;
max-height: 150px;
overflow-y: auto;
background: white;
border: 1px solid #ddd;
}

#suggestions li {
padding: 0.5em;
cursor: pointer;
}

#suggestions li:hover {
background-color: #f0f0f0;
}

.unit-switch {
display: flex;
align-items: center;
}

.unit-switch label {
display: flex;
align-items: center;
cursor: pointer;
}

.unit-switch input {
appearance: none;
width: 40px;
height: 20px;
background: #ccc;
border-radius: 20px;
position: relative;
outline: none;
margin-right: 0.5em;
}

.unit-switch input:checked {
background: #4caf50;
}

.unit-switch input::before {
content: "";
position: absolute;
width: 16px;
height: 16px;
background: white;
border-radius: 50%;
top: 2px;
left: 2px;
transition: transform 0.2s;
}

.unit-switch input:checked::before {
transform: translateX(20px);
}

0 comments on commit 1d969f2

Please sign in to comment.