11"use client" ;
22
3- import { DefaultChatTransport } from "ai" ;
43import { useChat } from "@ai-sdk/react" ;
54import { useAIPanel } from "./ai-panel-provider" ;
65import { ChatMessage } from "./chat-message" ;
76import { IconSparkle2 } from "@karrotmarket/react-multicolor-icon" ;
8- import { IconXmarkLine } from "@karrotmarket/react-monochrome-icon" ;
7+ import { IconTrashcanLine , IconXmarkLine } from "@karrotmarket/react-monochrome-icon" ;
98import { Icon } from "@seed-design/react" ;
109import { ActionButton } from "seed-design/ui/action-button" ;
10+ import { ProgressCircle } from "seed-design/ui/progress-circle" ;
1111import { TextField , TextFieldInput } from "seed-design/ui/text-field" ;
1212import { useEffect , useRef , useState , type FormEvent } from "react" ;
1313
@@ -17,16 +17,12 @@ const SUGGESTIONS = [
1717 "SEED Design 색상 토큰은 어떻게 사용해?" ,
1818] ;
1919
20- const chatTransport = new DefaultChatTransport ( {
21- api : "/api/chat" ,
22- } ) ;
23-
2420export function ChatInterface ( ) {
25- const { close } = useAIPanel ( ) ;
21+ const { close, chat } = useAIPanel ( ) ;
2622 const [ input , setInput ] = useState ( "" ) ;
2723
28- const { messages, sendMessage, status } = useChat ( {
29- transport : chatTransport ,
24+ const { messages, sendMessage, setMessages , status, stop } = useChat ( {
25+ chat ,
3026 } ) ;
3127
3228 const isLoading = status === "submitted" || status === "streaming" ;
@@ -56,6 +52,19 @@ export function ChatInterface() {
5652 setInput ( "" ) ;
5753 } ;
5854
55+ const handleClearConversation = ( ) => {
56+ if ( ! window . confirm ( "현재 대화를 모두 삭제할까요?" ) ) {
57+ return ;
58+ }
59+
60+ if ( isLoading ) {
61+ stop ( ) ;
62+ }
63+
64+ setMessages ( [ ] ) ;
65+ setInput ( "" ) ;
66+ } ;
67+
5968 return (
6069 < div className = "flex flex-col h-full bg-fd-background" >
6170 { /* Header */ }
@@ -64,18 +73,33 @@ export function ChatInterface() {
6473 < IconSparkle2 width = { 18 } height = { 18 } />
6574 < span className = "font-semibold text-sm" > SEED Assistant</ span >
6675 </ div >
67- < ActionButton
68- type = "button"
69- onClick = { close }
70- variant = "ghost"
71- layout = "iconOnly"
72- size = "xsmall"
73- bleedX = "asPadding"
74- bleedY = "asPadding"
75- aria-label = "패널 닫기"
76- >
77- < Icon svg = { < IconXmarkLine /> } />
78- </ ActionButton >
76+ < div className = "flex items-center gap-1" >
77+ < ActionButton
78+ type = "button"
79+ onClick = { handleClearConversation }
80+ variant = "ghost"
81+ layout = "iconOnly"
82+ size = "xsmall"
83+ bleedX = "asPadding"
84+ bleedY = "asPadding"
85+ aria-label = "대화 삭제"
86+ disabled = { messages . length === 0 }
87+ >
88+ < Icon svg = { < IconTrashcanLine /> } />
89+ </ ActionButton >
90+ < ActionButton
91+ type = "button"
92+ onClick = { close }
93+ variant = "ghost"
94+ layout = "iconOnly"
95+ size = "xsmall"
96+ bleedX = "asPadding"
97+ bleedY = "asPadding"
98+ aria-label = "패널 닫기"
99+ >
100+ < Icon svg = { < IconXmarkLine /> } />
101+ </ ActionButton >
102+ </ div >
79103 </ div >
80104
81105 { /* Messages */ }
@@ -109,16 +133,9 @@ export function ChatInterface() {
109133
110134 { isLoading && messages . length > 0 && messages [ messages . length - 1 ] ?. role === "user" && (
111135 < div className = "flex justify-start" >
112- < div className = "flex items-center gap-1.5 text-sm text-fd-muted-foreground" >
113- < span className = "inline-block size-1.5 rounded-full bg-fd-muted-foreground animate-pulse" />
114- < span
115- className = "inline-block size-1.5 rounded-full bg-fd-muted-foreground animate-pulse"
116- style = { { animationDelay : "0.2s" } }
117- />
118- < span
119- className = "inline-block size-1.5 rounded-full bg-fd-muted-foreground animate-pulse"
120- style = { { animationDelay : "0.4s" } }
121- />
136+ < div className = "flex items-center gap-2 text-sm text-fd-muted-foreground" >
137+ < ProgressCircle size = "24" value = { undefined } />
138+ 응답 생성 중...
122139 </ div >
123140 </ div >
124141 ) }
0 commit comments