-
Notifications
You must be signed in to change notification settings - Fork 8
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
MISSION3 / 곽민준 #26
base: main
Are you sure you want to change the base?
MISSION3 / 곽민준 #26
Changes from all commits
d0af73d
4595483
81e073b
ce3a25c
3c71e64
5e10c36
b350177
517ddec
221af16
d9786cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,124 @@ | ||
#root { | ||
max-width: 1280px; | ||
margin: 0 auto; | ||
padding: 2rem; | ||
text-align: center; | ||
html, | ||
body, | ||
div, | ||
span, | ||
applet, | ||
object, | ||
iframe, | ||
h1, | ||
h2, | ||
h3, | ||
h4, | ||
h5, | ||
h6, | ||
p, | ||
blockquote, | ||
pre, | ||
a, | ||
abbr, | ||
acronym, | ||
address, | ||
big, | ||
cite, | ||
code, | ||
del, | ||
dfn, | ||
em, | ||
img, | ||
ins, | ||
kbd, | ||
q, | ||
s, | ||
samp, | ||
small, | ||
strike, | ||
strong, | ||
sub, | ||
sup, | ||
tt, | ||
var, | ||
b, | ||
u, | ||
i, | ||
center, | ||
dl, | ||
dt, | ||
dd, | ||
ol, | ||
ul, | ||
li, | ||
fieldset, | ||
form, | ||
label, | ||
legend, | ||
table, | ||
caption, | ||
tbody, | ||
tfoot, | ||
thead, | ||
tr, | ||
th, | ||
td, | ||
article, | ||
aside, | ||
canvas, | ||
details, | ||
embed, | ||
figure, | ||
figcaption, | ||
footer, | ||
header, | ||
hgroup, | ||
menu, | ||
nav, | ||
output, | ||
ruby, | ||
section, | ||
summary, | ||
time, | ||
mark, | ||
audio, | ||
video { | ||
margin: 0; | ||
padding: 0; | ||
border: 0; | ||
font-size: 100%; | ||
font: inherit; | ||
vertical-align: baseline; | ||
} | ||
|
||
.logo { | ||
height: 6em; | ||
padding: 1.5em; | ||
will-change: filter; | ||
transition: filter 300ms; | ||
/* HTML5 display-role reset for older browsers */ | ||
article, | ||
aside, | ||
details, | ||
figcaption, | ||
figure, | ||
footer, | ||
header, | ||
hgroup, | ||
menu, | ||
nav, | ||
section { | ||
display: block; | ||
} | ||
.logo:hover { | ||
filter: drop-shadow(0 0 2em #646cffaa); | ||
body { | ||
line-height: 1; | ||
} | ||
.logo.react:hover { | ||
filter: drop-shadow(0 0 2em #61dafbaa); | ||
ol, | ||
ul { | ||
list-style: none; | ||
} | ||
|
||
@keyframes logo-spin { | ||
from { | ||
transform: rotate(0deg); | ||
} | ||
to { | ||
transform: rotate(360deg); | ||
} | ||
blockquote, | ||
q { | ||
quotes: none; | ||
} | ||
|
||
@media (prefers-reduced-motion: no-preference) { | ||
a:nth-of-type(2) .logo { | ||
animation: logo-spin infinite 20s linear; | ||
} | ||
blockquote:before, | ||
blockquote:after, | ||
q:before, | ||
q:after { | ||
content: ""; | ||
content: none; | ||
} | ||
|
||
.card { | ||
padding: 2em; | ||
} | ||
|
||
.read-the-docs { | ||
color: #888; | ||
table { | ||
border-collapse: collapse; | ||
border-spacing: 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,21 @@ | ||
import { useState } from 'react' | ||
import reactLogo from './assets/react.svg' | ||
import viteLogo from '/vite.svg' | ||
import './App.css' | ||
import React from "react"; | ||
import styled from "styled-components"; | ||
import CardRegisterForm from "./components/CardRegisterForm"; | ||
import "./App.css"; | ||
|
||
function App() { | ||
const [count, setCount] = useState(0) | ||
|
||
return ( | ||
<> | ||
<div> | ||
<a href="https://vitejs.dev" target="_blank"> | ||
<img src={viteLogo} className="logo" alt="Vite logo" /> | ||
</a> | ||
<a href="https://react.dev" target="_blank"> | ||
<img src={reactLogo} className="logo react" alt="React logo" /> | ||
</a> | ||
</div> | ||
<h1>Vite + React</h1> | ||
<div className="card"> | ||
<button onClick={() => setCount((count) => count + 1)}> | ||
count is {count} | ||
</button> | ||
<p> | ||
Edit <code>src/App.jsx</code> and save to test HMR | ||
</p> | ||
</div> | ||
<p className="read-the-docs"> | ||
Click on the Vite and React logos to learn more | ||
</p> | ||
</> | ||
) | ||
<GreyBackground> | ||
<CardRegisterForm /> | ||
</GreyBackground> | ||
Comment on lines
+8
to
+10
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 컴포넌트에 대한 컴포넌트 명을 구분할 수 있다면 가독성이 더 좋아질 것 같아요ㅎㅎ 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 default App | ||
export default App; | ||
|
||
const GreyBackground = styled.div` | ||
background-color: #efeff0; | ||
height: 100vh; | ||
display: flex; | ||
justify-content: center; | ||
`; |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import React from "react"; | ||
import styled from "styled-components"; | ||
|
||
const Card = ({ cardNumber }) => { | ||
return ( | ||
<CardList> | ||
<CardImage /> | ||
<CardNumber>카드 번호: {cardNumber}</CardNumber> | ||
</CardList> | ||
); | ||
}; | ||
|
||
export default Card; | ||
|
||
const CardImage = styled.div` | ||
width: 9.375rem; | ||
height: 5rem; | ||
background-color: white; | ||
border-radius: 0.3125rem; | ||
`; | ||
|
||
const CardList = styled.div` | ||
display: flex; | ||
padding: 0.625rem 0.625rem 0.625rem 0rem; | ||
`; | ||
|
||
const CardNumber = styled.div` | ||
padding: 0.625rem; | ||
`; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,26 @@ | ||||||||||||||||||||||||||||||||||||||
// CardNumberInputs 컴포넌트 | ||||||||||||||||||||||||||||||||||||||
import React from "react"; | ||||||||||||||||||||||||||||||||||||||
import DataInput from "./DataInput"; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
const CardNumberInputs = ({ cardNumbers, handleInputChange }) => { | ||||||||||||||||||||||||||||||||||||||
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. CardRegisterForm에서 DataInput을 바로 사용하지 않고 CardNumberInputs 컴포넌트를 따로생성한 이유가 있을까요??
Suggested change
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. 다른 부분과 카드 입력하는 부분이 뭔가 다르게 구성되어져있다고 생각해서 따로 만들었는데, 이런식으로 하면 컴포넌트를 추가로 만들 필요 없이 재사용성을 높일 수 있겠네요! 이렇게 컴포넌트 하나로만 해보고싶었는데 어떻게 해야 할 지 막막했는데 알려주셔서 감사합니다! 다시 만들어보도록 하겠습니다 |
||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||
<div | ||||||||||||||||||||||||||||||||||||||
style={{ | ||||||||||||||||||||||||||||||||||||||
display: "flex", | ||||||||||||||||||||||||||||||||||||||
width: "100%", | ||||||||||||||||||||||||||||||||||||||
justifyContent: "space-between", | ||||||||||||||||||||||||||||||||||||||
}} | ||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||
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 컴포넌트로 구현해주시면 좋을 것 같은데, style을 인라인으로 삽입한 이유가 있을까요?? 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. 저 당시에 제가 왜 저렇게 작성했는지 모르겠네요ㅠㅠ 일관성 있게 작성하도록 하겠습니다! |
||||||||||||||||||||||||||||||||||||||
{cardNumbers.map((number, index) => ( | ||||||||||||||||||||||||||||||||||||||
<DataInput | ||||||||||||||||||||||||||||||||||||||
key={index} | ||||||||||||||||||||||||||||||||||||||
placeholder={"0000"} | ||||||||||||||||||||||||||||||||||||||
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. react에서는 변수가 아니여도 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. 변수나 표현식을 사용해야 할 경우에는 중괄호를 사용해야 하지만, 속성값이 정적인 문자열이라면, 바로 값을 할당하는 것이 좋겠네요! |
||||||||||||||||||||||||||||||||||||||
value={number} | ||||||||||||||||||||||||||||||||||||||
onChange={handleInputChange(index)} | ||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||
))} | ||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
export default CardNumberInputs; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import DataInput from "./DataInput"; | ||
import React, { useState } from "react"; | ||
import styled from "styled-components"; | ||
import Card from "./Card"; | ||
import CardNumberInputs from "./CardNumberInputs"; | ||
Comment on lines
+1
to
+5
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. 외부 라이브러리 import와 내부 파일 import는 각각 묶어주시는게 조금 더 보기 좋을 것 같아요ㅎㅎ 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.
이런식으로 내부 파일 사용하는 것과 외부 라이브러리 import하는 것을 나누면 훨씬 가독성이 높겠네요! 감사합니다 |
||
|
||
const CardRegisterForm = () => { | ||
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. CardRegisterForm에 대해 몇가지 제안드리고 싶은게 있습니다.
코드로 표현하면 아래와 같아요. 정확히 구현되는지는 확인을 안해봐서 흐름만 참고 해주시면 좋을 것 같아요ㅎㅎ // CardRegisterForm.jsx
const CardRegisterForm = () => {
// 카드 정보 객체를 state로 관리
const [cardInfo, setCardInfo] = useState({
name: "",
number: ["", "", "", ""],
expirationDate: "",
cvc: "",
passward: "",
});
// 저장된 카드 정보를 state로 관리
const [savedCardInfo, setSavedCardInfo] = useState([]);
// 사용자가 입력할 때마다 카드 정보 객체 업데이트
const handleInputEvent = (e) => {
const { name, value } = e.target;
setCardInfo((prev) => ({ ...prev, [name]: value }));
};
// 완료 클릭 시 Card 컴포넌트에 카드 정보 전달
const saveCardInfo = (e) => {
// form 기본 액션 새로고침 방지
e.preventDefault();
setSavedCardInfo((prev) => [...prev, cardInfo]);
};
return (
<div>
<FormTitle>카드 정보를 입력해주세요</FormTitle>
<form onSubmit={handleSubmit}>
<DataInput
name="name"
InputData={"카드 이름"}
placeholder={"카드 이름을 입력해주세요"}
value={cardInfo.name}
onChange={handleInputEvent}
/>
<DataInput
type={"text"}
name="expirationDate"
InputData={"유효기간"}
placeholder={"MM/YY"}
value={cardInfo.expirationDate}
onChange={handleInputEvent}
/>
<DataInput
name="cvc"
type={"password"}
InputData={"CVC"}
placeholder={"카드 뒷면 3자리 숫자"}
onChange={handleInputEvent}
value={cardInfo.cvc}
/>
<DataInput
name="password"
type={"password"}
InputData={"카드 비밀번호"}
placeholder={"카드 앞면 2자리 숫자"}
value={cardInfo.password}
onChange={handleInputEvent}
/>
<button type="submit">완료</button>
<Card savedCardInfo={savedCardInfo} />
</form>
</div>
);
}; 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. Input에 name이라는 기본 속성이 있는지도 몰랐고, form도 사실 안써봐서 써 볼 생각 자체를 못해봤던거 같네요 기본 속성에는 어떤게 있는지 찾아보면서 익혀보도록 하겠습니다! |
||
const [cardNumbers, setCardNumbers] = useState(["", "", "", ""]); | ||
const [submittedCardNumbers, setSubmittedCardNumbers] = useState([]); | ||
|
||
const handleInputChange = (index) => (e) => { | ||
const newCardNumbers = [...cardNumbers]; | ||
newCardNumbers[index] = e.target.value; | ||
setCardNumbers(newCardNumbers); | ||
}; | ||
|
||
const handleSubmit = () => { | ||
const cardNumber = cardNumbers.join(""); | ||
setSubmittedCardNumbers((prev) => [...prev, cardNumber]); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<FormTitle>카드 정보를 입력해주세요</FormTitle> | ||
<DataInput | ||
InputData={"카드 이름"} | ||
placeholder={"카드 이름을 입력해주세요"} | ||
/> | ||
<CardNumberInputs | ||
cardNumbers={cardNumbers} | ||
handleInputChange={handleInputChange} | ||
/> | ||
<DataInput type={"text"} InputData={"유효기간"} placeholder={"MM/YY"} /> | ||
<DataInput | ||
type={"password"} | ||
InputData={"CVC"} | ||
placeholder={"카드 뒷면 3자리 숫자"} | ||
/> | ||
<DataInput | ||
type={"password"} | ||
InputData={"카드 비밀번호"} | ||
placeholder={"카드 앞면 2자리 숫자"} | ||
/> | ||
<CompleteButton onClick={handleSubmit}>완료</CompleteButton> | ||
{submittedCardNumbers.map((number, index) => ( | ||
<Card key={index} cardNumber={number} /> | ||
))} | ||
</div> | ||
); | ||
}; | ||
|
||
export default CardRegisterForm; | ||
|
||
const CompleteButton = styled.button` | ||
margin-top: 0.625rem; | ||
padding: 1.25rem 21.5625rem; | ||
background-color: white; | ||
border-radius: 0px 0px 0.3125rem 0.3125rem; | ||
border: none; | ||
`; | ||
|
||
const FormTitle = styled.div` | ||
background-color: #8991a0; | ||
color: white; | ||
font-size: 0.875rem; | ||
padding: 0.9375rem; | ||
border-radius: 0.3125rem 0.3125rem 0px 0px; | ||
margin-top: 3.125rem; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import React from "react"; | ||
import styled from "styled-components"; | ||
|
||
function DataInput({ type, placeholder, InputData, value, onChange }) { | ||
return ( | ||
<InputForm> | ||
<label>{InputData} </label> | ||
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. 실수로 InputData만 UpperCamelCase로 작성 한 것 같은데, 다음에는 이런 부분도 유심하게 살펴봐야겠네요! 확실히 subTitle이라는 이름이 더 어울리는 것 같습니다. |
||
<input | ||
type={type} | ||
placeholder={placeholder} | ||
value={value} | ||
onChange={onChange} | ||
/> | ||
</InputForm> | ||
); | ||
} | ||
|
||
export default DataInput; | ||
|
||
const InputForm = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
padding: 0.625rem; | ||
background-color: white; | ||
border-bottom: 0.0625rem solid #d9d9d9; | ||
input { | ||
border: none; | ||
} | ||
|
||
label { | ||
text-align: left; | ||
} | ||
`; |
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.
사용하지 않는 태그도 포함해서 스타일 속성을 부여한 이유가 궁금합니다!
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.
CSS초기화를 하고 시작해야할 거 같아서 블로그 게시글을 보고 코드를 붙여넣었는데, 잘못된 방법일까요?!
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.
궁금해서 여쭤봤어요ㅎㅎ 이런 것도 있네요~ 하나 알아갑니다ㅎㅎ