From 4e502d4591240eb9c6664a5cecf2f8d3435a560a Mon Sep 17 00:00:00 2001 From: Park-min-hyoung Date: Sat, 1 Mar 2025 08:57:44 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=8B=9C=20=EC=9C=A0=EC=A0=80=20=EC=9D=B4=EB=A6=84,=20?= =?UTF-8?q?=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EB=B0=9B=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/auth/routes/GoogleCallback.tsx | 12 ++++++++++-- src/features/auth/routes/KakaoCallback.tsx | 12 ++++++++++-- src/features/reward/api/path.ts | 5 ++++- src/features/reward/api/reward.ts | 13 ++++++++++--- src/features/reward/types/index.ts | 5 +++++ src/stores/user.ts | 4 +++- 6 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 src/features/reward/types/index.ts diff --git a/src/features/auth/routes/GoogleCallback.tsx b/src/features/auth/routes/GoogleCallback.tsx index c0e932f..a7ff9c5 100644 --- a/src/features/auth/routes/GoogleCallback.tsx +++ b/src/features/auth/routes/GoogleCallback.tsx @@ -4,12 +4,15 @@ import { Spinner } from "@/components/ui/spinner"; import { useCallback, useEffect, useState } from "react"; import { postGoogleLogin } from "@/features/auth/api/auth"; +import { getPoint } from "@/features/reward/api/reward"; import { useNavigate, useSearchParams } from "react-router"; import { useAuthStore } from "@/stores/auth-store"; +import { useUserStore } from "@/stores/user"; import { paths } from "@/config/paths"; const GoogleCallback = (): JSX.Element | null => { + const { setUserName, setPoint } = useUserStore(); const [searchParams] = useSearchParams(); const navigate = useNavigate(); const setTokens = useAuthStore((state) => state.setTokens); @@ -25,9 +28,14 @@ const GoogleCallback = (): JSX.Element | null => { throw new Error("구글 인증에 실패했습니다."); } - const { accessToken, refreshToken } = response.data; + const { accessToken, refreshToken, username, socialId } = response.data; setTokens(accessToken, refreshToken); + setUserName(username); + + const { totalPoints } = await getPoint(socialId); + + setPoint(totalPoints); navigate(paths.home.path); } catch (error) { @@ -37,7 +45,7 @@ const GoogleCallback = (): JSX.Element | null => { setIsLoading(false); } }, - [navigate, setTokens] + [navigate, setTokens, setUserName, setPoint] ); useEffect(() => { diff --git a/src/features/auth/routes/KakaoCallback.tsx b/src/features/auth/routes/KakaoCallback.tsx index a45d336..64aa255 100644 --- a/src/features/auth/routes/KakaoCallback.tsx +++ b/src/features/auth/routes/KakaoCallback.tsx @@ -4,12 +4,15 @@ import { Spinner } from "@/components/ui/spinner"; import { useCallback, useEffect, useState } from "react"; import { postKakaoLogin } from "@/features/auth/api/auth"; +import { getPoint } from "@/features/reward/api/reward"; import { useNavigate, useSearchParams } from "react-router"; import { useAuthStore } from "@/stores/auth-store"; +import { useUserStore } from "@/stores/user"; import { paths } from "@/config/paths"; const KakaoCallback = (): JSX.Element | null => { + const { setUserName, setPoint } = useUserStore(); const [searchParams] = useSearchParams(); const navigate = useNavigate(); const setTokens = useAuthStore((state) => state.setTokens); @@ -27,9 +30,14 @@ const KakaoCallback = (): JSX.Element | null => { throw new Error("카카오 인증에 실패했습니다."); } - const { accessToken, refreshToken } = response.data; + const { accessToken, refreshToken, username, socialId } = response.data; setTokens(accessToken, refreshToken); + setUserName(username); + + const { totalPoints } = await getPoint(socialId); + + setPoint(totalPoints); navigate(paths.home.path); } catch (error) { @@ -39,7 +47,7 @@ const KakaoCallback = (): JSX.Element | null => { setIsLoading(false); } }, - [navigate, setTokens] + [navigate, setTokens, setUserName, setPoint] ); useEffect(() => { diff --git a/src/features/reward/api/path.ts b/src/features/reward/api/path.ts index e8b2618..2ac3a14 100644 --- a/src/features/reward/api/path.ts +++ b/src/features/reward/api/path.ts @@ -2,5 +2,8 @@ import { generatePathByBase, genreateBasePath } from "@/lib/axios/utils"; export const BASE_PATH = genreateBasePath("points", "v1"); -export const POINT_DEDUC = (socialId) => +export const POINTS = (socialId: string) => + generatePathByBase(BASE_PATH, socialId); + +export const POINT_DEDUC = (socialId: string) => generatePathByBase(BASE_PATH, socialId, "deduc"); diff --git a/src/features/reward/api/reward.ts b/src/features/reward/api/reward.ts index 93d9ef5..732b187 100644 --- a/src/features/reward/api/reward.ts +++ b/src/features/reward/api/reward.ts @@ -1,10 +1,17 @@ import type { R } from "@/types/common"; -import { POST } from "@/lib/axios"; +import { GET, POST } from "@/lib/axios"; import type { RoOnlyPathParamsType } from "@/lib/axios/utils"; -import { POINT_DEDUC } from "./path"; +import type { Point } from "../types"; +import { POINT_DEDUC, POINTS } from "./path"; export function postRewards({ pathParams: { socialId } -}: RoOnlyPathParamsType<{ socialId: number }>): R<{ point: number }> { +}: RoOnlyPathParamsType<{ socialId: string }>): R<{ point: number }> { return POST({ url: POINT_DEDUC(socialId) }); } + +export function getPoint({ + pathParams: { socialId } +}: RoOnlyPathParamsType<{ socialId: string }>): R { + return GET({ url: POINTS(socialId) }); +} diff --git a/src/features/reward/types/index.ts b/src/features/reward/types/index.ts new file mode 100644 index 0000000..88aefb7 --- /dev/null +++ b/src/features/reward/types/index.ts @@ -0,0 +1,5 @@ +export interface Point { + userId: number; + socialId: string; + totalPoints: number; +} diff --git a/src/stores/user.ts b/src/stores/user.ts index eaf2f56..0ae6c3d 100644 --- a/src/stores/user.ts +++ b/src/stores/user.ts @@ -4,10 +4,12 @@ interface UserState { userName: string; point: number; setPoint: (point: number) => void; + setUserName: (userName: string) => void; } export const useUserStore = create((set) => ({ userName: "park", point: 100000, - setPoint: (point) => set({ point }) + setPoint: (point) => set({ point }), + setUserName: (userName) => set({ userName }) })); From 2bb1d7749c24df465e77b301adbb6ff3f3064190 Mon Sep 17 00:00:00 2001 From: Park-min-hyoung Date: Sat, 1 Mar 2025 08:58:49 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=ED=86=A0=ED=81=B0=20=EB=A7=8C?= =?UTF-8?q?=EB=A3=8C=20=EC=8B=9C=20=EC=9C=A0=EC=A0=80=20=EC=9C=A0=EC=A0=80?= =?UTF-8?q?=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=83=88=EB=A1=9C=20=EB=B0=9B?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/axios/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib/axios/index.ts b/src/lib/axios/index.ts index 4b26dd6..57707b9 100644 --- a/src/lib/axios/index.ts +++ b/src/lib/axios/index.ts @@ -1,4 +1,5 @@ import { postRefreshAccessToken } from "@/features/auth/api/auth"; +import { getPoint } from "@/features/reward/api/reward"; import type { AxiosRequestConfig, AxiosResponse, @@ -10,6 +11,7 @@ import { get, isArray } from "es-toolkit/compat"; import { Nullable } from "@/types/common"; import { useAuthStore } from "@/stores/auth-store"; +import { useUserStore } from "@/stores/user"; import { ENDPOINT_URL, MEDIUM_REQUEST_TIMEOUT } from "@/config/envs"; import { paths } from "@/config/paths"; import { generateQueryParams } from "@/lib/axios/utils"; @@ -58,6 +60,10 @@ export const handleTokenExpiration = async ( axios.defaults.headers.common["Authorization"] = `Bearer ${response.data.accessToken}`; + + const { totalPoints } = await getPoint(response.data.socialId); + useUserStore.setState({ point: totalPoints }); + return axios.request(config); } catch (error) { window.location.href = paths.auth.login.path; From b8cb089c49abdded4c3402990002b911aa17fcf8 Mon Sep 17 00:00:00 2001 From: Park-min-hyoung Date: Sat, 1 Mar 2025 09:01:38 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20api=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=A0=84=EB=8B=AC=EC=9D=B8=EC=9E=90=20=ED=98=95=ED=83=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/auth/routes/GoogleCallback.tsx | 3 +-- src/features/auth/routes/KakaoCallback.tsx | 3 +-- src/lib/axios/index.ts | 4 +++- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/features/auth/routes/GoogleCallback.tsx b/src/features/auth/routes/GoogleCallback.tsx index a7ff9c5..2450a4c 100644 --- a/src/features/auth/routes/GoogleCallback.tsx +++ b/src/features/auth/routes/GoogleCallback.tsx @@ -33,8 +33,7 @@ const GoogleCallback = (): JSX.Element | null => { setTokens(accessToken, refreshToken); setUserName(username); - const { totalPoints } = await getPoint(socialId); - + const { totalPoints } = await getPoint({ pathParams: { socialId } }); setPoint(totalPoints); navigate(paths.home.path); diff --git a/src/features/auth/routes/KakaoCallback.tsx b/src/features/auth/routes/KakaoCallback.tsx index 64aa255..9a7d5bc 100644 --- a/src/features/auth/routes/KakaoCallback.tsx +++ b/src/features/auth/routes/KakaoCallback.tsx @@ -35,8 +35,7 @@ const KakaoCallback = (): JSX.Element | null => { setTokens(accessToken, refreshToken); setUserName(username); - const { totalPoints } = await getPoint(socialId); - + const { totalPoints } = await getPoint({ pathParams: { socialId } }); setPoint(totalPoints); navigate(paths.home.path); diff --git a/src/lib/axios/index.ts b/src/lib/axios/index.ts index 57707b9..fec1c0c 100644 --- a/src/lib/axios/index.ts +++ b/src/lib/axios/index.ts @@ -61,7 +61,9 @@ export const handleTokenExpiration = async ( axios.defaults.headers.common["Authorization"] = `Bearer ${response.data.accessToken}`; - const { totalPoints } = await getPoint(response.data.socialId); + const { totalPoints } = await getPoint({ + pathParams: { socialId: response.data.socialId } + }); useUserStore.setState({ point: totalPoints }); return axios.request(config); From 129bfa065c2eeae6699c976d1f6dbbad04d4d124 Mon Sep 17 00:00:00 2001 From: Park-min-hyoung Date: Sat, 1 Mar 2025 18:43:59 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=ED=83=80=EC=9E=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/reward/api/path.ts | 4 ++-- src/features/reward/api/reward.ts | 6 +++--- src/features/reward/components/reward.tsx | 4 ++-- src/lib/react-query/queryOptions/reward.ts | 6 +++--- src/stores/user.ts | 2 ++ src/testing/mocks/handlers/browser.ts | 2 +- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/features/reward/api/path.ts b/src/features/reward/api/path.ts index 2ac3a14..314c948 100644 --- a/src/features/reward/api/path.ts +++ b/src/features/reward/api/path.ts @@ -5,5 +5,5 @@ export const BASE_PATH = genreateBasePath("points", "v1"); export const POINTS = (socialId: string) => generatePathByBase(BASE_PATH, socialId); -export const POINT_DEDUC = (socialId: string) => - generatePathByBase(BASE_PATH, socialId, "deduc"); +export const POINT_DEDUC = (userId: string) => + generatePathByBase(BASE_PATH, userId, "deduc"); diff --git a/src/features/reward/api/reward.ts b/src/features/reward/api/reward.ts index 732b187..beaae33 100644 --- a/src/features/reward/api/reward.ts +++ b/src/features/reward/api/reward.ts @@ -5,9 +5,9 @@ import type { Point } from "../types"; import { POINT_DEDUC, POINTS } from "./path"; export function postRewards({ - pathParams: { socialId } -}: RoOnlyPathParamsType<{ socialId: string }>): R<{ point: number }> { - return POST({ url: POINT_DEDUC(socialId) }); + pathParams: { userId } +}: RoOnlyPathParamsType<{ userId: string }>): R<{ point: number }> { + return POST({ url: POINT_DEDUC(userId) }); } export function getPoint({ diff --git a/src/features/reward/components/reward.tsx b/src/features/reward/components/reward.tsx index 88963cc..c6c7b63 100644 --- a/src/features/reward/components/reward.tsx +++ b/src/features/reward/components/reward.tsx @@ -10,10 +10,10 @@ import { generateCoupons } from "./index.const"; import SuccessToast from "./success-toast"; export default function Reward() { - const { point, setPoint } = useUserStore(); + const { point, setPoint, userId } = useUserStore(); const { mutate, isPending } = useMutation({ - ...generate_qo_postRewards(1), + ...generate_qo_postRewards(userId), onSuccess: (data) => { setPoint(data.point); toast(, { diff --git a/src/lib/react-query/queryOptions/reward.ts b/src/lib/react-query/queryOptions/reward.ts index 5c9b23c..f2e6bf7 100644 --- a/src/lib/react-query/queryOptions/reward.ts +++ b/src/lib/react-query/queryOptions/reward.ts @@ -4,9 +4,9 @@ import { AxiosError } from "axios"; interface UseMutationRewardsOptions extends UseMutationOptions<{ point: number }, AxiosError, void, unknown> {} -type GenerateQoPostRewards = (id: number) => UseMutationRewardsOptions; -export const generate_qo_postRewards: GenerateQoPostRewards = (socialId) => { +type GenerateQoPostRewards = (userId: string) => UseMutationRewardsOptions; +export const generate_qo_postRewards: GenerateQoPostRewards = (userId) => { return { - mutationFn: () => postRewards({ pathParams: { socialId } }) + mutationFn: () => postRewards({ pathParams: { userId } }) }; }; diff --git a/src/stores/user.ts b/src/stores/user.ts index 0ae6c3d..4522342 100644 --- a/src/stores/user.ts +++ b/src/stores/user.ts @@ -3,6 +3,7 @@ import { create } from "zustand"; interface UserState { userName: string; point: number; + userId: string; setPoint: (point: number) => void; setUserName: (userName: string) => void; } @@ -10,6 +11,7 @@ interface UserState { export const useUserStore = create((set) => ({ userName: "park", point: 100000, + userId: "0", setPoint: (point) => set({ point }), setUserName: (userName) => set({ userName }) })); diff --git a/src/testing/mocks/handlers/browser.ts b/src/testing/mocks/handlers/browser.ts index a9fe237..a23c13e 100644 --- a/src/testing/mocks/handlers/browser.ts +++ b/src/testing/mocks/handlers/browser.ts @@ -31,7 +31,7 @@ export const handlers = [ return HttpResponse.json({ message: "success" }); }), - http.post(`${ENDPOINT_URL}${POINT_DEDUC(1)}`, async () => { + http.post(`${ENDPOINT_URL}${POINT_DEDUC("1")}`, async () => { await delay(500); return HttpResponse.json({ point: 10000 }); From bc69573860b8577c38ce8b5e0064cdb4202ee737 Mon Sep 17 00:00:00 2001 From: Park-min-hyoung Date: Sun, 2 Mar 2025 11:02:34 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20api=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/reward/api/path.ts | 3 +-- src/features/reward/api/reward.ts | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/features/reward/api/path.ts b/src/features/reward/api/path.ts index 314c948..487cbeb 100644 --- a/src/features/reward/api/path.ts +++ b/src/features/reward/api/path.ts @@ -2,8 +2,7 @@ import { generatePathByBase, genreateBasePath } from "@/lib/axios/utils"; export const BASE_PATH = genreateBasePath("points", "v1"); -export const POINTS = (socialId: string) => - generatePathByBase(BASE_PATH, socialId); +export const POINTS = (userId: string) => generatePathByBase(BASE_PATH, userId); export const POINT_DEDUC = (userId: string) => generatePathByBase(BASE_PATH, userId, "deduc"); diff --git a/src/features/reward/api/reward.ts b/src/features/reward/api/reward.ts index beaae33..492af7b 100644 --- a/src/features/reward/api/reward.ts +++ b/src/features/reward/api/reward.ts @@ -11,7 +11,7 @@ export function postRewards({ } export function getPoint({ - pathParams: { socialId } -}: RoOnlyPathParamsType<{ socialId: string }>): R { - return GET({ url: POINTS(socialId) }); + pathParams: { userId } +}: RoOnlyPathParamsType<{ userId: string }>): R { + return GET({ url: POINTS(userId) }); } From 0419c94466b4c1bc63a671498f35f3f160ef39ab Mon Sep 17 00:00:00 2001 From: Park-min-hyoung Date: Sun, 2 Mar 2025 11:05:54 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20type=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/axios/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/axios/index.ts b/src/lib/axios/index.ts index 2be2279..f7f0857 100644 --- a/src/lib/axios/index.ts +++ b/src/lib/axios/index.ts @@ -62,7 +62,7 @@ export const handleTokenExpiration = async ( `Bearer ${response.data.accessToken}`; const { totalPoints } = await getPoint({ - pathParams: { socialId: response.data.socialId } + pathParams: { userId: response.data.userId } }); useUserStore.setState({ point: totalPoints });