Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 125 additions & 77 deletions app/[docs_id]/chatForm.tsx
Original file line number Diff line number Diff line change
@@ -1,112 +1,160 @@
"use client";

import { hello } from "./chatServer";
import { useState, FormEvent } from "react";

export function ChatForm() {return (
interface ChatApiResponse {
response: string;
}

export function ChatForm() {
const [inputValue, setInputValue] = useState("");
const [response, setResponse] = useState("");
const [isLoading, setIsLoading] = useState(false);

const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
setIsLoading(true);
setResponse("");

try {
const res = await fetch("/api/chat", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ message: inputValue }),
});

const data = (await res.json()) as ChatApiResponse;
if (!res.ok) {
throw new Error(data.response || "エラーが発生しました。");
}
setResponse(data.response);
} catch (error: unknown) {
if (error instanceof Error) {
setResponse(`エラー: ${error.message}`);
} else {
setResponse(`エラー: ${String(error)}`);
}
} finally {
setIsLoading(false);
}
};
return (
<>
<style jsx>{`
<style jsx>{`
/* 簡単なCSSで見た目を整える(オプション) */
.form-container {
background-color: white;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(67, 204, 216, 0.86);
padding: 20px;
width: 90%;
max-width: 1000px;
display: flex;
flex-direction: column;
background-color: white;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(67, 204, 216, 0.86);
padding: 20px;
width: 90%;
max-width: 1000px;
display: flex;
flex-direction: column;
}
.input-area {
border: 1px solid #ccc;
border-radius: 8px;
padding: 5px 15 px;
margin-bottom: 15px;
min-height: 150px; /* 入力欄の高さ */
display: flex;
border: 1px solid #ccc;
border-radius: 8px;
padding: 5px 15 px;
margin-bottom: 15px;
min-height: 150px; /* 入力欄の高さ */
display: flex;
}
.text-input {
border: none;
outline: none;
flex-grow: 1;
font-size: 16px;
resize: none; /* テキストエリアのリサイズを無効化 */
overflow: auto;
padding: 10px;
border: none;
outline: none;
flex-grow: 1;
font-size: 16px;
resize: none; /* テキストエリアのリサイズを無効化 */
overflow: auto;
padding: 10px;
}
.controls {
display: flex;
align-items: center;
justify-content: space-between;
display: flex;
align-items: center;
justify-content: space-between;
}
.left-icons button {
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #555;
margin-right: 15px;
padding: 5px;
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #555;
margin-right: 15px;
padding: 5px;
}
.left-icons button:hover {
color: #000;
color: #000;
}
.left-icons span {
font-size: 14px;
vertical-align: middle;
margin-left: 5px;
color: #555;
font-size: 14px;
vertical-align: middle;
margin-left: 5px;
color: #555;
}
.right-controls {
display: flex;
align-items: center;
display: flex;
align-items: center;
}
.voice-icon button {
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #555;
margin-right: 15px;
padding: 5px;
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #555;
margin-right: 15px;
padding: 5px;
}
.voice-icon button:hover {
color: #000;
color: #000;
}
.send-button {
background-color: #007bff; /* 青色の送信ボタン */
color: white;
border: none;
border-radius: 50%; /* 丸いボタン */
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
cursor: pointer;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
transition: background-color 0.3s ease;
background-color: #007bff; /* 青色の送信ボタン */
color: white;
border: none;
border-radius: 50%; /* 丸いボタン */
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
cursor: pointer;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
transition: background-color 0.3s ease;
}
.send-button:hover {
background-color: #0056b3;
background-color: #0056b3;
}
`}</style>
`}</style>

<div className="form-container">
<form className="form-container" onSubmit={handleSubmit}>
<div className="input-area">
<textarea className="text-input" placeholder="質問を入力してください"></textarea>
<textarea
className="text-input"
placeholder="質問を入力してください"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
disabled={isLoading}
></textarea>
</div>

<div className="controls">
<div className="left-icons">

</div>
<div className="right-controls">
<button type="submit" className="send-button" title="送信">
<span className="icon">➤</span>
</button>
</div>
<div className="left-icons"></div>
<div className="right-controls">
<button
type="submit"
className="send-button"
title="送信"
disabled={isLoading}
>
<span className="icon">➤</span>
</button>
</div>
</div>
</div>
</form>
{response && <div className="response-container">{response}</div>}
</>
)}
);
}
12 changes: 4 additions & 8 deletions app/chat/route.js → app/api/chat/route.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { NextResponse } from 'next/server';
import { GoogleGenerativeAI } from '@google/generative-ai';

import { NextResponse } from "next/server";
import { GoogleGenerativeAI } from "@google/generative-ai";

const genAI = new GoogleGenerativeAI(process.env.API_KEY);

export async function POST(request) {
const { message } = await request.json();


if (!message) {
return NextResponse.json(
{ error: "メッセージがありません。" },
Expand All @@ -17,19 +15,17 @@ export async function POST(request) {

try {
const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" });

const result = await model.generateContent(message);
const response = result.response;
const text = response.text();

return NextResponse.json({ response: text });

} catch (e) {

console.error("Error:", e);
return NextResponse.json(
{ response: "エラーが発生しました。" },
{ status: 500 }
);
}
}
}
Loading