Skip to content

Commit

Permalink
Merge pull request #89 from GDG-Hackathon-77ia/feature#85
Browse files Browse the repository at this point in the history
ChatPage API 연동
  • Loading branch information
Youn-Rha authored Nov 15, 2024
2 parents c4a6dc0 + a791072 commit aad4933
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 29 deletions.
2 changes: 1 addition & 1 deletion src/apis/chatbot/chatbot.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import axiosInstance from "../axiosInstance";

interface ChatEntry {
export interface ChatEntry {
question: string;
response: string;
responseDateTime: string;
Expand Down
16 changes: 14 additions & 2 deletions src/components/PageBar/index.style.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import styled from "@emotion/styled";

import backArrow from "../../assets/backarrow.png";

export const Container = styled.div`
height: 70px;
width: 100%;
Expand All @@ -14,10 +16,20 @@ export const Container = styled.div`
gap: 12px;
flex-shrink: 0;
`;
export const Arrow = styled.img`
export const Arrow = styled.button`
height: 20px;
width: 10px;
margin-left: 20px;
display: inline-block;
background-image: url(${backArrow});
background-image: url(${backArrow});
background-size: contain;
background-repeat: no-repeat;
background-position: center;
background-color: transparent;
outline: none;
border: none;
cursor: pointer;
`;
10 changes: 4 additions & 6 deletions src/components/PageBar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { Text } from "../Text";
import * as Styles from "./index.style";
import backArrow from "../../assets/backarrow.png"
import { useNavigate } from "react-router-dom";

export interface PageBarProps {
pageName: string;
onClick?: () => void; // 수정: `onClick`은 매개변수를 받지 않음
}

export const PageBar = ({pageName}: PageBarProps) => {
const navi = useNavigate();
export const PageBar = ({ pageName, onClick }: PageBarProps) => {
return (
<Styles.Container>
<Styles.Arrow src={backArrow} onClick={() => {navi(-1)}}/>
<Styles.Arrow onClick={onClick} />
<Text size="m" weight="bold" color="black">
{pageName}
</Text>
</Styles.Container>
);
}
};
19 changes: 19 additions & 0 deletions src/hooks/ChatPage/useChatSave.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { saveChatHistory } from "@/apis/chatbot/chatbot";
import { ChatEntry } from "@/apis/chatbot/chatbot";

export const useChatSave = () => {
const handleChatSave = async (chatHistory: ChatEntry[]) => {
try {
console.log(chatHistory);
const response = await saveChatHistory("chat", chatHistory);
console.log("Chat saved:", response.message);
} catch (error) {
const errorMessage =
(error as { response?: { data?: { detail?: string } } }).response?.data?.detail ||
"Failed to save chat history.";
console.error(errorMessage);
}
};

return { handleChatSave };
};
59 changes: 59 additions & 0 deletions src/hooks/ChatPage/useChatStart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { useState, useRef } from "react";

import { startOrContinueChat } from "@/apis/chatbot/chatbot";

// interface ChatEntry {
// question: string;
// response: string;
// responseDateTime: string;
// type: "chat" | "diary";
// }

export const useChatStart = () => {
const [chatHistory, setChatHistory] = useState<{ variant: "AI" | "USER"; text: string }[]>([
{ variant: "AI", text: "무엇을 도와드릴까요?" },
]);
const textAreaRef = useRef<HTMLTextAreaElement>(null);

const handleSendMessage = async () => {
const userMessage = textAreaRef.current?.value.trim();
if (!userMessage) return;

const currentDateTime = new Date().toISOString();

// 사용자의 메시지 추가
setChatHistory((prevHistory) => [...prevHistory, { variant: "USER", text: userMessage }]);

// AI의 응답 요청
try {
const response = await startOrContinueChat("chat", [
...chatHistory.map((msg, idx) => ({
question: idx % 2 === 0 ? msg.text : "", // AI 메시지를 question으로 설정
response: idx % 2 !== 0 ? msg.text : "", // 사용자 메시지를 response로 설정
responseDateTime: currentDateTime,
type: "chat" as const,
})),
{
question: "",
response: userMessage,
responseDateTime: currentDateTime,
type: "chat",
},
]);

// AI의 응답을 chatHistory에 추가
setChatHistory((prevHistory) => [...prevHistory, { variant: "AI", text: response.response }]);
} catch (error) {
const errorMessage =
(error as { response?: { data?: { detail?: string } } }).response?.data?.detail ||
"An unknown error occurred";
console.error("Chat failed:", errorMessage);
}

if (textAreaRef.current) {
textAreaRef.current.value = "";
}
};

return { chatHistory, textAreaRef, handleSendMessage };
};
48 changes: 28 additions & 20 deletions src/pages/ChatPage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,50 @@
import { useState, useRef, useEffect } from "react";
import { useRef, useEffect } from "react";

import { Button } from "@/components/Button";
import { Chat } from "@/components/Chat";
import { PageBar } from "@/components/PageBar";
import { TextArea } from "@/components/TextArea";

import { useChatSave } from "@/hooks/ChatPage/useChatSave";
import { useChatStart } from "@/hooks/ChatPage/useChatStart";

import * as Styles from "./index.style";
import { ChatEntry } from "@/apis/chatbot/chatbot";

export const ChatPage = () => {
const [messages, setMessages] = useState<{ variant: "AI" | "USER"; text: string }[]>([
{ variant: "AI", text: "무엇을 도와드릴까요?" },
]);
const textAreaRef = useRef<HTMLTextAreaElement>(null);
const messagesEndRef = useRef<HTMLDivElement>(null);

const handleSendClick = () => {
const inputText = textAreaRef.current?.value.trim();
if (!inputText) return;

setMessages((prevMessages) => [...prevMessages, { variant: "USER", text: inputText }]);
const { chatHistory, textAreaRef, handleSendMessage } = useChatStart();
const { handleChatSave } = useChatSave();

if (textAreaRef.current) {
textAreaRef.current.value = "";
}
};
const messagesEndRef = useRef<HTMLDivElement>(null);

useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages]);
}, [chatHistory]);

const handleSaveAndGoBack = async () => {
const formattedChatHistory = chatHistory.reduce<ChatEntry[]>((acc, msg, idx, arr) => {
if (msg.variant === "AI" && arr[idx + 1]?.variant === "USER") {
acc.push({
question: msg.text,
response: arr[idx + 1].text,
responseDateTime: new Date().toISOString(),
type: "chat",
});
}
return acc;
}, []);
await handleChatSave(formattedChatHistory); // 채팅 기록 저장
window.history.back(); // 뒤로 가기
};

return (
<Styles.Container>
<Styles.FixedHeader>
<PageBar pageName="채팅" />
<PageBar pageName="채팅" onClick={handleSaveAndGoBack} />
</Styles.FixedHeader>

<Styles.ChatContainer>
{messages.map((message, index) => (
{chatHistory.map((message, index) => (
<Styles.MessageWrapper key={index} variant={message.variant}>
<Chat variant={message.variant}>{message.text}</Chat>
</Styles.MessageWrapper>
Expand All @@ -46,7 +54,7 @@ export const ChatPage = () => {

<Styles.InputContainer>
<TextArea ref={textAreaRef} variant="secondary" width="80%" height="60px" placeholder="메세지 입력" />
<Button variant="rectangle" width="70px" height="60px" onClick={handleSendClick}>
<Button variant="rectangle" width="70px" height="60px" onClick={handleSendMessage}>
전송
</Button>
</Styles.InputContainer>
Expand Down

0 comments on commit aad4933

Please sign in to comment.