Skip to content

Commit 0e687af

Browse files
committedJan 20, 2024
feat: add weather-dashboard.jsx solution
1 parent 33df2b6 commit 0e687af

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed
 

‎solutions/weather-dashboard.jsx

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import React, { useState } from "react"
2+
import { createRoot } from "react-dom/client"
3+
4+
const style = {
5+
marginTop: {
6+
marginTop: "10px",
7+
},
8+
marginRight: {
9+
marginRight: "10px",
10+
},
11+
}
12+
13+
const WeatherDashboard = () => {
14+
// instead of requesting data from an API, use this mock data
15+
const mockWeatherData = {
16+
"New York": {
17+
temperature: "22°C",
18+
humidity: "56%",
19+
windSpeed: "15 km/h",
20+
},
21+
"Los Angeles": {
22+
temperature: "27°C",
23+
humidity: "45%",
24+
windSpeed: "10 km/h",
25+
},
26+
London: {
27+
temperature: "15°C",
28+
humidity: "70%",
29+
windSpeed: "20 km/h",
30+
},
31+
}
32+
33+
const defaultWeather = {
34+
temperature: "",
35+
humidity: "",
36+
windSpeed: "",
37+
}
38+
39+
const [city, setCity] = useState("")
40+
const [cache, setCache] = useState({})
41+
const [notFound, setNotFound] = useState(false)
42+
const [previousSearches, setPreviousSearches] = useState([])
43+
const [weather, setWeather] = useState(defaultWeather)
44+
45+
const mockFetchWeatherData = city => {
46+
return new Promise((resolve, reject) => {
47+
setTimeout(() => {
48+
if (mockWeatherData[city]) {
49+
resolve(mockWeatherData[city])
50+
} else {
51+
reject(new Error("City not found."))
52+
setNotFound(true)
53+
setWeather(defaultWeather)
54+
}
55+
}, 500)
56+
})
57+
}
58+
59+
const search = async city => {
60+
setNotFound(false)
61+
62+
if (!city || city === "") {
63+
setWeather(defaultWeather)
64+
setNotFound(true)
65+
return
66+
}
67+
68+
if (cache[city]) {
69+
setWeather(cache[city])
70+
return
71+
}
72+
73+
try {
74+
const data = await mockFetchWeatherData(city)
75+
setCache({ ...cache, [city]: data })
76+
setWeather(data)
77+
setPreviousSearches([...previousSearches, city])
78+
} catch {
79+
throw new Error("Could not fetch weather data.")
80+
}
81+
}
82+
83+
return (
84+
<div>
85+
<input
86+
type="text"
87+
id="citySearch"
88+
placeholder="Search for a city..."
89+
value={city}
90+
onChange={e => setCity(e.target.value)}
91+
/>
92+
<button id="searchButton" onClick={() => search(city)}>
93+
Search
94+
</button>
95+
<div id="weatherData" style={style.marginTop}>
96+
<div>Temperature: {weather.temperature}</div>
97+
<div>Humidity: {weather.humidity}</div>
98+
<div>Wind Speed: {weather.windSpeed}</div>
99+
{notFound && <div style={style.marginTop}>City not found.</div>}
100+
</div>
101+
<div id="previousSearches" style={style.marginTop}>
102+
{previousSearches.length > 0 &&
103+
previousSearches.map((previousSearch, index) => (
104+
<button
105+
key={index}
106+
onClick={() => {
107+
setCity(previousSearch)
108+
search(previousSearch)
109+
}}
110+
style={style.marginRight}
111+
>
112+
{previousSearch}
113+
</button>
114+
))}
115+
</div>
116+
</div>
117+
)
118+
}
119+
120+
const root = createRoot(document.getElementById("root"))
121+
root.render(<WeatherDashboard />)

0 commit comments

Comments
 (0)
Please sign in to comment.