11"use client" ;
22
3- import { hello } from "./chatServer " ;
3+ import { useState , FormEvent } from "react " ;
44
5- export function ChatForm ( ) { return (
5+ interface ChatApiResponse {
6+ response : string ;
7+ }
8+
9+ export function ChatForm ( ) {
10+ const [ inputValue , setInputValue ] = useState ( "" ) ;
11+ const [ response , setResponse ] = useState ( "" ) ;
12+ const [ isLoading , setIsLoading ] = useState ( false ) ;
13+
14+ const handleSubmit = async ( e : FormEvent < HTMLFormElement > ) => {
15+ e . preventDefault ( ) ;
16+ setIsLoading ( true ) ;
17+ setResponse ( "" ) ;
18+
19+ try {
20+ const res = await fetch ( "/api/chat" , {
21+ method : "POST" ,
22+ headers : {
23+ "Content-Type" : "application/json" ,
24+ } ,
25+ body : JSON . stringify ( { message : inputValue } ) ,
26+ } ) ;
27+
28+ const data = ( await res . json ( ) ) as ChatApiResponse ;
29+ if ( ! res . ok ) {
30+ throw new Error ( data . response || "エラーが発生しました。" ) ;
31+ }
32+ setResponse ( data . response ) ;
33+ } catch ( error : any ) {
34+ setResponse ( `エラー: ${ error . message } ` ) ;
35+ } finally {
36+ setIsLoading ( false ) ;
37+ }
38+ } ;
39+ return (
640 < >
7- < style jsx > { `
41+ < style jsx > { `
842 /* 簡単なCSSで見た目を整える(オプション) */
943 .form-container {
10- background-color: white;
11- border-radius: 10px;
12- box-shadow: 0 4px 8px rgba(67, 204, 216, 0.86);
13- padding: 20px;
14- width: 90%;
15- max-width: 1000px;
16- display: flex;
17- flex-direction: column;
44+ background-color: white;
45+ border-radius: 10px;
46+ box-shadow: 0 4px 8px rgba(67, 204, 216, 0.86);
47+ padding: 20px;
48+ width: 90%;
49+ max-width: 1000px;
50+ display: flex;
51+ flex-direction: column;
1852 }
1953 .input-area {
20- border: 1px solid #ccc;
21- border-radius: 8px;
22- padding: 5px 15 px;
23- margin-bottom: 15px;
24- min-height: 150px; /* 入力欄の高さ */
25- display: flex;
54+ border: 1px solid #ccc;
55+ border-radius: 8px;
56+ padding: 5px 15 px;
57+ margin-bottom: 15px;
58+ min-height: 150px; /* 入力欄の高さ */
59+ display: flex;
2660 }
2761 .text-input {
28- border: none;
29- outline: none;
30- flex-grow: 1;
31- font-size: 16px;
32- resize: none; /* テキストエリアのリサイズを無効化 */
33- overflow: auto;
34- padding: 10px;
62+ border: none;
63+ outline: none;
64+ flex-grow: 1;
65+ font-size: 16px;
66+ resize: none; /* テキストエリアのリサイズを無効化 */
67+ overflow: auto;
68+ padding: 10px;
3569 }
3670 .controls {
37- display: flex;
38- align-items: center;
39- justify-content: space-between;
71+ display: flex;
72+ align-items: center;
73+ justify-content: space-between;
4074 }
4175 .left-icons button {
42- background: none;
43- border: none;
44- font-size: 24px;
45- cursor: pointer;
46- color: #555;
47- margin-right: 15px;
48- padding: 5px;
76+ background: none;
77+ border: none;
78+ font-size: 24px;
79+ cursor: pointer;
80+ color: #555;
81+ margin-right: 15px;
82+ padding: 5px;
4983 }
5084 .left-icons button:hover {
51- color: #000;
85+ color: #000;
5286 }
5387 .left-icons span {
54- font-size: 14px;
55- vertical-align: middle;
56- margin-left: 5px;
57- color: #555;
88+ font-size: 14px;
89+ vertical-align: middle;
90+ margin-left: 5px;
91+ color: #555;
5892 }
5993 .right-controls {
60- display: flex;
61- align-items: center;
94+ display: flex;
95+ align-items: center;
6296 }
6397 .voice-icon button {
64- background: none;
65- border: none;
66- font-size: 24px;
67- cursor: pointer;
68- color: #555;
69- margin-right: 15px;
70- padding: 5px;
98+ background: none;
99+ border: none;
100+ font-size: 24px;
101+ cursor: pointer;
102+ color: #555;
103+ margin-right: 15px;
104+ padding: 5px;
71105 }
72106 .voice-icon button:hover {
73- color: #000;
107+ color: #000;
74108 }
75109 .send-button {
76- background-color: #007bff; /* 青色の送信ボタン */
77- color: white;
78- border: none;
79- border-radius: 50%; /* 丸いボタン */
80- width: 40px;
81- height: 40px;
82- display: flex;
83- justify-content: center;
84- align-items: center;
85- font-size: 20px;
86- cursor: pointer;
87- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
88- transition: background-color 0.3s ease;
110+ background-color: #007bff; /* 青色の送信ボタン */
111+ color: white;
112+ border: none;
113+ border-radius: 50%; /* 丸いボタン */
114+ width: 40px;
115+ height: 40px;
116+ display: flex;
117+ justify-content: center;
118+ align-items: center;
119+ font-size: 20px;
120+ cursor: pointer;
121+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
122+ transition: background-color 0.3s ease;
89123 }
90124 .send-button:hover {
91- background-color: #0056b3;
125+ background-color: #0056b3;
92126 }
93- ` } </ style >
127+ ` } </ style >
94128
95- < div className = "form-container" >
129+ < form className = "form-container" onSubmit = { handleSubmit } >
96130 < div className = "input-area" >
97- < textarea className = "text-input" placeholder = "質問を入力してください" > </ textarea >
131+ < textarea
132+ className = "text-input"
133+ placeholder = "質問を入力してください"
134+ value = { inputValue }
135+ onChange = { ( e ) => setInputValue ( e . target . value ) }
136+ disabled = { isLoading }
137+ > </ textarea >
98138 </ div >
99-
100139 < div className = "controls" >
101- < div className = "left-icons" >
102-
103- </ div >
104- < div className = "right-controls" >
105- < button type = "submit" className = "send-button" title = "送信" >
106- < span className = "icon" > ➤</ span >
107- </ button >
108- </ div >
140+ < div className = "left-icons" > </ div >
141+ < div className = "right-controls" >
142+ < button
143+ type = "submit"
144+ className = "send-button"
145+ title = "送信"
146+ disabled = { isLoading }
147+ >
148+ < span className = "icon" > ➤</ span >
149+ </ button >
150+ </ div >
109151 </ div >
110- </ div >
152+ </ form >
153+ { response && < div className = "response-container" > { response } </ div > }
111154 </ >
112- ) }
155+ ) ;
156+ }
0 commit comments