-
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
[GGFE-229] 상점 모달 로딩 처리 #982
Changes from 9 commits
a562729
68e6651
11136cd
cbb66a6
5616250
b0ed92d
5c0bb96
72e055b
4165903
cb18a8b
6c125b5
90b1aa9
218cfb0
2dd9b78
4ad1ab9
fdcc12b
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 |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import styles from 'styles/modal/LoadingButton.module.scss'; | ||
|
||
export default function LoadingButton() { | ||
return ( | ||
<div className={styles.loadingButton}> | ||
<div className={styles.loading}> | ||
<span className={styles.span1}>o</span> | ||
<span className={styles.span2}>o</span> | ||
<span className={styles.span3}>o</span> | ||
</div> | ||
</div> | ||
); | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,32 @@ | ||
import { useEffect, useState } from 'react'; | ||
import { Purchase } from 'types/itemTypes'; | ||
import { useState } from 'react'; | ||
import { useSetRecoilState, useResetRecoilState } from 'recoil'; | ||
import { PriceTag } from 'types/modalTypes'; | ||
import { instance } from 'utils/axios'; | ||
import { errorState } from 'utils/recoil/error'; | ||
import { modalState } from 'utils/recoil/modal'; | ||
import { | ||
ModalButtonContainer, | ||
ModalButton, | ||
} from 'components/modal/ModalButton'; | ||
import useBuyModal from 'hooks/modal/store/purchase/useBuyModal'; | ||
import styles from 'styles/modal/store/BuyModal.module.scss'; | ||
|
||
export default function BuyModal({ itemId, product, price }: PriceTag) { | ||
const [purchaseItem, setPurchaseItem] = useState<Purchase>({ itemId: -1 }); | ||
const { onPurchase, onCancel } = useBuyModal(purchaseItem); | ||
const [isLoading, setIsLoading] = useState<boolean>(false); | ||
const resetModal = useResetRecoilState(modalState); | ||
const setError = useSetRecoilState<string>(errorState); | ||
|
||
useEffect(() => { | ||
setPurchaseItem({ | ||
itemId: itemId, | ||
}); | ||
}, [itemId]); | ||
// TODO: 에러 처리 | ||
const onPurchase = async () => { | ||
setIsLoading(true); | ||
try { | ||
await instance.post(`/pingpong/items/purchases/${itemId}`, null); | ||
alert(`구매 성공!`); | ||
} catch (error) { | ||
setError('HB03'); | ||
} | ||
setIsLoading(false); | ||
resetModal(); | ||
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. setIsLoading(false)는 없어도 될거 같아요! 요청이 빠르게 완료되고 나면 로딩 버튼 애니메이션이랑 아닐 때 버튼 배경이랑 겹치는 것 같아요 |
||
}; | ||
|
||
return ( | ||
<div className={styles.container}> | ||
|
@@ -38,8 +48,13 @@ export default function BuyModal({ itemId, product, price }: PriceTag) { | |
</div> | ||
</div> | ||
<ModalButtonContainer> | ||
<ModalButton style='negative' value='아니오' onClick={onCancel} /> | ||
<ModalButton style='positive' value='예' onClick={onPurchase} /> | ||
<ModalButton style='negative' value='아니오' onClick={resetModal} /> | ||
<ModalButton | ||
style='positive' | ||
value='예' | ||
isLoading={isLoading} | ||
onClick={onPurchase} | ||
/> | ||
</ModalButtonContainer> | ||
</div> | ||
); | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,28 +1,46 @@ | ||||||||||||||||||||||||||
import { useEffect, useState } from 'react'; | ||||||||||||||||||||||||||
import { Gift } from 'types/itemTypes'; | ||||||||||||||||||||||||||
import { useState } from 'react'; | ||||||||||||||||||||||||||
import { useSetRecoilState, useResetRecoilState } from 'recoil'; | ||||||||||||||||||||||||||
import { GiftRequest } from 'types/itemTypes'; | ||||||||||||||||||||||||||
import { PriceTag } from 'types/modalTypes'; | ||||||||||||||||||||||||||
import { instance } from 'utils/axios'; | ||||||||||||||||||||||||||
import { errorState } from 'utils/recoil/error'; | ||||||||||||||||||||||||||
import { modalState } from 'utils/recoil/modal'; | ||||||||||||||||||||||||||
import { | ||||||||||||||||||||||||||
ModalButtonContainer, | ||||||||||||||||||||||||||
ModalButton, | ||||||||||||||||||||||||||
} from 'components/modal/ModalButton'; | ||||||||||||||||||||||||||
import GiftSearchBar from 'components/store/purchase/GiftSearchBar'; | ||||||||||||||||||||||||||
import useGiftModal from 'hooks/modal/store/purchase/useGiftModal'; | ||||||||||||||||||||||||||
import styles from 'styles/modal/store/GiftModal.module.scss'; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
export default function GiftModal({ itemId, product, price }: PriceTag) { | ||||||||||||||||||||||||||
const [recipient, setRecipient] = useState<string>(''); | ||||||||||||||||||||||||||
const [gift, setGift] = useState<Gift>({ | ||||||||||||||||||||||||||
itemId: -1, | ||||||||||||||||||||||||||
const [isLoading, setIsLoading] = useState<boolean>(false); | ||||||||||||||||||||||||||
const resetModal = useResetRecoilState(modalState); | ||||||||||||||||||||||||||
const setError = useSetRecoilState<string>(errorState); | ||||||||||||||||||||||||||
const [giftReqData, setGiftReqData] = useState<GiftRequest>({ | ||||||||||||||||||||||||||
ownerId: '', | ||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||
const { onPurchase, onCancel } = useGiftModal(gift); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
useEffect(() => { | ||||||||||||||||||||||||||
setGift({ | ||||||||||||||||||||||||||
itemId: itemId, | ||||||||||||||||||||||||||
ownerId: recipient, | ||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||
}, [itemId, recipient]); | ||||||||||||||||||||||||||
// TODO: 에러 처리 | ||||||||||||||||||||||||||
const onPurchase = async () => { | ||||||||||||||||||||||||||
if (giftReqData.ownerId === '') { | ||||||||||||||||||||||||||
alert('선물할 유저를 선택해주세요.'); | ||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
setIsLoading(true); | ||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||
const res = await instance.post( | ||||||||||||||||||||||||||
`/pingpong/items/gift/${itemId}`, | ||||||||||||||||||||||||||
giftReqData | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
if (res.status === 201) { | ||||||||||||||||||||||||||
alert(`${giftReqData.ownerId}님께 선물이 전달되었습니다.`); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
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. 여기
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. 그렇게 하는게 좋을 것 같네요! 수정하겠습니다👍 |
||||||||||||||||||||||||||
} catch (error) { | ||||||||||||||||||||||||||
setError('HB02'); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
setIsLoading(false); | ||||||||||||||||||||||||||
resetModal(); | ||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||
<div className={styles.container}> | ||||||||||||||||||||||||||
|
@@ -39,19 +57,24 @@ export default function GiftModal({ itemId, product, price }: PriceTag) { | |||||||||||||||||||||||||
<div>{price} 코인</div> | ||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||
<GiftSearchBar setRecipient={setRecipient} /> | ||||||||||||||||||||||||||
{recipient !== '' && ( | ||||||||||||||||||||||||||
<GiftSearchBar setGiftReqData={setGiftReqData} /> | ||||||||||||||||||||||||||
{giftReqData.ownerId !== '' && ( | ||||||||||||||||||||||||||
<div className={styles.recipient}> | ||||||||||||||||||||||||||
<span>{recipient}</span>님에게 선물하시겠습니까? | ||||||||||||||||||||||||||
<span>{giftReqData.ownerId}</span>님에게 선물하시겠습니까? | ||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||
)} | ||||||||||||||||||||||||||
<div className={styles.warning}> | ||||||||||||||||||||||||||
<p>⚠ 선물한 아이템은 환불 및 취소가 불가합니다 ⚠</p> | ||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||
<ModalButtonContainer> | ||||||||||||||||||||||||||
<ModalButton style='negative' value='취소' onClick={onCancel} /> | ||||||||||||||||||||||||||
<ModalButton style='positive' value='보내기' onClick={onPurchase} /> | ||||||||||||||||||||||||||
<ModalButton style='negative' value='취소' onClick={resetModal} /> | ||||||||||||||||||||||||||
<ModalButton | ||||||||||||||||||||||||||
style='positive' | ||||||||||||||||||||||||||
value='보내기' | ||||||||||||||||||||||||||
isLoading={isLoading} | ||||||||||||||||||||||||||
onClick={onPurchase} | ||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||
</ModalButtonContainer> | ||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
|
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.
이 컴포넌트 이름은 버튼인데 사실은 버튼이 아니라 (?) 나중에 보면 헷갈릴수도 있을 것 같아요 🥲
LoadingEffect같이 애니메이션이나 효과를 보여주는 컴포넌트 이름으로 바꾸면 좋을 것 같아요!
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.
사실 버튼은 아니지만 버튼 모양처럼 생기긴해서 버튼이라고 지었습니다! ㅎㅎ 로딩애니메이션은 따로 컴포넌트로 분리하진 않아서 이것도 시간 되면 분리하면 좋을 것 같긴 하네요!