@@ -4,16 +4,9 @@ import Link from 'next/link';
44import { useParams } from 'next/navigation' ;
55import { useAnalysisPolling } from '@/src/features/analysis/hooks/useAnalysisPolling' ;
66import { InsightReport } from '@/src/features/analysis/components/InsightReport' ;
7+ import { AnalysisProgress } from '@/src/features/analysis/components/AnalysisProgress' ;
78import { Card } from '@/src/shared/components/ui' ;
8- import type { AnalysisStatus } from '@/src/features/analysis/types' ;
9-
10- const PROGRESS_LABEL : Record < AnalysisStatus , string > = {
11- pending : '분석 대기 중' ,
12- crawling : '리뷰 수집 중' ,
13- analyzing : 'AI 분석 중' ,
14- completed : '완료' ,
15- failed : '실패' ,
16- } ;
9+ import type { Analysis , AnalysisResult } from '@/src/features/analysis/types' ;
1710
1811function BackLink ( ) {
1912 return (
@@ -23,19 +16,33 @@ function BackLink() {
2316 ) ;
2417}
2518
26- function ProgressView ( { status } : { status : AnalysisStatus } ) {
19+ function formatCompletedAt ( iso : string ) : string {
20+ const date = new Date ( iso ) ;
21+ if ( Number . isNaN ( date . getTime ( ) ) ) return iso ;
22+ return date . toLocaleString ( 'ko-KR' ) ;
23+ }
24+
25+ function ResultHeader ( {
26+ result,
27+ completedAt,
28+ } : {
29+ result : AnalysisResult ;
30+ completedAt : string | null ;
31+ } ) {
32+ const totalReviews = result . products . reduce (
33+ ( sum , product ) => sum + product . total_reviews ,
34+ 0 ,
35+ ) ;
2736 return (
28- < Card className = "p-8 text-center" >
29- < div
30- className = "mx-auto mb-4 h-8 w-8 animate-spin rounded-full border-4 border-gray-200 border-t-brand-600"
31- role = "status"
32- aria-label = "로딩 중"
33- />
34- < p className = "font-medium text-gray-900" > { PROGRESS_LABEL [ status ] } </ p >
35- < p className = "mt-1 text-sm text-gray-500" > 분석 중입니다. 잠시만 기다려 주세요.</ p >
36- < div className = "mx-auto mt-4 h-1.5 w-48 overflow-hidden rounded-full bg-gray-100" >
37- < div className = "h-full w-1/2 animate-pulse rounded-full bg-brand-500" />
38- </ div >
37+ < Card className = "p-5" >
38+ < p className = "font-semibold text-gray-900" >
39+ { result . products . length } 개 상품 · 총 { totalReviews } 개 리뷰 분석 완료
40+ </ p >
41+ { completedAt && (
42+ < p className = "mt-1 text-sm text-gray-500" >
43+ { formatCompletedAt ( completedAt ) } 생성
44+ </ p >
45+ ) }
3946 </ Card >
4047 ) ;
4148}
@@ -49,6 +56,16 @@ function ErrorView({ message }: { message: string }) {
4956 ) ;
5057}
5158
59+ function CompletedView ( { analysis } : { analysis : Analysis } ) {
60+ if ( ! analysis . result ) return null ;
61+ return (
62+ < div className = "flex flex-col gap-6" >
63+ < ResultHeader result = { analysis . result } completedAt = { analysis . completed_at } />
64+ < InsightReport result = { analysis . result } />
65+ </ div >
66+ ) ;
67+ }
68+
5269export default function AnalysisResultPage ( ) {
5370 const params = useParams < { id : string } > ( ) ;
5471 const id = params ?. id ?? '' ;
@@ -58,13 +75,13 @@ export default function AnalysisResultPage() {
5875 if ( isError ) {
5976 content = < ErrorView message = "분석 정보를 불러오지 못했습니다." /> ;
6077 } else if ( isLoading || ! analysis ) {
61- content = < ProgressView status = "pending" /> ;
78+ content = < AnalysisProgress status = "pending" /> ;
6279 } else if ( analysis . status === 'failed' ) {
6380 content = < ErrorView message = { analysis . error ?? '알 수 없는 오류가 발생했습니다.' } /> ;
6481 } else if ( analysis . status === 'completed' && analysis . result ) {
65- content = < InsightReport result = { analysis . result } /> ;
82+ content = < CompletedView analysis = { analysis } /> ;
6683 } else {
67- content = < ProgressView status = { analysis . status } /> ;
84+ content = < AnalysisProgress status = { analysis . status } /> ;
6885 }
6986
7087 return (
0 commit comments