diff --git a/.gitignore b/.gitignore
index a547bf3..3b0b403 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,5 @@ dist-ssr
*.njsproj
*.sln
*.sw?
+
+.env
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index e7a3fb4..714014e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,6 +18,7 @@
},
"devDependencies": {
"@eslint/js": "^9.25.0",
+ "@types/node": "^22.15.24",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
"@types/react-router-dom": "^5.3.3",
@@ -1269,6 +1270,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/node": {
+ "version": "22.15.24",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.24.tgz",
+ "integrity": "sha512-w9CZGm9RDjzTh/D+hFwlBJ3ziUaVw7oufKA3vOFSOZlzmW9AkZnfjPb+DLnrV6qtgL/LNmP0/2zBNCFHL3F0ng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.21.0"
+ }
+ },
"node_modules/@types/react": {
"version": "19.1.5",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.5.tgz",
@@ -3280,6 +3291,13 @@
"typescript": ">=4.8.4 <5.9.0"
}
},
+ "node_modules/undici-types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
diff --git a/package.json b/package.json
index 7c109d4..6b2d3a1 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
},
"devDependencies": {
"@eslint/js": "^9.25.0",
+ "@types/node": "^22.15.24",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
"@types/react-router-dom": "^5.3.3",
diff --git "a/public/images/characters/\354\225\231\352\270\200\354\235\264.png" "b/public/images/characters/\354\225\231\352\270\200\354\235\264.png"
new file mode 100644
index 0000000..04a4cfd
Binary files /dev/null and "b/public/images/characters/\354\225\231\352\270\200\354\235\264.png" differ
diff --git "a/public/images/characters/\354\233\205\354\235\264.png" "b/public/images/characters/\354\233\205\354\235\264.png"
new file mode 100644
index 0000000..6699d14
Binary files /dev/null and "b/public/images/characters/\354\233\205\354\235\264.png" differ
diff --git "a/public/images/characters/\355\213\260\353\260\224\353\205\270.png" "b/public/images/characters/\355\213\260\353\260\224\353\205\270.png"
new file mode 100644
index 0000000..9c0c4b7
Binary files /dev/null and "b/public/images/characters/\355\213\260\353\260\224\353\205\270.png" differ
diff --git a/src/App.tsx b/src/App.tsx
index 6c80a53..3d55f46 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -10,6 +10,7 @@ import SettingPage from "./pages/chatting/SettingPage";
import ChatPage from "./pages/chatting/ChatPage";
import styled from "styled-components";
import WritingPage from "./pages/writing/WritingPage";
+import Testpage from "./pages/Testpage";
function App() {
return (
@@ -19,13 +20,14 @@ function App() {
} />
} />
} />
- } />
+ } />
} />
} />
} />
} />
} />
+ } />
diff --git a/src/components/home/DiaryList.tsx b/src/components/home/DiaryList.tsx
index ebdbba6..1735393 100644
--- a/src/components/home/DiaryList.tsx
+++ b/src/components/home/DiaryList.tsx
@@ -1,49 +1,48 @@
+import { useEffect, useState } from "react";
import styled from "styled-components";
+import { getAllDiary } from "../../services/apis/diary/diary";
+import { useNavigate } from "react-router-dom";
-const diaries = [
- {
- date: "2025.05.01.",
- title: "오늘은 영화 보러 간 날",
- tags: ["#취미", "#휴식"],
- content: "재밌었다!".repeat(30),
- },
- {
- date: "2025.05.01.",
- title: "오늘은 영화 보러 간 날",
- tags: ["#취미", "#휴식"],
- content: "재밌었다!".repeat(30),
- },
- {
- date: "2025.05.01.",
- title: "오늘은 영화 보러 간 날",
- tags: ["#취미", "#휴식"],
- content: "재밌었다!".repeat(30),
- },
- {
- date: "2025.05.01.",
- title: "오늘은 영화 보러 간 날",
- tags: ["#취미", "#휴식"],
- content: "재밌었다!".repeat(30),
- },
- {
- date: "2025.05.01.",
- title: "오늘은 영화 보러 간 날",
- tags: ["#취미", "#휴식"],
- content: "재밌었다!".repeat(30),
- },
-];
+interface Diary {
+ id: number;
+ date: string;
+ title: string;
+ hashTags: string[];
+ content: string;
+}
const DiaryList = () => {
+ const [diaries, setDiaries] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+ const navigate = useNavigate();
+
+ useEffect(() => {
+ getAllDiary()
+ .then((data) => {
+ setDiaries(data);
+ setLoading(false);
+ })
+ .catch((err) => {
+ console.error("일기 불러오기 실패:", err);
+ setError("일기를 불러오지 못했습니다.");
+ setLoading(false);
+ });
+ }, []);
+
+ if (loading) return 로딩 중...
;
+ if (error) return {error}
;
+
return (
- {diaries.map((diary, index) => (
-
+ {diaries.map((diary) => (
+ navigate(`/diary/${diary.id}`)}>
{diary.date}
{diary.title}
- {diary.tags.map((tag, i) => (
- {tag}
+ {diary.hashTags.map((tag, i) => (
+ #{tag}
))}
{diary.content}
diff --git a/src/pages/DiaryDetail.tsx b/src/pages/DiaryDetail.tsx
index e4e7093..cc07fa6 100644
--- a/src/pages/DiaryDetail.tsx
+++ b/src/pages/DiaryDetail.tsx
@@ -1,52 +1,82 @@
import styled from "styled-components";
import { IoHomeOutline } from "react-icons/io5";
import { BsPencil } from "react-icons/bs";
-import { useNavigate } from "react-router-dom";
+import { useNavigate, useParams } from "react-router-dom";
+import { useEffect, useState } from "react";
+import { getDiary } from "../services/apis/diary/diary";
+
+interface DiaryResponse {
+ id: number;
+ date: string;
+ title: string;
+ content: string;
+ comment: string;
+ character: string;
+ hashTags: string[];
+}
const DiaryDetail = () => {
const navigate = useNavigate();
+ const { diaryId } = useParams();
+
+ const [diary, setDiary] = useState(null);
+ const [error, setError] = useState(null);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ if (diaryId) {
+ getDiary(diaryId)
+ .then((data) => {
+ setDiary(data);
+ setLoading(false);
+ })
+ .catch((err) => {
+ console.error("Error fetching diary:", err);
+ setError("일기를 불러오는 데 실패했습니다.");
+ setLoading(false);
+ });
+ }
+ }, [diaryId]);
+
+ const formatDate = (rawDate: string) => {
+ const date = new Date(rawDate);
+ return `${date.getFullYear()}.${String(date.getMonth() + 1).padStart(2, "0")}.${String(date.getDate()).padStart(2, "0")}.`;
+ };
+
+ if (loading) return 로딩 중...
;
+ if (error) return {error}
;
+ if (!diary) return 일기 데이터가 없습니다.
;
return (
navigate("/")} />
- 2025.05.01.
-
+ {formatDate(diary.date)}
+ navigate(`/edit/${diary.id}`)} />
- 오늘은 영화 보러 간 날
+ {diary.title}
- #취미
- #휴식
+ {diary.hashTags && diary.hashTags.length > 0 ? (
+ diary.hashTags.map((tag, idx) => #{tag})
+ ) : (
+ #태그없음
+ )}
-
- 오늘은 오랜만에 영화관에 가서 영화를 보고 왔다. 요즘 바빠서 제대로
- 쉬지도 못했는데, 이렇게 여유롭게 시간을 보내니 기분이 참 좋았다.
- 친구와 약속을 잡고 미리 예매까지 해두었는데, 다행히 좋은 자리에서
- 관람할 수 있었다.
-
- 보고 싶었던 영화라 기대가 컸는데, 그 기대를 저버리지 않고 정말
- 재미있었다. 배우들의 연기도 훌륭했고, 스토리도 탄탄해서 중간에 지루할
- 틈이 없었다. 영화관 특유의 분위기, 어두운 조명과 커다란 스크린, 웅장한
- 사운드까지 모든 게 몰입감을 더해줬다.
-
- 팝콘과 콜라도 빠질 수 없어서, 먹으면서 영화 보는 재미도 쏠쏠했다. 엔딩
- 크레딧이 올라갈 때는 아쉬운 마음도 들었지만, 오랜만에 힐링되는 시간을
- 보낸 것 같아 만족스럽다. 다음엔 다른 장르의 영화도 보러 가고 싶다.
-
+ {diary.content}
AI 친구의 코멘트
-
-
- 웅이
-
-
- 오랜만에 영화관에서 좋은 시간 보냈다니 내가 다 기쁘다! 너의 여유로운
- 하루가 참 따뜻하게 느껴져 :)
-
+
+
+ {diary.character}
+
+ {diary.comment}
diff --git a/src/pages/Testpage.tsx b/src/pages/Testpage.tsx
new file mode 100644
index 0000000..f607683
--- /dev/null
+++ b/src/pages/Testpage.tsx
@@ -0,0 +1,30 @@
+import { useState } from "react";
+import { sendMessageToGPT } from "../services/gpt/openai";
+
+const Testpage = () => {
+ const [input, setInput] = useState("");
+ const [response, setResponse] = useState("");
+
+ const handleSubmit = async () => {
+ const result = await sendMessageToGPT(input);
+ setResponse(result);
+ };
+
+ return (
+
+ );
+};
+
+export default Testpage;
diff --git a/src/pages/chatting/ChatPage.tsx b/src/pages/chatting/ChatPage.tsx
index e6b51ea..d79e8cf 100644
--- a/src/pages/chatting/ChatPage.tsx
+++ b/src/pages/chatting/ChatPage.tsx
@@ -81,7 +81,9 @@ const EndChatButton = styled.button`
const ChatPage = () => {
const { chatId = "", character = "" } = useParams();
- const [messages, setMessages] = useState<{ role: string; content: string }[]>([]);
+ const [messages, setMessages] = useState<{ role: string; content: string }[]>(
+ [],
+ );
const [input, setInput] = useState("");
const [loading, setLoading] = useState(false);
const { selectedDate } = useSettingStore();
@@ -99,13 +101,28 @@ const ChatPage = () => {
const reply = await postComment(chatId, character, userMessage.content);
if (reply?.content) {
- setMessages((prev) => [...prev, { role: "bot", content: reply.content }]);
+ setMessages((prev) => [
+ ...prev,
+ { role: "bot", content: reply.content },
+ ]);
} else {
- setMessages((prev) => [...prev, { role: "bot", content: "응답을 받지 못했습니다. 다시 시도해 주세요." }]);
+ setMessages((prev) => [
+ ...prev,
+ {
+ role: "bot",
+ content: "응답을 받지 못했습니다. 다시 시도해 주세요.",
+ },
+ ]);
}
} catch (error) {
console.error("Failed to send message:", error);
- setMessages((prev) => [...prev, { role: "bot", content: "에러가 발생했습니다. 나중에 다시 시도해 주세요." }]);
+ setMessages((prev) => [
+ ...prev,
+ {
+ role: "bot",
+ content: "에러가 발생했습니다. 나중에 다시 시도해 주세요.",
+ },
+ ]);
} finally {
setLoading(false);
}
@@ -125,9 +142,10 @@ const ChatPage = () => {
}
try {
- const formattedDate = selectedDate instanceof Date
- ? selectedDate.toISOString().split("T")[0]
- : selectedDate;
+ const formattedDate =
+ selectedDate instanceof Date
+ ? selectedDate.toISOString().split("T")[0]
+ : selectedDate;
const response = await postDiary(chatId, character, formattedDate);
alert("대화가 저장되었습니다.");
diff --git a/src/pages/writing/WritingPage.tsx b/src/pages/writing/WritingPage.tsx
index 9a7d41d..6eace6d 100644
--- a/src/pages/writing/WritingPage.tsx
+++ b/src/pages/writing/WritingPage.tsx
@@ -98,7 +98,7 @@ const TextInput = styled.input`
outline: none;
&::placeholder {
- color: #B0BCD2;
+ color: #b0bcd2;
}
`;
@@ -110,7 +110,7 @@ const TagInput = styled.input`
border-radius: 12px;
outline: none;
&::placeholder {
- color: #B0BCD2;
+ color: #b0bcd2;
}
`;
@@ -127,6 +127,6 @@ const ContentArea = styled.textarea`
outline: none;
&::placeholder {
- color: #6D7EA0;
+ color: #6d7ea0;
}
`;
diff --git a/src/services/apis/chatting/chat.ts b/src/services/apis/chatting/chat.ts
index 46d817c..7c1e5a1 100644
--- a/src/services/apis/chatting/chat.ts
+++ b/src/services/apis/chatting/chat.ts
@@ -62,14 +62,11 @@ export async function postDiary(
date: string,
) {
try {
- const response = await axiosInstanceWithToken.post(
- `https://soulmate.o-r.kr/api/diary/generate`,
- {
- chatId: chatId,
- character: character,
- date: date,
- },
- );
+ const response = await axiosInstanceWithToken.post(`/api/diary/generate`, {
+ chatId: chatId,
+ character: character,
+ date: date,
+ });
return response.data;
} catch (error) {
throw error;
diff --git a/src/services/apis/diary/diary.ts b/src/services/apis/diary/diary.ts
new file mode 100644
index 0000000..fa48b62
--- /dev/null
+++ b/src/services/apis/diary/diary.ts
@@ -0,0 +1,23 @@
+import { CreateAxiosInstanceWithToken } from "../axiosInstanceWithToken";
+
+const axiosInstanceWithToken = CreateAxiosInstanceWithToken();
+
+export async function getAllDiary() {
+ try {
+ const response = await axiosInstanceWithToken.get(`/api/diary/get`);
+ return response.data;
+ } catch (error) {
+ throw error;
+ }
+}
+
+export async function getDiary(diaryId: string) {
+ try {
+ const response = await axiosInstanceWithToken.get(
+ `/api/diary/get/${diaryId}`,
+ );
+ return response.data;
+ } catch (error) {
+ throw error;
+ }
+}
diff --git a/src/services/gpt/openai.ts b/src/services/gpt/openai.ts
new file mode 100644
index 0000000..f104945
--- /dev/null
+++ b/src/services/gpt/openai.ts
@@ -0,0 +1,27 @@
+import axios from "axios";
+
+const API_KEY = import.meta.env.VITE_OPENAI_API_KEY;
+const API_URL = "https://api.openai.com/v1/chat/completions";
+
+export const sendMessageToGPT = async (message: string) => {
+ try {
+ const response = await axios.post(
+ API_URL,
+ {
+ model: "gpt-3.5-turbo",
+ messages: [{ role: "user", content: message }],
+ },
+ {
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ },
+ );
+
+ return response.data.choices[0].message.content;
+ } catch (error) {
+ console.error("GPT API 호출 오류:", error);
+ throw error;
+ }
+};