diff --git a/package.json b/package.json
index d1f223bb..24d44713 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
"next-themes": "^0.2.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-error-boundary": "^4.0.11",
"react-hook-form": "^7.47.0",
"react-lottie-player": "^1.5.5",
"sharp": "^0.32.6",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8f02f745..5ed303dc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -77,6 +77,9 @@ dependencies:
react-dom:
specifier: ^18.2.0
version: 18.2.0(react@18.2.0)
+ react-error-boundary:
+ specifier: ^4.0.11
+ version: 4.0.11(react@18.2.0)
react-hook-form:
specifier: ^7.47.0
version: 7.47.0(react@18.2.0)
@@ -11428,6 +11431,15 @@ packages:
react-is: 18.1.0
dev: true
+ /react-error-boundary@4.0.11(react@18.2.0):
+ resolution: {integrity: sha512-U13ul67aP5DOSPNSCWQ/eO0AQEYzEFkVljULQIjMV0KlffTAhxuDoBKdO0pb/JZ8mDhMKFZ9NZi0BmLGUiNphw==}
+ peerDependencies:
+ react: '>=16.13.1'
+ dependencies:
+ '@babel/runtime': 7.23.2
+ react: 18.2.0
+ dev: false
+
/react-hook-form@7.47.0(react@18.2.0):
resolution: {integrity: sha512-F/TroLjTICipmHeFlMrLtNLceO2xr1jU3CyiNla5zdwsGUGu2UOxxR4UyJgLlhMwLW/Wzp4cpJ7CPfgJIeKdSg==}
engines: {node: '>=12.22.0'}
diff --git a/public/images/chevron-left-gray.svg b/public/images/chevron-left-gray.svg
new file mode 100644
index 00000000..91d57b90
--- /dev/null
+++ b/public/images/chevron-left-gray.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/app/(root)/(routes)/(auth)/login/components/RouteCallback.tsx b/src/app/(root)/(routes)/(auth)/login/components/RouteCallback.tsx
index de6469f0..b9ba6fbe 100644
--- a/src/app/(root)/(routes)/(auth)/login/components/RouteCallback.tsx
+++ b/src/app/(root)/(routes)/(auth)/login/components/RouteCallback.tsx
@@ -26,11 +26,13 @@ const RouteCallback = ({ tokenResponse }: RouteCallbackProps) => {
useEffect(() => {
if (tokenResponse?.data) {
+ let inHour = new Date()
+ inHour.setHours(inHour.getHours() + 1)
Cookies.set(
Environment.tokenName(),
tokenResponse?.data?.token?.accessToken,
{
- expires: 60 * 60 * 24 * 7,
+ expires: inHour,
},
)
window.location.href = AppPath.home()
diff --git a/src/app/(root)/(routes)/(home)/components/CategorySection.tsx b/src/app/(root)/(routes)/(home)/components/CategorySection.tsx
index 064732c8..94adc34c 100644
--- a/src/app/(root)/(routes)/(home)/components/CategorySection.tsx
+++ b/src/app/(root)/(routes)/(home)/components/CategorySection.tsx
@@ -1,35 +1,25 @@
-'use client'
-
import Image from 'next/image'
-import { useRouter } from 'next/navigation'
-import Button from '@/components/ui/button'
+import Link from 'next/link'
import AppPath from '@/config/appPath'
import { CATEGORY_BUTTON_LIST } from '@/constants/card'
import { TYPOGRAPHY } from '@/styles/sizes'
const CategorySection = () => {
- const router = useRouter()
-
- const handleClick = (name: string) => {
- if (name === 'ALL_CARD') {
- router.push(`${AppPath.cards()}`)
- } else {
- router.push(`${AppPath.cards()}?category=${name}`)
- }
- }
return (
{CATEGORY_BUTTON_LIST.map((v) => (
-
+
))}
)
diff --git a/src/app/(root)/(routes)/(home)/page.tsx b/src/app/(root)/(routes)/(home)/page.tsx
index b3257151..8ee18f11 100644
--- a/src/app/(root)/(routes)/(home)/page.tsx
+++ b/src/app/(root)/(routes)/(home)/page.tsx
@@ -5,7 +5,7 @@ import PopularCardSection from './components/PopularCardSection'
function HomePage() {
return (
-
+
diff --git a/src/app/(root)/(routes)/cards/[cardId]/components/ProfileSection/ProfileSection.tsx b/src/app/(root)/(routes)/cards/[cardId]/components/ProfileSection/ProfileSection.tsx
index d0b51eb9..aeb65417 100644
--- a/src/app/(root)/(routes)/cards/[cardId]/components/ProfileSection/ProfileSection.tsx
+++ b/src/app/(root)/(routes)/cards/[cardId]/components/ProfileSection/ProfileSection.tsx
@@ -12,7 +12,7 @@ const ProfileSection = ({ profileImg, userName }: ProfileSectionProps) => {
- {userName}
+ {userName}
)
}
diff --git a/src/app/(root)/(routes)/cards/[cardId]/components/description-section/DescriptionSection.tsx b/src/app/(root)/(routes)/cards/[cardId]/components/description-section/DescriptionSection.tsx
index 574ef132..e69f9a7c 100644
--- a/src/app/(root)/(routes)/cards/[cardId]/components/description-section/DescriptionSection.tsx
+++ b/src/app/(root)/(routes)/cards/[cardId]/components/description-section/DescriptionSection.tsx
@@ -1,11 +1,14 @@
import formatDistanceToNow from 'date-fns/formatDistanceToNow'
import koLocale from 'date-fns/locale/ko'
+import { useRouter } from 'next/navigation'
import Badge from '@/components/ui/badge'
+import AppPath from '@/config/appPath'
import { CATEGORY_OBJS, TRADE_STATUS_OBJS } from '@/constants/card'
import { useAuth } from '@/contexts/AuthProvider'
import { TYPOGRAPHY } from '@/styles/sizes'
import { CardDetail } from '@/types/card'
import { cn } from '@/utils'
+import { getQueryParams } from '@/utils/getQueryParams'
import { getValueByKey } from '@/utils/getValueByKey'
import Dibs from './Dibs'
import MoreButton from './MoreButton'
@@ -36,6 +39,7 @@ const DescriptionSection = ({
}: DescriptionSectionProps) => {
const { isLoggedIn } = useAuth()
const { currentUser } = useAuth()
+ const router = useRouter()
const isMyItem = currentUser?.userId === authorId
@@ -68,7 +72,14 @@ const DescriptionSection = ({
TYPOGRAPHY.description,
)}
>
- {getValueByKey(CATEGORY_OBJS, category)}
+
+ router.push(`${AppPath.cards()}?${getQueryParams({ category })}`)
+ }
+ >
+ {getValueByKey(CATEGORY_OBJS, category)}
+
{formatDistanceToNow(new Date(createdAt), {
diff --git a/src/app/(root)/(routes)/cards/[cardId]/components/trade-section/SuggestList.tsx b/src/app/(root)/(routes)/cards/[cardId]/components/trade-section/SuggestList.tsx
index 192b496b..9e1b5cfb 100644
--- a/src/app/(root)/(routes)/cards/[cardId]/components/trade-section/SuggestList.tsx
+++ b/src/app/(root)/(routes)/cards/[cardId]/components/trade-section/SuggestList.tsx
@@ -1,4 +1,6 @@
+import { Suspense } from 'react'
import { useRouter } from 'next/navigation'
+import Loading from '@/app/loading'
import SuggestCard from '@/components/domain/card/suggest-card'
import NoData from '@/components/domain/no-data'
import { Tabs, TabsTrigger, TabsList, TabsContent } from '@/components/ui/tabs'
@@ -51,19 +53,21 @@ const SuggestList = ({ pokeAvailable, toCardId }: SuggestListProps) => {
오퍼하기
찔러보기
- {['OFFER', 'POKE'].map((type) => (
-
- {!pokeAvailable && type === 'POKE' ? (
-
- ) : (
- filterData(type)
- )}
-
- ))}
+ }>
+ {['OFFER', 'POKE'].map((type) => (
+
+ {!pokeAvailable && type === 'POKE' ? (
+
+ ) : (
+ filterData(type)
+ )}
+
+ ))}
+
)
}
diff --git a/src/app/(root)/(routes)/cards/[cardId]/components/trade-section/TradeInfo.tsx b/src/app/(root)/(routes)/cards/[cardId]/components/trade-section/TradeInfo.tsx
index e32035cf..748a0f95 100644
--- a/src/app/(root)/(routes)/cards/[cardId]/components/trade-section/TradeInfo.tsx
+++ b/src/app/(root)/(routes)/cards/[cardId]/components/trade-section/TradeInfo.tsx
@@ -14,7 +14,7 @@ const TradeInfo = ({ title, content, variant, icon }: TradeInfoProps) => {
{title}
- {content}
+ {content === '' ? '미입력' : content}
)
diff --git a/src/app/(root)/(routes)/cards/[cardId]/modify/CardModifyTemplate.tsx b/src/app/(root)/(routes)/cards/[cardId]/modify/CardModifyTemplate.tsx
index 4fc8f57a..ea8da4ab 100644
--- a/src/app/(root)/(routes)/cards/[cardId]/modify/CardModifyTemplate.tsx
+++ b/src/app/(root)/(routes)/cards/[cardId]/modify/CardModifyTemplate.tsx
@@ -68,7 +68,7 @@ const CardModifyTemplate = ({ cardInfo, cardId }: CardModifyTemplateProps) => {
variant={'gradation'}
disabled={isSubmitting}
>
- 등록하기
+ 수정하기
diff --git a/src/app/(root)/(routes)/cards/[cardId]/page.tsx b/src/app/(root)/(routes)/cards/[cardId]/page.tsx
index 30cf736c..f49b8ae1 100644
--- a/src/app/(root)/(routes)/cards/[cardId]/page.tsx
+++ b/src/app/(root)/(routes)/cards/[cardId]/page.tsx
@@ -1,6 +1,10 @@
'use client'
+import Image from 'next/image'
+import { useRouter } from 'next/navigation'
import Slider from '@/components/domain/slider'
+import Button from '@/components/ui/button'
+import Assets from '@/config/assets'
import { useAuth } from '@/contexts/AuthProvider'
import useCardInfoQuery from '@/hooks/api/queries/useCardInfoQuery'
import ProfileSection from './components/ProfileSection'
@@ -15,6 +19,7 @@ type CardPageProps = {
const CardPage = ({ params }: CardPageProps) => {
const { isLoggedIn } = useAuth()
+ const router = useRouter()
const { data } = useCardInfoQuery(Number(params.cardId), isLoggedIn)
const cardData = data?.data
@@ -22,6 +27,18 @@ const CardPage = ({ params }: CardPageProps) => {
{cardData && (
<>
+
{
const searchParams = useSearchParams()
// TODO: 현재 API 명세에 status에 어떤 값을 줘야하는지에 대한 정의가 되어 있지 않기 때문에 임시로 상수 값을 전달함 => 추후에 실제 동작 값으로 고치기
- const { data, fetchNextPage, isError, isFetchingNextPage, isLoading } =
- useCardsQuery({
- category:
- (searchParams.get('category') as CategoryObjs['key']) || undefined,
- priceRange:
- (searchParams.get('priceRange') as PriceRangeObjs['key']) || undefined,
- cardTitle: searchParams.get('cardTitle' as string) || '',
- })
+ const {
+ data,
+ fetchNextPage,
+ isError,
+ isFetchingNextPage,
+ isLoading,
+ hasNextPage,
+ } = useCardsQuery({
+ category:
+ (searchParams.get('category') as CategoryObjs['key']) || undefined,
+ priceRange:
+ (searchParams.get('priceRange') as PriceRangeObjs['key']) || undefined,
+ cardTitle: searchParams.get('cardTitle' as string) || '',
+ })
const lastElementRef = useRef(null)
const entry = useIntersectionObserver(lastElementRef, { threshold: 1.0 })
useEffect(() => {
- if (isFetchingNextPage) {
+ if (isFetchingNextPage || !hasNextPage) {
return
}
if (entry?.isIntersecting) {
fetchNextPage()
}
- }, [entry?.isIntersecting, fetchNextPage, isFetchingNextPage])
+ }, [entry?.isIntersecting, fetchNextPage, isFetchingNextPage, hasNextPage])
// TODO: 아이템이 없을시 어떤 UI를 보여줄지 차후에 결정
@@ -48,7 +55,9 @@ const CardListContent = () => {
isEmpty={isEmpty}
isFetchingNextPage={isFetchingNextPage}
>
-
+ 렌더링 중 문제가 발생했습니다.}>
+
+
>
diff --git a/src/app/(root)/(routes)/cards/components/filter-form-dialog/FilterFormDialog.tsx b/src/app/(root)/(routes)/cards/components/filter-form-dialog/FilterFormDialog.tsx
index 5ff1a368..863d0dec 100644
--- a/src/app/(root)/(routes)/cards/components/filter-form-dialog/FilterFormDialog.tsx
+++ b/src/app/(root)/(routes)/cards/components/filter-form-dialog/FilterFormDialog.tsx
@@ -6,7 +6,6 @@ import {
Dialog,
DialogContent,
DialogDescription,
- DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
@@ -21,11 +20,17 @@ import {
import AppPath from '@/config/appPath'
import Assets from '@/config/assets'
import { CATEGORY_OBJS, PRICE_RANGE_OBJS } from '@/constants/card'
-import useCreateQueryString from '@/hooks/useCreateQueryString'
import { CategoryObjs, PriceRangeObjs } from '@/types/card'
+import { getQueryParams } from '@/utils/getQueryParams'
import { getValueByKey } from '@/utils/getValueByKey'
const FilterFormDialog = () => {
+ const router = useRouter()
+ const searchParams = useSearchParams()
+ const priceRange = searchParams.get('priceRange') || undefined
+ const category = searchParams.get('category') || undefined
+ const [priceRangeState, setPriceRangeState] = useState(priceRange)
+ const [categoryState, setCategoryState] = useState(category)
const [isOpen, setIsOpen] = useState(false)
const openModal = () => {
setIsOpen(true)
@@ -33,12 +38,19 @@ const FilterFormDialog = () => {
const closeModal = () => {
setIsOpen(false)
}
- const searchParams = useSearchParams()
- const router = useRouter()
-
- const { createQueryString } = useCreateQueryString()
- const priceRange = searchParams.get('priceRange') || undefined
- const category = searchParams.get('category') || undefined
+ const handleApplyFilter = () => {
+ router.push(
+ `${AppPath.cards()}?${getQueryParams({
+ priceRange: priceRangeState,
+ category: categoryState,
+ })}`,
+ )
+ closeModal()
+ }
+ const handleResetFilter = () => {
+ setPriceRangeState(undefined)
+ setCategoryState(undefined)
+ }
const hasNoFilter = priceRange !== undefined || category !== undefined
@@ -70,15 +82,13 @@ const FilterFormDialog = () => {
가격대