Files
artwork21c.sample.admin.react/src/views/pages/login/Login.tsx

135 lines
4.4 KiB
TypeScript

import React, { useState, useEffect } from 'react'
import { Link, useNavigate, Navigate } from 'react-router-dom'
import {
CButton,
CCard,
CCardBody,
CCardGroup,
CCol,
CContainer,
CForm,
CFormInput,
CInputGroup,
CInputGroupText,
CRow,
CSpinner,
} from '@coreui/react'
import CIcon from '@coreui/icons-react'
import { cilLockLocked, cilUser } from '@coreui/icons'
import { login as apiLogin, DecodedToken, getAccessTokenFromCookie } from 'src/axios/authService';
import { useAuth } from 'src/hooks/useAuth';
import { jwtDecode } from 'jwt-decode';
const Login = () => {
const [memberId, setMemberId] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const { login } = useAuth();
const navigate = useNavigate();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError('');
setLoading(true);
try {
const response = await apiLogin({ memberId, password });
if (response.resultCode === '200') {
const accessToken = getAccessTokenFromCookie();
if (accessToken) {
const decodedToken = jwtDecode<DecodedToken>(accessToken);
const member = {
memberId: decodedToken.memberId,
memberName: decodedToken.memberName,
};
login(accessToken, member);
navigate('/dashboard');
} else {
setError('쿠키에서 accessToken을 찾을 수 없습니다.');
}
} else {
setError(response.resultMessage || '로그인에 실패했습니다.');
}
} catch (err: any) {
setError(err.response?.data?.message || '로그인 중 오류가 발생했습니다.');
} finally {
setLoading(false);
}
};
return (
<div className="bg-body-tertiary min-vh-100 d-flex flex-row align-items-center">
<CContainer>
<CRow className="justify-content-center">
<CCol md={8}>
<CCardGroup>
<CCard className="p-4">
<CCardBody>
<CForm onSubmit={handleSubmit}>
<h1>Login</h1>
<p className="text-body-secondary">Sign In to your account</p>
{error && <div className="text-danger mb-3">{error}</div>}
<CInputGroup className="mb-3">
<CInputGroupText>
<CIcon icon={cilUser} />
</CInputGroupText>
<CFormInput
placeholder="Member ID"
autoComplete="memberId"
value={memberId}
onChange={(e) => setMemberId(e.target.value)}
/>
</CInputGroup>
<CInputGroup className="mb-4">
<CInputGroupText>
<CIcon icon={cilLockLocked} />
</CInputGroupText>
<CFormInput
type="password"
placeholder="Password"
autoComplete="current-password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</CInputGroup>
<CRow>
<CCol xs={12}>
<CButton color="primary" className="w-100" type="submit" disabled={loading}>
{loading ? 'Logging in...' : 'Login'}
</CButton>
</CCol>
</CRow>
</CForm>
</CCardBody>
</CCard>
<CCard className="text-white bg-primary py-5">
<CCardBody className="text-center">
<div>
<h2>Sign up</h2>
<p>
, .
</p>
<Link to="/register">
<CButton color="primary" className="mt-3" active tabIndex={-1}>
Register Now!
</CButton>
</Link>
</div>
</CCardBody>
</CCard>
</CCardGroup>
</CCol>
</CRow>
</CContainer>
</div>
)
}
export default Login