1+ 'use client' ;
2+
3+ import { useEffect , useState } from 'react' ;
4+ import { useParams } from 'next/navigation' ;
5+ import Header from '@/components/Header' ;
6+ import Footer from '@/components/Footer' ;
7+ import NoImage from '@/components/NoImage' ;
8+
9+ export default function DrugDetailPage ( ) {
10+ const params = useParams ( ) ;
11+ const drugId = params . id ;
12+
13+ const [ drug , setDrug ] = useState ( null ) ;
14+ const [ loading , setLoading ] = useState ( true ) ;
15+ const [ error , setError ] = useState ( null ) ;
16+
17+ useEffect ( ( ) => {
18+ // API 개발이 완료되면 아래 주석을 해제하고 mock 데이터 대신 실제 API를 사용하면 됩니다.
19+
20+ const fetchDrugDetail = async ( ) => {
21+ try {
22+ setLoading ( true ) ;
23+ const response = await fetch ( `/api/api/drugs/search/detail/${ drugId } ` ) ;
24+ if ( ! response . ok ) {
25+ throw new Error ( '약품 정보를 불러오는 데 실패했습니다.' ) ;
26+ }
27+
28+ const data = await response . json ( ) ;
29+ setDrug ( data . data ) ;
30+ } catch ( err ) {
31+ console . error ( '약품 상세 정보 조회 오류:' , err ) ;
32+ setError ( err . message ) ;
33+ } finally {
34+ setLoading ( false ) ;
35+ }
36+ } ;
37+
38+ fetchDrugDetail ( ) ;
39+
40+
41+ // Mock 데이터 사용
42+ // setTimeout(() => {
43+ // setDrug({
44+ // ...mockDrugData,
45+ // item_seq: drugId, // URL의 ID 반영
46+ // });
47+ // setLoading(false);
48+ // }, 500); // 로딩 효과를 위한 지연 시간
49+ } , [ drugId ] ) ;
50+
51+ if ( loading ) {
52+ return (
53+ < div className = "min-h-screen flex flex-col" >
54+ < Header />
55+ < main className = "flex-1 flex items-center justify-center" >
56+ < div className = "text-center py-16" > 로딩 중...</ div >
57+ </ main >
58+ < Footer />
59+ </ div >
60+ ) ;
61+ }
62+
63+ if ( error || ! drug ) {
64+ return (
65+ < div className = "min-h-screen flex flex-col" >
66+ < Header />
67+ < main className = "flex-1 flex items-center justify-center" >
68+ < div className = "text-center py-16 text-red-500" >
69+ { error || '약품 정보를 찾을 수 없습니다.' }
70+ </ div >
71+ </ main >
72+ < Footer />
73+ </ div >
74+ ) ;
75+ }
76+
77+ // 약품 전문/일반 구분
78+ const getEtcOtcName = ( isGeneral ) => {
79+ return isGeneral ? "일반의약품" : "전문의약품" ;
80+ } ;
81+
82+ // 주의사항 키 값 추출
83+ const precautionKeys = drug . precaution ? Object . keys ( drug . precaution ) : [ ] ;
84+
85+ return (
86+ < div className = "min-h-screen flex flex-col bg-gray-50" >
87+ < Header />
88+ < main className = "flex-1 w-full mt-[64px]" >
89+ < div className = "max-w-5xl mx-auto w-full px-4 py-8" >
90+ < div className = "bg-white rounded-lg shadow-md p-6" >
91+ { /* 상단 영역: 약품 기본 정보 */ }
92+ < div className = "flex flex-col md:flex-row gap-8 mb-8" >
93+ { /* 약품 이미지 */ }
94+ < div className = "w-full md:w-80 h-80 flex-shrink-0" >
95+ { drug . imageUrl ? (
96+ < img
97+ src = { drug . imageUrl }
98+ alt = { drug . drugName }
99+ className = "w-full h-full rounded-lg object-contain border border-gray-200"
100+ />
101+ ) : (
102+ < NoImage className = "w-full h-full" />
103+ ) }
104+ </ div >
105+
106+ { /* 약품 기본 정보 */ }
107+ < div className = "flex-1 space-y-4" >
108+ < h1 className = "text-2xl font-bold text-gray-800" > { drug . drugName } </ h1 >
109+ < div className = "grid grid-cols-1 md:grid-cols-2 gap-4" >
110+ < div className = "space-y-2" >
111+ < div className = "flex items-center" >
112+ < span className = "w-24 text-sm font-medium text-gray-500" > 제약회사</ span >
113+ < span className = "text-gray-700" > { drug . company } </ span >
114+ </ div >
115+ < div className = "flex items-center" >
116+ < span className = "w-24 text-sm font-medium text-gray-500" > 품목기준코드</ span >
117+ < span className = "text-gray-700" > { drug . drugId } </ span >
118+ </ div >
119+ < div className = "flex items-center" >
120+ < span className = "w-24 text-sm font-medium text-gray-500" > 보관방법</ span >
121+ < span className = "text-gray-700" > { drug . storeMethod } </ span >
122+ </ div >
123+ < div className = "flex items-center" >
124+ < span className = "w-24 text-sm font-medium text-gray-500" > 의약품 구분</ span >
125+ < span className = "text-gray-700" > { getEtcOtcName ( drug . isGeneral ) } / { drug . isHerbal ? '한약' : '양약' } </ span >
126+ </ div >
127+ </ div >
128+ < div className = "space-y-2" >
129+
130+ < div className = "flex items-center" >
131+ < span className = "w-24 text-sm font-medium text-gray-500" > 허가일</ span >
132+ < span className = "text-gray-700" > { drug . permitDate } </ span >
133+ </ div >
134+ < div className = "flex items-center" >
135+ < span className = "w-24 text-sm font-medium text-gray-500" > 유효기간</ span >
136+ < span className = "text-gray-700" >
137+ { drug . validTerm ? drug . validTerm : '정보 없음' }
138+ </ span >
139+ </ div >
140+ < div className = "flex items-center" >
141+ < span className = "w-24 text-sm font-medium text-gray-500" > 취소일자</ span >
142+ < span className = "text-gray-700" >
143+ { drug . cancelDate ? drug . cancelDate : '해당 없음' }
144+ </ span >
145+ </ div >
146+ < div className = "flex items-center" >
147+ < span className = "w-24 text-sm font-medium text-gray-500" > 취소사유</ span >
148+ < span className = "text-gray-700" >
149+ { drug . cancelName ? drug . cancelName : '해당 없음' }
150+ </ span >
151+ </ div >
152+ </ div >
153+ </ div >
154+ </ div >
155+ </ div >
156+
157+ { /* 성분 정보 */ }
158+ { drug . materialInfo && drug . materialInfo . length > 0 && (
159+ < div className = "mb-6" >
160+ < h2 className = "text-lg font-bold px-4 py-2 rounded-md mb-3 border-b border-gray-300 pb-2" >
161+ 성분 정보
162+ </ h2 >
163+ < div className = "overflow-x-auto" >
164+ < table className = "min-w-full divide-y divide-gray-200" >
165+ < thead >
166+ < tr >
167+ < th className = "px-4 py-2 bg-gray-50 text-left text-sm font-medium text-gray-500" > 성분명</ th >
168+ < th className = "px-4 py-2 bg-gray-50 text-left text-sm font-medium text-gray-500" > 분량</ th >
169+ < th className = "px-4 py-2 bg-gray-50 text-left text-sm font-medium text-gray-500" > 단위</ th >
170+ < th className = "px-4 py-2 bg-gray-50 text-left text-sm font-medium text-gray-500" > 총량</ th >
171+ < th className = "px-4 py-2 bg-gray-50 text-left text-sm font-medium text-gray-500" > 규격</ th >
172+ </ tr >
173+ </ thead >
174+ < tbody className = "bg-white divide-y divide-gray-200" >
175+ { drug . materialInfo . map ( ( material , index ) => (
176+ < tr key = { index } >
177+ < td className = "px-4 py-2 whitespace-nowrap text-sm text-gray-700" > { material . 성분명 } </ td >
178+ < td className = "px-4 py-2 whitespace-nowrap text-sm text-gray-700" > { material . 분량 } </ td >
179+ < td className = "px-4 py-2 whitespace-nowrap text-sm text-gray-700" > { material . 단위 } </ td >
180+ < td className = "px-4 py-2 whitespace-nowrap text-sm text-gray-700" > { material . 총량 } </ td >
181+ < td className = "px-4 py-2 whitespace-nowrap text-sm text-gray-700" > { material . 규격 } </ td >
182+ </ tr >
183+ ) ) }
184+ </ tbody >
185+ </ table >
186+ </ div >
187+ </ div >
188+ ) }
189+
190+ { /* 상세 정보 섹션 */ }
191+ < div className = "border-t pt-6 space-y-6" >
192+ { /* 효능효과 */ }
193+ < div className = "space-y-3" >
194+ < h2 className = "text-lg font-bold px-4 py-2 text-[#2BA89C] rounded-md border-b border-gray-300 pb-2" >
195+ 효능효과
196+ </ h2 >
197+ < div className = "px-4 py-2 text-gray-700" >
198+ { drug . efficacy ?. length > 0 ? (
199+ < ul className = "list-none pl-0 space-y-1" >
200+ { drug . efficacy . map ( ( item , i ) => (
201+ < li key = { i } > { item } </ li >
202+ ) ) }
203+ </ ul >
204+ ) : (
205+ < p > 정보가 없습니다.</ p >
206+ ) }
207+ </ div >
208+ </ div >
209+
210+ { /* 용법용량 */ }
211+ < div className = "space-y-3" >
212+ < h2 className = "text-lg font-bold px-4 py-2 text-[#2BA89C] rounded-md border-b border-gray-300 pb-2" >
213+ 용법용량
214+ </ h2 >
215+ < div className = "px-4 py-2 text-gray-700" >
216+ { drug . usage ?. length > 0 ? (
217+ < ul className = "list-none pl-0 space-y-1" >
218+ { drug . usage . map ( ( item , i ) => (
219+ < li key = { i } > { item } </ li >
220+ ) ) }
221+ </ ul >
222+ ) : (
223+ < p > 정보가 없습니다.</ p >
224+ ) }
225+ </ div >
226+ </ div >
227+
228+ { /* 주의사항 및 기타 정보 */ }
229+ { precautionKeys . length > 0 && (
230+ < div className = "space-y-3" >
231+ < h2 className = "text-lg font-bold px-4 py-2 text-[#2BA89C] rounded-md border-b border-gray-300 pb-2" >
232+ 주의사항
233+ </ h2 >
234+ { precautionKeys . map ( ( key ) => (
235+ < div key = { key } className = "space-y-3" >
236+ < h3 className = "text-md font-semibold px-4 py-2 text-gray-700" >
237+ { key }
238+ </ h3 >
239+ < div className = "px-4 py-2 text-gray-700" >
240+ { drug . precaution [ key ] ?. length > 0 ? (
241+ < ul className = "list-none pl-0 space-y-1" >
242+ { drug . precaution [ key ] . map ( ( item , i ) => (
243+ < li key = { i } > { item } </ li >
244+ ) ) }
245+ </ ul >
246+ ) : (
247+ < p > 정보가 없습니다.</ p >
248+ ) }
249+ </ div >
250+ </ div >
251+ ) ) }
252+ </ div >
253+ ) }
254+ </ div >
255+ </ div >
256+ </ div >
257+ </ main >
258+ < Footer />
259+ </ div >
260+ ) ;
261+ }
0 commit comments