11'use client' ;
22
3- import React , { useCallback , useState } from 'react' ;
3+ import React , { useCallback , useState , KeyboardEvent } from 'react' ;
44import { Dialog , DialogContent , DialogHeader , DialogTitle , DialogTrigger } from '@/components/ui/dialog' ;
55import Image from 'next/image' ;
66import { Button } from '@/components/ui/button' ;
7+ import { Textarea } from '@/components/ui/textarea' ;
78import { ExternalLink , ShoppingBag , Loader2 } from 'lucide-react' ;
89import { useAtom , useSetAtom } from 'jotai' ;
910import { activeClothAtom , panelAtom } from '@/atoms/chatAtoms' ;
@@ -22,6 +23,8 @@ export default function ClothModal({ product, cloth, children }: ClothModalProps
2223 const setPanel = useSetAtom ( panelAtom ) ;
2324 const [ productDescription , setProductDescription ] = useState ( '' ) ;
2425 const [ isLoadingDescription , setIsLoadingDescription ] = useState ( false ) ;
26+ const [ showQuestionInput , setShowQuestionInput ] = useState ( false ) ;
27+ const [ questionInput , setQuestionInput ] = useState ( '' ) ;
2528
2629 // 스토리지 훅 사용
2730 const { closet, addClothToCloset } = useCloset ( ) ;
@@ -64,6 +67,8 @@ export default function ClothModal({ product, cloth, children }: ClothModalProps
6467 setIsOpen ( false ) ;
6568 setProductDescription ( '' ) ;
6669 setIsLoadingDescription ( false ) ;
70+ setShowQuestionInput ( false ) ;
71+ setQuestionInput ( '' ) ;
6772 }
6873 } ,
6974 [ product , cloth , setActiveCloth ] ,
@@ -82,6 +87,16 @@ export default function ClothModal({ product, cloth, children }: ClothModalProps
8287 setIsOpen ( false ) ;
8388 } , [ activeCloth , closet , addClothToCloset , setPanel ] ) ;
8489
90+ const handleGetProductDescription = useCallback ( async ( ) => {
91+ if ( ! activeCloth || activeCloth . id === 'user' || ! questionInput . trim ( ) ) return ;
92+ setIsLoadingDescription ( true ) ;
93+ const res = await getChatProductDescription ( activeCloth . id , questionInput . trim ( ) ) ;
94+ setProductDescription (
95+ res . status === 'success' ? ( typeof res . data === 'string' ? res . data : '' ) : '' ,
96+ ) ;
97+ setIsLoadingDescription ( false ) ;
98+ } , [ activeCloth , questionInput ] ) ;
99+
85100 return (
86101 < Dialog open = { isOpen } onOpenChange = { handleOpenChange } >
87102 < DialogTrigger asChild > { children } </ DialogTrigger >
@@ -151,18 +166,57 @@ export default function ClothModal({ product, cloth, children }: ClothModalProps
151166 < Button
152167 variant = "outline"
153168 className = "w-full h-12 text-lg"
154- onClick = { async ( ) => {
169+ onClick = { ( ) => {
155170 if ( ! activeCloth || activeCloth . id === 'user' ) return ;
156- setIsLoadingDescription ( true ) ;
157- const res = await getChatProductDescription ( activeCloth . id ) ;
158- setProductDescription (
159- res . status === 'success' ? ( typeof res . data === 'string' ? res . data : '' ) : '' ,
160- ) ;
161- setIsLoadingDescription ( false ) ;
171+ setShowQuestionInput ( ! showQuestionInput ) ;
172+ if ( showQuestionInput ) {
173+ setQuestionInput ( '' ) ;
174+ }
162175 } }
163176 >
164177 상품 설명 보기
165178 </ Button >
179+ { showQuestionInput && (
180+ < div className = "mt-3 space-y-2" >
181+ < Textarea
182+ value = { questionInput }
183+ onChange = { ( e ) => setQuestionInput ( e . target . value ) }
184+ placeholder = "상품에 대해 궁금한 점에 대해 물어보세요!"
185+ onKeyDown = { ( e : KeyboardEvent < HTMLTextAreaElement > ) => {
186+ const isEmpty = ! questionInput . trim ( ) ;
187+ const isComposing = e . nativeEvent . isComposing ;
188+
189+ if ( isComposing ) {
190+ return ;
191+ }
192+
193+ const isEnter = e . key === 'Enter' && ! e . shiftKey ;
194+ const submitOnEnter = isEnter && ! isEmpty ;
195+
196+ if ( submitOnEnter ) {
197+ e . preventDefault ( ) ;
198+ handleGetProductDescription ( ) ;
199+ }
200+ } }
201+ className = "w-full min-h-[80px] resize-none"
202+ rows = { 3 }
203+ />
204+ < Button
205+ className = "w-full bg-blue-600 hover:bg-blue-700 text-white"
206+ onClick = { handleGetProductDescription }
207+ disabled = { ! questionInput . trim ( ) || isLoadingDescription }
208+ >
209+ { isLoadingDescription ? (
210+ < >
211+ < Loader2 className = "w-4 h-4 mr-2 animate-spin" />
212+ 설명을 불러오는 중...
213+ </ >
214+ ) : (
215+ '질문하기'
216+ ) }
217+ </ Button >
218+ </ div >
219+ ) }
166220 </ div >
167221 { isLoadingDescription && (
168222 < div className = "mt-4 p-4 bg-gray-50 dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 flex items-center gap-3" >
0 commit comments