diff --git a/README.md b/README.md
index 2deccb0..b43cb53 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@
| PM | 최도현 | **프론트엔드 리드**, 프론트 인프라 구축 & 서버 연동 및 배포, 화면 UI 구현,
UI/UX, GUI 디자인, 백엔드 API 및 DB 구축 |
| 백엔드 | 유승완 | **백엔드 리드**, 백엔드 인프라 구축 & 서버 연동 및 배포, API 및 DB 구축 |
| 백엔드 | 윤도훈 | **백엔드**, API 및 DB 구축 |
+| 백엔드 | 주천수 | **백엔드**, 활동 연혁 API 개발, ADMIN 권한 구현 |
| 프론트엔드 | 김수현 | **프론트엔드**, 화면 UI 구현, API 연동 |
| 프론트엔드 | 김태우 | **프론트엔드**, 화면 UI 구현, API 연동 |
| 프론트엔드 | 임성환 | **프론트엔드**, 화면 UI 구현, API 연동 |
@@ -34,10 +35,8 @@



-


-
### BE
@@ -69,157 +68,4 @@



-
-
-## 컨벤션
-
-### Commit Convention
-
-| 태그 | 설명 | 예시 |
-| --- | --- | --- |
-| feat | 새로운 기능 추가 | `feat: 로그인 기능 추가` |
-| fix | 버그 수정 | `fix: 로그인 예외 처리 버그 수정` |
-| docs | README 등의 문서 수정 | `docs: API 명세 업데이트` |
-| style | 코드 스타일 변경 | `style: 코드 포맷팅 개선` |
-| refactor | 기능 변경 없이 코드 내부 구조 리팩토링 | `refactor: 로그인 처리 로직 리팩토링` |
-| test | 테스트 케이스 작성 혹은 수정 | `test: 사용자 인증 로직 테스트 케이스 추가` |
-| chore | 라이브러리 버전 수정, 패키지 관리 등 | `chore: 의존성 버전 업데이트` |
-| comment | 주석 추가 / 수정 | `comment: 불필요한 주석 제거` |
-| hotfix | 배포된 버전에서의 급한 버그 수정 | `hotfix: 서버 Timezone 설정 변경` |
-| rename | 파일, 클래스 등의 이름 변경 | `rename: UserController → AuthController 변경` |
-| remove | 파일, 클래스 등의 삭제 | `remove: 사용하지 않는 DTO 제거` |
-| cicd | CI/CD 관련 설정 | `cicd: Github Actions workflow 추가` |
-| design | 애니메이션, 컬러 등의 디자인 수정 | `design: hover 애니메이션 추가` |
-
-### Issue Template
-
-```markdown
-# [태그] 제목
-(예: [feat] 로그인 기능 추가)
-
-## 목적
-- 해당 Issue가 발생한 원인과 배경을 설명한다.
- - 예: 회원 기능 구현을 위한 로그인 기능 추가 필요
-- 문제점이나 개선해야 할 사항을 기술한다.
- - 예: 사용자 인증 과정에서 빈약한 예외 처리로 인한 오류 발생 위험 제거
-
-## 상세 내용
-- 구현할 기능 또는 수정 사항에 대한 구체적인 설명
- - 예: 이메일 및 비밀번호 입력값 검증 로직 추가, OAuth 연동 검토
-- 참고할 자료나 관련 디자인, API 명세 등을 첨부(링크 포함 가능)
-
-## 추가 사항 (필요 시)
-- 관련 이슈 번호, 담당자, 예상 완료일, 테스트 방법 등 기타 참고해야 할 사항을 기재
-```
-
-### PR Template
-
-```markdown
-# [태그] 제목
-(예: [feat] 사용자 인증 기능 추가)
-
-## Issue
-- 예시: #111, #112
- (해당 PR과 관련된 이슈 번호를 명시하여 추적 용이성을 확보)
-
-## 변경 내용
-- 이번 PR에서 어떤 변경이 이루어졌는지 간략하게 기술합니다.
- (예: 기존 로그인 API에 JWT 기반 인증 로직 추가)
-
-## 구현 사항
-- 새로운 기능 구현 내용 및 기존 코드 수정 경위를 상세하게 설명합니다.
- (예: 로그인 요청 처리 로직 개선, 예외 처리 추가, API 응답 포맷 변경 등)
-
-## 테스트 (필요 시)
-- 적용된 테스트 방법과 결과를 기록합니다.
- (예: 단위 테스트 결과, 통합 테스트 진행 및 QA 결과, 관련 스크린샷 첨부)
-
-## 참고 사항 (필요 시)
-- 추가적으로 검토가 필요한 사항이나 관련 문서, 디자인 파일 등의 링크를 첨부합니다.
- (예: API 명세서, 디자인 목업 파일 링크 등)
-```
-
-## 패키지 구조
-
-### 백엔드
-```
-dmu.dasom.api
-├── global
-│ ├── admin
-│ │ ├── controller
-│ │ ├── dto
-│ │ └── service
-│ ├── auth
-│ │ ├── config
-│ │ ├── filter
-│ │ ├── handler
-│ │ ├── jwt
-│ │ └── userdetails
-│ └── swagger
-│ └── SwaggerConfig
-└── domain
- ├── common
- │ ├── exception
- │ │ ├── CustomControllerAdvice
- │ │ ├── CustomException
- │ │ ├── ErrorCode
- │ │ └── ErrorResponse
- │ └── BaseEntity
- ├── member
- │ ├── controller
- │ ├── dto
- │ ├── entity
- │ ├── enums
- │ ├── repository
- │ └── service
- ├── recruit
- │ ├── controller
- │ ├── dto
- │ ├── entity
- │ ├── enums
- │ ├── repository
- │ └── service
- └── … (기타 도메인)
-```
-
-### 프론트엔드
-```
-├─ src
-│ ├─ assets
-│ │ ├─ images
-│ │ └─ styles # css 설정 등
-│ ├─ components
-│ │ ├─ UI # 재사용 가능한 UI 컴포넌트 ex)버튼, 입력폼
-│ │ └─ layout # 헤더, 푸터 등 레이아웃 컴포넌트들
-│ ├─ context
-│ ├─ hooks
-│ │ └─ useWindowSize.tsx
-│ ├─ pages
-│ │ ├─ Main.tsx
-│ │ ├─ FAQ.tsx
-│ │ ├─ News.tsx
-│ │ ├─ NewsInfo.tsx
-│ │ ├─ CoreMembers.tsx
-│ │ ├─ Login.tsx
-│ │ ├─ Recruit.tsx
-│ │ ├─ RecruitCheck.tsx
-│ │ ├─ RecruitCheckFinal.tsx
-│ │ ├─ RecruitMeeting.tsx
-│ │ ├─ RecruitResult.tsx
-│ │ ├─ RecruitSubmit.tsx
-│ │ ├─ RecruitSubmitMeeting.tsx
-│ │ ├─ UserMain.tsx
-│ │ └─ admin
-│ │ ├─ AdminMain.tsx
-│ │ ├─ ManMembers.tsx
-│ │ ├─ ManApplicants.tsx
-│ │ ├─ ManRecruitDate.tsx
-│ │ └─ ManNews.tsx
-│ ├─ utils
-│ │ └─ utils.ts
-│ └─ types
-├─ App.tsx
-├─ index.tsx
-├─ react-app-env.d.ts
-└─ setupTests.ts
-```
+
diff --git a/src/components/UI/RecruitUI.tsx b/src/components/UI/RecruitUI.tsx
index 6273b71..c363273 100644
--- a/src/components/UI/RecruitUI.tsx
+++ b/src/components/UI/RecruitUI.tsx
@@ -243,19 +243,27 @@ export const SomRecruitUI: React.FC = () => {
📅 모집 일정 :
-
4월 11일 (금) ~ 4월 16일 (수)
+
10월 20일 (월) ~ 11월 02일 (일)
+
+
+
+
🚀 진행 일정 :
+
+ 11월 10일 (월) ~ 11월 22일 (토)
+ 발표 및 심사: 2025.11.22(토) 09:00 ~ 20:30
+
📝 모집 대상 :
- 25년도 1학기 솜커톤에 참가하는 학우 여러분
+ 25년도 2학기 솜커톤에 참가하는 학우 여러분
🌿 신청 조건 :
-
컴퓨터공학부 학생
+
동양미래대학교 재학생
diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx
index cf66a13..7158ba0 100644
--- a/src/components/layout/Header.tsx
+++ b/src/components/layout/Header.tsx
@@ -30,6 +30,10 @@ const Header = () => {
title: '가입안내',
links: [{ name: '지원하기', path: '/join/apply' }],
},
+ {
+ title: '솜커톤',
+ links: [{ name: '지원하기', path: '/somkathon' }],
+ },
]
return (
diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx
index 50cd207..9963b3d 100644
--- a/src/pages/Login.tsx
+++ b/src/pages/Login.tsx
@@ -1,7 +1,8 @@
import React, { useState } from 'react'
import apiClient from '../utils/apiClient'
import { useNavigate } from 'react-router-dom'
-import { setTokens } from '../utils/tokenUtils'
+import { setTokens, removeAllTokens } from '../utils/tokenUtils'
+import { authService } from '../utils/authService'
const Login: React.FC = () => {
const [email, setEmail] = useState('')
@@ -11,11 +12,13 @@ const Login: React.FC = () => {
const handleLogin = async () => {
if (!email || !password) {
- alert('아이디와 비밀번호를 입력하세요.')
return
}
setIsLoading(true)
+
+ // 기존 토큰 제거
+ removeAllTokens()
try {
const response = await apiClient.post('/auth/admin-login', {
@@ -24,8 +27,6 @@ const Login: React.FC = () => {
})
console.log('로그인 응답:', response)
- console.log('응답 헤더:', response.headers)
- console.log('응답 데이터:', response.data)
// 백엔드에서 헤더로 토큰을 전송하는 경우
const accessToken = response.headers['access-token'] || response.headers['accessToken']
@@ -43,33 +44,29 @@ const Login: React.FC = () => {
// 로컬 스토리지에 토큰 저장
setTokens(finalAccessToken, finalRefreshToken)
- console.log('로그인 성공: 토큰이 저장되었습니다.')
- console.log('저장된 액세스 토큰:', finalAccessToken)
- console.log('저장된 리프레시 토큰:', finalRefreshToken)
+ // authService에 로그인 성공 알림
+ authService.onLoginSuccess()
+
+ console.log('로그인 성공!')
// 로그인 성공 시 어드민 페이지로 이동
navigate('/admin')
} else {
- console.error('토큰을 찾을 수 없습니다.')
- console.error('헤더 액세스 토큰:', accessToken)
- console.error('헤더 리프레시 토큰:', refreshToken)
- console.error('바디 액세스 토큰:', bodyAccessToken)
- console.error('바디 리프레시 토큰:', bodyRefreshToken)
- alert('토큰을 받지 못했습니다. 다시 시도해주세요.')
+ console.log('토큰을 받지 못했습니다. 잠시 후 다시 시도합니다.')
+ // 토큰을 받지 못한 경우 잠시 후 다시 시도
+ setTimeout(() => {
+ handleLogin()
+ }, 1000)
}
} catch (err: any) {
- console.error('로그인 오류:', err)
+ console.log('로그인 시도 중...')
- const errorCode = err.response?.data?.code
- if (errorCode === 'C005') {
- alert('이메일 또는 비밀번호가 잘못되었습니다.')
- } else if (err.response?.status === 401) {
- alert('인증에 실패했습니다. 이메일과 비밀번호를 확인해주세요.')
- } else if (err.response?.status === 403) {
- alert('접근 권한이 없습니다.')
- } else {
- alert('로그인 실패. 다시 시도해주세요.')
- }
+ // 에러가 발생해도 조용히 처리하고 잠시 후 다시 시도
+ setTimeout(() => {
+ if (email && password) {
+ handleLogin()
+ }
+ }, 2000)
} finally {
setIsLoading(false)
}
@@ -113,7 +110,7 @@ const Login: React.FC = () => {
}`}
onClick={isLoading ? undefined : handleLogin}
>
- {isLoading ? '로그인 중...' : '로그인'}
+ {isLoading ? '접속 중...' : '로그인'}
diff --git a/src/pages/admin/SomkatonApplicants.tsx b/src/pages/admin/SomkatonApplicants.tsx
index 365edbd..7b00508 100644
--- a/src/pages/admin/SomkatonApplicants.tsx
+++ b/src/pages/admin/SomkatonApplicants.tsx
@@ -5,6 +5,7 @@ import {
getSomkathonParticipant,
listSomkathonParticipants,
} from './adminService'
+import { useAuth } from '../../hooks/useAuth'
const SomkatonApplicants: React.FC = () => {
const [applicants, setApplicants] = useState([])
@@ -13,15 +14,22 @@ const SomkatonApplicants: React.FC = () => {
)
const [selectedId, setSelectedId] = useState(null)
const [count, setCount] = useState(0)
- const accessToken = localStorage.getItem('accessToken')
+ const { isAuthenticated, isLoading } = useAuth()
// 지원자 전체 조회
const getData = async () => {
try {
- if (!accessToken) {
+ // 로딩 중이면 대기
+ if (isLoading) {
+ return
+ }
+
+ // 로딩이 완료되었는데 인증되지 않은 경우
+ if (!isAuthenticated) {
alert('로그인이 필요합니다.')
return
}
+
const response = await listSomkathonParticipants()
setApplicants(response)
setCount(response.length)
@@ -33,7 +41,7 @@ const SomkatonApplicants: React.FC = () => {
useEffect(() => {
getData()
- }, [])
+ }, [isAuthenticated, isLoading])
// 지원자 상세 조회
const toggleDetail = async (id: number) => {
@@ -119,6 +127,8 @@ const SomkatonApplicants: React.FC = () => {
+
+