diff --git a/package.json b/package.json index fc627c14..bf3dbf5b 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "axios": "^1.2.3", "cookies-next": "^4.1.0", "dayjs": "^1.11.10", + "lodash": "^4.17.21", "next": "^13.4.8", "react": "18.2.0", "react-dom": "18.2.0" diff --git a/src/components/home/CategorySlider/index.tsx b/src/components/home/CategorySlider/index.tsx index 9baa8263..9fbcfb87 100644 --- a/src/components/home/CategorySlider/index.tsx +++ b/src/components/home/CategorySlider/index.tsx @@ -120,11 +120,9 @@ const CategorySlider = (): ReactElement => { })}`}> {name} diff --git a/src/components/home/CategorySlider/styled.ts b/src/components/home/CategorySlider/styled.ts index 21a74054..fe944d02 100644 --- a/src/components/home/CategorySlider/styled.ts +++ b/src/components/home/CategorySlider/styled.ts @@ -1,7 +1,6 @@ import { css } from '@emotion/react' import styled from '@emotion/styled' import { IconButton } from '@offer-ui/react' -import Image from 'next/image' import Link from 'next/link' import type { CateGoryBoxWrapperProps } from './types' import { theme } from '@styles' @@ -35,6 +34,10 @@ export const CateGoryWrapper = styled.div` ` export const CategoryLink = styled(Link)` + display: flex; + flex-direction: column; + align-items: center; + background: transparent; color: ${({ theme }) => theme.colors.grayScale90}; @@ -139,15 +142,13 @@ export const CategoryItem = styled.button` ` export const CategoryImgWrapper = styled.div` - display: flex; - align-items: center; - justify-content: center; - width: 108px; height: 86px; cursor: pointer; + ${({ theme }) => css` + padding: 10px; border-radius: ${theme.radius.round12}; background-color: ${theme.colors.grayScale05}; @@ -155,27 +156,26 @@ export const CategoryImgWrapper = styled.div` ${theme.mediaQuery.tablet} { width: 80px; height: 80px; + padding: 8px; } ${theme.mediaQuery.mobile} { width: 60px; height: 60px; + padding: 4px; } `}; ` -export const CategoryImg = styled(Image)` - border-radius: 12px; +export const CategoryImg = styled.div<{ url: string }>` + ${({ url }) => css` + width: 100%; + height: 100%; - ${({ theme }): string => theme.mediaQuery.tablet} { - width: 52px; - height: 52px; - } - ${({ theme }): string => theme.mediaQuery.mobile} { - width: 40px; - height: 40px; - } + background: url(${url}) center/contain no-repeat; + `} ` + export const CateGoryName = styled.div` margin-top: 12px; diff --git a/src/components/home/ProductItem/styled.ts b/src/components/home/ProductItem/styled.ts index 1d679b42..19bd1303 100644 --- a/src/components/home/ProductItem/styled.ts +++ b/src/components/home/ProductItem/styled.ts @@ -5,27 +5,28 @@ import { Image, ToggleButton } from '@offer-ui/react' const Container = styled.div` flex: 1 0 22%; - max-width: 22%; + max-width: 25%; cursor: pointer; ${({ theme }) => theme.mediaQuery.mobile} { flex: 1 0 44%; - max-width: 44%; + max-width: 48%; } ` const ProductImg = styled(Image)` width: 100%; max-width: none; + height: 276px; ${({ theme }): string => theme.mediaQuery.tablet} { height: 166px; } ${({ theme }): string => theme.mediaQuery.mobile} { - height: 200px; + height: 160px; } ` diff --git a/src/components/home/ProductList/styled.ts b/src/components/home/ProductList/styled.ts index a013b32b..ed68ee8b 100644 --- a/src/components/home/ProductList/styled.ts +++ b/src/components/home/ProductList/styled.ts @@ -14,7 +14,7 @@ const ProductListWrapper = styled.div` margin-top: 20px; } ${({ theme }): string => theme.mediaQuery.mobile} { - gap: 15px 50px; + gap: 8px 20px; margin-top: 16px; } diff --git a/src/hooks/usePreventLeavePage.ts b/src/hooks/usePreventLeavePage.ts index 80a000e1..3a194360 100644 --- a/src/hooks/usePreventLeavePage.ts +++ b/src/hooks/usePreventLeavePage.ts @@ -11,26 +11,30 @@ const handleBeforeUnload = (e: BeforeUnloadEvent) => { export const usePreventLeavePage = (isPrevent = true) => { const router = useRouter() - useEffect(() => { - const handleBeforeChangeRoute = (url: string) => { - if (router.pathname !== url && !confirm(ALERT_MESSAGE.LEAVE_PAGE)) { - router.events.emit('routeChangeError') + const handleBeforePopState = () => { + const userConfirmed = confirm(ALERT_MESSAGE.LEAVE_PAGE) + + window.history.pushState(null, '', router.asPath) - throw `사이트 변경 취소` - } + if (userConfirmed) { + router.beforePopState(() => true) + router.back() } + return false + } + + useEffect(() => { if (!isPrevent) { return } window.addEventListener('beforeunload', handleBeforeUnload) - router.events.on('routeChangeStart', handleBeforeChangeRoute) + router.beforePopState(handleBeforePopState) // eslint-disable-next-line consistent-return return () => { window.removeEventListener('beforeunload', handleBeforeUnload) - router.events.off('routeChangeStart', handleBeforeChangeRoute) } }, [isPrevent]) } diff --git a/src/pages/post/[postId]/index.tsx b/src/pages/post/[postId]/index.tsx index 2cee1c8c..a33d88ad 100644 --- a/src/pages/post/[postId]/index.tsx +++ b/src/pages/post/[postId]/index.tsx @@ -210,7 +210,7 @@ const Layout = styled.div` width: 100%; max-width: 1200px; height: fit-content; - margin: 0 auto 15px; + margin: 0 auto 120px; padding-top: 20px; ${({ theme }): SerializedStyles => css` diff --git a/src/pages/post/index.tsx b/src/pages/post/index.tsx index b7fe37aa..c824aeaf 100644 --- a/src/pages/post/index.tsx +++ b/src/pages/post/index.tsx @@ -79,12 +79,16 @@ const PostPage = ({ type, editPostId }: Props): ReactElement => { const getCategoriesQuery = useGetCategoriesQuery() const updatePostMutation = useUpdatePostMutation() - const initialPostForm: PostFormState = getPostQuery.data?.postForm || {} const [postForm, setPostForm] = useState({}) - const hasChanged = !isEqual(initialPostForm, postForm) - const canPosting = hasChanged && isCompleteForm(postForm) + const [isLoading, setIsLoading] = useState(false) const router = useRouter() + const { user } = useAuth() + + const initialPostForm: PostFormState = getPostQuery.data?.postForm || {} + const hasChanged = !isEqual(initialPostForm, postForm) + const canPosting = hasChanged && isCompleteForm(postForm) && !isLoading + usePreventLeavePage(hasChanged) const InputSize = useResponsive({ @@ -107,6 +111,8 @@ const PostPage = ({ type, editPostId }: Props): ReactElement => { return } + setIsLoading(true) + const { imageInfos, price, ...post } = postForm const imageFiles = imageInfos .filter(({ file }) => Boolean(file)) @@ -145,6 +151,7 @@ const PostPage = ({ type, editPostId }: Props): ReactElement => { } router.replace(`/post/${postId}`) + setIsLoading(false) } useEffect(() => {