App.js
import { useEffect, useState } from "react";
import WeatherBox from "./components/WeatherBox";
import WeatherButton from "./components/WeatherButton";
import PacmanLoader from "react-spinners/PacmanLoader";
import "bootstrap/dist/css/bootstrap.min.css"; // !๋ถํธ์คํธ๋ฉ css ์ฐ๊ฒฐ
import "./App.css";
function App() {
// * 4. ๋ ์จ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ useState
const [weather, setWeather] = useState(null); //๋ ์จ๋ฐ์ดํฐ
// * 6. ํ์ฌ ์ ํํ ๋์๊ฐ ์ด๋์ง ์ ์ฅํ๋ useState
const [city, setCity] = useState("current");
// * 8. loading ์ค์ ์ ์ ์ฅํ๋ useState
const [loading, setLoading] = useState(true);
// * 5. ๋์ ์ด๋ฆ์ ๋ฐฐ์ด๋ก ์ ์ธ
const cities = ["sydney", "oslo", "baghdad", "paris"];
// * 1. ํ์ฌ ์์น ๊ธฐ๋ฐ ๋ ์จ ์ถ๋ ฅํ๋ ํจ์ ์ ์
const getCurrentLocation = () => {
navigator.geolocation.getCurrentPosition((position) => {
let lat = position.coords.latitude; // ์๋
let lon = position.coords.longitude; // ๊ฒฝ๋
//console.log('ํ์ฌ ๋ด ์์น๋?',lat,lon)
// * 2-2. ํด๋น ์์น์ ๋ ์จ๋ฅผ ๋ถ๋ฌ์ด
getWeatherByCurrentLocation(lat, lon);
});
};
// * 2. ์ขํ๋ฅผ ์ด์ฉํ์ฌ ๋ ์จ API๋ฅผ ๊ฐ์ ธ์ค๋ ํจ์
const getWeatherByCurrentLocation = async (lat, lon) => {
// * 8-2. setLoading ์คํ
setLoading(true);
let url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=83aeb80a15d50ee7a248d29575f07e8d&units=metric`;
let response = await fetch(url);
let data = await response.json();
setWeather(data);
// * 8-3. setLoading ์ข
๋ฃ
setLoading(false);
};
// * 7. ๋์ ์ด๋ฆ์ ์ด์ฉํ์ฌ ๋ ์จ API๋ฅผ ๊ฐ์ ธ์ค๋ ํจ์
const getWeatherByCity = async () => {
// * 8-2. setLoading ์คํ
setLoading(true);
let url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=83aeb80a15d50ee7a248d29575f07e8d&units=metric`;
let response = await fetch(url);
let data = await response.json();
setWeather(data);
// * 8-3. setLoading ์ข
๋ฃ
setLoading(false);
};
// * 3. ์ฒ์ ํ๋ฉด ์ถ๋ ฅ ์ ๋ฑ ํ๋ฒ๋ง ๋ฐ์๋๋๋ก ํจ
// * 6-2. city ๋ณ์๊ฐ current์ ๊ฐ์ผ๋ฉด getCurrentLocation() ์คํ
// * 7-2. city ๋ณ์๊ฐ ๋ฐ๋๋ฉด getWeatherByCity ์คํ. useEffect()๋ฅผ ํ๋๋ก ํฉ์นจ
useEffect(() => {
if (city === "current") {
getCurrentLocation();
} else {
getWeatherByCity();
}
}, [city]);
// // * 6-2. city ๋ณ์๊ฐ ๋ฐ๋ ๋๋ง๋ค console์คํ
// useEffect(() => {
// getWeatherByCity();
// console.log("์ ํํ ๋์๋ city??", city);
// }, [city]);
return (
<>
{loading ? (
<div className='container'>
<PacmanLoader color="#000" speedMultiplier={2} />
</div>
) : (
<div className='container'>
<WeatherBox weather={weather} />
<WeatherButton cities={cities} setCity={setCity} />
</div>
)}
</>
// <div className="container">
// {/* // * 9. ๋ก๋ฉํ ๋๋ง ๋ก๋๊ฐ ๋ณด์ด๋๋ก ํจ */}
// {loading ? <PacmanLoader color="#fff" height={40} speedMultiplier={1} /> : null}
// {/*// * 4. ํ๋ฉด์ ๋ ์จ ์ถ๋ ฅ. props๋ก WeatherBox๋ก ๋ ์จ ๋ฐ์ดํฐ ๋ณด๋ */}
// <WeatherBox weather={weather} />
// {/*// * 6-2. props๋ก WeatherButton์ผ๋ก ๋ฐ์ดํฐ ๋ณด๋ */}
// <WeatherButton cities={cities} setCity={setCity} />
// </div>
);
}
export default App;
App.css
body { background: url('./img/weather.jpg') no-repeat center center / cover; height: 100vh; }
.container { display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; }
.weather-box { width: 100%; max-width: 700px; background: rgba(184, 184, 184, 0.7); text-align: center; border-radius: 24px; padding: 50px 0 20px; margin-bottom: 20px; }
.weather-button { padding: 5px 30px; background: rgba(0, 0, 0, 0.4); border-radius: 60px; text-align: center; }
.weather-button button { margin: 5px; }
WeatherBox.jsx
import React from "react";
const WeatherBox = ({ weather }) => {
console.log("WeatherBox์ปดํฌ๋ํธ์ weather", weather);
// * 1. ๋ ์จ ์์ด์ฝ์ ํ์ํ๋ ๋ณ์ ์ ์
const iconNow = weather?.weather[0].icon;
return (
<div className="weather-box">
{/* ๋ถํธ์คํธ๋ฉ */}
<h3 className="h5 text-danger">{weather?.name}</h3>
<h1 className="fw-semibold">
{weather?.main.temp} โ / {weather?.main.humidity}%
</h1>
<div className="text-primary h3 text-uppercase fw-semibold">
{weather?.weather[0].description}
</div>
<div>
{/* // * 1-2. ๋ ์จ ์์ด์ฝ์ ํ์ํ๋ ๋ณ์ ์ฌ์ฉ */}
<img src={`https://openweathermap.org/img/wn/${iconNow}@2x.png`} />
</div>
</div>
);
};
export default WeatherBox;
// {weather && weather.name}
// {weather?.name}
WeatherButton.jsx
import React from "react";
import Button from "react-bootstrap/Button"; // ๋ถํธ์คํธ๋ฉ(์ปดํฌ๋ํธ๋ก ์ฌ์ฉํ ๋๋ importํด์ผ ํจ)
const WeatherButton = ({ cities, setCity }) => {
return (
<div className="weather-button">
{/* ๋ถํธ์คํธ๋ฉ */}
<Button variant="warning" onClick={() => setCity("current")}>
Current Location
</Button>
{cities.map((city, index) => ( // * 1. city ์์ ๊ฐ๊ฐ์ array์ item(๋ฒํผ)์ ํ๋ฉด์ ์ถ๋ ฅ
<Button
variant="outline-warning"
key={index}
onClick={() => setCity(city)}
>
{city}
{/* ๋ด๊ฐ ๋๋ฅธ ๋์์ ์ด๋ฆ์ด ๋ค์ด๊ฐ๊ฒ */}
</Button>
)
)}
</div>
);
};
export default WeatherButton;
App.js
import './App.css';
import Tailwind from './Tailwind';
function App() {
return (
<>
<Tailwind />
</>
);
}
export default App;
App.css
@tailwind base;
@tailwind components;
@tailwind utilities;
Tailwind.jsx
import React from 'react'
export default function Tailwind() {
return (
<>
<div className='border-4 border-lime-600 m-5 p-20'>
<h1 className='text-sm text-end'>ํ
์ผ์๋ ์ฌ์ฉ</h1>
<h1 className='text-3xl text-blue-800'>ํ
์ผ์๋ ์ฌ์ฉ</h1>
</div>
<button className=' bg-orange-400 py-3 px-10 rounded-full'>BUTTON</button>
</>
)
}