139 lines
4.0 KiB
TypeScript
139 lines
4.0 KiB
TypeScript
|
|
import { useState, useEffect } from "react";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { useToast } from "@/hooks/useToast.wrapper";
|
|
import { useAuth } from "@/contexts/auth";
|
|
import { useTableSetup } from "@/hooks/useTableSetup";
|
|
import {
|
|
getLoginErrorMessage,
|
|
showLoginErrorToast,
|
|
showLoginSuccessToast,
|
|
isCorsOrJsonError
|
|
} from "@/utils/auth/loginUtils";
|
|
|
|
export function useLogin() {
|
|
const [email, setEmail] = useState("");
|
|
const [password, setPassword] = useState("");
|
|
const [showPassword, setShowPassword] = useState(false);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [loginError, setLoginError] = useState<string | null>(null);
|
|
const [isOfflineMode, setIsOfflineMode] = useState(() =>
|
|
localStorage.getItem('offline_mode') === 'true' || !navigator.onLine
|
|
);
|
|
|
|
const navigate = useNavigate();
|
|
const { toast } = useToast();
|
|
const { signIn } = useAuth();
|
|
const { isSettingUpTables, setupTables } = useTableSetup();
|
|
|
|
// 네트워크 상태 감지
|
|
useEffect(() => {
|
|
const handleOnline = () => {
|
|
if (isOfflineMode && navigator.onLine) {
|
|
toast({
|
|
title: "네트워크 연결됨",
|
|
description: "인터넷에 다시 연결되었습니다. 온라인 모드로 전환할 수 있습니다.",
|
|
});
|
|
}
|
|
};
|
|
|
|
const handleOffline = () => {
|
|
if (!isOfflineMode) {
|
|
toast({
|
|
title: "네트워크 연결 끊김",
|
|
description: "인터넷 연결이 끊겼습니다. 오프라인 모드로 전환할 수 있습니다.",
|
|
variant: "destructive"
|
|
});
|
|
}
|
|
};
|
|
|
|
window.addEventListener('online', handleOnline);
|
|
window.addEventListener('offline', handleOffline);
|
|
|
|
return () => {
|
|
window.removeEventListener('online', handleOnline);
|
|
window.removeEventListener('offline', handleOffline);
|
|
};
|
|
}, [isOfflineMode, toast]);
|
|
|
|
const handleLogin = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setLoginError(null);
|
|
|
|
if (!email || !password) {
|
|
toast({
|
|
title: "입력 오류",
|
|
description: "이메일과 비밀번호를 모두 입력해주세요.",
|
|
variant: "destructive"
|
|
});
|
|
return;
|
|
}
|
|
|
|
setIsLoading(true);
|
|
|
|
try {
|
|
// 오프라인 모드를 위한 환경 설정
|
|
if (isOfflineMode) {
|
|
localStorage.setItem('offline_mode', 'true');
|
|
}
|
|
|
|
const { error, user } = await signIn(email, password);
|
|
|
|
if (error) {
|
|
console.error("로그인 실패:", error);
|
|
const errorMessage = getLoginErrorMessage(error);
|
|
setLoginError(errorMessage);
|
|
showLoginErrorToast(errorMessage);
|
|
} else if (user) {
|
|
// 로그인 성공
|
|
showLoginSuccessToast();
|
|
|
|
// 온라인 모드에서만 테이블 설정
|
|
if (!isOfflineMode) {
|
|
await setupTables();
|
|
}
|
|
|
|
navigate("/");
|
|
} else {
|
|
// user가 없지만 error도 없는 경우 (드문 경우)
|
|
console.warn("로그인 성공했지만 사용자 정보가 없습니다.");
|
|
toast({
|
|
title: "로그인 상태 확인 중",
|
|
description: "로그인은 성공했지만 사용자 정보를 확인하지 못했습니다. 페이지를 새로고침해보세요.",
|
|
variant: "default"
|
|
});
|
|
navigate("/");
|
|
}
|
|
} catch (err: any) {
|
|
console.error("로그인 과정에서 예외 발생:", err);
|
|
const errorMessage = err.message || "알 수 없는 오류가 발생했습니다.";
|
|
setLoginError(errorMessage);
|
|
|
|
toast({
|
|
title: "로그인 오류",
|
|
description: errorMessage,
|
|
variant: "destructive"
|
|
});
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
return {
|
|
email,
|
|
setEmail,
|
|
password,
|
|
setPassword,
|
|
showPassword,
|
|
setShowPassword,
|
|
isLoading,
|
|
isSettingUpTables,
|
|
loginError,
|
|
setLoginError,
|
|
isOfflineMode,
|
|
setIsOfflineMode,
|
|
handleLogin,
|
|
isCorsOrJsonError: (msg: string | null) => isCorsOrJsonError(msg)
|
|
};
|
|
}
|