99 lines
3.3 KiB
TypeScript
99 lines
3.3 KiB
TypeScript
import React from "react";
|
|
import { useState } from "react";
|
|
import { fetchWeather } from "../utils/apiFunc";
|
|
import { toast } from "react-toastify";
|
|
import WeatherData from "./WeatherData";
|
|
import { useEffect } from "react";
|
|
import { X } from "lucide-react";
|
|
|
|
const WeatherCard: React.FC = () => {
|
|
const [city, setCity] = useState("");
|
|
const [weatherData, setWeatherData] = useState(false);
|
|
const getUnit = () => localStorage.getItem("unit") || "metric";
|
|
|
|
const handleCityChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
setCity(event.target.value);
|
|
};
|
|
|
|
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
|
event.preventDefault();
|
|
setWeatherData(false);
|
|
toast
|
|
.promise(fetchWeather(city, getUnit()), {
|
|
pending: "Fetching weather data...",
|
|
success: "Weather data loaded successfully!",
|
|
error:
|
|
"Failed to load weather data. Please check your entered city name. (Error: x4040)",
|
|
})
|
|
.then(() => {
|
|
if (localStorage.getItem("weather")) {
|
|
setWeatherData(true);
|
|
} else {
|
|
setWeatherData(false);
|
|
}
|
|
});
|
|
};
|
|
|
|
// Check if weather data is already in localStorage - when entering the page via URL/reload
|
|
useEffect(() => {
|
|
if (localStorage.getItem("weather")) {
|
|
setWeatherData(true);
|
|
} else {
|
|
setWeatherData(false);
|
|
}
|
|
}, []);
|
|
|
|
return (
|
|
<div className="w-full max-w-lg mx-auto bg-white/80 rounded-2xl shadow-xl p-8 mt-8">
|
|
<h2 className="text-3xl font-bold mb-4 text-blue-700 flex items-center gap-2">
|
|
Weather
|
|
</h2>
|
|
<p className="mb-2 text-gray-600">
|
|
Current weather will be displayed here.
|
|
</p>
|
|
<p className="mb-2 text-gray-600">
|
|
<strong>You don't need an API Key!</strong>
|
|
</p>
|
|
<form onSubmit={handleSubmit} className="flex flex-col gap-4 mt-4">
|
|
<label htmlFor="city" className="font-medium text-gray-700">
|
|
Enter City:
|
|
</label>
|
|
<input
|
|
type="text"
|
|
id="city"
|
|
name="city"
|
|
onChange={handleCityChange}
|
|
value={city}
|
|
placeholder="City Name"
|
|
required
|
|
className="border border-blue-300 rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-blue-400 bg-blue-50 text-blue-900 font-mono"
|
|
/>
|
|
<div className="cursor-pointer flex items-center gap-2">
|
|
<button
|
|
type="submit"
|
|
className="cursor-pointer flex-1 bg-gradient-to-r from-blue-600 to-blue-400 text-white font-bold px-4 py-3 rounded-xl shadow-lg hover:from-blue-700 hover:to-blue-500 transition-all"
|
|
>
|
|
Get Weather
|
|
</button>
|
|
{weatherData && (
|
|
<button
|
|
type="button"
|
|
onClick={() => {
|
|
setWeatherData(false);
|
|
localStorage.removeItem("weather");
|
|
}}
|
|
className="cursor-pointer flex-shrink-0 bg-red-500 hover:bg-red-600 text-white rounded-xl p-3 shadow-lg transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-red-400"
|
|
aria-label="Close weather data"
|
|
>
|
|
<X />
|
|
</button>
|
|
)}
|
|
</div>
|
|
</form>
|
|
{weatherData && <WeatherData />}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default WeatherCard;
|