Skip to content

Commit 78487c6

Browse files
committed
feat: 소셜 로그인 실패 시 실패 사유가 노출되도록 수정
1 parent 07da51d commit 78487c6

2 files changed

Lines changed: 62 additions & 2 deletions

File tree

apps/pyconkr-2025/src/components/pages/sign_in.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { DevSetCookieButton } from "@frontend/common/components";
22
import { useBackendContext } from "@frontend/common/hooks/useAPI";
33
import { useShopClient, useSignInWithSNSMutation, useUserStatus } from "@frontend/shop/hooks";
44
import { AccountCircleOutlined, Google } from "@mui/icons-material";
5-
import { Backdrop, Button, ButtonProps, CircularProgress, Stack, Typography } from "@mui/material";
5+
import { Alert, Backdrop, Button, ButtonProps, CircularProgress, Stack, Typography, alpha } from "@mui/material";
66
import { Suspense } from "@suspensive/react";
77
import { enqueueSnackbar, OptionsObject } from "notistack";
88
import { FC, ReactNode, useEffect, useState } from "react";
@@ -15,10 +15,16 @@ type PageeStateType = {
1515
openBackdrop: boolean;
1616
};
1717

18+
type OAuthErrorType = {
19+
error: string;
20+
errorProcess: string | null;
21+
};
22+
1823
export const ShopSignInPage: FC = Suspense.with({ fallback: <CircularProgress /> }, () => {
1924
const { setAppContext, language } = useAppContext();
2025
const { backendApiAbsoluteDomain, backendApiSessionCookieName } = useBackendContext();
2126
const [state, setState] = useState<PageeStateType>({ openBackdrop: false });
27+
const [oauthError, setOauthError] = useState<OAuthErrorType | null>(null);
2228
const navigate = useNavigate();
2329
const shopAPIClient = useShopClient();
2430
const SignInMutation = useSignInWithSNSMutation(shopAPIClient);
@@ -30,6 +36,7 @@ export const ShopSignInPage: FC = Suspense.with({ fallback: <CircularProgress />
3036
enqueueSnackbar(c, { variant, anchorOrigin: { vertical: "bottom", horizontal: "center" } });
3137

3238
const triggerSignIn = (provider: "google" | "kakao" | "naver") => {
39+
setOauthError(null);
3340
setState((ps) => ({ ...ps, openBackdrop: true }));
3441
SignInMutation.mutate({ provider, callback_url: window.location.origin });
3542
};
@@ -42,6 +49,17 @@ export const ShopSignInPage: FC = Suspense.with({ fallback: <CircularProgress />
4249
const signInWithKakaoStr = language === "ko" ? "카카오로 로그인" : "Sign In with Kakao";
4350
const signInWithNaverStr = language === "ko" ? "네이버로 로그인" : "Sign In with Naver";
4451

52+
useEffect(() => {
53+
const params = new URLSearchParams(window.location.search);
54+
const error = params.get("error");
55+
if (!error) return;
56+
setOauthError({ error, errorProcess: params.get("error_process") });
57+
params.delete("error");
58+
params.delete("error_process");
59+
const clean = window.location.pathname + (params.toString() ? `?${params.toString()}` : "");
60+
window.history.replaceState({}, "", clean);
61+
}, []);
62+
4563
useEffect(() => {
4664
if (data && data.meta.is_authenticated) {
4765
addSnackbar(
@@ -95,6 +113,18 @@ export const ShopSignInPage: FC = Suspense.with({ fallback: <CircularProgress />
95113
<PageLayout spacing={6}>
96114
<Typography variant="h4" sx={{ textAlign: "center", fontWeight: "bolder" }} children={signInTitleStr} />
97115
<Stack spacing={1} sx={{ width: "100%", maxWidth: "400px" }}>
116+
{oauthError && (
117+
<Alert
118+
severity="error"
119+
variant="outlined"
120+
onClose={() => setOauthError(null)}
121+
sx={{ backgroundColor: (theme) => alpha(theme.palette.error.main, 0.08) }}
122+
>
123+
{language === "ko"
124+
? `소셜 로그인이 실패했습니다: ${oauthError.error}${oauthError.errorProcess ? ` (${oauthError.errorProcess})` : ""}`
125+
: `Social login failed: ${oauthError.error}${oauthError.errorProcess ? ` (${oauthError.errorProcess})` : ""}`}
126+
</Alert>
127+
)}
98128
{import.meta.env.DEV && (
99129
<DevSetCookieButton
100130
backendDomain={backendApiAbsoluteDomain ?? ""}

apps/pyconkr-2026/src/components/pages/sign_in.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { DevSetCookieButton } from "@frontend/common/components";
22
import { useBackendContext } from "@frontend/common/hooks/useAPI";
33
import { useShopClient, useSignInWithSNSMutation, useUserStatus } from "@frontend/shop/hooks";
44
import { AccountCircleOutlined, Google } from "@mui/icons-material";
5-
import { Backdrop, Button, ButtonProps, CircularProgress, Stack, Typography } from "@mui/material";
5+
import { Alert, Backdrop, Button, ButtonProps, CircularProgress, Stack, Typography, alpha } from "@mui/material";
66
import { Suspense } from "@suspensive/react";
77
import { enqueueSnackbar, OptionsObject } from "notistack";
88
import { FC, ReactNode, useEffect, useState } from "react";
@@ -15,10 +15,16 @@ type PageeStateType = {
1515
openBackdrop: boolean;
1616
};
1717

18+
type OAuthErrorType = {
19+
error: string;
20+
errorProcess: string | null;
21+
};
22+
1823
export const ShopSignInPage: FC = Suspense.with({ fallback: <CircularProgress /> }, () => {
1924
const { setAppContext, language } = useAppContext();
2025
const { backendApiAbsoluteDomain, backendApiSessionCookieName } = useBackendContext();
2126
const [state, setState] = useState<PageeStateType>({ openBackdrop: false });
27+
const [oauthError, setOauthError] = useState<OAuthErrorType | null>(null);
2228
const navigate = useNavigate();
2329
const shopAPIClient = useShopClient();
2430
const SignInMutation = useSignInWithSNSMutation(shopAPIClient);
@@ -30,6 +36,7 @@ export const ShopSignInPage: FC = Suspense.with({ fallback: <CircularProgress />
3036
enqueueSnackbar(c, { variant, anchorOrigin: { vertical: "bottom", horizontal: "center" } });
3137

3238
const triggerSignIn = (provider: "google" | "kakao" | "naver") => {
39+
setOauthError(null);
3340
setState((ps) => ({ ...ps, openBackdrop: true }));
3441
SignInMutation.mutate({ provider, callback_url: window.location.origin });
3542
};
@@ -42,6 +49,17 @@ export const ShopSignInPage: FC = Suspense.with({ fallback: <CircularProgress />
4249
const signInWithKakaoStr = language === "ko" ? "카카오로 로그인" : "Sign In with Kakao";
4350
const signInWithNaverStr = language === "ko" ? "네이버로 로그인" : "Sign In with Naver";
4451

52+
useEffect(() => {
53+
const params = new URLSearchParams(window.location.search);
54+
const error = params.get("error");
55+
if (!error) return;
56+
setOauthError({ error, errorProcess: params.get("error_process") });
57+
params.delete("error");
58+
params.delete("error_process");
59+
const clean = window.location.pathname + (params.toString() ? `?${params.toString()}` : "");
60+
window.history.replaceState({}, "", clean);
61+
}, []);
62+
4563
useEffect(() => {
4664
if (data && data.meta.is_authenticated) {
4765
addSnackbar(
@@ -95,6 +113,18 @@ export const ShopSignInPage: FC = Suspense.with({ fallback: <CircularProgress />
95113
<PageLayout spacing={6}>
96114
<Typography variant="h4" sx={{ textAlign: "center", fontWeight: "bolder" }} children={signInTitleStr} />
97115
<Stack spacing={1} sx={{ width: "100%", maxWidth: "400px" }}>
116+
{oauthError && (
117+
<Alert
118+
severity="error"
119+
variant="outlined"
120+
onClose={() => setOauthError(null)}
121+
sx={{ backgroundColor: (theme) => alpha(theme.palette.error.main, 0.08) }}
122+
>
123+
{language === "ko"
124+
? `소셜 로그인이 실패했습니다: ${oauthError.error}${oauthError.errorProcess ? ` (${oauthError.errorProcess})` : ""}`
125+
: `Social login failed: ${oauthError.error}${oauthError.errorProcess ? ` (${oauthError.errorProcess})` : ""}`}
126+
</Alert>
127+
)}
98128
{import.meta.env.DEV && (
99129
<DevSetCookieButton
100130
backendDomain={backendApiAbsoluteDomain ?? ""}

0 commit comments

Comments
 (0)