-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'release/2.1.0' into feat/#309-last_card
- Loading branch information
Showing
20 changed files
with
355 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import React, { PropsWithChildren, useCallback, useState } from "react"; | ||
|
||
import { ToastContext } from "./context"; | ||
import useTimeout from "./hooks/useTimeout"; | ||
import * as St from "./style"; | ||
|
||
export type ToastType = { | ||
message: string; | ||
duration: number; | ||
}; | ||
|
||
export default function ToastProvider({ children }: PropsWithChildren) { | ||
const [toast, setToast] = useState<ToastType | null>(null); | ||
const toastTimeout = useTimeout(); | ||
|
||
const showToast = useCallback( | ||
async ({ message, duration }: ToastType) => { | ||
setToast({ message, duration }); | ||
|
||
toastTimeout.set(() => { | ||
setToast(null); | ||
}, duration * 1000); | ||
}, | ||
[setToast, toastTimeout], | ||
); | ||
|
||
return ( | ||
<ToastContext.Provider value={{ showToast }}> | ||
{children} | ||
{toast && ( | ||
<St.ToastContainer> | ||
<St.ToastMessage>{toast.message}</St.ToastMessage> | ||
</St.ToastContainer> | ||
)} | ||
</ToastContext.Provider> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from "react"; | ||
|
||
import { ToastType } from "./ToastProvider"; | ||
|
||
interface ToastController { | ||
showToast: (toast: ToastType) => void; | ||
} | ||
|
||
export const ToastContext = React.createContext<ToastController>({ | ||
showToast: () => { | ||
throw new Error("Function not implemented."); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { useRef } from "react"; | ||
|
||
import { ToastType } from "../ToastProvider"; | ||
|
||
export default function useTimeout() { | ||
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null); | ||
|
||
return { | ||
set(handler: () => void, duration: number) { | ||
if (timerRef.current !== null) { | ||
clearTimeout(timerRef.current); | ||
} | ||
timerRef.current = setTimeout(handler, duration); | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { useContext } from "react"; | ||
|
||
import { ToastContext } from "../context"; | ||
import { ToastType } from "../ToastProvider"; | ||
|
||
export default function useToast() { | ||
const { showToast } = useContext(ToastContext); | ||
|
||
return (toast: ToastType) => showToast(toast); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import styled from "styled-components"; | ||
|
||
export const ToastContainer = styled.div` | ||
position: absolute; | ||
bottom: 7.2rem; | ||
width: 100%; | ||
padding: 0 0.8rem; | ||
z-index: 10; | ||
`; | ||
|
||
export const ToastMessage = styled.div` | ||
display: flex; | ||
height: 4.8rem; | ||
padding: 0.8rem 1.6rem; | ||
align-items: center; | ||
border-radius: 0.6rem; | ||
border: 0.1rem solid ${({ theme }) => theme.newColors.gray200}; | ||
background: ${({ theme }) => theme.newColors.white}; | ||
${({ theme }) => theme.newFonts.caption1} | ||
color: ${({ theme }) => theme.newColors.gray900}; | ||
`; |
42 changes: 42 additions & 0 deletions
42
src/@components/CardCollectionPage/Card/CardMenu/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import IcBookmarkCheck_23_28 from "../../../../asset/icon/IcBookmarkCheck_23_28"; | ||
import IcMenuBtn from "../../../../asset/icon/IcMenuBtn"; | ||
import IcShareBtn from "../../../../asset/icon/IcShareBtn"; | ||
import { GTM_CLASS_NAME } from "../../../../util/const/gtm"; | ||
import useCardBookmark from "../../hooks/useCardBookmark"; | ||
import * as St from "./style"; | ||
|
||
interface CardMenuProps { | ||
_id: string; | ||
isBookmark: boolean; | ||
openLoginModalHandler: () => void; | ||
toggleMenuModal: () => void; | ||
} | ||
|
||
export default function CardMenu(props: CardMenuProps) { | ||
const { _id, isBookmark, openLoginModalHandler, toggleMenuModal } = props; | ||
|
||
const { isBookmarked, handleClickBookmark } = useCardBookmark(isBookmark, openLoginModalHandler); | ||
return ( | ||
<St.MenuContainer> | ||
<St.ButtonWrapper onClick={toggleMenuModal}> | ||
<IcMenuBtn /> | ||
</St.ButtonWrapper> | ||
<St.ButtonWrapper> | ||
<St.IconWrapper> | ||
<IcShareBtn /> | ||
</St.IconWrapper> | ||
<St.ButtonLabel>공유하기</St.ButtonLabel> | ||
</St.ButtonWrapper> | ||
<St.ButtonWrapper | ||
className={GTM_CLASS_NAME.cardBookmark} | ||
onClick={() => handleClickBookmark(_id)} | ||
aria-label="북마크" | ||
role="dialog"> | ||
<St.IconWrapper> | ||
<IcBookmarkCheck_23_28 isChecked={isBookmarked} /> | ||
</St.IconWrapper> | ||
<St.ButtonLabel>저장하기</St.ButtonLabel> | ||
</St.ButtonWrapper> | ||
</St.MenuContainer> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import styled from "styled-components"; | ||
|
||
export const MenuContainer = styled.article` | ||
display: flex; | ||
flex-direction: column; | ||
position: absolute; | ||
bottom: 1.7rem; | ||
right: 1.2rem; | ||
gap: 2.4rem; | ||
`; | ||
|
||
export const ButtonWrapper = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
width: 4.1rem; | ||
`; | ||
|
||
export const IconWrapper = styled.div` | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
width: 4rem; | ||
height: 4rem; | ||
`; | ||
|
||
export const ButtonLabel = styled.p` | ||
margin-top: 0.6rem; | ||
${({ theme }) => theme.newFonts.caption1}; | ||
color: ${({ theme }) => theme.newColors.gray600}; | ||
`; |
60 changes: 60 additions & 0 deletions
60
src/@components/CardCollectionPage/Card/MenuModal/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import Modal from "../../../@common/Modal"; | ||
import useToast from "../../../@common/Toast/hooks/useToast"; | ||
import * as St from "./style"; | ||
|
||
interface MenuModalProps { | ||
closeHandler: () => void; | ||
} | ||
|
||
type ModalItem = { | ||
emoji: string; | ||
title: string; | ||
isNeedLogin?: boolean; | ||
handleClickItem: () => void; | ||
}; | ||
|
||
export default function MenuModal(props: MenuModalProps) { | ||
const { closeHandler } = props; | ||
const showToast = useToast(); | ||
|
||
const ModalItems: ModalItem[] = [ | ||
{ | ||
emoji: "🥲", | ||
title: "이 주제 별로예요", | ||
handleClickItem: () => { | ||
closeHandler(); | ||
showToast({ message: "🥰 소중한 의견 주셔서 감사해요", duration: 2.5 }); | ||
}, | ||
}, | ||
{ | ||
emoji: "👀", | ||
title: "주제 다시 안보기", | ||
isNeedLogin: true, | ||
handleClickItem: () => { | ||
/* todo */ | ||
}, | ||
}, | ||
{ | ||
emoji: "❓", | ||
title: "주제에 대한 다른 사람들의 의견이 궁금해요", | ||
handleClickItem: () => { | ||
closeHandler(); | ||
showToast({ message: "📢 다른 사람들의 의견을 모아서 들려드릴게요", duration: 2.5 }); | ||
}, | ||
}, | ||
]; | ||
|
||
return ( | ||
<Modal theme="WHITE_BOTTOM" closeHandler={closeHandler} isNoCloseBtn> | ||
<St.ModalContainer> | ||
{ModalItems.map(({ emoji, title, isNeedLogin, handleClickItem }, idx) => ( | ||
<St.ModalItemWrapper key={idx} onClick={handleClickItem}> | ||
<St.EmojiWrapper>{emoji}</St.EmojiWrapper> | ||
{title} | ||
{isNeedLogin && <St.MessageWrapper>로그인 시 사용가능 합니다</St.MessageWrapper>} | ||
</St.ModalItemWrapper> | ||
))} | ||
</St.ModalContainer> | ||
</Modal> | ||
); | ||
} |
39 changes: 39 additions & 0 deletions
39
src/@components/CardCollectionPage/Card/MenuModal/style.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import styled from "styled-components"; | ||
|
||
export const ModalContainer = styled.aside` | ||
position: relative; | ||
display: flex; | ||
flex-direction: column; | ||
width: 36rem; | ||
`; | ||
|
||
export const ModalItemWrapper = styled.div` | ||
display: flex; | ||
width: 36rem; | ||
padding: 1.6rem; | ||
${({ theme }) => theme.newFonts.body4}; | ||
color: ${({ theme }) => theme.newColors.gray900}; | ||
&:first-child { | ||
padding-top: 0; | ||
border-bottom: 0.1rem solid ${({ theme }) => theme.newColors.gray200}; | ||
} | ||
&:last-child { | ||
border-top: 1.2rem solid ${({ theme }) => theme.newColors.gray100}; | ||
} | ||
`; | ||
|
||
export const EmojiWrapper = styled.span` | ||
margin-right: 0.8rem; | ||
`; | ||
|
||
export const MessageWrapper = styled.span` | ||
margin-left: 1.2rem; | ||
${({ theme }) => theme.newFonts.caption1}; | ||
color: ${({ theme }) => theme.newColors.gray600}; | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.