104 lines
2.7 KiB
TypeScript
Executable File
104 lines
2.7 KiB
TypeScript
Executable File
|
|
import React, { useState, useEffect } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { getKakaoLoginUrl, kakaoCallback } from '../../utils/api';
|
|
|
|
interface LoginSectionProps {
|
|
onBack: () => void;
|
|
onLogin: () => void;
|
|
}
|
|
|
|
const LoginSection: React.FC<LoginSectionProps> = ({ onBack, onLogin }) => {
|
|
const { t } = useTranslation();
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
// 카카오 콜백 처리 (URL에서 code 파라미터 확인)
|
|
useEffect(() => {
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const code = urlParams.get('code');
|
|
|
|
if (code) {
|
|
handleKakaoCallback(code);
|
|
}
|
|
}, []);
|
|
|
|
const handleKakaoCallback = async (code: string) => {
|
|
setIsLoading(true);
|
|
setError(null);
|
|
|
|
try {
|
|
await kakaoCallback(code);
|
|
|
|
// URL에서 code 파라미터 제거
|
|
const url = new URL(window.location.href);
|
|
url.searchParams.delete('code');
|
|
window.history.replaceState({}, document.title, url.pathname);
|
|
|
|
// 로그인 성공
|
|
onLogin();
|
|
} catch (err) {
|
|
console.error('Kakao callback failed:', err);
|
|
setError(t('login.kakaoLoginFailed'));
|
|
|
|
// URL에서 code 파라미터 제거
|
|
const url = new URL(window.location.href);
|
|
url.searchParams.delete('code');
|
|
window.history.replaceState({}, document.title, url.pathname);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleKakaoLogin = async () => {
|
|
setIsLoading(true);
|
|
setError(null);
|
|
|
|
try {
|
|
const response = await getKakaoLoginUrl();
|
|
|
|
// 카카오 로그인 페이지로 리다이렉트
|
|
window.location.href = response.auth_url;
|
|
} catch (err) {
|
|
console.error('Failed to get Kakao login URL:', err);
|
|
setError(t('login.loginUrlFailed'));
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="login-container">
|
|
{/* Back Button */}
|
|
<button onClick={onBack} className="login-back-btn" disabled={isLoading}>
|
|
<img src="/assets/images/icon-back.svg" alt="Back" />
|
|
<span>{t('login.back')}</span>
|
|
</button>
|
|
|
|
<div className="login-content">
|
|
{/* Logo */}
|
|
<div className="login-logo">
|
|
<img src="/assets/images/ado2-login-logo.svg" alt="ADO2" />
|
|
</div>
|
|
|
|
{/* Error Message */}
|
|
{error && (
|
|
<div className="login-error">
|
|
{error}
|
|
</div>
|
|
)}
|
|
|
|
{/* Kakao Login Button */}
|
|
<button
|
|
onClick={handleKakaoLogin}
|
|
className="btn-kakao"
|
|
disabled={isLoading}
|
|
>
|
|
{isLoading ? t('login.loggingIn') : t('login.kakaoStart')}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default LoginSection;
|