1919 * - [ ] Animate background transitions
2020 * - [ ] Add geolocation: auto-detect user city (with permission)
2121 */
22- import { useEffect , useState } from 'react' ;
23- import Loading from '../components/Loading.jsx' ;
24- import ErrorMessage from '../components/ErrorMessage.jsx' ;
25- import Card from '../components/Card.jsx' ;
26- import { getWeatherData , clearWeatherCache , getCacheStats } from '../services/weather.js' ;
22+ import { useEffect , useState } from "react" ;
23+ import Loading from "../components/Loading.jsx" ;
24+ import ErrorMessage from "../components/ErrorMessage.jsx" ;
25+ import Card from "../components/Card.jsx" ;
26+ import {
27+ getWeatherData ,
28+ clearWeatherCache ,
29+ getCacheStats ,
30+ } from "../services/weather.js" ;
2731
2832export default function Weather ( ) {
2933 const [ city , setCity ] = useState ( ( ) => {
30- return localStorage . getItem ( ' lastCity' ) || ' London' ;
34+ return localStorage . getItem ( " lastCity" ) || " London" ;
3135 } ) ;
3236 const [ data , setData ] = useState ( null ) ;
3337 const [ loading , setLoading ] = useState ( false ) ;
3438 const [ error , setError ] = useState ( null ) ;
35- const [ unit , setUnit ] = useState ( 'C' ) ; // °C by default
39+ const [ unit , setUnit ] = useState ( "C" ) ; // °C by default
3640
3741 useEffect ( ( ) => {
3842 fetchWeather ( city ) ;
3943 // eslint-disable-next-line react-hooks/exhaustive-deps
40- } , [ ] ) ;
44+ } , [ ] ) ;
4145
4246 async function fetchWeather ( c ) {
4347 try {
4448 setLoading ( true ) ;
4549 setError ( null ) ;
4650
47- const json = await getWeatherData ( c ) ; // Using the service instead of direct fetch
51+ const json = await getWeatherData ( c ) ; // Using the service instead of direct fetch
4852 setData ( json ) ;
4953
5054 // Save the searched city to localStorage
51- localStorage . setItem ( ' lastCity' , c ) ;
55+ localStorage . setItem ( " lastCity" , c ) ;
5256 } catch ( e ) {
5357 setError ( e ) ;
5458 } finally {
@@ -71,15 +75,28 @@ export default function Weather() {
7175 // Helper function to show cache stats (for development)
7276 const handleShowCacheStats = ( ) => {
7377 const stats = getCacheStats ( ) ;
74- console . log ( ' Cache Statistics:' , stats ) ;
78+ console . log ( " Cache Statistics:" , stats ) ;
7579 alert ( `Cache has ${ stats . size } entries. Check console for details.` ) ;
7680 } ;
7781
7882 const current = data ?. current_condition ?. [ 0 ] ;
7983 const forecast = data ?. weather ?. slice ( 0 , 3 ) || [ ] ;
8084
8185 // Helper to convert °C to °F
82- const displayTemp = ( c ) => ( unit === 'C' ? c : Math . round ( ( c * 9 ) / 5 + 32 ) ) ;
86+ const displayTemp = ( c ) => ( unit === "C" ? c : Math . round ( ( c * 9 ) / 5 + 32 ) ) ;
87+
88+ const getBadgeStyle = ( condition ) => {
89+ if ( ! condition ) return { color : "#E0E0E0" , label : "Clear 🌤️" } ;
90+
91+ const desc = condition . toLowerCase ( ) ;
92+ if ( desc . includes ( "sun" ) ) return { color : "#FFD54F" , label : "Sunny ☀️" } ;
93+ if ( desc . includes ( "rain" ) ) return { color : "#4FC3F7" , label : "Rainy 🌧️" } ;
94+ if ( desc . includes ( "snow" ) ) return { color : "#81D4FA" , label : "Snowy ❄️" } ;
95+ if ( desc . includes ( "cloud" ) ) return { color : "#B0BEC5" , label : "Cloudy ☁️" } ;
96+ if ( desc . includes ( "storm" ) || desc . includes ( "thunder" ) )
97+ return { color : "#9575CD" , label : "Storm ⛈️" } ;
98+ return { color : "#E0E0E0" , label : "Clear 🌤️" } ;
99+ } ;
83100
84101 return (
85102 < div className = "dashboard-page" >
@@ -96,32 +113,38 @@ export default function Weather() {
96113 </ form >
97114
98115 { /* Development tools - you can remove these later */ }
99- < div style = { { marginTop : ' 10px' , display : ' flex' , gap : ' 10px' } } >
100- < button onClick = { handleClearCache } style = { { fontSize : ' 12px' } } >
116+ < div style = { { marginTop : " 10px" , display : " flex" , gap : " 10px" } } >
117+ < button onClick = { handleClearCache } style = { { fontSize : " 12px" } } >
101118 Clear Cache
102119 </ button >
103- < button onClick = { handleShowCacheStats } style = { { fontSize : ' 12px' } } >
120+ < button onClick = { handleShowCacheStats } style = { { fontSize : " 12px" } } >
104121 Cache Stats
105122 </ button >
106123 < button
107- onClick = { ( ) => setUnit ( unit === 'C' ? 'F' : 'C' ) }
108- style = { { fontSize : ' 12px' } }
124+ onClick = { ( ) => setUnit ( unit === "C" ? "F" : "C" ) }
125+ style = { { fontSize : " 12px" } }
109126 >
110- Switch to °{ unit === 'C' ? 'F' : 'C' }
127+ Switch to °{ unit === "C" ? "F" : "C" }
111128 </ button >
112129 </ div >
113130 </ div >
114131
115132 { loading && < Loading /> }
116- { error && < ErrorMessage message = { error . message } onRetry = { ( ) => fetchWeather ( city ) } /> }
133+ { error && (
134+ < ErrorMessage
135+ message = { error . message }
136+ onRetry = { ( ) => fetchWeather ( city ) }
137+ />
138+ ) }
117139
118140 { data && ! loading && (
119141 < div className = "dashboard-grid" >
120142 { /* Current Weather */ }
121143 < Card title = "Current Weather" size = "large" >
122144 < h2 > { data . nearest_area ?. [ 0 ] ?. areaName ?. [ 0 ] ?. value || city } </ h2 >
123145 < p >
124- < strong > Temperature:</ strong > { displayTemp ( Number ( current . temp_C ) ) } °{ unit }
146+ < strong > Temperature:</ strong > { " " }
147+ { displayTemp ( Number ( current . temp_C ) ) } °{ unit }
125148 </ p >
126149 < p >
127150 < strong > Humidity:</ strong > { current . humidity } %
@@ -132,22 +155,44 @@ export default function Weather() {
132155 </ Card >
133156
134157 { /* 3-Day Forecast */ }
135- { forecast . map ( ( day , i ) => (
136- < Card key = { i } title = { i === 0 ? 'Today' : `Day ${ i + 1 } ` } >
137- < p >
138- < strong > Avg Temp:</ strong > { displayTemp ( Number ( day . avgtempC ) ) } °{ unit }
139- </ p >
140- < p >
141- < strong > Sunrise:</ strong > { day . astronomy ?. [ 0 ] ?. sunrise }
142- </ p >
143- < p >
144- < strong > Sunset:</ strong > { day . astronomy ?. [ 0 ] ?. sunset }
145- </ p >
146- </ Card >
147- ) ) }
158+ { forecast . map ( ( day , i ) => {
159+ const condition =
160+ day . hourly ?. [ 0 ] ?. weatherDesc ?. [ 0 ] ?. value || "Clear" ;
161+ const badge = getBadgeStyle ( condition ) ;
162+
163+ return (
164+ < Card key = { i } title = { i === 0 ? "Today" : `Day ${ i + 1 } ` } >
165+ { /* Badge Section */ }
166+ < div
167+ style = { {
168+ backgroundColor : badge . color ,
169+ borderRadius : "8px" ,
170+ padding : "4px 8px" ,
171+ display : "inline-block" ,
172+ fontSize : "12px" ,
173+ fontWeight : "bold" ,
174+ marginBottom : "8px" ,
175+ color : "#333" ,
176+ } }
177+ >
178+ { badge . label }
179+ </ div >
180+
181+ < p >
182+ < strong > Avg Temp:</ strong > { displayTemp ( Number ( day . avgtempC ) ) }
183+ °{ unit }
184+ </ p >
185+ < p >
186+ < strong > Sunrise:</ strong > { day . astronomy ?. [ 0 ] ?. sunrise }
187+ </ p >
188+ < p >
189+ < strong > Sunset:</ strong > { day . astronomy ?. [ 0 ] ?. sunset }
190+ </ p >
191+ </ Card >
192+ ) ;
193+ } ) }
148194 </ div >
149195 ) }
150196 </ div >
151197 ) ;
152198}
153-
0 commit comments