componenet
-Input.jsx
-Button.jsx
-Checkbox.jsx
module
-Login.jsx
-Clock.jsx
-Weather.jsx
-ToDoList.jsx
page
-ChromeApp.jsx
css
-List.css
img
-1.jpg, 2.jpg, 3.jpg, 4.jpg, 5.jpg
App.js
component - <Input.jsx>
import React from 'react'
function Input({className, type, name, value, onChange, maxLength, placeholder, checked}) {
return (
<div>
<input
className={className}
type={type}
name={name}
value={value}
onChange={onChange}
maxLength={maxLength}
placeholder={placeholder}
checked={checked}
/>
</div>
)
}
export default Input
component - <Button.jsx>
import React from 'react'
function Button({type, className, name, onClick}) {
return (
<div>
<button type={type} className={className} onClick={onClick}>
{name}
</button>
</div>
)
}
export default Button
component - <Checkbox.jsx>
import React from 'react'
import '../css/List.css'
import Input from './Input'
import Button from './Button'
function CheckboxList({id, checkBool, listContent, removeList, checkToggle}) {
const changeCheckBool = () => {
checkToggle(id)
}
const handleRemoveList = () => {
removeList(id)
}
return (
<div className="checkboxListDiv" key={id}>
<Input
type={'checkbox'}
className={'checkboxInput'}
checked={checkBool}
onChange={changeCheckBool}
/>
<p className={checkBool ? 'checkboxP_2' : 'checkboxP_1'}>{listContent}</p>
<Button name={'X'} onClick={handleRemoveList} className={'deleteListButton'} />
</div>
)
}
export default CheckboxList
module - <Clock.jsx>
import React, {useEffect, useState} from 'react'
function Clock() {
const [clock, setClock] = useState(new Date())
const renewTime = () => setClock(clock => new Date())
const clockHour = String(clock.getHours()).padStart(2, 0)
const clockMinutes = String(clock.getMinutes()).padStart(2, 0)
const clockSeconds = String(clock.getSeconds()).padStart(2, 0)
useEffect(() => {
const time = setInterval(renewTime, 1000)
return () => clearInterval(time)
})
return (
<div>
<h2>{`${clockHour}:${clockMinutes}:${clockSeconds}`}</h2>
</div>
)
}
export default Clock
module - <Weather.jsx>
import React, {useEffect, useState} from 'react'
import '../css/List.css'
function Weather() {
const [weather, setWeather] = useState()
const getWeather = position => {
const lat = position.coords.latitude
const lng = position.coords.longitude
const API_KEY = 'API_키'
const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lng}&appid=${API_KEY}&units=metric`
fetch(url)
.then(response => response.json())
.then(data => {
setWeather(data)
})
}
useEffect(() => {
navigator.geolocation.getCurrentPosition(getWeather)
}, [])
return (
<div>
<span className="weatherName">{weather?.name}</span>
<div className="weatherDiv">
<img
src={`http://openweathermap.org/img/wn/${weather?.weather[0].icon}.png`}
alt="아이콘"
className="weatherIcon"
/>
<span className="weatherTemp">{`${weather?.main.temp}°C`}</span>
</div>
</div>
)
}
export default Weather
module - <ToDoList.jsx>
import React, {useEffect, useRef, useState} from 'react'
import '../css/List.css'
import Input from '../component/Input'
import Button from '../component/Button'
import Checkbox from '../component/Checkbox'
function ToDoList() {
const [listValue, setListValue] = useState('')
const [todoList, setToDoList] = useState(
JSON.parse(localStorage.getItem('todoList')) || []
)
const listKey = useRef(parseInt(localStorage.getItem('ListKey')) || 0)
const changeListValue = event => {
setListValue(event.target.value)
}
const addList = event => {
event.preventDefault()
const checkBool = false
if (listValue === '') {
alert('할 일 목록을 입력해주세요.')
} else {
const newList = {
listContent: listValue,
id: listKey.current,
checked: checkBool
}
listKey.current += 1
setToDoList([newList, ...todoList])
setListValue('')
}
}
const removeList = id => {
const remainList = todoList.filter(remove => remove.id !== id)
setToDoList(remainList)
}
const checkToggle = id => {
setToDoList(
todoList.map(toggle =>
toggle.id === id ? {...toggle, checked: !toggle.checked} : toggle
)
)
}
useEffect(() => {
localStorage.setItem('todoList', JSON.stringify(todoList))
localStorage.setItem('ListKey', parseInt(listKey.current))
})
return (
<div>
<div>
<form className="todoListForm">
<Input
type={'text'}
className={'todoListInput'}
value={listValue || ''}
onChange={changeListValue}
placeholder={'Write your List...'}
/>
<Button
className={'addListButton'}
name={'+'}
type={'submit'}
onClick={addList}
/>
</form>
</div>
<div className="checkboxDiv">
{todoList.map(listData => {
return (
<Checkbox
key={listData.id}
{...listData}
checkBool={listData.checked}
removeList={removeList}
checkToggle={checkToggle}
/>
)
})}
</div>
</div>
)
}
export default ToDoList
module - <Login.jsx>
import React, {useEffect, useState} from 'react'
import '../css/List.css'
import Input from '../component/Input'
import Button from '../component/Button'
import ToDoList from './ToDoList'
import Clock from './Clock'
import Weather from './Weather'
function Login() {
const checkUsername = localStorage.getItem('username')
const [loginValue, setLoginValue] = useState(checkUsername)
const [loginBool, setLoginBool] = useState(true)
const [timeTitle, setTimeTitle] = useState('')
const time = new Date().getHours()
const onChangeLogin = event => {
setLoginValue(event.target.value)
}
const handleLogin = e => {
e.preventDefault()
if (loginValue === '') {
alert('이름을 입력해주세요.')
} else {
setLoginBool(false)
localStorage.setItem('username', loginValue)
}
}
const handleLogout = () => {
setLoginBool(true)
setLoginValue('')
localStorage.removeItem('username')
}
useEffect(() => {
if (checkUsername === null) {
setLoginBool(true)
} else {
setLoginBool(false)
}
}, [checkUsername])
useEffect(() => {
if (6 <= time && time < 12) {
setTimeTitle('Good Morning')
} else if (12 <= time && time < 18) {
setTimeTitle('Good Afternoon')
} else if (18 <= time && time < 21) {
setTimeTitle('Good Evening')
} else if ((21 <= time && time <= 23) || (0 <= time && time < 6)) {
setTimeTitle('Good Night')
}
}, [time])
return (
<div>
<div className="loginWeatherDiv">
<Weather />
</div>
{loginBool ? (
<div>
<div className="logoutClockDiv">
<Clock />
</div>
<form className="logoutDiv" onSubmit={handleLogin}>
<Input
className={'loginInput'}
type={'text'}
value={loginValue}
onChange={onChangeLogin}
maxLength={15}
placeholder={'What your name...?'}
/>
<Button className={'loginButton'} name={'≪'} />
</form>
</div>
) : (
<div className="loginDiv">
<div className="loginClockDiv">
<Clock />
</div>
<div className="loginNameDiv">
<h1 className="loginName">{`${timeTitle}, ${loginValue}`}</h1>
<Button className={'loginButton'} name={'≫'} onClick={handleLogout} />
</div>
<div>
<ToDoList />
</div>
</div>
)}
</div>
)
}
export default Login
Page - <ChromeApp.jsx >
import React from 'react'
import '../css/List.css'
import Login from '../module/Login'
import Image1 from '../img/1.jpg'
import Image2 from '../img/2.jpg'
import Image3 from '../img/3.jpg'
import Image4 from '../img/4.jpg'
import Image5 from '../img/5.jpg'
const randomImage = [Image1, Image2, Image3, Image4, Image5]
function ChromeApp() {
const bgImage = randomImage[Math.floor(Math.random() * randomImage.length)]
return (
<div style={{backgroundImage: `url(${bgImage})`}} className="ChromeAppDiv">
<Login />
</div>
)
}
export default ChromeApp
List.css
body {
margin: 0;
}
//로그인
.loginDiv {
margin-left: 570px;
}
.loginInput {
background-color: transparent;
border: 0px;
border-bottom: 1px solid white;
color: white;
width: 400px;
height: 50px;
font-size: 30px;
outline: none;
}
.loginInput::placeholder {
color: white;
}
.loginNameDiv {
display: flex;
align-items: center;
color: white;
text-shadow: 0px 0px 10px black;
}
.loginName {
font-size: 40px;
}
.loginClockDiv {
color: white;
display: flex;
font-size: 70px;
height: 200px;
padding-top: 20px;
padding-left: 0px;
text-shadow: 0px 0px 10px black;
}
.loginWeatherDiv {
color: white;
display: flex;
float: right;
margin-right: 20px;
margin-top: 10px;
text-shadow: 0px 0px 10px black;
}
.logoutDiv {
display: flex;
align-items: center;
color: white;
padding-top: 50px;
padding-left: 550px;
}
.logoutClockDiv {
color: white;
font-size: 70px;
height: 200px;
padding-top: 90px;
padding-left: 560px;
text-shadow: 0px 0px 10px black;
}
//체크박스
.checkboxDiv {
margin-top: 10px;
margin-bottom: 20px;
}
.checkboxListDiv {
display: flex;
justify-content: flex-start;
align-items: center;
width: 440px;
}
.checkboxInput {
margin-right: 20px;
width: 18px;
height: 18px;
}
.checkboxP_1 {
margin-right: auto;
color: white;
font-size: 20px;
text-shadow: 0px 0px 10px black;
}
.checkboxP_2 {
margin-right: auto;
color: gray;
text-decoration: line-through;
font-size: 20px;
text-shadow: 0px 0px 10px black;
}
//투두리스트
.todoListForm {
display: flex;
justify-content: flex-start;
align-items: center;
}
.todoListInput {
margin-right: 20px;
background: transparent;
border: 0px;
border-bottom: 1px solid white;
outline: none;
width: 390px;
height: 50px;
font-size: 25px;
color: white;
}
.todoListInput::placeholder {
color: white;
}
//날씨
.weatherName {
margin-left: 18px;
font-size: 20px;
}
.weatherDiv {
display: flex;
}
.weatherIcon {
height: 50px;
}
.weatherTemp {
font-size: 18px;
padding-top: 13px;
}
//버튼
.loginButton {
margin-left: 55px;
background-color: transparent;
border: 0px;
color: white;
font-size: 30px;
}
.loginButton:hover {
color: orange;
}
.addListButton {
background-color: transparent;
border: 0px;
color: white;
font-size: 30px;
}
.addListButton:hover {
color: aqua;
}
.deleteListButton {
background-color: transparent;
border: 0px;
font-size: 20px;
color: white;
}
.deleteListButton:hover {
color: red;
}
//크롬앱
.ChromeAppDiv {
background-size: 100% 100%;
width: 100vw;
height: 100vh;
overflow: auto;
}
App.JS
import React from 'react'
import ChromeApp from './page/ChromeApp.jsx'
function App() {
return (
<div>
<ChromeApp />
</div>
)
}
export default App
최종 완성본
'노마드코더 > REACT 크롬 앱' 카테고리의 다른 글
11. 시간에 따른 Title (0) | 2024.02.04 |
---|---|
10. 체크박스 체크 유무 확인 (0) | 2024.02.04 |
9. 오늘의 할 일 추가, 삭제 (0) | 2024.02.03 |
8. OpenWeatherMap API 가져오기 (0) | 2024.02.01 |
7. 위도, 경도 불러오기 (0) | 2024.02.01 |