Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 13 additions & 30 deletions vær/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions vær/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import { useState } from 'react'
import heroImg from './assets/hero.png'
import reactLogo from './assets/react.svg'
import viteLogo from './assets/vite.svg'
import './App.css'
import LocationList from './components/location-list'
import ViewCity from './components/ViewCity'
import useGetWeather from './hooks/fetchWeather/useGetWeather'

function App() {
const [count, setCount] = useState(0)

return (
<>
<section id="center">
<LocationList />
<ViewCity city = {'sørumsand'}/>
</section>
<section id="spacer"></section>
Expand Down
36 changes: 36 additions & 0 deletions vær/src/components/listItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@


type cityWeather = {
name: string
temperature?: number
precipitation?: number
nextDays?: { time: string; temperature: number | undefined}[]
}


const listItem = ({ city: item }: { city: cityWeather }) => {

return (
<li key={item.name} style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', backgroundColor: '#bcebff', color: '#000000', padding: '10px', borderRadius: '15px', width: '80%', marginRight: '5px' }}>
<span style={{ display: 'flex', }}>
{item.name}:
<span>
{typeof item.precipitation === 'number' && item.precipitation > 0.6 ? '🌧️' : '⛅'}
</span>
<p style={{ color: '#ff3232'}}>{typeof item.temperature === 'number' ? `${item.temperature.toFixed()}°` : '—'}</p>
</span>


<div style={{ display: 'flex', flexDirection: 'row', gap: '10px'}}>
{item.nextDays?.map((day) => (
<span key={day.time} style={{ color: '#ff3232' }}>
{typeof day.temperature === 'number' ? `${day.temperature.toFixed()}°` : '—'}
</span>
))}

</div>
</li>
)
}

export default listItem
82 changes: 82 additions & 0 deletions vær/src/components/location-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import type { WeatherApiResponse } from '../hooks/fetchWeather/types'
import useGetWeather from '../hooks/fetchWeather/useGetWeather'
import ListItem from './listItem'

type City = {
name: string
lat: number
lon: number
}

const cities: City[] = [
{ name: 'Oslo', lat: 59.91273, lon: 10.74609 },
{ name: 'Sørumsand', lat: 59.98621, lon: 11.24154 },
{ name: 'Trondheim', lat: 63.41667, lon: 10.41667 },
{ name: 'Las Vegas', lat: 36.1699, lon: -115.1398 },
]

const getTemperature = (data?: WeatherApiResponse) =>
data?.properties?.timeseries?.[0]?.data?.instant?.details?.air_temperature

const getPrecipitation = (data?: WeatherApiResponse) =>
data?.properties?.timeseries?.[0]?.data?.next_6_hours?.details?.precipitation_amount

const getNextDays = (data?: WeatherApiResponse) => {
const now = new Date()

const noonTemperatures = data?.properties.timeseries
.filter((entry) => {
const date = new Date(entry.time)
return date >= now && date.getUTCHours() === 12 && date < new Date(now.getTime() + 3* 24 * 60 * 60 * 1000)
})
.map((entry) => ({
time: entry.time,
temperature: entry.data.instant.details?.air_temperature,
}))

return noonTemperatures
}


const LocationList = () => {
const weatherResults = cities.map((city) => useGetWeather(city.lat, city.lon))

console.log(weatherResults)

if (weatherResults.some((result) => result.isLoading)) {
return <div>Loading weather…</div>
}

if (weatherResults.some((result) => result.error)) {
return <div>Could not load weather data.</div>
}

const cityWeather = cities.map((city, index) => ({
name: city.name,
temperature: getTemperature(weatherResults[index]?.result),
precipitation: getPrecipitation(weatherResults[index]?.result),
nextDays: getNextDays(weatherResults[index]?.result),
}))

return (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10, marginTop: '20px' }}>
<div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', width: '80%', marginBottom: '10px', }}>
<span style={{ fontWeight: 'bold' }}>City</span>
<span style={{ fontWeight: 'bold' }}>Next 3 Days</span>
</div>
<hr style={{ width: '80%', marginBottom: '10px' }} />

<ul style={{ listStyleType: 'none', gap: 15, display: 'flex', flexDirection: 'column', alignItems: 'center', width: '100%' }}>
{cityWeather.map((item) => (
<ListItem key={item.name} city={item}/>
// <li key={item.name}>
// {item.name}: {typeof item.temperature === 'number' ? `${item.temperature}°` : '—'}
// {typeof item.precipitation === 'number' ? `, ${item.precipitation} mm` : ''}
// </li>
))}
</ul>
</div>
)
}

export default LocationList
25 changes: 5 additions & 20 deletions vær/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,6 @@
}
}

@media (prefers-color-scheme: dark) {
:root {
--text: #9ca3af;
--text-h: #f3f4f6;
--bg: #16171d;
--border: #2e303a;
--code-bg: #1f2028;
--accent: #c084fc;
--accent-bg: rgba(192, 132, 252, 0.15);
--accent-border: rgba(192, 132, 252, 0.5);
--social-bg: rgba(47, 48, 58, 0.5);
--shadow:
rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
}

#social .button-icon {
filter: invert(1) brightness(2);
}
}

#root {
width: 1126px;
max-width: 100%;
Expand Down Expand Up @@ -109,3 +89,8 @@ code {
padding: 4px 8px;
background: var(--code-bg);
}

ul {
list-style-type: none; /* Removes the dots */
padding: 0; /* Removes default left indentation */
}