Skip to content

Commit

Permalink
[FEATURE] 학과 변경 기능 (#42)
Browse files Browse the repository at this point in the history
* feat: 사용자 조회 API 스펙 변경 (#37)

* feat: 학과 교육과정 url 추가 (#37)

* feat: 학과 선택바 추가 (#37)

* feat: API 권한 수정 (#37)

* feat: 학과 조회 (#37)

* feat: 학과 업데이트 (#37)

* feat: 학과 초기값 설정 (#37)
  • Loading branch information
hyunmin0317 authored Dec 14, 2024
1 parent 01ea306 commit 5c082ab
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 11 deletions.
10 changes: 10 additions & 0 deletions src/api/departmentApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {Department} from '../types/Department'
import {Base} from '../types/Result'
import api from './config'

export const fetchDepartments = async (
params?: Record<string, string>
): Promise<Base<Department>> => {
const res = await api.get('/api/v1/departments', {params})
return res.data
}
7 changes: 7 additions & 0 deletions src/api/memberApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export type TPasswordParam = {
password: string
}

export type TDepartmentParam = {
departmentId: number
}

export const fetchMember = async (): Promise<MemberInfo> => {
const res = await jwtAxios.get('/api/v1/members/me')
return res.data
Expand All @@ -19,6 +23,9 @@ export const updateMember = async (loginParam: TLoginParam): Promise<AxiosRespon
export const changePassword = async (passwordParam: TPasswordParam) =>
await jwtAxios.patch('/api/v1/members/me/password', passwordParam)

export const changeDepartment = async (departmentParam: TDepartmentParam) =>
await jwtAxios.patch('/api/v1/members/me/department', departmentParam)

export const deleteMember = async (): Promise<AxiosResponse> =>
await jwtAxios.delete('/api/v1/members/me')

Expand Down
5 changes: 3 additions & 2 deletions src/api/questionApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ import {AxiosResponse} from 'axios'
import {Page} from '../types/Page'
import {Question, QuestionRequest} from '../types/Question'
import jwtAxios from '../util/jwtUtil'
import api from './config'

export const fetchQuestions = async (
params: Record<string, string>
): Promise<Page<Question>> => {
if (params.page) {
params.page = (parseInt(params.page) - 1).toString()
}
const res = await jwtAxios.get('/api/v1/questions', {params})
const res = await api.get('/api/v1/questions', {params})
return res.data
}

export const fetchQuestion = async (id: string): Promise<AxiosResponse> =>
await jwtAxios.get(`/api/v1/questions/${id}`)
await api.get(`/api/v1/questions/${id}`)

export const createQuestion = async (request: QuestionRequest): Promise<AxiosResponse> =>
await jwtAxios.post('/api/v1/questions', request)
Expand Down
51 changes: 51 additions & 0 deletions src/components/mypage/ChangeDepartment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {useEffect, useState} from 'react'
import {fetchDepartments} from '../../api/departmentApi'
import {Base} from '../../types/Result'
import {Department} from '../../types/Department'
import useCustomMypage, {TCustomMypage} from '../../hooks/useCustomMypage'
import useCustomMove, {TCustomMove} from '../../hooks/useCustomMove'

interface ChangeDepartmentProps {
department: string
}

const ChangeDepartment: React.FC<ChangeDepartmentProps> = ({department}) => {
const {departmentChange}: TCustomMypage = useCustomMypage()
const {reload}: TCustomMove = useCustomMove()
const [departments, setDepartments] = useState<Base<Department>>()
const [selectedDepartmentId, setSelectedDepartmentId] = useState<number | undefined>()

useEffect(() => {
fetchDepartments({isEditable: 'true'}).then((data: Base<Department>) => {
setDepartments(data)
const initialDepartment = data.content.find(dept => dept.name === department)
if (initialDepartment) {
setSelectedDepartmentId(initialDepartment.id)
}
})
}, [department])

const handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
const departmentId: number = parseInt(event.target.value, 10)
departmentChange({departmentId: departmentId}).then(success => {
if (success) {
alert('학과가 업데이트 되었습니다.')
reload()
}
})
}

return (
<td className="regi_box" style={{width: '90%', marginLeft: '0', marginRight: '1rem'}}>
<select id="major" value={selectedDepartmentId} onChange={handleSelectChange}>
{departments?.content?.map(department => (
<option key={department.id} value={department.id}>
{department.name}
</option>
))}
</select>
</td>
)
}

export default ChangeDepartment
19 changes: 14 additions & 5 deletions src/components/mypage/InfoTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {MemberInfo} from '../../types/MemberInfo'
import ChangeDepartment from './ChangeDepartment'

interface InfoTableProps {
member?: MemberInfo
Expand All @@ -17,11 +18,19 @@ const InfoTable: React.FC<InfoTableProps> = ({member}) => {
</tr>
<tr>
<td className="my_box_table_1st_td">학과</td>
<td>
<a className="link_site" href="" target="_blank" rel="noopener noreferrer">
{member?.department}
</a>
</td>
{member?.deptEditable ? (
<ChangeDepartment department={member?.department} />
) : (
<td>
<a
className="link_site"
href={`https://www.smu.ac.kr/_custom/smu/_app/curriculum.do?srSust=${member?.deptCode}&srShyr=all`}
target="_blank"
rel="noopener noreferrer">
{member?.department}
</a>
</td>
)}
</tr>
</table>
)
Expand Down
12 changes: 11 additions & 1 deletion src/hooks/useCustomMypage.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {TLoginParam} from '../api/accountApi'
import {courseUpload} from '../api/courseApi'
import {
changeDepartment,
changePassword,
deleteMember,
TDepartmentParam,
TPasswordParam,
updateMember
} from '../api/memberApi'
Expand All @@ -11,6 +13,7 @@ export interface TCustomMypage {
uploadCourse: (loginParam: TLoginParam) => Promise<boolean>
memberUpdate: (loginParam: TLoginParam) => Promise<boolean>
passwordChange: (passwordParam: TPasswordParam) => Promise<boolean>
departmentChange: (departmentParam: TDepartmentParam) => Promise<boolean>
memberDelete: () => Promise<boolean>
}

Expand All @@ -36,14 +39,21 @@ const useCustomMypage = (): TCustomMypage => {
return success
}

const departmentChange = async (departmentParam: TDepartmentParam) => {
const response = await changeDepartment(departmentParam)
const success = response.status < 400
!success && alert(response.data.message)
return success
}

const memberDelete = async () => {
const response = await deleteMember()
const success = response.status < 400
!success && alert(response.data.message)
return success
}

return {uploadCourse, memberUpdate, passwordChange, memberDelete}
return {uploadCourse, memberUpdate, passwordChange, departmentChange, memberDelete}
}

export default useCustomMypage
2 changes: 1 addition & 1 deletion src/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -1366,7 +1366,7 @@ input[type='checkbox'] {
background: none;
border: 0.01px solid rgb(216, 216, 216);
padding: 0px 10px 0px 10px;
margin-top: 0.5rem;
margin: 0.5rem 0 0 0;
outline: 0;
height: 2.8rem;
}
Expand Down
8 changes: 8 additions & 0 deletions src/types/Department.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface Department {
id: number
college: string
name: string
subDomain: string
isEditable: boolean
code: string
}
4 changes: 2 additions & 2 deletions src/types/MemberInfo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export interface MemberInfo {
id: number
username: string
name: string
department: string
email: string
deptCode: string
deptEditable: boolean
}

0 comments on commit 5c082ab

Please sign in to comment.