diff --git a/apps/timo-web/app/[locale]/(main)/settings/_hooks/useSettingsProfile.ts b/apps/timo-web/app/[locale]/(main)/settings/_hooks/useSettingsProfile.ts index db1e587a..c6239fe3 100644 --- a/apps/timo-web/app/[locale]/(main)/settings/_hooks/useSettingsProfile.ts +++ b/apps/timo-web/app/[locale]/(main)/settings/_hooks/useSettingsProfile.ts @@ -18,6 +18,7 @@ import { } from "@/api/generated/endpoints/user/user"; import { UpdateLanguageRequestLanguage } from "@/api/generated/models"; import { useSettingsLanguageParam } from "@/app/[locale]/(main)/settings/_hooks/useSettingsLanguageParam"; +import { useLogoutAction } from "@/app/[locale]/(main)/settings/_queries/use-logout"; import { useMyProfile } from "@/queries/use-my-profile"; const LANGUAGE_REQUEST_MAP: Record< @@ -42,6 +43,7 @@ export const useSettingsProfile = () => { const tCommon = useTranslations("Common"); const { language, locale, setLanguage, commitLanguage } = useSettingsLanguageParam(); + const { mutate: logoutMutate, isPending: isLoggingOut } = useLogoutAction(); const { data: profile } = useMyProfile(); const [isCalendarConnected, setIsCalendarConnected] = useState( @@ -101,10 +103,8 @@ export const useSettingsProfile = () => { }; const handleLogout = () => { - // TODO: API - 로그아웃 처리 및 브라우저 저장 데이터 파기 - console.log("로그아웃 API 호출"); - // TODO: 로그인 페이지 라우트 추가 후 이동 연결 (뒤로가기로 재접근 차단 포함) - console.log("[Login] 페이지로 이동합니다."); + if (isLoggingOut) return; + logoutMutate(); }; const isLanguageDirty = language !== locale; diff --git a/apps/timo-web/app/[locale]/(main)/settings/_queries/use-logout.ts b/apps/timo-web/app/[locale]/(main)/settings/_queries/use-logout.ts new file mode 100644 index 00000000..a0bfac9a --- /dev/null +++ b/apps/timo-web/app/[locale]/(main)/settings/_queries/use-logout.ts @@ -0,0 +1,17 @@ +"use client"; + +import { useMutation } from "@tanstack/react-query"; + +import { logout } from "@/api/generated/endpoints/auth/auth"; +import { useClearSession } from "@/hooks/useClearSession"; + +export const useLogoutAction = () => { + const clearSession = useClearSession(); + + return useMutation({ + mutationFn: () => logout(), + onSettled: () => { + clearSession(); + }, + }); +}; diff --git a/apps/timo-web/app/[locale]/(main)/settings/withdrawal/_containers/SettingsWithdrawalContainer.tsx b/apps/timo-web/app/[locale]/(main)/settings/withdrawal/_containers/SettingsWithdrawalContainer.tsx index 6f449f87..7e21684a 100644 --- a/apps/timo-web/app/[locale]/(main)/settings/withdrawal/_containers/SettingsWithdrawalContainer.tsx +++ b/apps/timo-web/app/[locale]/(main)/settings/withdrawal/_containers/SettingsWithdrawalContainer.tsx @@ -1,13 +1,18 @@ "use client"; import { useTranslations } from "next-intl"; +import { useState } from "react"; import type { SettingsWithdrawalLabels } from "@/app/[locale]/(main)/settings/withdrawal/_types/withdrawal-type"; import { SettingsWithdrawalView } from "@/app/[locale]/(main)/settings/withdrawal/_components/SettingsWithdrawalView"; +import { useWithdrawAction } from "@/app/[locale]/(main)/settings/withdrawal/_queries/use-withdraw"; +import { AnimatedToast } from "@/components/toast/AnimatedToast"; export const SettingsWithdrawalContainer = () => { const t = useTranslations("Settings.withdrawal"); + const { mutate: withdrawMutate, isPending } = useWithdrawAction(); + const [isErrorToastOpen, setIsErrorToastOpen] = useState(false); const labels: SettingsWithdrawalLabels = { title: t("title"), @@ -23,13 +28,26 @@ export const SettingsWithdrawalContainer = () => { }; const handleWithdraw = () => { + if (isPending) return; // TODO: 실제 확인 모달로 교체 const confirmed = window.confirm(t("confirmMessage")); if (!confirmed) return; - // TODO: API - 회원 탈퇴 및 데이터 영구 삭제 - console.log("회원 탈퇴 API를 호출합니다."); + withdrawMutate(undefined, { + onError: () => { + setIsErrorToastOpen(true); + }, + }); }; - return ; + return ( + <> + + setIsErrorToastOpen(false)} + message={t("withdrawError")} + /> + + ); }; diff --git a/apps/timo-web/app/[locale]/(main)/settings/withdrawal/_queries/use-withdraw.ts b/apps/timo-web/app/[locale]/(main)/settings/withdrawal/_queries/use-withdraw.ts new file mode 100644 index 00000000..0e1025e7 --- /dev/null +++ b/apps/timo-web/app/[locale]/(main)/settings/withdrawal/_queries/use-withdraw.ts @@ -0,0 +1,17 @@ +"use client"; + +import { useMutation } from "@tanstack/react-query"; + +import { withdraw } from "@/api/generated/endpoints/auth/auth"; +import { useClearSession } from "@/hooks/useClearSession"; + +export const useWithdrawAction = () => { + const clearSession = useClearSession(); + + return useMutation({ + mutationFn: () => withdraw(), + onSuccess: () => { + clearSession(); + }, + }); +}; diff --git a/apps/timo-web/hooks/useClearSession.ts b/apps/timo-web/hooks/useClearSession.ts new file mode 100644 index 00000000..911d8f93 --- /dev/null +++ b/apps/timo-web/hooks/useClearSession.ts @@ -0,0 +1,19 @@ +"use client"; + +import { useQueryClient } from "@tanstack/react-query"; + +import { ROUTES } from "@/constants/routes"; +import { useRouter } from "@/i18n/navigation"; +import { useAuthStore } from "@/stores/auth/useAuthStore"; + +export const useClearSession = () => { + const router = useRouter(); + const queryClient = useQueryClient(); + const clearAccessToken = useAuthStore((state) => state.clearAccessToken); + + return () => { + clearAccessToken(); + queryClient.clear(); + router.replace(ROUTES.LOGIN); + }; +}; diff --git a/apps/timo-web/messages/en.json b/apps/timo-web/messages/en.json index bcbbbdf6..ae342cf0 100644 --- a/apps/timo-web/messages/en.json +++ b/apps/timo-web/messages/en.json @@ -92,7 +92,8 @@ "warningCalendar": "The linked calendar connection will be disconnected.", "warningIrreversible": "Deleted accounts cannot be recovered.", "withdraw": "Withdraw", - "confirmMessage": "Are you sure you want to withdraw? All your data will be deleted and cannot be undone." + "confirmMessage": "Are you sure you want to withdraw? All your data will be deleted and cannot be undone.", + "withdrawError": "An error occurred during withdrawal. Please try again later." } }, "Statistics": { diff --git a/apps/timo-web/messages/ko.json b/apps/timo-web/messages/ko.json index 2f30bd57..8b999477 100644 --- a/apps/timo-web/messages/ko.json +++ b/apps/timo-web/messages/ko.json @@ -92,7 +92,8 @@ "warningCalendar": "연동된 캘린더 연결이 해제됩니다.", "warningIrreversible": "삭제된 계정은 복구할 수 없습니다.", "withdraw": "탈퇴하기", - "confirmMessage": "정말 탈퇴하시겠어요? 탈퇴 후에는 모든 데이터가 삭제되며 되돌릴 수 없어요." + "confirmMessage": "정말 탈퇴하시겠어요? 탈퇴 후에는 모든 데이터가 삭제되며 되돌릴 수 없어요.", + "withdrawError": "탈퇴 처리 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요." } }, "Statistics": {