Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7ffd471
commit 3d0dedd
Showing
12 changed files
with
478 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,15 @@ | ||
function App() { | ||
import Navbar from "./components/Navbar"; | ||
import Forecasts from "./components/forecasts/Index"; | ||
|
||
const App = () => { | ||
return ( | ||
<h1 className="text-3xl font-bold underline"> | ||
Hello world! | ||
</h1> | ||
<div className="px-4 py-3 min-h-screen bg-gray-200"> | ||
<Navbar /> | ||
<main className="mt-8 max-w-5xl mx-auto"> | ||
<Forecasts /> | ||
</main> | ||
</div> | ||
); | ||
} | ||
|
||
export default App; | ||
export default App |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import { useEffect, useRef } from "react"; | ||
import { ClockIcon } from "@heroicons/react/20/solid"; | ||
|
||
// Comment 1 | ||
const modalHeight = "!h-[calc(100vh-2.75rem)]" | ||
|
||
const Histories = () => { | ||
// Comment 2 | ||
const locations: string[] = JSON.parse(localStorage.getItem("locations") || "[]"); | ||
// Comment 3 | ||
const ulRef = useRef<HTMLDivElement>(null); | ||
|
||
const toggleUl = () => { | ||
const { current: container } = ulRef; | ||
|
||
if (!container) return; | ||
|
||
container.classList.toggle("!w-screen"); | ||
container.classList.toggle(modalHeight); | ||
}; | ||
|
||
useEffect(() => { | ||
const closeUIModal = () => { | ||
const { current: container } = ulRef; | ||
|
||
if (!container) return; | ||
|
||
container.classList.remove("!w-screen"); | ||
container.classList.remove(modalHeight); | ||
} | ||
|
||
window.addEventListener("click", closeUIModal); | ||
|
||
return () => window.removeEventListener("click", closeUIModal) | ||
}, []) | ||
|
||
return ( | ||
<div className="relative"> | ||
<button type="button" onClick={(e) => { | ||
e.stopPropagation(); | ||
toggleUl(); | ||
}}> | ||
<ClockIcon className="h-6 w-6" /> | ||
</button> | ||
<div | ||
ref={ulRef} | ||
className="absolute top-8 right-0 z-10 overflow-hidden h-0 w-0 bg-white transition-all duration-300 ease-in-out flex items-start justify-end pl-3 bg-opacity-5" | ||
> | ||
<div className="w-full max-w-[15rem]" onClick={e => { | ||
e.stopPropagation(); | ||
}}> | ||
{locations.length === 0 ? ( | ||
<p className="text-center text-gray-700 font-extrabold"> | ||
No history | ||
</p> | ||
) : ( | ||
<ul className="bg-white shadow-xl rounded-lg overflow-y-auto h-full max-w-[15rem] max-h-60"> | ||
{locations.map((location) => ( | ||
<li | ||
key={location} | ||
className="flex items-center justify-between" | ||
> | ||
<button | ||
className="text-ellipsis text-left overflow-hidden whitespace-nowrap px-4 py-2 hover:bg-gray-500 transition-colors duration-150 w-full" | ||
type="button" | ||
onClick={() => { console.log("Get Data") }} | ||
> | ||
{location} | ||
</button> | ||
</li> | ||
))} | ||
</ul> | ||
)} | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Histories; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import Histories from "./Histories" | ||
import Search from "./Search" | ||
|
||
const Navbar = () => { | ||
return ( | ||
<nav className="flex item-center justify-between"> | ||
<div className="w-full max-w-5xl mx-auto flex item-center justify-between"> | ||
<div> | ||
<a href="/" className="text-2xl font-semibold"> | ||
Forecast | ||
</a> | ||
</div> | ||
<Search /> | ||
<Histories /> | ||
</div> | ||
</nav> | ||
) | ||
} | ||
|
||
export default Navbar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { useState } from "react"; | ||
|
||
const Search = () => { | ||
const [query, setQuery] = useState(""); | ||
|
||
return ( | ||
<form | ||
className="w-full max-w-xs" | ||
onSubmit={(e) => { | ||
e.preventDefault(); | ||
console.log("Get data"); | ||
}} | ||
> | ||
<input | ||
type="search" | ||
name="search" | ||
id="search" | ||
aria-label="Search for city/country forecast" | ||
placeholder="Search for city/country forecast" | ||
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" | ||
value={query} | ||
onChange={(e) => setQuery(e.target.value)} | ||
/> | ||
</form> | ||
); | ||
}; | ||
|
||
export default Search; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import Today from "./Today"; | ||
import Other from "./Other"; | ||
|
||
const Index = () => { | ||
return ( | ||
<section className="text-white-1 lg:flex"> | ||
<Today /> | ||
<Other /> | ||
</section> | ||
); | ||
}; | ||
|
||
export default Index; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { forecasts } from "../../data/weather"; | ||
|
||
const dateOptions: Intl.DateTimeFormatOptions = { | ||
weekday: "long", | ||
year: "numeric", | ||
month: "long", | ||
day: "numeric", | ||
}; | ||
|
||
const Other = () => { | ||
return ( | ||
<ul className="grid grid-cols-[repeat(auto-fit,minmax(20rem,1fr))] lg:flex-grow lg:flex-shrink"> | ||
{forecasts.map((forecast, key) => { | ||
const date = new Date(forecast.dt * 1000); | ||
const day = date.toLocaleDateString(undefined, dateOptions).split(", ")[0]; | ||
|
||
return <li key={key} className="bg-black-3 even:bg-black-1 flex flex-col items-center justify-center text-center"> | ||
<time className="bg-black-2 py-4 block w-full">{day}</time> | ||
<figure className="mt-8"> | ||
<img | ||
src={`https://openweathermap.org/img/wn/${forecast.weather[0].icon}@2x.png`} | ||
alt="sun icon" | ||
/> | ||
</figure> | ||
<p className="text-4xl mb-8 mt-4"> | ||
{forecast.main.temp} | ||
<sup className="relative text-[1.8rem] -top-8 font-semibold">o</sup> | ||
C | ||
</p> | ||
</li> | ||
})} | ||
</ul> | ||
) | ||
} | ||
|
||
export default Other |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { today as data } from "../../data/weather"; | ||
import { windDirection } from "../../utils/weather"; | ||
import WeatherCondition from "./WeatherCondition"; | ||
|
||
const dateOptions: Intl.DateTimeFormatOptions = { | ||
weekday: "long", | ||
year: "numeric", | ||
month: "long", | ||
day: "numeric", | ||
}; | ||
|
||
const timeOptions: Intl.DateTimeFormatOptions = { | ||
hour: "2-digit", | ||
minute: "2-digit", | ||
}; | ||
|
||
const Today = () => { | ||
const date = new Date(data.dt * 1000); | ||
|
||
return ( | ||
<div className="bg-black-1"> | ||
<time | ||
dateTime={date.toString()} | ||
className="flex items-center justify-between bg-black-2 p-4" | ||
> | ||
<span>{date.toLocaleString(undefined, dateOptions)}</span> | ||
<span>{date.toLocaleTimeString(undefined, timeOptions)}</span> | ||
</time> | ||
<div className="px-4 py-12 lg:flex lg:items-center lg:justify-center lg:flex-col lg:h-[90%]"> | ||
<h3 className="text-4xl mb-4">{data.name}</h3> | ||
<p>{data.weather[0].main}</p> | ||
<div className="mt-8 flex items-center justify-start"> | ||
<p className="text-7xl"> | ||
{data.main.temp} | ||
<sup className="relative text-[1.8rem] -top-8 font-semibold">o</sup> | ||
C | ||
</p> | ||
<figure className="w-16 h-16"> | ||
<img | ||
src={`https://openweathermap.org/img/wn/${data.weather[0].icon}@2x.png`} | ||
alt="sun icon" | ||
/> | ||
</figure> | ||
</div> | ||
<div className="flex items-center justify-start space-x-2 mt-4"> | ||
<WeatherCondition icon="umbrella" value={data.main.humidity} /> | ||
<WeatherCondition icon="wind" value={`${data.wind.speed}m/sec`} /> | ||
<WeatherCondition | ||
icon="direction" | ||
value={windDirection(data.wind.deg)} // Comment 1 | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Today; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { FC } from "react"; | ||
import Umbrella from "../icons/Umbrella"; | ||
import Wind from "../icons/Wind"; | ||
import Direction from "../icons/Direction"; | ||
|
||
const Icons = { | ||
"umbrella": <Umbrella />, | ||
"wind": <Wind />, | ||
"direction": <Direction /> | ||
} | ||
|
||
interface Props { | ||
value: string | number; | ||
icon: keyof typeof Icons; | ||
} | ||
|
||
const WeatherCondition: FC<Props> = ({ value, icon }) => { | ||
return ( | ||
<div className="flex items-center justify-start"> | ||
<figure className="w-5 h-5 mr-2"> | ||
{Icons[icon]} | ||
</figure> | ||
<p className="font-semibold">{value}</p> | ||
</div> | ||
) | ||
} | ||
|
||
export default WeatherCondition |
Oops, something went wrong.