From 3d91be7443e444e32b764f0b3abc88ff5032184d Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Mon, 27 Jan 2025 21:26:35 +0900 Subject: [PATCH 01/11] =?UTF-8?q?feat:=20=ED=83=80=EB=A1=9C=20=EC=A7=88?= =?UTF-8?q?=EB=AC=B8=20=EC=B6=94=EC=B2=9C=20API=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=8A=A4=ED=82=A4=EB=A7=88=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tarot/apis/getTarotQuestionRecommends.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tarot/apis/getTarotQuestionRecommends.ts b/src/tarot/apis/getTarotQuestionRecommends.ts index 485db64..fe2a149 100644 --- a/src/tarot/apis/getTarotQuestionRecommends.ts +++ b/src/tarot/apis/getTarotQuestionRecommends.ts @@ -2,7 +2,7 @@ import apiClient from '@/shared/lib/axios/apiClient'; import { z } from 'zod'; export type TarotQuestionRecommendListResponse = { - question: { + questions: { recommendQuestionId: number; question: string; referenceCount: number; @@ -10,7 +10,7 @@ export type TarotQuestionRecommendListResponse = { }; const schema = z.object({ - question: z.array( + questions: z.array( z.object({ recommendQuestionId: z.number(), question: z.string(), @@ -19,7 +19,7 @@ const schema = z.object({ ), }); -type TarotQuestionRecommendListData = z.infer; +export type TarotQuestionRecommendListData = z.infer; const validate = (data: TarotQuestionRecommendListResponse): TarotQuestionRecommendListData => { const validatedData = schema.parse(data); From a67b4c7a90cd659dc83ee6c176655905c69794fe Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Mon, 27 Jan 2025 21:28:00 +0900 Subject: [PATCH 02/11] =?UTF-8?q?feat:=20=ED=83=80=EB=A1=9C=20=EC=A7=88?= =?UTF-8?q?=EB=AC=B8=20=EC=B6=94=EC=B2=9C=20=EB=B3=80=EA=B2=BD=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RefreshQuickQuestionButton/index.tsx | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/chat/components/RefreshQuickQuestionButton/index.tsx diff --git a/src/chat/components/RefreshQuickQuestionButton/index.tsx b/src/chat/components/RefreshQuickQuestionButton/index.tsx new file mode 100644 index 0000000..1a95442 --- /dev/null +++ b/src/chat/components/RefreshQuickQuestionButton/index.tsx @@ -0,0 +1,33 @@ +import { useQueryClient } from '@tanstack/react-query'; +import { css } from 'styled-components'; + +export default function RefreshQuickQuestionButton() { + const queryClient = useQueryClient(); + + const handleClick = () => { + queryClient.invalidateQueries({ queryKey: ['tarotQuestionRecommends'] }); + }; + + return ( + + ); +} From 3c40c529af595c7362aa61d4fbd531dbd88c0ade Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Mon, 27 Jan 2025 22:46:52 +0900 Subject: [PATCH 03/11] =?UTF-8?q?feat:=20=ED=83=80=EB=A1=9C=20=EC=A7=88?= =?UTF-8?q?=EB=AC=B8=20mock=20api=20=EC=9D=91=EB=8B=B5=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/api/v1/tarot/question/recommends/route.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/app/api/v1/tarot/question/recommends/route.ts b/src/app/api/v1/tarot/question/recommends/route.ts index 0b02c62..0c761b4 100644 --- a/src/app/api/v1/tarot/question/recommends/route.ts +++ b/src/app/api/v1/tarot/question/recommends/route.ts @@ -3,7 +3,7 @@ import { NextResponse } from 'next/server'; export async function GET() { const mockData: TarotQuestionRecommendListResponse = { - question: [ + questions: [ { recommendQuestionId: 1, question: '썸남 썸녀랑 잘 될까?', @@ -11,7 +11,7 @@ export async function GET() { }, { recommendQuestionId: 2, - question: '상반기에 취업할 수 있을까?', + question: '상반기에 취업할 수 있을까? 상반기에 취업할 수 있을까? 상반기에 취업할 수 있을까?', referenceCount: 222, }, { @@ -19,6 +19,11 @@ export async function GET() { question: '그 사람은 내 생각하고 있을까?', referenceCount: 3333, }, + { + recommendQuestionId: 4, + question: '그 사람은 내 생각하고 있을까?', + referenceCount: 3334, + }, ], }; From 21638dad8b4229100d143c81365d845f7ddbc10a Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Mon, 27 Jan 2025 22:47:32 +0900 Subject: [PATCH 04/11] =?UTF-8?q?feat:=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20API=20=EC=9D=91=EB=8B=B5=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/apis/createChatRoom.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/chat/apis/createChatRoom.ts b/src/chat/apis/createChatRoom.ts index f07a3ad..d82f06e 100644 --- a/src/chat/apis/createChatRoom.ts +++ b/src/chat/apis/createChatRoom.ts @@ -5,7 +5,7 @@ import { MessageSenderTypeSchema } from '../models/messageSender'; export type CreateChatRoomResponse = { roomId: number; - message: { + message?: { messageId: number; type: string; sender: string; @@ -15,12 +15,14 @@ export type CreateChatRoomResponse = { const schema = z.object({ roomId: z.number(), - message: z.object({ - messageId: z.number(), - type: z.literal(MessageCategorySchema.Enum.SYSTEM_NORMAL_REPLY), - sender: z.literal(MessageSenderTypeSchema.Enum.SYSTEM), - answer: z.array(z.string()), - }), + message: z + .object({ + messageId: z.number(), + type: z.literal(MessageCategorySchema.Enum.SYSTEM_NORMAL_REPLY), + sender: z.literal(MessageSenderTypeSchema.Enum.SYSTEM), + answer: z.array(z.string()), + }) + .optional(), }); type CreateChatRoomData = z.infer; @@ -36,6 +38,6 @@ export const createChatRoom = () => { .then((res) => validate(res.data)) .catch((error) => { console.error(error); - return undefined; + throw error; }); }; From af29994cc87b60a3a0aeb8dad92baba1084be833 Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Mon, 27 Jan 2025 22:47:58 +0900 Subject: [PATCH 05/11] =?UTF-8?q?feat:=20=EC=B6=94=EC=B2=9C=20=EC=A7=88?= =?UTF-8?q?=EB=AC=B8=20=EC=B9=B4=EB=93=9C=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/QuickQuestionPicker/index.tsx | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/chat/components/QuickQuestionPicker/index.tsx diff --git a/src/chat/components/QuickQuestionPicker/index.tsx b/src/chat/components/QuickQuestionPicker/index.tsx new file mode 100644 index 0000000..15160d5 --- /dev/null +++ b/src/chat/components/QuickQuestionPicker/index.tsx @@ -0,0 +1,70 @@ +import { ColorsTypes } from '@/shared/lib/styledComponents/theme'; +import { css, useTheme } from 'styled-components'; +type Props = { + question: string; + onClick: () => void; + selectedCount: number; + color: keyof Pick; +}; + +export default function QuickQuestionPicker({ question, onClick, selectedCount, color }: Props) { + const theme = useTheme(); + const formattedSelectedCount = selectedCount.toLocaleString(); + + const componentTheme = (() => { + switch (color) { + case 'primary03': + case 'grey60': + return { + backgroundColor: theme.colors[color], + titleColor: theme.colors.white, + captionColor: theme.colors.grey10, + }; + case 'primary01': + case 'grey10': + return { + backgroundColor: theme.colors[color], + titleColor: theme.colors.grey70, + captionColor: theme.colors.grey60, + }; + + default: + const _exhausted: never = color; + throw new Error(`처리되지 않은 색상 타입입니다. ${_exhausted}`); + } + })(); + + return ( + + ); +} From a0004415e2fa4942898b43fb1cc4f37980ed6a1c Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Mon, 27 Jan 2025 22:48:08 +0900 Subject: [PATCH 06/11] =?UTF-8?q?feat:=20=20=EC=B6=94=EC=B2=9C=20=EC=A7=88?= =?UTF-8?q?=EB=AC=B8=20=EC=B9=B4=EB=93=9C=20=EC=BB=A8=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=84=88=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../QuickQuestionPickerBox/index.tsx | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/chat/components/QuickQuestionPickerBox/index.tsx diff --git a/src/chat/components/QuickQuestionPickerBox/index.tsx b/src/chat/components/QuickQuestionPickerBox/index.tsx new file mode 100644 index 0000000..0cb2cbc --- /dev/null +++ b/src/chat/components/QuickQuestionPickerBox/index.tsx @@ -0,0 +1,77 @@ +import { createUserKeyCookie } from '@/auth/utils/createUserKeyCookie'; +import { useCreateChatRoom } from '@/chat/hooks/useCreateChatRoom'; +import { useSendChatMessage } from '@/chat/hooks/useSendChatMesasge'; +import { TarotQuestionRecommendListData } from '@/tarot/apis/getTarotQuestionRecommends'; +import { useTarotQuestionRecommends } from '@/tarot/hooks/useTarotQuestionRecommends'; +import { useRouter } from 'next/navigation'; +import { css } from 'styled-components'; +import QuickQuestionPicker from '../QuickQuestionPicker'; +import RefreshQuickQuestionButton from '../RefreshQuickQuestionButton'; + +export default function QuickQuestionPickerBox() { + const { data } = useTarotQuestionRecommends(); + const { mutate: createChatRoom } = useCreateChatRoom(); + const { mutateAsync: sendChatMessage } = useSendChatMessage(); + const router = useRouter(); + + if (!data) return null; + + const adaptQuestionRecommends = (data: TarotQuestionRecommendListData) => { + const colors = ['primary03', 'grey10', 'primary01', 'grey60'] as const; + return data.questions.map((question, i) => ({ + ...question, + color: colors[i], + onClick: async () => { + await createUserKeyCookie(); + createChatRoom(undefined, { + onSuccess: (data) => { + sendChatMessage( + { + roomId: data.roomId, + message: question.question, + intent: 'RECOMMEND_QUESTION', + referenceQuestionId: question.recommendQuestionId, + }, + { + onSuccess: () => { + router.push(`/chats/${data.roomId}`); + }, + } + ); + }, + }); + }, + })); + }; + + return ( +
+
+ {adaptQuestionRecommends(data).map((question) => ( + + ))} +
+
+ +
+
+ ); +} From 7e98822db12257a9f634191108f67d8329319a4e Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Mon, 27 Jan 2025 22:48:27 +0900 Subject: [PATCH 07/11] =?UTF-8?q?feat:=20=EC=9D=B8=EB=8D=B1=EC=8A=A4=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/page.tsx | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index f9e4e5b..e3f1c27 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,11 +1,31 @@ -import HeaderContent from '@/shared/components/HeaderContent'; +'use client'; + +import QuickQuestionPickerBox from '@/chat/components/QuickQuestionPickerBox'; import MainContent from '@/shared/components/MainContent'; +import { css } from 'styled-components'; export default function HomePage() { return ( <> - {null} - {null} + +

props.theme.fonts.headline2} + `} + > + AI 타로 술사, 타로냥에게 +
무엇이든 물어봐라냥 +

+
+ +
+
); } From 93e91909c2f8047f9ba98d42acc0757855507a71 Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Mon, 27 Jan 2025 23:27:40 +0900 Subject: [PATCH 08/11] =?UTF-8?q?feat:=20=EC=B1=84=ED=8C=85=20=EA=B0=9C?= =?UTF-8?q?=EC=9A=94=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/components/ChatOverview/index.tsx | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/chat/components/ChatOverview/index.tsx diff --git a/src/chat/components/ChatOverview/index.tsx b/src/chat/components/ChatOverview/index.tsx new file mode 100644 index 0000000..e82cfc3 --- /dev/null +++ b/src/chat/components/ChatOverview/index.tsx @@ -0,0 +1,29 @@ +'use client'; + +import QuickQuestionPickerBox from '@/chat/components/QuickQuestionPickerBox'; +import MainContent from '@/shared/components/MainContent'; +import { css } from 'styled-components'; + +export default function ChatOverview() { + return ( + +

props.theme.fonts.headline2} + `} + > + AI 타로 술사, 타로냥에게 +
무엇이든 물어봐라냥 +

+
+ +
+
+ ); +} From 133288ff77453261592ab34ce1a1d096f647f764 Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Mon, 27 Jan 2025 23:28:23 +0900 Subject: [PATCH 09/11] =?UTF-8?q?feat:=20=EC=B6=94=EC=B2=9C=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=ED=94=84=EB=A6=AC?= =?UTF-8?q?=ED=8E=98=EC=B9=98=20SSR=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/page.tsx | 39 +++++++------------ .../reactQuery/ReactQueryClientProvider.tsx | 25 +++++++++++- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index e3f1c27..fb1e950 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,31 +1,18 @@ -'use client'; +import ChatOverview from '@/chat/components/ChatOverview'; +import { getTarotQuestionRecommends } from '@/tarot/apis/getTarotQuestionRecommends'; +import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query'; -import QuickQuestionPickerBox from '@/chat/components/QuickQuestionPickerBox'; -import MainContent from '@/shared/components/MainContent'; -import { css } from 'styled-components'; +export default async function HomePage() { + const queryClient = new QueryClient(); + + await queryClient.prefetchQuery({ + queryKey: ['tarotQuestionRecommends'], + queryFn: getTarotQuestionRecommends, + }); -export default function HomePage() { return ( - <> - -

props.theme.fonts.headline2} - `} - > - AI 타로 술사, 타로냥에게 -
무엇이든 물어봐라냥 -

-
- -
-
- + + + ); } diff --git a/src/shared/lib/reactQuery/ReactQueryClientProvider.tsx b/src/shared/lib/reactQuery/ReactQueryClientProvider.tsx index 0111787..f47009c 100644 --- a/src/shared/lib/reactQuery/ReactQueryClientProvider.tsx +++ b/src/shared/lib/reactQuery/ReactQueryClientProvider.tsx @@ -1,10 +1,31 @@ 'use client'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { isServer, QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ReactNode } from 'react'; -const queryClient = new QueryClient(); +function makeQueryClient() { + return new QueryClient({ + defaultOptions: { + queries: { + staleTime: 60 * 1000, + }, + }, + }); +} + +let browserQueryClient: QueryClient | undefined = undefined; + +function getQueryClient() { + if (isServer) { + return makeQueryClient(); + } else { + if (!browserQueryClient) browserQueryClient = makeQueryClient(); + return browserQueryClient; + } +} export default function ReactQueryClientProvider({ children }: { children: ReactNode }) { + const queryClient = getQueryClient(); + return {children}; } From 6aaf17ae6f492c1f6a46e08dd313eb1c39c26221 Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Tue, 28 Jan 2025 00:06:02 +0900 Subject: [PATCH 10/11] =?UTF-8?q?feat:=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20API=20=EC=9D=91=EB=8B=B5=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/chat/apis/createChatRoom.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/chat/apis/createChatRoom.ts b/src/chat/apis/createChatRoom.ts index d82f06e..378c6ff 100644 --- a/src/chat/apis/createChatRoom.ts +++ b/src/chat/apis/createChatRoom.ts @@ -1,28 +1,12 @@ import apiClient from '@/shared/lib/axios/apiClient'; import { z } from 'zod'; -import { MessageCategorySchema } from '../models/messageCategory'; -import { MessageSenderTypeSchema } from '../models/messageSender'; export type CreateChatRoomResponse = { roomId: number; - message?: { - messageId: number; - type: string; - sender: string; - answer: string[]; - }; }; const schema = z.object({ roomId: z.number(), - message: z - .object({ - messageId: z.number(), - type: z.literal(MessageCategorySchema.Enum.SYSTEM_NORMAL_REPLY), - sender: z.literal(MessageSenderTypeSchema.Enum.SYSTEM), - answer: z.array(z.string()), - }) - .optional(), }); type CreateChatRoomData = z.infer; From 09220ba6893db0fbc02729c846c862edf69a513c Mon Sep 17 00:00:00 2001 From: Jay Lee Date: Tue, 28 Jan 2025 00:06:56 +0900 Subject: [PATCH 11/11] =?UTF-8?q?feat:=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20mock=20api=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/api/v1/chat/room/route.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/app/api/v1/chat/room/route.ts b/src/app/api/v1/chat/room/route.ts index cb6f246..10b4621 100644 --- a/src/app/api/v1/chat/room/route.ts +++ b/src/app/api/v1/chat/room/route.ts @@ -4,12 +4,6 @@ import { NextResponse } from 'next/server'; export async function POST() { const mockData: CreateChatRoomResponse = { roomId: 1, - message: { - messageId: 1, - type: 'SYSTEM_NORMAL', - sender: 'SYSTEM', - answer: ['안녕이다냥?'], - }, }; return NextResponse.json({ data: mockData });