diff --git a/frontend/public/celuveat-logo.png b/frontend/public/celuveat-logo.png new file mode 100644 index 000000000..f13cd3fd2 Binary files /dev/null and b/frontend/public/celuveat-logo.png differ diff --git a/frontend/public/index.html b/frontend/public/index.html index 615b5e221..dd88b36a5 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -2,6 +2,7 @@ + celuveat diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index c51d4e5a3..5b928f19f 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -22,7 +22,9 @@ export const apiClient = axios.create({ export const getRestaurants = async (queryParams: GetRestaurantsQueryParams) => { const queryString = getQueryString(queryParams); + const response = await apiClient.get(`/restaurants?${queryString}`); + return response.data; }; diff --git a/frontend/src/assets/icons/dot.svg b/frontend/src/assets/icons/dot.svg index 6aecd1bdc..ac0aa6048 100644 --- a/frontend/src/assets/icons/dot.svg +++ b/frontend/src/assets/icons/dot.svg @@ -1,3 +1,3 @@ - - + + diff --git a/frontend/src/assets/icons/logo.svg b/frontend/src/assets/icons/logo.svg new file mode 100644 index 000000000..e70fdd957 --- /dev/null +++ b/frontend/src/assets/icons/logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/frontend/src/assets/logo.png b/frontend/src/assets/logo.png deleted file mode 100644 index a13cf2584..000000000 Binary files a/frontend/src/assets/logo.png and /dev/null differ diff --git a/frontend/src/components/@common/Header/Header.tsx b/frontend/src/components/@common/Header/Header.tsx index 6e9431c64..20dd7182c 100644 --- a/frontend/src/components/@common/Header/Header.tsx +++ b/frontend/src/components/@common/Header/Header.tsx @@ -1,6 +1,6 @@ import React, { useMemo } from 'react'; import { styled } from 'styled-components'; -import Logo from '~/assets/logo.png'; +import Logo from '~/assets/icons/logo.svg'; import { Modal, ModalContent } from '~/components/@common/Modal'; import InfoDropDown from '~/components/InfoDropDown'; import LoginModalContent from '~/components/LoginModalContent'; @@ -31,7 +31,7 @@ function Header() { return ( <> - + @@ -55,14 +55,10 @@ const StyledHeader = styled.header<{ isMobile: boolean }>` z-index: 20; width: 100%; - height: 80px; + height: ${({ isMobile }) => (isMobile ? '60px' : '80px')}; padding: 1.2rem 2.4rem; background-color: var(--white); border-bottom: 1px solid var(--gray-1); `; - -const StyledLogo = styled.img` - width: 136px; -`; diff --git a/frontend/src/components/@common/ImageCarousel/ImageCarousel.tsx b/frontend/src/components/@common/ImageCarousel/ImageCarousel.tsx index 312fbc60f..f83554cd8 100644 --- a/frontend/src/components/@common/ImageCarousel/ImageCarousel.tsx +++ b/frontend/src/components/@common/ImageCarousel/ImageCarousel.tsx @@ -19,19 +19,25 @@ function ImageCarousel({ images, type }: ImageCarouselProps) { const { movingDirection } = useTouchMoveDirection(ref); const [currentIndex, setCurrentIndex] = useState(0); - const goToPrevious = () => setCurrentIndex(prevIndex => prevIndex - 1); - const goToNext = () => setCurrentIndex(prevIndex => prevIndex + 1); + const goToPrevious: React.MouseEventHandler = e => { + e.stopPropagation(); + setCurrentIndex(prevIndex => prevIndex - 1); + }; + const goToNext: React.MouseEventHandler = e => { + e.stopPropagation(); + setCurrentIndex(prevIndex => prevIndex + 1); + }; useEffect(() => { - if (movingDirection.X === 'left' && currentIndex !== images.length - 1) goToNext(); - if (movingDirection.X === 'right' && currentIndex !== 0) goToPrevious(); + if (movingDirection.X === 'left' && currentIndex !== images.length - 1) setCurrentIndex(prevIndex => prevIndex + 1); + if (movingDirection.X === 'right' && currentIndex !== 0) setCurrentIndex(prevIndex => prevIndex - 1); }, [movingDirection.X]); return ( {images.map(({ id, name, author }) => ( - + ))} {!isMobile && currentIndex !== 0 && ( @@ -122,9 +128,6 @@ const StyledCarouselSlide = styled.div<{ currentIndex: number }>` transition: transform 0.3s ease-in-out; transform: ${({ currentIndex }) => `translateX(-${currentIndex * 100}%)`}; - flex-wrap: nowrap; - - aspect-ratio: 1.05 / 1; `; const StyledDots = styled.div<{ currentIndex: number }>` diff --git a/frontend/src/components/@common/LoadingDots/LoadingDots.tsx b/frontend/src/components/@common/LoadingDots/LoadingDots.tsx index e87ce43d2..b2efa0ce8 100644 --- a/frontend/src/components/@common/LoadingDots/LoadingDots.tsx +++ b/frontend/src/components/@common/LoadingDots/LoadingDots.tsx @@ -21,7 +21,7 @@ export default LoadingDots; const StyledLoadingDots = styled.div` display: flex; - gap: 0 1.4rem; + gap: 0 1rem; & > div:nth-child(2) { animation-delay: 0.14s; @@ -34,10 +34,10 @@ const StyledLoadingDots = styled.div` const pulseAnimation = keyframes` 0% { - transform: scale(0); + transform: scale(1); } 90%, 100% { - transform: scale(10); + transform: scale(0); } `; @@ -46,8 +46,8 @@ const StyledLoadingDot = styled.div` justify-content: center; align-items: center; - width: 1.2px; - height: 1.2px; + width: 12px; + height: 12px; animation: ${pulseAnimation} 0.4s ease-in-out infinite alternate; animation-timing-function: cubic-bezier(0, 0, 1, 1); diff --git a/frontend/src/components/@common/LoginButton/LoginButton.tsx b/frontend/src/components/@common/LoginButton/LoginButton.tsx index 4fd1b0e19..1617552c2 100644 --- a/frontend/src/components/@common/LoginButton/LoginButton.tsx +++ b/frontend/src/components/@common/LoginButton/LoginButton.tsx @@ -20,7 +20,7 @@ const LoginIcon: Record = { function LoginButton({ type }: LoginButtonProps) { return ( - +
{LoginIcon[type]}
{OAUTH_BUTTON_MESSAGE[type]} diff --git a/frontend/src/components/@common/Map/OverlayMarker.tsx b/frontend/src/components/@common/Map/OverlayMarker.tsx index 2d658ccd2..d33fdffce 100644 --- a/frontend/src/components/@common/Map/OverlayMarker.tsx +++ b/frontend/src/components/@common/Map/OverlayMarker.tsx @@ -34,16 +34,16 @@ function OverlayMarker({ celeb, restaurant, map, quadrant, isRestaurantHovered } return ( map && ( -
+ - + {isClicked && ( )} -
+
) ); @@ -51,6 +51,10 @@ function OverlayMarker({ celeb, restaurant, map, quadrant, isRestaurantHovered } export default OverlayMarker; +const StyledMarkerContainer = styled.div` + position: relative; +`; + const scaleUp = keyframes` 0% { transform: scale(1); @@ -73,10 +77,10 @@ const StyledMarker = styled.div<{ isClicked: boolean; isRestaurantHovered: boole border-radius: 50%; transition: transform 0.2s ease-in-out; - transform: ${({ isClicked }) => (isClicked ? 'scale(1.5)' : 'scale(1)')}; + transform: ${({ isClicked }) => (isClicked ? 'scale(1.4)' : 'scale(1)')}; &:hover { - transform: scale(1.5); + transform: scale(1.4); } ${({ isRestaurantHovered }) => @@ -97,10 +101,10 @@ const fadeInAnimation = keyframes` const StyledModal = styled.div<{ quadrant: Quadrant }>` position: absolute; - top: ${({ quadrant }) => (quadrant === 1 || quadrant === 2 ? '40px' : '-280px')}; - right: ${({ quadrant }) => (quadrant === 1 || quadrant === 4 ? '45px' : '-210px')}; + top: ${({ quadrant }) => (quadrant === 1 || quadrant === 2 ? '48px' : '-288px')}; + right: ${({ quadrant }) => (quadrant === 1 || quadrant === 4 ? '0px' : '-210px')}; - width: 200px; + width: 248px; border-radius: 12px; background-color: #fff; diff --git a/frontend/src/components/@common/ProfileImage/ProfileImage.tsx b/frontend/src/components/@common/ProfileImage/ProfileImage.tsx index e2efe8345..9f6c51186 100644 --- a/frontend/src/components/@common/ProfileImage/ProfileImage.tsx +++ b/frontend/src/components/@common/ProfileImage/ProfileImage.tsx @@ -3,17 +3,16 @@ import { styled } from 'styled-components'; interface ProfileImageProps extends React.HTMLAttributes { name: string; imageUrl: string; - border?: boolean; size?: string; } -function ProfileImage({ name = '셀럽', imageUrl, size, border = false, ...props }: ProfileImageProps) { - return ; +function ProfileImage({ name = '셀럽', imageUrl, size, ...props }: ProfileImageProps) { + return ; } export default ProfileImage; -const StyledProfile = styled.img<{ size: string; border: boolean }>` +const StyledProfile = styled.img<{ size: string }>` width: ${({ size }) => size || 'auto'}; height: ${({ size }) => size || 'auto'}; diff --git a/frontend/src/components/@common/WaterMarkImage/WaterMarkImage.tsx b/frontend/src/components/@common/WaterMarkImage/WaterMarkImage.tsx index b84551b84..aa42d7a99 100644 --- a/frontend/src/components/@common/WaterMarkImage/WaterMarkImage.tsx +++ b/frontend/src/components/@common/WaterMarkImage/WaterMarkImage.tsx @@ -4,12 +4,13 @@ import { BORDER_RADIUS, FONT_SIZE, paintSkeleton } from '~/styles/common'; interface WaterMarkImageProps { waterMark: string; imageUrl: string; + type: 'list' | 'map'; } -function WaterMarkImage({ waterMark, imageUrl }: WaterMarkImageProps) { +function WaterMarkImage({ waterMark, imageUrl, type }: WaterMarkImageProps) { return ( - - + + ); @@ -17,23 +18,23 @@ function WaterMarkImage({ waterMark, imageUrl }: WaterMarkImageProps) { export default WaterMarkImage; -const StyledWaterMarkImage = styled.div` +const StyledWaterMarkImage = styled.div<{ type: 'list' | 'map' }>` position: relative; width: 100%; - aspect-ratio: 1.05 / 1; - - height: auto; + min-width: 100%; + ${({ type }) => (type === 'list' ? `padding-top: 95%;` : `padding-top: 65%;`)} `; const StyledImage = styled.img` ${paintSkeleton} - display: block; + position: absolute; + inset: 0; - aspect-ratio: 1.05 / 1; object-fit: cover; width: 100%; + height: 100%; `; const StyledWaterMark = styled.div` diff --git a/frontend/src/components/CategoryNavbar/CategoryNavbar.tsx b/frontend/src/components/CategoryNavbar/CategoryNavbar.tsx index 06a767329..dc8633c8e 100644 --- a/frontend/src/components/CategoryNavbar/CategoryNavbar.tsx +++ b/frontend/src/components/CategoryNavbar/CategoryNavbar.tsx @@ -41,6 +41,9 @@ const StyledCategoryNavbarWrapper = styled.ul` display: flex; align-items: center; + width: 100%; + height: 100%; + background: transparent; overflow-x: scroll; diff --git a/frontend/src/components/CelebDropDown/CelebDropDown.tsx b/frontend/src/components/CelebDropDown/CelebDropDown.tsx index 5abb8439a..2e4445ffa 100644 --- a/frontend/src/components/CelebDropDown/CelebDropDown.tsx +++ b/frontend/src/components/CelebDropDown/CelebDropDown.tsx @@ -9,6 +9,7 @@ import NavItem from '~/components/@common/NavButton/NavButton'; import useBooleanState from '~/hooks/useBooleanState'; import type { Celeb } from '~/@types/celeb.types'; +import { BORDER_RADIUS, FONT_SIZE } from '~/styles/common'; interface DropDownProps { celebs: Celeb[]; @@ -35,13 +36,16 @@ function CelebDropDown({ celebs, externalOnClick, isOpen = false }: DropDownProp {isShow && ( - {celebs.map(({ id, name, profileImageUrl }) => ( + {celebs.map(({ id, name, youtubeChannelName, profileImageUrl }) => (
- - {name} + +
+ {name} + {youtubeChannelName} +
- {isEqual(selected, name) && } + {isEqual(selected, name) && }
))}
@@ -74,20 +78,20 @@ const StyledDropDownWrapper = styled.ul` top: calc(100% + 16px); left: 18px; - width: 216px; - height: 176px; + width: 380px; + height: 440px; - padding: 1.8rem 0; + padding: 1.2rem 0; - border-radius: 10px; - background: white; + border-radius: ${BORDER_RADIUS.md}; + background: var(--white); box-shadow: var(--shadow); `; const StyledSelectContainer = styled.div` width: 100%; - height: 150px; + height: 100%; background: transparent; @@ -99,9 +103,11 @@ const StyledDropDownOption = styled.li` justify-content: space-between; align-items: center; - height: 44px; + height: 60px; - margin: 0 1.8rem; + padding: 0 1.8rem; + + font-size: ${FONT_SIZE.md}; cursor: pointer; @@ -116,6 +122,21 @@ const StyledDropDownOption = styled.li` & > div { display: flex; align-items: center; - gap: 0.4rem; + gap: 0 1.2rem; + } + + &:hover { + background-color: var(--gray-1); } `; + +const StyledCelebName = styled.div` + font-family: SUIT-Medium; +`; + +const StyledChannelName = styled.div` + padding-top: 0.4rem; + + color: var(--gray-3); + font-size: ${FONT_SIZE.sm}; +`; diff --git a/frontend/src/components/InfoDropDown/InfoDropDown.tsx b/frontend/src/components/InfoDropDown/InfoDropDown.tsx index 7fb6db9db..2f2e77876 100644 --- a/frontend/src/components/InfoDropDown/InfoDropDown.tsx +++ b/frontend/src/components/InfoDropDown/InfoDropDown.tsx @@ -57,9 +57,6 @@ const StyledInfoDropDown = styled.div` display: relative; z-index: 100000000; - - width: 77px; - height: 42px; `; const StyledDropDownWrapper = styled.ul` diff --git a/frontend/src/components/RestaurantCard/RestaurantCard.tsx b/frontend/src/components/RestaurantCard/RestaurantCard.tsx index 8e9466dd9..58ddfa723 100644 --- a/frontend/src/components/RestaurantCard/RestaurantCard.tsx +++ b/frontend/src/components/RestaurantCard/RestaurantCard.tsx @@ -12,30 +12,18 @@ interface RestaurantCardProps { celebs?: Celeb[]; size?: string; type?: 'list' | 'map'; - onClick?: React.MouseEventHandler; setHoveredId?: React.Dispatch>; } -function RestaurantCard({ - restaurant, - celebs, - size, - type = 'list', - onClick = () => {}, - setHoveredId = () => {}, -}: RestaurantCardProps) { - const { images, name, roadAddress, category, phoneNumber } = restaurant; +function RestaurantCard({ restaurant, celebs, size, type = 'list', setHoveredId = () => {} }: RestaurantCardProps) { + const { images, name, roadAddress, category, phoneNumber, naverMapUrl } = restaurant; - const onMouseEnter = () => { - setHoveredId(restaurant.id); - }; - - const onMouseLeave = () => { - setHoveredId(null); - }; + const onMouseEnter = () => setHoveredId(restaurant.id); + const onMouseLeave = () => setHoveredId(null); + const openDetail = () => window.open(naverMapUrl, '_blank'); return ( - + diff --git a/frontend/src/components/RestaurantCardList/RestaurantCardList.tsx b/frontend/src/components/RestaurantCardList/RestaurantCardList.tsx index 9cdf26be4..da81f6329 100644 --- a/frontend/src/components/RestaurantCardList/RestaurantCardList.tsx +++ b/frontend/src/components/RestaurantCardList/RestaurantCardList.tsx @@ -49,17 +49,30 @@ function RestaurantCardList({ restaurantDataList, loading, setHoveredId, setCurr return ( - {!isMobile && 음식점 수 {restaurantDataList.totalElementsCount} 개} - - {restaurantDataList.content?.map(({ celebs, ...restaurant }: RestaurantData) => ( - - ))} - - + {restaurantDataList.content.length !== 0 ? ( + <> + {!isMobile && ( + 음식점 수 {restaurantDataList.totalElementsCount} 개 + )} + + {restaurantDataList.content?.map(({ celebs, ...restaurant }: RestaurantData) => ( + + ))} + + + + ) : ( + <> +

일치하는 음식점이 없어요.

+ + 더 많은 음식점을 둘러보려면 필터링 옵션 살펴보거나 지도를 움직여 주세요! + + + )}
); } @@ -78,6 +91,10 @@ const StyledRestaurantCardListContainer = styled.div` margin: 3.2rem 2.4rem; `; +const StyledDescription = styled.div` + font-size: ${FONT_SIZE.md}; +`; + const StyledCardListHeader = styled.p` font-size: ${FONT_SIZE.md}; font-weight: 700; diff --git a/frontend/src/constants/restaurantCategory.tsx b/frontend/src/constants/restaurantCategory.tsx index 9868f508c..93d391ae6 100644 --- a/frontend/src/constants/restaurantCategory.tsx +++ b/frontend/src/constants/restaurantCategory.tsx @@ -41,6 +41,10 @@ const RESTAURANT_CATEGORY: Category[] = [ label: '양식', icon: , }, + { + label: '와인', + icon: , + }, { label: '육류,고기요리', icon: , @@ -57,10 +61,6 @@ const RESTAURANT_CATEGORY: Category[] = [ label: '요리주점', icon: , }, - { - label: '와인', - icon: , - }, ]; export default RESTAURANT_CATEGORY; diff --git a/frontend/src/pages/MainPage.tsx b/frontend/src/pages/MainPage.tsx index 8e0a3a1d4..c629befb4 100644 --- a/frontend/src/pages/MainPage.tsx +++ b/frontend/src/pages/MainPage.tsx @@ -79,7 +79,7 @@ function MainPage() { {isMobile ? ( - + ` align-items: center; position: ${({ isMobile }) => (isMobile ? 'fixed' : 'sticky')}; - top: 80px; + top: ${({ isMobile }) => (isMobile ? '60px' : '80px')}; z-index: 11; width: 100%; @@ -152,12 +152,12 @@ const StyledLine = styled.div` background-color: var(--gray-3); `; -const StyledLayer = styled.div` +const StyledLayer = styled.div<{ isMobile: boolean }>` display: flex; flex-direction: column; position: fixed; - top: 160px; + top: ${({ isMobile }) => (isMobile ? '140px' : '160px')}; z-index: 0; width: 100%; @@ -182,7 +182,7 @@ const StyledMapBottomCover = styled.div<{ isBottomSheetOpen: boolean }>` css` z-index: 20; - height: 36vh; + height: calc(36vh - 74px); `} `; @@ -201,31 +201,23 @@ const StyledLayout = styled.div<{ isMapExpanded: boolean }>` width: 100%; height: 100%; - grid-template-columns: 63% 37%; + grid-template-columns: 63vw 37vw; ${({ isMapExpanded }) => isMapExpanded && css` - grid-template-columns: 100%; + grid-template-columns: 100vw; `} @media screen and (width <= 1240px) { - grid-template-columns: 55% 45%; + grid-template-columns: 55vw 45vw; ${({ isMapExpanded }) => isMapExpanded && css` - grid-template-columns: 100%; + grid-template-columns: 100vw; `} } - - @media screen and (width <= 950px) { - & > div:last-child { - display: none; - } - - grid-template-columns: 100% 0; - } `; const StyledLeftSide = styled.div<{ isMapExpanded: boolean }>`