diff options
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/Nav.svelte | 60 | ||||
-rw-r--r-- | src/components/PredictedSpaceWeather.svelte | 174 | ||||
-rw-r--r-- | src/components/PredictedSpaceWeatherThing.svelte | 64 | ||||
-rw-r--r-- | src/components/WeatherCurrent.svelte | 210 |
4 files changed, 508 insertions, 0 deletions
diff --git a/src/components/Nav.svelte b/src/components/Nav.svelte new file mode 100644 index 0000000..3240ecf --- /dev/null +++ b/src/components/Nav.svelte @@ -0,0 +1,60 @@ +<script lang="ts"> + export let segment: string; +</script> + +<style> + nav { + border-bottom: 1px solid rgba(255,62,0,0.1); + font-weight: 300; + padding: 0 1em; + } + + ul { + margin: 0; + padding: 0; + } + + /* clearfix */ + ul::after { + content: ''; + display: block; + clear: both; + } + + li { + display: block; + float: left; + } + + [aria-current] { + position: relative; + display: inline-block; + } + + [aria-current]::after { + position: absolute; + content: ''; + width: calc(100% - 1em); + height: 2px; + background-color: rgb(255,62,0); + display: block; + bottom: -1px; + } + + a { + text-decoration: none; + padding: 1em 0.5em; + display: block; + } +</style> + +<nav> + <ul> + <li><a aria-current="{segment === undefined ? 'page' : undefined}" href=".">home</a></li> + <li><a aria-current="{segment === 'about' ? 'page' : undefined}" href="about">about</a></li> + + <!-- for the blog link, we're using rel=prefetch so that Sapper prefetches + the blog data when we hover over the link or tap it on a touchscreen --> + <li><a rel=prefetch aria-current="{segment === 'blog' ? 'page' : undefined}" href="blog">blog</a></li> + </ul> +</nav> diff --git a/src/components/PredictedSpaceWeather.svelte b/src/components/PredictedSpaceWeather.svelte new file mode 100644 index 0000000..9194447 --- /dev/null +++ b/src/components/PredictedSpaceWeather.svelte @@ -0,0 +1,174 @@ +<script lang="ts"> + // import { onMount } from 'svelte'; + import PredictedSpaceWeatherThing from './PredictedSpaceWeatherThing.svelte'; + + let predictions; + // async function haschange() { + // let data = await fetch(`https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=${latitude}&lon=${longitude}`).then(res => res.json()); + // let data = await fetch("https://services.swpc.noaa.gov/products/noaa-planetary-k-index-forecast.json").then(res => res.json()); + // data.shift(); + // let updatedPredictions = []; + // data.forEach((pred, i) => { + // if (pred[2] != "observed") { + // updatedPredictions.push(pred); + // } + // }); + // predictions = updatedPredictions; + // } + // + // onMount(haschange); + + + + import { onMount } from 'svelte'; + const monthNames = ["January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" + ]; + + let longitude; + let latitude; + let locationSupported; + let dataLoading = true; + let defaultLocation = false; + let weather; + let days = Array(); + + async function getWeather(longitude, latitude) { + let yr_data = await fetch(`https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=${latitude}&lon=${longitude}`).then(res => res.json()); + + let kp_data = await fetch("https://services.swpc.noaa.gov/products/noaa-planetary-k-index-forecast.json").then(res => res.json()); + kp_data.shift(); + let updatedPredictions = []; + kp_data.forEach((pred, i) => { + if (pred[2] != "observed") { + let temp; + let clouds; + let cDate = new Date(pred[0]); + let closestDate = new Date(0,0,0); + yr_data["properties"]["timeseries"].forEach((pred, i) => { + let predDate = new Date(pred["time"]); + if (Math.abs(predDate.getTime() - cDate.getTime()) < Math.abs(closestDate.getTime() - cDate.getTime())) { + closestDate = predDate; + temp = (pred["data"]["instant"]["details"]["air_temperature"]); + clouds = pred["data"]["instant"]["details"]["cloud_area_fraction"]; + } + }) + + updatedPredictions.push({ + "time": pred[0], + "kp": pred[1], + "temp": temp, + "clouds": clouds + }); + } + }); + predictions = updatedPredictions; + } + function getDays(daily) { + var data = daily.data.slice(0,5) + data.forEach(element => { + var a = new Date(element.time*1000) + var dayStrings = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']; + days.push(dayStrings[a.getDay()]) + }); + } + function getLocation() { + if (navigator.geolocation) { + dataLoading = true + locationSupported = true + navigator.geolocation.getCurrentPosition(setLocation, locationError) + } else { + locationSupported = false + noLocation() + } + } + + function setLocation(position) { + longitude = position.coords.longitude + latitude = position.coords.latitude + getWeather(longitude, latitude) + } + + function locationError(err) { + noLocation() + } + + function noLocation() { + longitude = 28.283333 + latitude = -15.416667 + toggleLoading() + } + function toggleLoading() { + dataLoading = !dataLoading + } + function toggleDefault() { + defaultLocation = !defaultLocation + } + onMount(getLocation); +</script> + +<style> + .predicted-weather { + --bg-opacity: 1; + background-color: #f7fafc; + background-color: rgba(247, 250, 252, var(--bg-opacity)); + padding: 1.5rem; + --text-opacity: 1; + color: #1a202c; + color: rgba(26, 32, 44, var(--text-opacity)); + height: 100%; + overflow: hidden; + + /* border-top-left-radius: 1rem; + border-top-right-radius: 1rem; + transform: translatey(-1rem); */ + } + + @media (min-width: 640px), (min-height: 720px) { + .predicted-weather { + padding: 2rem; + padding-top: 1.5rem; + } + } + + @media (min-width: 640px) { + .predicted-weather { + border-bottom-right-radius: 1rem; + border-bottom-left-radius: 1rem; + } + } + + .predicted-weather h2 { + text-transform: uppercase; + font-size: 0.875rem; + letter-spacing: 0.1em; + font-weight: 700; + margin-top: 0.25rem; + margin-bottom: 0.5rem; + } + + .prediction-table { + height: 100%; + overflow-y: scroll; + padding-bottom: 1rem; + } + + .prediction-table::-webkit-scrollbar { + display: none; + } +</style> + +<div class="predicted-weather"> + <div className="flex flex-row justify-between items-top"> + <h2>Predicted</h2> + </div> + <div class="prediction-table"> + {#if predictions} + {#each predictions as prediction, i} + <PredictedSpaceWeatherThing {prediction}/> + {/each} + {:else} + Cannot connect to NOAA + {/if} + </div> +</div> diff --git a/src/components/PredictedSpaceWeatherThing.svelte b/src/components/PredictedSpaceWeatherThing.svelte new file mode 100644 index 0000000..0a40e79 --- /dev/null +++ b/src/components/PredictedSpaceWeatherThing.svelte @@ -0,0 +1,64 @@ +<script> + export let prediction; + + const monthNames = ["January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" + ]; + + let kp = prediction["kp"]; + let dateTime = prediction["time"].split(" "); + let date = Number(dateTime[0].split("-")[2]) + ". " + monthNames[Number(dateTime[0].split("-")[1])]; + let time = dateTime[1].substring(0,5); + let temp = prediction["temp"]; + let clouds = prediction["clouds"]; +</script> + +<style> + .prediction-details { + display: flex; + justify-content: space-between; + border-bottom-width: 1px; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + font-size: 0.75rem; + letter-spacing: 0.05em; + } + + .prediction-details:last-of-type { + border-width: 0; + padding-bottom: 0; + } + + .prediction-details h3 { + font-size: 0.875rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + margin-right: 0.5rem; + } + + .prediction-details .data { + display: flex; + flex-direction: row; + } + + .prediction-details .data h2 { + margin-right: 1rem; + font-size: 1.5rem; + } + +</style> + +<div class="prediction-details"> + <div> + <h3>{time}</h3> + <p>{date}</p> + </div> + <div class="data"> + <h2>{kp}</h2> + <div> + <p><i class="fas fa-thermometer-half"></i> {temp}°C</p> + <p><i class="fas fa-cloud"></i> {clouds}%</p> + </div> + </div> +</div> diff --git a/src/components/WeatherCurrent.svelte b/src/components/WeatherCurrent.svelte new file mode 100644 index 0000000..6f92b20 --- /dev/null +++ b/src/components/WeatherCurrent.svelte @@ -0,0 +1,210 @@ +<script lang="ts"> + import { onMount } from 'svelte'; + const monthNames = ["January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" + ]; + + let longitude; + let latitude; + let locationSupported; + let dataLoading = true; + let defaultLocation = false; + let weather; + let days = Array(); + + let location = "The earth"; + let date = "-"; + let kp_now = "-"; + let kp_min = "-"; + let kp_max = "-"; + let bz = "-"; + let clouds = "-"; + + async function getWeather(longitude, latitude) { + let yr_data = await fetch(`https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=${latitude}&lon=${longitude}`).then(res => res.json()); + clouds = yr_data["properties"]["timeseries"][0]["data"]["instant"]["details"]["cloud_area_fraction"]; + bz = (await fetch("https://services.swpc.noaa.gov/products/summary/solar-wind-mag-field.json").then(res => res.json()))["Bz"]; + //console.log (await fetch(`http://maps.googleapis.com/maps/api/geocode/json?latlng=${latitude},${longitude}&sensor=true`).then(res => res.json())); + let kp_data = await fetch('https://services.swpc.noaa.gov/products/noaa-planetary-k-index-forecast.json').then(res => res.json()); + kp_data.shift(); + let cDate = new Date(); + let closestDate = new Date(0,0,0); + let minkp = 1000; // Just a larger number than any plausable value + let maxkp = 0; + + kp_data.forEach((pred, i) => { + if (pred[1] > maxkp) { + maxkp = pred[1]; + } + if (pred[1] < minkp) { + minkp = pred[1]; + } + let predDate = new Date(pred[0]); + if (Math.abs(predDate.getTime() - cDate.getTime()) < Math.abs(closestDate.getTime() - cDate.getTime())) { + closestDate = predDate; + kp_now = pred[1]; + } + }); + kp_min = minkp.toString(); + kp_max = maxkp.toString(); + + date = cDate.getDay() + ". " + monthNames[cDate.getMonth()] + " " + cDate.getHours() + ":" + cDate.getMinutes(); + } + function getDays(daily) { + var data = daily.data.slice(0,5) + data.forEach(element => { + var a = new Date(element.time*1000) + var dayStrings = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']; + days.push(dayStrings[a.getDay()]) + }); + } + function getLocation() { + if (navigator.geolocation) { + dataLoading = true + locationSupported = true + navigator.geolocation.getCurrentPosition(setLocation, locationError) + } else { + locationSupported = false + noLocation() + } + } + + function setLocation(position) { + longitude = position.coords.longitude + latitude = position.coords.latitude + getWeather(longitude, latitude) + } + + function locationError(err) { + noLocation() + } + + function noLocation() { + longitude = 28.283333 + latitude = -15.416667 + toggleLoading() + } + function toggleLoading() { + dataLoading = !dataLoading + } + function toggleDefault() { + defaultLocation = !defaultLocation + } + onMount(getLocation); +</script> + +<style> + + .weatherCurrent-wrapper { + height: 100%; + font-family: Roboto, sans-serif; + font-size: 1rem; + letter-spacing: 0.05em; + --bg-opacity: 1; + background-color: #1a202c; + background-color: rgba(26, 32, 44, var(--bg-opacity)); + background: + linear-gradient( + rgba(0, 0, 0, 0.5), + rgba(0, 0, 0, 0.5) + ), url(/aurora.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: center; + } + + .weatherCurrent-data { + width: 100%; + padding: 1.5rem; + flex-grow: 1; + display: flex; + flex-direction: column; + justify-content: space-between; + height: 100%; + --text-opacity: 1; + color: #fff; + color: rgba(255, 255, 255, var(--text-opacity)); + text-align: center; + letter-spacing: 0.05em; + text-shadow: 1px 1px 2px rgba(0,0,0,.75); + } + + .weatherCurrent-data-location { + display: flex; + justify-content: center; + align-content: center; + } + + .weatherCurrent-data-location .symbol { + width: 1.5rem; + height: 1.5rem; + margin-right: 1rem; + } + + + .weatherCurrent-data-location h1 { + text-transform: uppercase; + font-family: Roboto Condensed, sans-serif; + font-size: 1.125rem; + letter-spacing: 0.1em; + margin-bottom: 0; + } + + .weatherCurrent-data-kp h2 { + font-weight: 700; + font-size: 3rem; + letter-spacing: 0.05em; + line-height: 1.25; + } + + .current-details { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + grid-gap: 1rem; + gap: 1rem; + text-shadow: 1px 1px 2px rgba(0,0,0,.75); + } + + .current-details p { + line-height: 1.375; + } + + +</style> + +<div class="weatherCurrent-wrapper"> + <div class="weatherCurrent-data"> + <div class="weatherCurrent-data-location"> + <i class="symbol fas fa-map-marker-alt"></i> + <h1>{location}</h1> + </div> + + <div class="weatherCurrent-data-date"> + <p>{date}</p> + </div> + + <div class="weatherCurrent-data-kp"> + <h2>KP {kp_now}</h2> + <p> + <span className="pr-2">↑ KP {kp_max}</span> + <span className="pl-2">↓ KP {kp_min}</span> + </p> + </div> + + <div class="current-details"> + <div> + <p>BZ</p> + <p>{bz}</p> + </div> + <div> + <p>Probability</p> + <p>10%</p> + </div> + <div> + <p>Clouds</p> + <p>{clouds}%</p> + </div> + </div> + + </div> +</div> |