어드민 회원 가입신청 기능 추가
This commit is contained in:
@@ -73,7 +73,7 @@ const App = () => {
|
||||
>
|
||||
<Routes>
|
||||
{/* 1. 로그인 여부와 관계없이 항상 독립적으로 표시되는 페이지 */}
|
||||
<Route path="/register" element={<Register />} />
|
||||
<Route path="/admin/member/register" element={<Register />} />
|
||||
<Route path="/404" element={<Page404 />} />
|
||||
<Route path="/500" element={<Page500 />} />
|
||||
|
||||
|
||||
@@ -62,3 +62,9 @@ export const deleteAdminMember = async (memberSeq: number): Promise<AdminMemberR
|
||||
const response = await axios.post<AdminMemberResponse>('/admin/member/delete', { memberSeq });
|
||||
return response.data;
|
||||
};
|
||||
|
||||
// 회원 가입 (비로그인 상태에서 회원가입)
|
||||
export const registerAdminMember = async (member: Partial<AdminMember>): Promise<AdminMemberResponse> => {
|
||||
const response = await axios.post<AdminMemberResponse>('/admin/member/register', member);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
@@ -53,7 +53,11 @@ const Login = () => {
|
||||
setError('쿠키에서 accessToken을 찾을 수 없습니다.');
|
||||
}
|
||||
} else {
|
||||
setError(response.resultMessage || '로그인에 실패했습니다.');
|
||||
let errorMsg = response.resultMessage || '로그인에 실패했습니다.'
|
||||
if (response.resultData && typeof response.resultData === 'string') {
|
||||
errorMsg += `\n${response.resultData}`
|
||||
}
|
||||
setError(errorMsg)
|
||||
}
|
||||
} catch (err: any) {
|
||||
setError(err.response?.data?.message || '로그인 중 오류가 발생했습니다.');
|
||||
@@ -65,16 +69,16 @@ const Login = () => {
|
||||
|
||||
return (
|
||||
<div className="bg-body-tertiary min-vh-100 d-flex flex-row align-items-center">
|
||||
<CContainer>
|
||||
<CContainer fluid>
|
||||
<CRow className="justify-content-center">
|
||||
<CCol md={8}>
|
||||
<CCardGroup>
|
||||
<CCardGroup style={{ minWidth: '300px' }}>
|
||||
<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>}
|
||||
{error && <div className="text-danger mb-3" style={{ whiteSpace: 'pre-line' }}>{error}</div>}
|
||||
<CInputGroup className="mb-3">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilUser} />
|
||||
@@ -108,16 +112,19 @@ const Login = () => {
|
||||
</CForm>
|
||||
</CCardBody>
|
||||
</CCard>
|
||||
<CCard className="text-white bg-primary py-5">
|
||||
<CCard className="text-white bg-primary py-5" style={{ minWidth: '300px' }}>
|
||||
<CCardBody className="text-center">
|
||||
<div>
|
||||
<h2>Sign up</h2>
|
||||
<h2>가입신청</h2>
|
||||
<br/>
|
||||
<p>
|
||||
신규 사용자의 경우, 가입신청 후 권한을 부여받아야 접속 가능합니다.
|
||||
신규 어드민 회원은<br/>
|
||||
가입신청 후 권한을 부여받아야<br/>
|
||||
접속 가능합니다.
|
||||
</p>
|
||||
<Link to="/register">
|
||||
<Link to="/admin/member/register">
|
||||
<CButton color="primary" className="mt-3" active tabIndex={-1}>
|
||||
Register Now!
|
||||
어드민 회원가입 신청
|
||||
</CButton>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { useNavigate, Link } from 'react-router-dom'
|
||||
import {
|
||||
CButton,
|
||||
CCard,
|
||||
@@ -7,14 +8,79 @@ import {
|
||||
CContainer,
|
||||
CForm,
|
||||
CFormInput,
|
||||
CInputGroup,
|
||||
CInputGroupText,
|
||||
CFormLabel,
|
||||
CRow,
|
||||
CSpinner,
|
||||
} from '@coreui/react'
|
||||
import CIcon from '@coreui/icons-react'
|
||||
import { cilLockLocked, cilUser } from '@coreui/icons'
|
||||
import { registerAdminMember } from 'src/services/adminMemberService'
|
||||
import { logout } from 'src/axios/authService'
|
||||
|
||||
const Register = () => {
|
||||
const navigate = useNavigate()
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
// 회원가입 페이지 진입 시 기존 토큰 제거
|
||||
useEffect(() => {
|
||||
logout()
|
||||
}, [])
|
||||
const [formData, setFormData] = useState({
|
||||
memberId: '',
|
||||
memberName: '',
|
||||
password: '',
|
||||
passwordConfirm: '',
|
||||
})
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { name, value } = e.target
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
[name]: value,
|
||||
}))
|
||||
}
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
|
||||
// 유효성 검사
|
||||
if (!formData.memberId.trim()) {
|
||||
alert('어드민 회원 ID를 입력해주세요.')
|
||||
return
|
||||
}
|
||||
if (!formData.memberName.trim()) {
|
||||
alert('이름을 입력해주세요.')
|
||||
return
|
||||
}
|
||||
if (!formData.password) {
|
||||
alert('비밀번호를 입력해주세요.')
|
||||
return
|
||||
}
|
||||
if (formData.password !== formData.passwordConfirm) {
|
||||
alert('비밀번호가 일치하지 않습니다.')
|
||||
return
|
||||
}
|
||||
|
||||
setLoading(true)
|
||||
try {
|
||||
const response = await registerAdminMember({
|
||||
memberId: formData.memberId,
|
||||
memberName: formData.memberName,
|
||||
password: formData.password,
|
||||
})
|
||||
|
||||
if (response.resultCode === '200') {
|
||||
alert('회원가입이 완료되었습니다. 관리자 승인 후 로그인이 가능합니다.')
|
||||
navigate('/login')
|
||||
} else {
|
||||
alert(response.resultMessage || '회원가입에 실패했습니다.')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('회원가입 실패:', error)
|
||||
alert('회원가입에 실패했습니다.')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-body-tertiary min-vh-100 d-flex flex-row align-items-center">
|
||||
<CContainer>
|
||||
@@ -22,41 +88,78 @@ const Register = () => {
|
||||
<CCol md={9} lg={7} xl={6}>
|
||||
<CCard className="mx-4">
|
||||
<CCardBody className="p-4">
|
||||
<CForm>
|
||||
<h1>Register</h1>
|
||||
<p className="text-body-secondary">Create your account</p>
|
||||
<CInputGroup className="mb-3">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilUser} />
|
||||
</CInputGroupText>
|
||||
<CFormInput placeholder="Username" autoComplete="username" />
|
||||
</CInputGroup>
|
||||
<CInputGroup className="mb-3">
|
||||
<CInputGroupText>@</CInputGroupText>
|
||||
<CFormInput placeholder="Email" autoComplete="email" />
|
||||
</CInputGroup>
|
||||
<CInputGroup className="mb-3">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilLockLocked} />
|
||||
</CInputGroupText>
|
||||
<CForm onSubmit={handleSubmit}>
|
||||
<h1>어드민 회원가입</h1>
|
||||
<p className="text-body-secondary">어드민 계정을 생성합니다</p>
|
||||
|
||||
<div className="mb-3">
|
||||
<CFormLabel htmlFor="memberId">어드민 회원 ID *</CFormLabel>
|
||||
<CFormInput
|
||||
type="text"
|
||||
id="memberId"
|
||||
name="memberId"
|
||||
value={formData.memberId}
|
||||
onChange={handleInputChange}
|
||||
placeholder="어드민 회원 ID를 입력하세요"
|
||||
autoComplete="username"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<CFormLabel htmlFor="memberName">이름 *</CFormLabel>
|
||||
<CFormInput
|
||||
type="text"
|
||||
id="memberName"
|
||||
name="memberName"
|
||||
value={formData.memberName}
|
||||
onChange={handleInputChange}
|
||||
placeholder="이름을 입력하세요"
|
||||
autoComplete="name"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<CFormLabel htmlFor="password">비밀번호 *</CFormLabel>
|
||||
<CFormInput
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
id="password"
|
||||
name="password"
|
||||
value={formData.password}
|
||||
onChange={handleInputChange}
|
||||
placeholder="비밀번호를 입력하세요"
|
||||
autoComplete="new-password"
|
||||
/>
|
||||
</CInputGroup>
|
||||
<CInputGroup className="mb-4">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilLockLocked} />
|
||||
</CInputGroupText>
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<CFormLabel htmlFor="passwordConfirm">비밀번호 확인 *</CFormLabel>
|
||||
<CFormInput
|
||||
type="password"
|
||||
placeholder="Repeat password"
|
||||
id="passwordConfirm"
|
||||
name="passwordConfirm"
|
||||
value={formData.passwordConfirm}
|
||||
onChange={handleInputChange}
|
||||
placeholder="비밀번호를 다시 입력하세요"
|
||||
autoComplete="new-password"
|
||||
/>
|
||||
</CInputGroup>
|
||||
</div>
|
||||
|
||||
<div className="d-grid">
|
||||
<CButton color="success">Create Account</CButton>
|
||||
<CButton color="success" type="submit" disabled={loading}>
|
||||
{loading ? (
|
||||
<>
|
||||
<CSpinner size="sm" className="me-2" />
|
||||
가입 중...
|
||||
</>
|
||||
) : (
|
||||
'회원가입'
|
||||
)}
|
||||
</CButton>
|
||||
</div>
|
||||
|
||||
<div className="text-center mt-3">
|
||||
<span className="text-body-secondary">이미 계정이 있으신가요? </span>
|
||||
<Link to="/login">로그인</Link>
|
||||
</div>
|
||||
</CForm>
|
||||
</CCardBody>
|
||||
|
||||
Reference in New Issue
Block a user