-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[2주차] 김문기 미션 제출합니다. #4
base: master
Are you sure you want to change the base?
Changes from 18 commits
376c73b
af8e2a2
c9f46ed
71c2161
97d2755
5643b9c
49c72eb
8812a80
ae2b787
924396a
a5cfc02
845f945
62c8462
5415824
7845621
4066b12
dce66f4
e8734c2
65d1d09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
node_modules | ||
|
||
.env |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,38 @@ | ||
import { useEffect, useState } from "react"; | ||
import Mainpage from "./pages/Mainpage/Mainpage"; | ||
|
||
function App() { | ||
return ( | ||
<div> | ||
<h1>17기 프론트 화이팅~ 우하하</h1> | ||
</div> | ||
const [clickedIcon, setClickedIcon] = useState(""); | ||
const [mainIconPosition, setMainIconPosition] = useState( | ||
JSON.parse(localStorage.getItem("mainIconPosition")) ?? { | ||
top: 30, | ||
left: 30, | ||
} | ||
); | ||
const [textIconPosition, setTextIconPosition] = useState( | ||
JSON.parse(localStorage.getItem("textIconPosition")) ?? { | ||
top: 160, | ||
left: 30, | ||
} | ||
); | ||
|
||
useEffect(() => { | ||
if (!localStorage.getItem("mainIconPosition")) { | ||
localStorage.setItem( | ||
"mainIconPosition", | ||
JSON.stringify(mainIconPosition) | ||
); | ||
} | ||
if (!localStorage.getItem("textIconPosition")) { | ||
localStorage.setItem( | ||
"textIconPosition", | ||
JSON.stringify(textIconPosition) | ||
); | ||
} | ||
}, [mainIconPosition, textIconPosition]); | ||
|
||
useEffect(() => {}); | ||
return <Mainpage clickedIcon={clickedIcon} setClickedIcon={setClickedIcon} />; | ||
} | ||
|
||
export default App; | ||
export default App; |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저도 styled-components 사용 시 코드가 위아래로 길어지는 게 너무 불편했는데 파일 분리 배워갑니다. ㅎㅎ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import styled from "styled-components"; | ||
|
||
export const CardContainer = styled.div` | ||
width: ${(props) => (props.display ? "max(300px, 30vw)" : "0")}; | ||
height: ${(props) => (props.display ? "max(500px, 50vw)" : "0")}; | ||
position: ${(props) => (props.display ? "initial" : "fixed")}; | ||
top: ${(props) => props.position.top}; | ||
left: ${(props) => props.position.left}; | ||
Comment on lines
+4
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 문기님 styled-components 에서 props 활용을 잘 하시는 것 같아요!! 저도 다음 과제에 적용해보고 싶습니다 👍 |
||
margin: 0 auto; | ||
background-color: #1e1e1e; | ||
border-radius: 12px; | ||
z-index: 2; | ||
visibility: ${(props) => (props.display ? "visible" : "hidden")}; | ||
box-shadow: 0 0 10px 0px #000000; | ||
transition: width 0.2s, height 0.2s, visibility 0.05s linear 0.15s; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 옆에 맥 켜놓고 최대한 비슷하게 만드려고 노력했습니다 ㅎㅎ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 우와........ 진짜 감탄만......... |
||
`; | ||
|
||
export const CardToolBar = styled.div` | ||
display: flex; | ||
align-items: center; | ||
height: 40px; | ||
padding: 12px; | ||
background-color: #312f34; | ||
border-radius: 12px 12px 0 0; | ||
box-sizing: border-box; | ||
position: relative; | ||
visibility: ${(props) => (props.display ? "visible" : "hidden")}; | ||
`; | ||
|
||
export const CardPlusBtn = styled.div` | ||
width: 20px; | ||
height: 20px; | ||
color: white; | ||
display: flex; | ||
justify-content: center; | ||
font-size: 24px; | ||
border-radius: 4px; | ||
position: absolute; | ||
right: 12px; | ||
padding: 2px; | ||
&:hover { | ||
background-color: #656565; | ||
cursor: url(Link.cur) 0 0, pointer; | ||
/* cursor: url(../../assets/Link.cur) 0 0, pointer; */ | ||
} | ||
Comment on lines
+41
to
+45
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 와 이런 디테일! |
||
&::before { | ||
content: "+"; | ||
} | ||
`; | ||
|
||
export const NotHoverDiv = styled.div` | ||
opacity: ${(props) => (props.hoverRender ? 0 : 1)}; | ||
display: ${(props) => (props.render ? "flex" : "none")}; | ||
flex-direction: column; | ||
height: 100%; | ||
transition: opacity 0.1s; | ||
`; | ||
|
||
export const CardMainDiv = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
justify-content: center; | ||
height: calc(100% - 40px); | ||
border-radius: 0 0 12px 12px; | ||
position: relative; | ||
`; | ||
|
||
export const CardTodoText = styled.h1` | ||
color: white; | ||
font-weight: 800; | ||
font-size: 20px; | ||
display: flex; | ||
width: 100%; | ||
text-align: left; | ||
box-sizing: border-box; | ||
padding: 8px 0 0 12px; | ||
margin-bottom: 8px; | ||
`; | ||
|
||
export const CardTodoDiv = styled.div` | ||
display: flex; | ||
flex-wrap: wrap; | ||
height: 100%; | ||
flex-direction: row; | ||
justify-content: center; | ||
overflow-y: auto; | ||
position: relative; | ||
align-content: flex-start; | ||
overflow-x: hidden; | ||
width: 100%; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { useEffect, useState } from "react"; | ||
import CircleBtn from "../circleBtn/CircleBtn"; | ||
|
||
import HoverDiv from "../hoverDiv/HoverDiv"; | ||
import Todo from "../todo/Todo"; | ||
import { | ||
CardContainer, | ||
CardToolBar, | ||
CardPlusBtn, | ||
CardMainDiv, | ||
CardTodoDiv, | ||
CardTodoText, | ||
NotHoverDiv, | ||
} from "./Card.element"; | ||
|
||
const Card = ({ render, setRender }) => { | ||
useEffect(() => { | ||
setHoverDivRender(false); | ||
}, [render]); | ||
const [hoverDivRender, setHoverDivRender] = useState(false); | ||
|
||
const [allList, setAllList] = useState([]); | ||
const todoList = allList ? allList.filter((item) => item.done === false) : []; | ||
const doneList = allList ? allList.filter((item) => item.done === true) : []; | ||
|
||
useEffect(() => { | ||
setAllList(JSON.parse(localStorage.getItem("todoList")) || []); | ||
}, [hoverDivRender]); | ||
return ( | ||
<CardContainer | ||
display={render} | ||
position={{ | ||
top: "50px", | ||
left: "50px", | ||
}} | ||
> | ||
<CardToolBar display={render}> | ||
<CircleBtn | ||
color="red" | ||
type="button" | ||
render={render} | ||
setRender={setRender} | ||
/> | ||
<CircleBtn color="yellow" type="button" /> | ||
<CircleBtn color="green" type="button" /> | ||
<CardPlusBtn onClick={() => setHoverDivRender(!hoverDivRender)} /> | ||
</CardToolBar> | ||
<CardMainDiv> | ||
<HoverDiv | ||
hoverDivRender={hoverDivRender && render} | ||
setHoverDivRender={setHoverDivRender} | ||
/> | ||
<NotHoverDiv render={render} hoverRender={hoverDivRender}> | ||
<CardTodoText>TODO [{todoList.length}개]</CardTodoText> | ||
<CardTodoDiv> | ||
{todoList.length > 0 && | ||
todoList.map((item) => { | ||
return ( | ||
<Todo | ||
key={item.id} | ||
id={item.id} | ||
content={item.content} | ||
tag={item.tag} | ||
done={item.done} | ||
setAllList={setAllList} | ||
allList={allList} | ||
/> | ||
); | ||
})} | ||
{todoList.length === 0 && <Todo tag={-1} />} | ||
</CardTodoDiv> | ||
<CardTodoText>DONE [{doneList.length}개]</CardTodoText> | ||
<CardTodoDiv> | ||
{doneList.length > 0 && | ||
doneList.map((item) => { | ||
return ( | ||
<Todo | ||
key={item.id} | ||
id={item.id} | ||
content={item.content} | ||
tag={item.tag} | ||
done={item.done} | ||
setAllList={setAllList} | ||
/> | ||
); | ||
})} | ||
{doneList.length === 0 && <Todo tag={-2} />} | ||
</CardTodoDiv> | ||
</NotHoverDiv> | ||
</CardMainDiv> | ||
</CardContainer> | ||
); | ||
}; | ||
|
||
export default Card; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import styled from "styled-components"; | ||
|
||
export const CardCircle = styled.div` | ||
display: inline-block; | ||
margin: 0 4px; | ||
align-items: center; | ||
width: 10px; | ||
height: 10px; | ||
padding: 1px; | ||
border-radius: 50%; | ||
background-color: ${(props) => `var(--${props.color}-${props.type})`}; | ||
&:hover { | ||
cursor: url(Link.cur) 0 0, pointer; | ||
} | ||
`; | ||
|
||
export const InputCircle = styled.input` | ||
appearance: none; | ||
display: inline-block; | ||
margin: 0 4px; | ||
align-items: center; | ||
width: max(12px, 1.2vw); | ||
height: max(12px, 1.2vw); | ||
padding: 1px; | ||
border-radius: 50%; | ||
background-color: ${(props) => `var(--${props.color}-${props._type})`}; | ||
&:hover { | ||
cursor: url(Link.cur) 0 0, pointer; | ||
} | ||
border: ${(props) => | ||
props.selectedTag === props.value ? "1px solid white" : "none"}; | ||
transition: border 0.3s ease-in-out; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { CardCircle, InputCircle } from "./CircleBtn.element"; | ||
|
||
const CircleBtn = ({ | ||
color, | ||
type, | ||
render, | ||
setRender, | ||
name, | ||
value, | ||
selectedTag, | ||
handleTagChange, | ||
}) => { | ||
if (type === "tag") { | ||
// using type as _type since 'type' is reserved word in input | ||
return ( | ||
<InputCircle | ||
type="radio" | ||
color={color} | ||
_type={type} | ||
name={name} | ||
value={value} | ||
selectedTag={selectedTag} | ||
onClick={handleTagChange} | ||
/> | ||
); | ||
} else if (color === "red" && type === "button") { | ||
return ( | ||
<CardCircle | ||
color={color} | ||
type={type} | ||
onClick={() => setRender(!render)} | ||
/> | ||
); | ||
} else { | ||
return <CardCircle color={color} type={type} />; | ||
} | ||
}; | ||
|
||
export default CircleBtn; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
그동안 style에 대한 값은 state로 지정해본 적이 없었는데 좋은 방법인 것 같아요! 배워갑니다. ㅎㅎ