diff --git a/client/src/components/CafeActionBar.tsx b/client/src/components/CafeActionBar.tsx deleted file mode 100644 index bd6224d4..00000000 --- a/client/src/components/CafeActionBar.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Suspense, useState } from 'react'; -import { BiSolidInfoCircle } from 'react-icons/bi'; -import { FaShare } from 'react-icons/fa'; -import { PiHeartFill, PiReadCvLogoFill } from 'react-icons/pi'; -import { styled, useTheme } from 'styled-components'; -import { useToast } from '../context/ToastContext'; -import useCafeLikes from '../hooks/useCafeLikes'; -import useClipboard from '../hooks/useClipboard'; -import useUser from '../hooks/useUser'; -import type { Cafe } from '../types'; -import CafeMenuBottomSheet from './CafeMenuBottomSheet'; -import IconButton from './IconButton'; - -type CafeActionBarProps = { - cafe: Cafe; -}; - -const CafeActionBar = (props: CafeActionBarProps) => { - const { cafe } = props; - const theme = useTheme(); - const showToast = useToast(); - const clipboard = useClipboard(); - - const { isLiked, setLiked } = useCafeLikes(cafe); - const { data: user } = useUser(); - const [isMenuOpened, setIsMenuOpened] = useState(false); - - const likeCount = cafe.likeCount + (isLiked ? 1 : 0); - - const handleShare = async () => { - try { - await clipboard.copyToClipboard(`https://yozm.cafe/cafes/${cafe.id}`); - showToast('success', 'URL이 복사되었습니다!'); - } catch (error) { - showToast('error', `URL 복사 실패: ${error}`); - } - }; - - const handleLikeCountIncrease = () => { - if (!user) { - showToast('error', '로그인이 필요합니다!'); - return; - } - setLiked({ isLiked: !isLiked }); - }; - - const handleMenuOpen = () => { - setIsMenuOpened(true); - }; - - const handleMenuClose = () => { - setIsMenuOpened(false); - }; - - return ( - - - - - - - - - - - - - - - - - - {isMenuOpened && ( - - - - )} - - ); -}; - -export default CafeActionBar; - -const Container = styled.aside` - display: flex; - flex-direction: column; - gap: ${({ theme }) => theme.space[5]}; - align-self: flex-end; - - padding: ${({ theme }) => theme.space[3]}; - - color: white; -`; diff --git a/client/src/components/CafeCard.tsx b/client/src/components/CafeCard.tsx index 5e5bac3d..4993c613 100644 --- a/client/src/components/CafeCard.tsx +++ b/client/src/components/CafeCard.tsx @@ -1,11 +1,19 @@ -import type { UIEventHandler } from 'react'; -import { useCallback, useState } from 'react'; -import { styled } from 'styled-components'; +import type { MouseEventHandler, UIEventHandler } from 'react'; +import { Suspense, useCallback, useState } from 'react'; +import { BiSolidInfoCircle } from 'react-icons/bi'; +import { FaShare } from 'react-icons/fa'; +import { PiHeartFill, PiReadCvLogoFill } from 'react-icons/pi'; +import { styled, useTheme } from 'styled-components'; +import { useToast } from '../context/ToastContext'; +import useCafeLikes from '../hooks/useCafeLikes'; +import useClipboard from '../hooks/useClipboard'; +import useUser from '../hooks/useUser'; import type { Cafe } from '../types'; import Resource from '../utils/Resource'; -import CafeActionBar from './CafeActionBar'; import CafeDetailBottomSheet from './CafeDetailBottomSheet'; +import CafeMenuBottomSheet from './CafeMenuBottomSheet'; import CafeSummary from './CafeSummary'; +import IconButton from './IconButton'; type CardProps = { cafe: Cafe; @@ -14,9 +22,18 @@ type CardProps = { const CafeCard = (props: CardProps) => { const { cafe } = props; + const theme = useTheme(); + const showToast = useToast(); + const clipboard = useClipboard(); + const { isLiked, setLiked } = useCafeLikes(cafe); + const { data: user } = useUser(); + const [isShowDetail, setIsShowDetail] = useState(false); + const [isMenuOpened, setIsMenuOpened] = useState(false); const [currentImageIndex, setCurrentImageIndex] = useState(0); + const likeCount = cafe.likeCount + (isLiked ? 1 : 0); + const handleScroll: UIEventHandler = useCallback((event) => { if (!(event.target instanceof HTMLDivElement)) return; @@ -25,6 +42,43 @@ const CafeCard = (props: CardProps) => { setCurrentImageIndex(index); }, []); + const handleShare = async () => { + try { + await clipboard.copyToClipboard(`https://yozm.cafe/cafes/${cafe.id}`); + showToast('success', 'URL이 복사되었습니다!'); + } catch (error) { + showToast('error', `URL 복사 실패: ${error}`); + } + }; + + const handleLikeCountIncrease = () => { + if (!user) { + showToast('error', '로그인이 필요합니다!'); + return; + } + setLiked({ isLiked: !isLiked }); + }; + + const handleDetailOpen = () => { + setIsShowDetail(true); + }; + + const handleDetailClose = () => { + setIsShowDetail(false); + }; + + const handleMenuOpen = () => { + setIsMenuOpened(true); + }; + + const handleMenuClose = () => { + setIsMenuOpened(false); + }; + + const handleStopPropagation: MouseEventHandler = (event) => { + event.stopPropagation(); + }; + return ( @@ -44,19 +98,29 @@ const CafeCard = (props: CardProps) => { ))} - + - { - event.stopPropagation(); - setIsShowDetail(true); - }} - /> + + - + + + + + + + + + + + + + + + + + @@ -66,7 +130,13 @@ const CafeCard = (props: CardProps) => { ))} - {isShowDetail && setIsShowDetail(false)} />} + {isShowDetail && } + + {isMenuOpened && ( + + + + )} ); }; @@ -163,3 +233,14 @@ const BottomItem = styled.div<{ $fullWidth?: boolean; $align?: 'left' | 'right' ${({ $align }) => $align === 'right' && 'right: 0;'} ${({ $fullWidth }) => $fullWidth && 'width: 100%;'} `; + +const ActionBar = styled.aside` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.space[5]}; + align-self: flex-end; + + padding: ${({ theme }) => theme.space[3]}; + + color: white; +`;