1
1
import { Button } from "@/components/ui/button" ;
2
2
import { Input } from "@/components/ui/input" ;
3
- import { useMutation } from "@tanstack/react-query" ;
3
+ import type { TextResponse } from "@/api" ;
4
+ import { useSendMessageMutation } from "@/api" ;
4
5
import { ImageIcon } from "lucide-react" ;
5
6
import { useEffect , useRef , useState } from "react" ;
6
7
import { useParams } from "react-router-dom" ;
7
8
import "./App.css" ;
8
9
9
- type TextResponse = {
10
- text : string ;
11
- user : string ;
12
- attachments ?: { url : string ; contentType : string ; title : string } [ ] ;
13
- } ;
14
-
15
10
export default function Chat ( ) {
16
11
const { agentId } = useParams ( ) ;
17
12
const [ input , setInput ] = useState ( "" ) ;
18
13
const [ messages , setMessages ] = useState < TextResponse [ ] > ( [ ] ) ;
19
14
const [ selectedFile , setSelectedFile ] = useState < File | null > ( null ) ;
20
15
const fileInputRef = useRef < HTMLInputElement > ( null ) ;
21
16
const messagesEndRef = useRef < HTMLDivElement > ( null ) ;
17
+ const { mutate : sendMessage , isPending } = useSendMessageMutation ( { setMessages, setSelectedFile } ) ;
22
18
23
19
const scrollToBottom = ( ) => {
24
20
messagesEndRef . current ?. scrollIntoView ( { behavior : "smooth" } ) ;
@@ -28,32 +24,9 @@ export default function Chat() {
28
24
scrollToBottom ( ) ;
29
25
} , [ messages ] ) ;
30
26
31
- const mutation = useMutation ( {
32
- mutationFn : async ( text : string ) => {
33
- const formData = new FormData ( ) ;
34
- formData . append ( "text" , text ) ;
35
- formData . append ( "userId" , "user" ) ;
36
- formData . append ( "roomId" , `default-room-${ agentId } ` ) ;
37
-
38
- if ( selectedFile ) {
39
- formData . append ( "file" , selectedFile ) ;
40
- }
41
-
42
- const res = await fetch ( `/api/${ agentId } /message` , {
43
- method : "POST" ,
44
- body : formData ,
45
- } ) ;
46
- return res . json ( ) as Promise < TextResponse [ ] > ;
47
- } ,
48
- onSuccess : ( data ) => {
49
- setMessages ( ( prev ) => [ ...prev , ...data ] ) ;
50
- setSelectedFile ( null ) ;
51
- } ,
52
- } ) ;
53
-
54
27
const handleSubmit = async ( e : React . FormEvent ) => {
55
28
e . preventDefault ( ) ;
56
- if ( ! input . trim ( ) && ! selectedFile ) return ;
29
+ if ( ( ! input . trim ( ) && ! selectedFile ) || ! agentId ) return ;
57
30
58
31
// Add user message immediately to state
59
32
const userMessage : TextResponse = {
@@ -63,7 +36,7 @@ export default function Chat() {
63
36
} ;
64
37
setMessages ( ( prev ) => [ ...prev , userMessage ] ) ;
65
38
66
- mutation . mutate ( input ) ;
39
+ sendMessage ( { text : input , agentId , selectedFile } ) ;
67
40
setInput ( "" ) ;
68
41
} ;
69
42
@@ -142,19 +115,19 @@ export default function Chat() {
142
115
onChange = { ( e ) => setInput ( e . target . value ) }
143
116
placeholder = "Type a message..."
144
117
className = "flex-1"
145
- disabled = { mutation . isPending }
118
+ disabled = { isPending }
146
119
/>
147
120
< Button
148
121
type = "button"
149
122
variant = "outline"
150
123
size = "icon"
151
124
onClick = { handleFileSelect }
152
- disabled = { mutation . isPending }
125
+ disabled = { isPending }
153
126
>
154
127
< ImageIcon className = "h-4 w-4" />
155
128
</ Button >
156
- < Button type = "submit" disabled = { mutation . isPending } >
157
- { mutation . isPending ? "..." : "Send" }
129
+ < Button type = "submit" disabled = { isPending } >
130
+ { isPending ? "..." : "Send" }
158
131
</ Button >
159
132
</ form >
160
133
{ selectedFile && (
0 commit comments