-
Notifications
You must be signed in to change notification settings - Fork 69
[클린코드 리액트 3기 김양하] 페이먼츠 미션 Step2 #165
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
base: ummaeha
Are you sure you want to change the base?
Changes from all commits
9a73074
db64f72
cdb24c6
b4c3f87
e1f9b75
80981d3
7271963
b83f6b0
29445b1
638146e
14d5624
be7e958
fabd958
6bd832a
3c29455
175e84b
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,42 +1,50 @@ | ||
#root { | ||
max-width: 1280px; | ||
margin: 0 auto; | ||
padding: 2rem; | ||
text-align: center; | ||
max-width: 1280px; | ||
margin: 0 auto; | ||
padding: 2rem; | ||
text-align: center; | ||
} | ||
|
||
.logo { | ||
height: 6em; | ||
padding: 1.5em; | ||
will-change: filter; | ||
transition: filter 300ms; | ||
height: 6em; | ||
padding: 1.5em; | ||
will-change: filter; | ||
transition: filter 300ms; | ||
} | ||
.logo:hover { | ||
filter: drop-shadow(0 0 2em #646cffaa); | ||
filter: drop-shadow(0 0 2em #646cffaa); | ||
} | ||
.logo.react:hover { | ||
filter: drop-shadow(0 0 2em #61dafbaa); | ||
filter: drop-shadow(0 0 2em #61dafbaa); | ||
} | ||
|
||
@keyframes logo-spin { | ||
from { | ||
transform: rotate(0deg); | ||
} | ||
to { | ||
transform: rotate(360deg); | ||
} | ||
from { | ||
transform: rotate(0deg); | ||
} | ||
to { | ||
transform: rotate(360deg); | ||
} | ||
} | ||
|
||
@media (prefers-reduced-motion: no-preference) { | ||
a:nth-of-type(2) .logo { | ||
animation: logo-spin infinite 20s linear; | ||
} | ||
a:nth-of-type(2) .logo { | ||
animation: logo-spin infinite 20s linear; | ||
} | ||
} | ||
|
||
.card { | ||
padding: 2em; | ||
padding: 2em; | ||
} | ||
|
||
.read-the-docs { | ||
color: #888; | ||
color: #888; | ||
} | ||
|
||
.card-add-button { | ||
width: 100%; | ||
background-color: #bcbaba; | ||
display: block; | ||
border-radius: 2px; | ||
height: 48px; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
import './App.css' | ||
import useStepper from './hooks/useStepper' | ||
import RegistCard, { RegisterDataType } from './components/page/RegistCard' | ||
import RegistCard, { RegisteredDataType } from './components/page/RegistCard' | ||
import Navigation from './components/navigation/navigation' | ||
import RegistEnd from './components/page/RegistEnd' | ||
import { useState } from 'react' | ||
|
@@ -18,48 +18,65 @@ import CardBox from './components/CardBox' | |
|
||
type Step = '카드목록' | '카드추가' | '카드등록완료' | ||
|
||
const INITIAL_CARD_STATE: RegisterDataType = { | ||
const INITIAL_CARD_STATE: RegisteredDataType = { | ||
cardNumber: '', | ||
expirationDate: '', | ||
ownerName: '', | ||
securityCode: '', | ||
secretCode: '', | ||
cardSelectionTypeName: '', | ||
} | ||
|
||
function App() { | ||
const { step, setStep, Stepper, Step } = useStepper<Step>('카드추가') | ||
const [registerData, setRegisterData] = useState<RegisterDataType>(INITIAL_CARD_STATE) | ||
const [cardName, setCardName] = useState<string>('') | ||
const [registeredData, setRegisteredData] = useState<RegisteredDataType>(INITIAL_CARD_STATE) | ||
const [cardName, setCardName] = useState<string>(registeredData.cardSelectionTypeName) | ||
const [cardList, setCardList] = useState<Map<string, RegisteredDataType>>(new Map()) | ||
|
||
const handleSetCardName = (value: string) => { | ||
setCardName(value) | ||
const addMapElement = () => { | ||
const newMap = new Map(cardList) | ||
|
||
newMap.set(cardName, registeredData) | ||
setCardList(newMap) | ||
} | ||
|
||
return ( | ||
<div className="app" id="app"> | ||
<Navigation currentStageName={step!}></Navigation> | ||
<Navigation currentStageName={step}></Navigation> | ||
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. Navigator는 여러 선택지중, 하나로 이동할 수 있게 만들어주는 느낌인데요. 여기서는 그냥 Header느낌인거같습니다! 이름을 바꾸는게 좋을거같아요!! |
||
|
||
<Stepper> | ||
<Step name="카드목록"> | ||
<CardBox | ||
cardName={cardName} | ||
ownerName={registerData.ownerName} | ||
expirationDate={registerData.expirationDate} | ||
cardNumber={registerData.cardNumber} | ||
/> | ||
<button className="card-add-button" onClick={() => setStep('카드추가')}> | ||
+ | ||
</button> | ||
{[...cardList].map(([key, value]) => ( | ||
<> | ||
<CardBox | ||
ownerName={value.ownerName} | ||
expirationDate={value.expirationDate} | ||
cardNumber={value.cardNumber} | ||
theme={value.theme} | ||
cardSelectionTypeName={value.cardSelectionTypeName} | ||
/> | ||
<div>{key}</div> | ||
</> | ||
))} | ||
Comment on lines
+52
to
+63
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. 음 key가 제대로 주어지지 않고 있는거같아요. 브라우저에서 console에러 확인해보시면 좋을거같습니다! |
||
</Step> | ||
<Step name="카드추가"> | ||
<RegistCard | ||
setRegisterData={setRegisterData} | ||
setRegisterData={setRegisteredData} | ||
onPrev={() => setStep('카드목록')} | ||
onNext={() => setStep('카드등록완료')} | ||
/> | ||
</Step> | ||
<Step name="카드등록완료"> | ||
<RegistEnd | ||
handleSetCardName={handleSetCardName} | ||
registCardInfo={registerData} | ||
onNext={() => setStep('카드목록')} | ||
handleSetCardName={setCardName} | ||
registCardInfo={registeredData} | ||
onNext={() => { | ||
addMapElement() | ||
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. 함수이름을 바꿔보는건 어떨까요? cardList에 현재 카드정보를 추가하는 액션같은데요! |
||
setStep('카드목록') | ||
}} | ||
/> | ||
</Step> | ||
</Stepper> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import './CardSelectionItem.css' | ||
type CardProps<T> = { | ||
cardNickName?: string | ||
cardName?: string | ||
ownerName?: string | ||
expirationDate?: string | ||
cardNumber?: string | ||
onClick?: () => void | ||
theme?: T | ||
cardSelectionTypeName?: string | ||
} | ||
|
||
const CardBox = <T,>(props: CardProps<T>) => { | ||
const { ownerName, expirationDate, cardNumber, onClick, theme, cardSelectionTypeName } = props | ||
|
||
return ( | ||
<div className="card-box" onClick={onClick}> | ||
<div className={`empty-card ${theme}-theme`}> | ||
<div className="card-top"> | ||
<span className="card-text">{cardSelectionTypeName}</span> | ||
</div> | ||
<div className="card-middle"> | ||
<div className={'big-card__chip'}></div> | ||
</div> | ||
<div className="card-bottom"> | ||
<div className="card-bottom__number"> | ||
<span className="card-text"> | ||
{cardNumber && | ||
cardNumber.replace(/(.{4})(.{4})(.{4})(.{4})/, '$1-$2-$3-$4')} | ||
</span> | ||
</div> | ||
<div className="card-bottom__info"> | ||
<span className="card-text">{ownerName || 'NAME'}</span> | ||
<span className="card-text">{expirationDate || 'MM/YY'}</span> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
export default CardBox |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
.red-theme { | ||
background-image: linear-gradient(to bottom, red, yellow); | ||
} | ||
.pink-theme { | ||
background-image: linear-gradient(to bottom, pink, yellow); | ||
} | ||
|
||
.orange-theme { | ||
background-image: linear-gradient(to bottom, orange, yellow); | ||
} | ||
.green-theme { | ||
background-image: linear-gradient(to bottom, rgb(79, 138, 79), rgb(215, 215, 147)); | ||
} | ||
.blue-theme { | ||
background-image: linear-gradient(to bottom, rgb(94, 94, 244), rgb(189, 189, 149)); | ||
} | ||
.yellow-theme { | ||
background-image: linear-gradient(to bottom, yellow, rgb(236, 236, 226)); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import './CardSelectionItem.css' | ||
|
||
type CardSelectionItemProps<T> = { | ||
theme: T | ||
name: string | ||
onClick?: () => void | ||
} | ||
|
||
function CardSelectionItem<T>(props: CardSelectionItemProps<T>) { | ||
const { theme, name, onClick } = props | ||
|
||
return ( | ||
<div className="modal-item-container" onClick={onClick}> | ||
<div className={`modal-item-dot ${theme}-theme`}></div> | ||
<span className="modal-item-name">{name}</span> | ||
</div> | ||
) | ||
} | ||
|
||
export default CardSelectionItem |
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.
음 이름이 list인데 자료형이 Map이군요.. 읽는이로 하여금 헷갈릴거같습니다!