Skip to content

Commit

Permalink
feat: make place detail page as a server component
Browse files Browse the repository at this point in the history
  • Loading branch information
hee-suh committed Sep 22, 2024
1 parent 1991e45 commit 0c88a30
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 43 deletions.
24 changes: 24 additions & 0 deletions src/app/place/[placeId]/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use client'

import { useEffect } from 'react'

import { notify } from '@/components/common/custom-toast'
import { APIError } from '@/models/api'
import useSafeRouter from '@/hooks/use-safe-router'

const PlaceError = ({ error }: { error: Error & { digest?: string } }) => {
const router = useSafeRouter()

useEffect(() => {
if (error instanceof APIError) {
notify.error(error.message)
} else {
notify.error('예상치 못한 오류가 발생했습니다.')
}
router.safeBack()
}, [error, router])

return null
}

export default PlaceError
80 changes: 80 additions & 0 deletions src/app/place/[placeId]/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import Icon from '@/components/common/icon'
import Skeleton from '@/components/common/skeleton'
import PlaceDivider from '@/components/place/place-divider'

const PlaceBoxSkeleton = () => {
return (
<div className="relative flex min-h-dvh flex-col bg-neutral-700">
<Skeleton className="h-[200px] w-full" />

<div className="space-y-3.5 px-5 py-4">
<Skeleton className="h-[36px] w-[90px] rounded-full" />

<div>
<Skeleton className="my-[3px] h-[20px] w-[194px] rounded-full" />

<div className="flex gap-[7px] py-1.5">
<Skeleton className="h-[14px] w-[37px] rounded-full" />
<Skeleton className="h-[14px] w-[244px] rounded-full" />
</div>
</div>

<ul className="flex gap-2">
{[...Array(3)].map((_, index) => (
<Skeleton key={index} className="h-[26px] w-[60px] rounded-full" />
))}
</ul>
</div>

<PlaceDivider className="w-full" />

<div className="space-y-4 px-5 pt-6">
<Skeleton className="h-[16px] w-[40px] rounded-full" />
<Skeleton className="h-[148px] w-full rounded-md" />
</div>

<ul className="flex flex-col divide-y divide-neutral-600 px-5">
{[...Array(4)].map((_, index) => (
<li
key={index}
className="flex items-center justify-between py-[18px]"
>
<div className="space-y-2">
<Skeleton className="h-[18px] w-[100px] rounded-full" />
<Skeleton className="h-[14px] w-[60px] rounded-full" />
</div>

<Skeleton className="h-[60px] w-[60px] rounded-md" />
</li>
))}
</ul>

<PlaceDivider className="w-full" />

<div className="space-y-[10px] p-5">
<Skeleton className="h-[16px] w-[40px] rounded-full" />

<div className="flex w-full items-center justify-between space-x-[14px] rounded-md bg-neutral-600 px-5 py-[14px]">
<img
src="/images/kakao-map-logo.png"
alt="카카오 지도 로고"
className="h-6 w-6 rounded-[2px]"
/>

<div className="flex flex-1 items-center gap-3">
<div className="h-[18px] w-[40px] rounded-[22.5px] bg-neutral-400" />
<div className="flex w-full gap-[2px]">
{[...Array(5)].map((_, index) => (
<Icon key={index} type="starGrey" />
))}
</div>
</div>

<Icon type="hyperlink" size="xl" aria-hidden />
</div>
</div>
</div>
)
}

export default PlaceBoxSkeleton
56 changes: 13 additions & 43 deletions src/app/place/[placeId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,22 @@
'use client'
import dynamic from 'next/dynamic'

import { useEffect, useState } from 'react'

import PlaceBox from './place-box'
import PlaceBoxSkeleton from './place-box-skeleton'

import { notify } from '@/components/common/custom-toast'
import useFetch from '@/hooks/use-fetch'
import { APIError } from '@/models/api/index'
import type { PlaceDetail as PlaceDetailType } from '@/models/api/place'
import { getMapId } from '@/services/map-id'
import { api } from '@/utils/api'

const PlaceDetail = ({ params }: { params?: { placeId?: number } }) => {
const [mapId, setMapId] = useState('')
const { data: place } = useFetch<PlaceDetailType>(
() =>
api.place.mapId.kakao.kakaoPlaceId.get({
mapId,
kakaoPlaceId: params?.placeId ?? -1,
}),
{ enabled: !!mapId && !!params?.placeId },
)

useEffect(() => {
;(async () => {
try {
const validMapId = await getMapId()
const PlaceBox = dynamic(() => import('./place-box'), { ssr: false })

if (!validMapId) {
throw new Error('잘못된 접근입니다.')
}
setMapId(validMapId)
} catch (error) {
if (error instanceof APIError) {
notify.error(error.message)
return
}
notify.error('예상치 못한 오류가 발생했습니다.')
}
})()
}, [mapId])
const PlaceDetail = async ({ params }: { params?: { placeId?: number } }) => {
const mapId = (await getMapId()) || ''
const response =
!!mapId && !!params?.placeId
? await api.place.mapId.kakao.kakaoPlaceId.get({
mapId,
kakaoPlaceId: params?.placeId ?? -1,
})
: null
const place = response?.data

return (
<>
{place ? <PlaceBox place={place} mapId={mapId} /> : <PlaceBoxSkeleton />}
</>
)
return place && <PlaceBox place={place} mapId={mapId} />
}

export default PlaceDetail

0 comments on commit 0c88a30

Please sign in to comment.