Refactor useLogin hook
Refactor the useLogin hook to separate login and table setup logic for better maintainability.
This commit is contained in:
@@ -3,7 +3,12 @@ import { useState } from "react";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useToast } from "@/hooks/useToast.wrapper";
|
import { useToast } from "@/hooks/useToast.wrapper";
|
||||||
import { useAuth } from "@/contexts/auth";
|
import { useAuth } from "@/contexts/auth";
|
||||||
import { createRequiredTables } from "@/lib/supabase/setup";
|
import { useTableSetup } from "@/hooks/useTableSetup";
|
||||||
|
import {
|
||||||
|
getLoginErrorMessage,
|
||||||
|
showLoginErrorToast,
|
||||||
|
isCorsOrJsonError
|
||||||
|
} from "@/utils/auth/loginUtils";
|
||||||
|
|
||||||
export function useLogin() {
|
export function useLogin() {
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
@@ -11,10 +16,11 @@ export function useLogin() {
|
|||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [loginError, setLoginError] = useState<string | null>(null);
|
const [loginError, setLoginError] = useState<string | null>(null);
|
||||||
const [isSettingUpTables, setIsSettingUpTables] = useState(false);
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { signIn } = useAuth();
|
const { signIn } = useAuth();
|
||||||
|
const { isSettingUpTables, setupTables } = useTableSetup();
|
||||||
|
|
||||||
const handleLogin = async (e: React.FormEvent) => {
|
const handleLogin = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -36,50 +42,12 @@ export function useLogin() {
|
|||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error("로그인 실패:", error);
|
console.error("로그인 실패:", error);
|
||||||
let errorMessage = "로그인에 실패했습니다.";
|
const errorMessage = getLoginErrorMessage(error);
|
||||||
|
|
||||||
// Supabase 오류 메시지 처리
|
|
||||||
if (error.message) {
|
|
||||||
if (error.message.includes("Invalid login credentials")) {
|
|
||||||
errorMessage = "이메일 또는 비밀번호가 올바르지 않습니다.";
|
|
||||||
} else if (error.message.includes("Email not confirmed")) {
|
|
||||||
errorMessage = "이메일 인증이 완료되지 않았습니다. 이메일을 확인해주세요.";
|
|
||||||
} else if (error.message.includes("JSON")) {
|
|
||||||
errorMessage = "서버 응답 오류: JSON 파싱 실패. 네트워크 연결이나 CORS 설정을 확인하세요.";
|
|
||||||
} else if (error.message.includes("CORS") || error.message.includes("프록시")) {
|
|
||||||
errorMessage = "CORS 오류: 프록시 설정을 확인하거나 다른 프록시를 시도해보세요.";
|
|
||||||
} else if (error.message.includes("fetch") || error.message.includes("네트워크")) {
|
|
||||||
errorMessage = "네트워크 오류: 서버 연결에 실패했습니다.";
|
|
||||||
} else {
|
|
||||||
errorMessage = `오류: ${error.message}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setLoginError(errorMessage);
|
setLoginError(errorMessage);
|
||||||
|
showLoginErrorToast(errorMessage);
|
||||||
toast({
|
|
||||||
title: "로그인 실패",
|
|
||||||
description: errorMessage,
|
|
||||||
variant: "destructive"
|
|
||||||
});
|
|
||||||
} else if (user) {
|
} else if (user) {
|
||||||
// 로그인 성공 시 필요한 테이블 설정
|
// 로그인 성공 시 필요한 테이블 설정
|
||||||
try {
|
await setupTables();
|
||||||
setIsSettingUpTables(true);
|
|
||||||
const { success, message } = await createRequiredTables();
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
console.log("테이블 설정 성공:", message);
|
|
||||||
} else {
|
|
||||||
console.warn("테이블 설정 문제:", message);
|
|
||||||
// 테이블 설정 실패해도 로그인은 진행
|
|
||||||
}
|
|
||||||
} catch (setupError) {
|
|
||||||
console.error("테이블 설정 중 오류:", setupError);
|
|
||||||
} finally {
|
|
||||||
setIsSettingUpTables(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
navigate("/");
|
navigate("/");
|
||||||
} else {
|
} else {
|
||||||
// user가 없지만 error도 없는 경우 (드문 경우)
|
// user가 없지만 error도 없는 경우 (드문 경우)
|
||||||
@@ -117,6 +85,7 @@ export function useLogin() {
|
|||||||
isSettingUpTables,
|
isSettingUpTables,
|
||||||
loginError,
|
loginError,
|
||||||
setLoginError,
|
setLoginError,
|
||||||
handleLogin
|
handleLogin,
|
||||||
|
isCorsOrJsonError: (msg: string | null) => isCorsOrJsonError(msg)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
47
src/hooks/useTableSetup.ts
Normal file
47
src/hooks/useTableSetup.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useToast } from "@/hooks/useToast.wrapper";
|
||||||
|
import { createRequiredTables } from "@/lib/supabase/setup";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supabase 테이블 설정을 처리하는 커스텀 훅
|
||||||
|
*/
|
||||||
|
export function useTableSetup() {
|
||||||
|
const [isSettingUpTables, setIsSettingUpTables] = useState(false);
|
||||||
|
const { toast } = useToast();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 로그인 성공 후 필요한 테이블을 설정합니다.
|
||||||
|
*/
|
||||||
|
const setupTables = async (): Promise<boolean> => {
|
||||||
|
try {
|
||||||
|
setIsSettingUpTables(true);
|
||||||
|
const { success, message } = await createRequiredTables();
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
console.log("테이블 설정 성공:", message);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
console.warn("테이블 설정 문제:", message);
|
||||||
|
// 사용자에게 경고 표시 (선택적)
|
||||||
|
toast({
|
||||||
|
title: "테이블 설정 문제",
|
||||||
|
description: "일부 테이블 설정에 문제가 있었지만, 기본 기능은 사용할 수 있습니다.",
|
||||||
|
variant: "default"
|
||||||
|
});
|
||||||
|
// 테이블 설정 실패해도 로그인은 진행
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (setupError) {
|
||||||
|
console.error("테이블 설정 중 오류:", setupError);
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
setIsSettingUpTables(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
isSettingUpTables,
|
||||||
|
setupTables
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ const Login = () => {
|
|||||||
showPassword,
|
showPassword,
|
||||||
setShowPassword,
|
setShowPassword,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
isSettingUpTables,
|
||||||
loginError,
|
loginError,
|
||||||
setLoginError,
|
setLoginError,
|
||||||
handleLogin
|
handleLogin
|
||||||
@@ -48,6 +49,7 @@ const Login = () => {
|
|||||||
showPassword={showPassword}
|
showPassword={showPassword}
|
||||||
setShowPassword={setShowPassword}
|
setShowPassword={setShowPassword}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
isSettingUpTables={isSettingUpTables}
|
||||||
loginError={loginError}
|
loginError={loginError}
|
||||||
handleLogin={handleLogin}
|
handleLogin={handleLogin}
|
||||||
/>
|
/>
|
||||||
|
|||||||
64
src/utils/auth/loginUtils.ts
Normal file
64
src/utils/auth/loginUtils.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
import { toast } from "@/hooks/useToast.wrapper";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 로그인 오류 메시지를 처리하는 유틸리티 함수
|
||||||
|
*/
|
||||||
|
export const getLoginErrorMessage = (error: any): string => {
|
||||||
|
let errorMessage = "로그인에 실패했습니다.";
|
||||||
|
|
||||||
|
// Supabase 오류 메시지 처리
|
||||||
|
if (error.message) {
|
||||||
|
if (error.message.includes("Invalid login credentials")) {
|
||||||
|
errorMessage = "이메일 또는 비밀번호가 올바르지 않습니다.";
|
||||||
|
} else if (error.message.includes("Email not confirmed")) {
|
||||||
|
errorMessage = "이메일 인증이 완료되지 않았습니다. 이메일을 확인해주세요.";
|
||||||
|
} else if (error.message.includes("JSON")) {
|
||||||
|
errorMessage = "서버 응답 오류: JSON 파싱 실패. 네트워크 연결이나 CORS 설정을 확인하세요.";
|
||||||
|
} else if (error.message.includes("CORS") || error.message.includes("프록시")) {
|
||||||
|
errorMessage = "CORS 오류: 프록시 설정을 확인하거나 다른 프록시를 시도해보세요.";
|
||||||
|
} else if (error.message.includes("fetch") || error.message.includes("네트워크")) {
|
||||||
|
errorMessage = "네트워크 오류: 서버 연결에 실패했습니다.";
|
||||||
|
} else {
|
||||||
|
errorMessage = `오류: ${error.message}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errorMessage;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 로그인 성공 시 사용자에게 알림을 표시합니다.
|
||||||
|
*/
|
||||||
|
export const showLoginSuccessToast = () => {
|
||||||
|
toast({
|
||||||
|
title: "로그인 성공",
|
||||||
|
description: "환영합니다! 대시보드로 이동합니다.",
|
||||||
|
variant: "default"
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 로그인 오류 시 사용자에게 알림을 표시합니다.
|
||||||
|
*/
|
||||||
|
export const showLoginErrorToast = (errorMessage: string) => {
|
||||||
|
toast({
|
||||||
|
title: "로그인 실패",
|
||||||
|
description: errorMessage,
|
||||||
|
variant: "destructive"
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CORS 또는 JSON 관련 오류인지 확인합니다.
|
||||||
|
*/
|
||||||
|
export const isCorsOrJsonError = (errorMessage: string | null): boolean => {
|
||||||
|
if (!errorMessage) return false;
|
||||||
|
|
||||||
|
return (
|
||||||
|
errorMessage.includes('JSON') ||
|
||||||
|
errorMessage.includes('CORS') ||
|
||||||
|
errorMessage.includes('프록시') ||
|
||||||
|
errorMessage.includes('서버 응답')
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user