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 : unknown ) {
34+ if ( error instanceof Error ) {
35+ setResponse ( `エラー: ${ error . message } ` ) ;
36+ } else {
37+ setResponse ( `エラー: ${ String ( error ) } ` ) ;
38+ }
39+ } finally {
40+ setIsLoading ( false ) ;
41+ }
42+ } ;
43+ return (
644 < >
7- < style jsx > { `
45+ < style jsx > { `
846 /* 簡単なCSSで見た目を整える(オプション) */
947 .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;
48+ background-color: white;
49+ border-radius: 10px;
50+ box-shadow: 0 4px 8px rgba(67, 204, 216, 0.86);
51+ padding: 20px;
52+ width: 90%;
53+ max-width: 1000px;
54+ display: flex;
55+ flex-direction: column;
1856 }
1957 .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;
58+ border: 1px solid #ccc;
59+ border-radius: 8px;
60+ padding: 5px 15 px;
61+ margin-bottom: 15px;
62+ min-height: 150px; /* 入力欄の高さ */
63+ display: flex;
2664 }
2765 .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;
66+ border: none;
67+ outline: none;
68+ flex-grow: 1;
69+ font-size: 16px;
70+ resize: none; /* テキストエリアのリサイズを無効化 */
71+ overflow: auto;
72+ padding: 10px;
3573 }
3674 .controls {
37- display: flex;
38- align-items: center;
39- justify-content: space-between;
75+ display: flex;
76+ align-items: center;
77+ justify-content: space-between;
4078 }
4179 .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;
80+ background: none;
81+ border: none;
82+ font-size: 24px;
83+ cursor: pointer;
84+ color: #555;
85+ margin-right: 15px;
86+ padding: 5px;
4987 }
5088 .left-icons button:hover {
51- color: #000;
89+ color: #000;
5290 }
5391 .left-icons span {
54- font-size: 14px;
55- vertical-align: middle;
56- margin-left: 5px;
57- color: #555;
92+ font-size: 14px;
93+ vertical-align: middle;
94+ margin-left: 5px;
95+ color: #555;
5896 }
5997 .right-controls {
60- display: flex;
61- align-items: center;
98+ display: flex;
99+ align-items: center;
62100 }
63101 .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;
102+ background: none;
103+ border: none;
104+ font-size: 24px;
105+ cursor: pointer;
106+ color: #555;
107+ margin-right: 15px;
108+ padding: 5px;
71109 }
72110 .voice-icon button:hover {
73- color: #000;
111+ color: #000;
74112 }
75113 .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;
114+ background-color: #007bff; /* 青色の送信ボタン */
115+ color: white;
116+ border: none;
117+ border-radius: 50%; /* 丸いボタン */
118+ width: 40px;
119+ height: 40px;
120+ display: flex;
121+ justify-content: center;
122+ align-items: center;
123+ font-size: 20px;
124+ cursor: pointer;
125+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
126+ transition: background-color 0.3s ease;
89127 }
90128 .send-button:hover {
91- background-color: #0056b3;
129+ background-color: #0056b3;
92130 }
93- ` } </ style >
131+ ` } </ style >
94132
95- < div className = "form-container" >
133+ < form className = "form-container" onSubmit = { handleSubmit } >
96134 < div className = "input-area" >
97- < textarea className = "text-input" placeholder = "質問を入力してください" > </ textarea >
135+ < textarea
136+ className = "text-input"
137+ placeholder = "質問を入力してください"
138+ value = { inputValue }
139+ onChange = { ( e ) => setInputValue ( e . target . value ) }
140+ disabled = { isLoading }
141+ > </ textarea >
98142 </ div >
99-
100143 < 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 >
144+ < div className = "left-icons" > </ div >
145+ < div className = "right-controls" >
146+ < button
147+ type = "submit"
148+ className = "send-button"
149+ title = "送信"
150+ disabled = { isLoading }
151+ >
152+ < span className = "icon" > ➤</ span >
153+ </ button >
154+ </ div >
109155 </ div >
110- </ div >
156+ </ form >
157+ { response && < div className = "response-container" > { response } </ div > }
111158 </ >
112- ) }
159+ ) ;
160+ }
0 commit comments