From 2c21ccbf9db65e41257658e36a82148b4ea20d9b Mon Sep 17 00:00:00 2001
From: JM Kim <106949557+CSE-Shaco@users.noreply.github.com>
Date: Wed, 18 Mar 2026 12:34:29 +0900
Subject: [PATCH 1/2] feat: update Inha major options
---
src/constant/majorOptions.ts | 285 ++++++++++++++++++-----------------
1 file changed, 147 insertions(+), 138 deletions(-)
diff --git a/src/constant/majorOptions.ts b/src/constant/majorOptions.ts
index 8411c3a..2808449 100644
--- a/src/constant/majorOptions.ts
+++ b/src/constant/majorOptions.ts
@@ -1,139 +1,148 @@
export const majorOptions = [
- {
- title: '소프트웨어융합대학',
- items: [
- { key: '인공지능공학과', value: '인공지능공학과' },
- { key: '데이터사이언스학과', value: '데이터사이언스학과' },
- { key: '스마트모빌리티공학과', value: '스마트모빌리티공학과' },
- { key: '디자인테크놀로지학과', value: '디자인테크놀로지학과' },
- { key: '컴퓨터공학과', value: '컴퓨터공학과' },
- ],
- },
- {
- title: '프런티어창의대학',
- items: [
- { key: '자유전공융합학부', value: '자유전공융합학부' },
- { key: '공학융합학부', value: '공학융합학부' },
- { key: '자연과학융합학부', value: '자연과학융합학부' },
- { key: '경영융합학부', value: '경영융합학부' },
- { key: '사회과학융합학부', value: '사회과학융합학부' },
- { key: '인문융합학부', value: '인문융합학부' },
- ],
- },
- {
- title: '바이오시스템융합학부',
- items: [
- { key: '생명공학과', value: '생명공학과' },
- { key: '생명과학과', value: '생명과학과' },
- { key: '첨단바이오의약학과', value: '첨단바이오의약학과' },
- ],
- },
- {
- title: '공과대학',
- items: [
- { key: '기계공학과', value: '기계공학과' },
- { key: '항공우주공학과', value: '항공우주공학과' },
- { key: '조선해양공학과', value: '조선해양공학과' },
- { key: '산업경영공학과', value: '산업경영공학과' },
- { key: '화학공학과', value: '화학공학과' },
- { key: '고분자공학과', value: '고분자공학과' },
- { key: '신소재공학과', value: '신소재공학과' },
- { key: '사회인프라공학과', value: '사회인프라공학과' },
- { key: '환경공학과', value: '환경공학과' },
- { key: '공간정보공학과', value: '공간정보공학과' },
- { key: '건축공학전공', value: '건축공학전공' },
- { key: '건축학전공(5년제)', value: '건축학전공(5년제)' },
- { key: '에너지자원공학과', value: '에너지자원공학과' },
- { key: '전기전자공학부', value: '전기전자공학부' },
- { key: '반도체시스템공학과', value: '반도체시스템공학과' },
- { key: '이차전지융합학과', value: '이차전지융합학과' },
- ],
- },
- {
- title: '자연과학대학',
- items: [
- { key: '수학과', value: '수학과' },
- { key: '통계학과', value: '통계학과' },
- { key: '물리학과', value: '물리학과' },
- { key: '화학과', value: '화학과' },
- { key: '해양과학과', value: '해양과학과' },
- { key: '식품영양학과', value: '식품영양학과' },
- ],
- },
- {
- title: '경영대학',
- items: [
- { key: '경영학과', value: '경영학과' },
- { key: '파이낸스경영학과', value: '파이낸스경영학과' },
- { key: '아태물류학부', value: '아태물류학부' },
- { key: '국제통상학과', value: '국제통상학과' },
- ],
- },
- {
- title: '사범대학',
- items: [
- { key: '국어교육과', value: '국어교육과' },
- { key: '영어교육과', value: '영어교육과' },
- { key: '사회교육과', value: '사회교육과' },
- { key: '체육교육과', value: '체육교육과' },
- { key: '교육학과', value: '교육학과' },
- { key: '수학교육과', value: '수학교육과' },
- ],
- },
- {
- title: '사회과학대학',
- items: [
- { key: '행정학과', value: '행정학과' },
- { key: '정치외교학과', value: '정치외교학과' },
- { key: '경제학과', value: '경제학과' },
- { key: '소비자학과', value: '소비자학과' },
- { key: '아동심리학과', value: '아동심리학과' },
- { key: '사회복지학과', value: '사회복지학과' },
- { key: '미디어커뮤니케이션학과', value: '미디어커뮤니케이션학과' },
- ],
- },
- {
- title: '문과대학',
- items: [
- { key: '한국어문학과', value: '한국어문학과' },
- { key: '사학과', value: '사학과' },
- { key: '철학과', value: '철학과' },
- { key: '중국학과', value: '중국학과' },
- { key: '일본언어문화학과', value: '일본언어문화학과' },
- { key: '영미유럽인문융합학부', value: '영미유럽인문융합학부' },
- { key: '문화콘텐츠문화경영학과', value: '문화콘텐츠문화경영학과' },
- ],
- },
- {
- title: '의과대학',
- items: [
- { key: '의예과', value: '의예과' },
- ],
- },
- {
- title: '간호대학',
- items: [
- { key: '간호학과', value: '간호학과' },
- ],
- },
- {
- title: '예술체육대학',
- items: [
- { key: '조형예술학과', value: '조형예술학과' },
- { key: '스포츠과학과', value: '스포츠과학과' },
- { key: '의류디자인학과', value: '의류디자인학과' },
- { key: '디자인융합학과', value: '디자인융합학과' },
- { key: '연극영화학과', value: '연극영화학과' },
- ],
- },
- {
- title: '미래융합대학',
- items: [
- { key: '메카트로닉스공학과', value: '메카트로닉스공학과' },
- { key: '산업경영학과', value: '산업경영학과' },
- { key: '반도체산업융합학과', value: '반도체산업융합학과' },
- { key: '소프트웨어융합공학과', value: '소프트웨어융합공학과' },
- { key: '금융투자학과', value: '금융투자학과' },
- ],
- },
- ];
\ No newline at end of file
+ {
+ title: '프런티어창의대학',
+ items: [
+ { key: '자유전공융합학부', value: '자유전공융합학부' },
+ { key: '공학융합학부', value: '공학융합학부' },
+ { key: '자연과학융합학부', value: '자연과학융합학부' },
+ { key: '경영융합학부', value: '경영융합학부' },
+ { key: '사회과학융합학부', value: '사회과학융합학부' },
+ { key: '인문융합학부', value: '인문융합학부' }
+ ]
+ },
+ {
+ title: '공과대학',
+ items: [
+ { key: '기계공학과', value: '기계공학과' },
+ { key: '항공우주공학과', value: '항공우주공학과' },
+ { key: '조선해양공학과', value: '조선해양공학과' },
+ { key: '산업경영공학과', value: '산업경영공학과' },
+ { key: '화학공학과', value: '화학공학과' },
+ { key: '고분자공학과', value: '고분자공학과' },
+ { key: '신소재공학과', value: '신소재공학과' },
+ { key: '사회인프라공학과', value: '사회인프라공학과' },
+ { key: '환경공학과', value: '환경공학과' },
+ { key: '공간정보공학과', value: '공간정보공학과' },
+ { key: '건축학부(건축공학)', value: '건축학부(건축공학)' },
+ { key: '건축학부(건축학)', value: '건축학부(건축학)' },
+ { key: '에너지자원공학과', value: '에너지자원공학과' },
+ { key: '융합기술경영학부', value: '융합기술경영학부' },
+ { key: '전기전자공학부', value: '전기전자공학부' },
+ { key: '반도체시스템공학과', value: '반도체시스템공학과' },
+ { key: '이차전지융합학과', value: '이차전지융합학과' }
+ ]
+ },
+ {
+ title: '자연과학대학',
+ items: [
+ { key: '수학과', value: '수학과' },
+ { key: '통계학과', value: '통계학과' },
+ { key: '물리학과', value: '물리학과' },
+ { key: '화학과', value: '화학과' },
+ { key: '해양과학과', value: '해양과학과' },
+ { key: '식품영양학과', value: '식품영양학과' }
+ ]
+ },
+ {
+ title: '경영대학',
+ items: [
+ { key: '경영학부(경영학과)', value: '경영학부(경영학과)' },
+ { key: '경영학부(파이낸스경영학과)', value: '경영학부(파이낸스경영학과)' },
+ { key: '아태물류학부', value: '아태물류학부' },
+ { key: '국제통상학과', value: '국제통상학과' }
+ ]
+ },
+ {
+ title: '사범대학',
+ items: [
+ { key: '국어교육과', value: '국어교육과' },
+ { key: '영어교육과', value: '영어교육과' },
+ { key: '사회교육과', value: '사회교육과' },
+ { key: '교육학과', value: '교육학과' },
+ { key: '체육교육과', value: '체육교육과' },
+ { key: '수학교육과', value: '수학교육과' }
+ ]
+ },
+ {
+ title: '사회과학대학',
+ items: [
+ { key: '행정학과', value: '행정학과' },
+ { key: '정치외교학과', value: '정치외교학과' },
+ { key: '미디어커뮤니케이션학과', value: '미디어커뮤니케이션학과' },
+ { key: '경제학과', value: '경제학과' },
+ { key: '소비자학과', value: '소비자학과' },
+ { key: '아동심리학과', value: '아동심리학과' },
+ { key: '사회복지학과', value: '사회복지학과' }
+ ]
+ },
+ {
+ title: '문과대학',
+ items: [
+ { key: '한국어문학과', value: '한국어문학과' },
+ { key: '사학과', value: '사학과' },
+ { key: '철학과', value: '철학과' },
+ { key: '중국학과', value: '중국학과' },
+ { key: '일본언어문화학과', value: '일본언어문화학과' },
+ { key: '영미유럽인문융합학부', value: '영미유럽인문융합학부' },
+ { key: '문화콘텐츠문화경영학과', value: '문화콘텐츠문화경영학과' }
+ ]
+ },
+ {
+ title: '의과대학',
+ items: [
+ { key: '의예과', value: '의예과' },
+ { key: '의학과', value: '의학과' }
+ ]
+ },
+ {
+ title: '간호대학',
+ items: [{ key: '간호학과', value: '간호학과' }]
+ },
+ {
+ title: '미래융합대학',
+ items: [
+ { key: '메카트로닉스공학과', value: '메카트로닉스공학과' },
+ { key: '소프트웨어융합공학과', value: '소프트웨어융합공학과' },
+ { key: '산업경영학과', value: '산업경영학과' },
+ { key: '금융투자학과', value: '금융투자학과' }
+ ]
+ },
+ {
+ title: '예술체육대학',
+ items: [
+ { key: '조형예술학과', value: '조형예술학과' },
+ { key: '디자인융합학과', value: '디자인융합학과' },
+ { key: '스포츠과학과', value: '스포츠과학과' },
+ { key: '연극영화학과', value: '연극영화학과' },
+ { key: '의류디자인학과', value: '의류디자인학과' }
+ ]
+ },
+ {
+ title: '국제학부',
+ items: [
+ { key: 'IBT학과', value: 'IBT학과' },
+ { key: 'ISE학과', value: 'ISE학과' },
+ { key: 'KLC학과', value: 'KLC학과' }
+ ]
+ },
+ {
+ title: '소프트웨어융합대학',
+ items: [
+ { key: '인공지능공학과', value: '인공지능공학과' },
+ { key: '데이터사이언스학과', value: '데이터사이언스학과' },
+ { key: '스마트모빌리티공학과', value: '스마트모빌리티공학과' },
+ { key: '디자인테크놀로지학과', value: '디자인테크놀로지학과' },
+ { key: '컴퓨터공학과', value: '컴퓨터공학과' }
+ ]
+ },
+ {
+ title: '바이오시스템융합학부',
+ items: [
+ { key: '생명공학과', value: '생명공학과' },
+ { key: '바이오제약공학과', value: '바이오제약공학과' },
+ { key: '생명과학과', value: '생명과학과' },
+ { key: '첨단바이오의약학과', value: '첨단바이오의약학과' },
+ { key: '바이오식품공학과', value: '바이오식품공학과' }
+ ]
+ }
+]
From 28ed14fedbd457b349480a5583f04a10873477b5 Mon Sep 17 00:00:00 2001
From: JM Kim <106949557+CSE-Shaco@users.noreply.github.com>
Date: Wed, 18 Mar 2026 13:02:44 +0900
Subject: [PATCH 2/2] feat: store and render majors by code on web
---
src/app/dashboard/core-applications/page.tsx | 5 +-
src/app/dashboard/members/page.tsx | 3 +-
src/app/dashboard/users/page.tsx | 3 +-
src/app/recruit/core/page.tsx | 5 +-
src/components/admin/AdminDashboard.tsx | 4 +-
src/components/admin/AdminTableCell.tsx | 4 +-
src/components/admin/UserDetailsModal.tsx | 4 +
src/components/auth/screen/AuthFindId.jsx | 10 +-
.../study/ui/card/ApplicantInfoList.jsx | 5 +-
.../study/ui/modal/ApplicantDetailModal.jsx | 5 +-
.../ui/design-system/GdgMajorDropdown.tsx | 8 +-
src/constant/majorOptions.ts | 228 +++++++++++-------
12 files changed, 172 insertions(+), 112 deletions(-)
diff --git a/src/app/dashboard/core-applications/page.tsx b/src/app/dashboard/core-applications/page.tsx
index 3356439..2c44153 100644
--- a/src/app/dashboard/core-applications/page.tsx
+++ b/src/app/dashboard/core-applications/page.tsx
@@ -4,6 +4,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'
import Link from 'next/link'
import Loader from '@/components/ui/common/Loader'
+import { formatMajorLabel } from '@/constant/majorOptions'
import { useAuthenticatedApi } from '@/hooks/useAuthenticatedApi'
type RecruitCoreResultStatus = 'SUBMITTED' | 'IN_REVIEW' | 'ACCEPTED' | 'REJECTED'
@@ -341,7 +342,7 @@ export default function DashboardCoreApplicationsPage() {
>
{application.name} |
{application.studentId} |
- {application.major} |
+ {formatMajorLabel(application.major)} |
{application.team} |
{application.resultStatus} |
{formatDateTime(application.createdAt)} |
@@ -410,7 +411,7 @@ export default function DashboardCoreApplicationsPage() {
이름: {detail.snapshot.name}
학번: {detail.snapshot.studentId}
-
전공: {detail.snapshot.major}
+
전공: {formatMajorLabel(detail.snapshot.major)}
전화번호: {detail.snapshot.phone}
이메일: {detail.snapshot.email}
지원 팀: {detail.team}
diff --git a/src/app/dashboard/members/page.tsx b/src/app/dashboard/members/page.tsx
index 75a2249..21d4967 100644
--- a/src/app/dashboard/members/page.tsx
+++ b/src/app/dashboard/members/page.tsx
@@ -6,6 +6,7 @@ import Link from 'next/link'
import Loader from '@/components/ui/common/Loader'
import UserDetailsModal from '@/components/admin/UserDetailsModal'
import { GdgSegmentedButton } from '@/components/ui/design-system'
+import { formatMajorLabel } from '@/constant/majorOptions'
import { useAuthenticatedApi } from '@/hooks/useAuthenticatedApi'
import { formatPhoneNumberDisplay } from '@/utils/phoneNumber'
@@ -264,7 +265,7 @@ export default function DashboardMembersPage() {
members.map((member) => (
| {member.name} |
- {member.major} |
+ {formatMajorLabel(member.major)} |
{member.studentId} |
{formatPhoneNumberDisplay(member.phoneNumber)}
diff --git a/src/app/dashboard/users/page.tsx b/src/app/dashboard/users/page.tsx
index 65cba77..e4be22f 100644
--- a/src/app/dashboard/users/page.tsx
+++ b/src/app/dashboard/users/page.tsx
@@ -4,6 +4,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'
import Link from 'next/link'
import Loader from '@/components/ui/common/Loader'
+import { formatMajorLabel } from '@/constant/majorOptions'
import { useAuth } from '@/hooks/useAuth'
import { useAuthenticatedApi } from '@/hooks/useAuthenticatedApi'
@@ -350,7 +351,7 @@ export default function DashboardUsersPage() {
| {user.id} |
{user.name} |
{user.email} |
- {user.major || '-'} |
+ {formatMajorLabel(user.major)} |
{user.studentId || '-'} |
{editable ? (
diff --git a/src/app/recruit/core/page.tsx b/src/app/recruit/core/page.tsx
index ddf8ed7..f7d42a1 100644
--- a/src/app/recruit/core/page.tsx
+++ b/src/app/recruit/core/page.tsx
@@ -15,6 +15,7 @@ import {
GdgInputField
} from '@/components/ui/design-system'
import { PrivacyPolicyNotice } from '@/components/ui/common/PrivacyPolicyNotice'
+import { normalizeMajorCode } from '@/constant/majorOptions'
import { useAuthenticatedApi } from '@/hooks/useAuthenticatedApi'
import { usePhoneNumber } from '@/hooks/usePhoneNumber'
import { unwrapApiResponse } from '@/utils/api/unwrap'
@@ -272,7 +273,7 @@ export default function RecruitCore() {
name: prev.name || payload.name || '',
studentId: prev.studentId || payload.studentId || '',
email: prev.email || payload.email || '',
- major: prev.major || payload.major || '',
+ major: prev.major || normalizeMajorCode(payload.major) || '',
phone: formatInput(prev.phone || payload.phone || '')
}))
} catch (error: any) {
@@ -439,7 +440,7 @@ export default function RecruitCore() {
name: formData.name,
studentId: formData.studentId,
phone: toDigits(formData.phone),
- major: formData.major,
+ major: normalizeMajorCode(formData.major),
email: formData.email
},
team: formData.team,
diff --git a/src/components/admin/AdminDashboard.tsx b/src/components/admin/AdminDashboard.tsx
index 6ee70e5..9c42770 100644
--- a/src/components/admin/AdminDashboard.tsx
+++ b/src/components/admin/AdminDashboard.tsx
@@ -1,6 +1,7 @@
'use client';
import React, { useMemo } from 'react';
+import { formatMajorLabel } from '@/constant/majorOptions';
import {
ResponsiveContainer,
PieChart,
@@ -21,7 +22,7 @@ function normalizeMembers(rawMembers = []) {
return rawMembers.map((u) => ({
id: u?.id ?? u?.member?.id,
name: u?.name ?? u?.member?.name ?? '',
- major: u?.major ?? u?.member?.major ?? u?.member?.majors?.main ?? '기타',
+ major: formatMajorLabel(u?.major ?? u?.member?.major ?? u?.member?.majors?.main ?? '기타'),
admissionSemester: u?.admissionSemester ?? u?.member?.admissionSemester ?? '미상',
studentId: String(u?.studentId ?? u?.member?.studentId ?? ''),
isPayed: typeof (u?.isPayed ?? u?.member?.isPayed) === 'boolean' ? (u?.isPayed ?? u?.member?.isPayed) : false,
@@ -207,4 +208,3 @@ export default function AdminDashboard({ members = [], totalCount }) {
);
}
-
diff --git a/src/components/admin/AdminTableCell.tsx b/src/components/admin/AdminTableCell.tsx
index 8f10642..1e80945 100644
--- a/src/components/admin/AdminTableCell.tsx
+++ b/src/components/admin/AdminTableCell.tsx
@@ -2,6 +2,7 @@
import React from 'react';
import { User, Chip, Checkbox } from '@nextui-org/react';
+import { formatMajorLabel } from '@/constant/majorOptions';
const statusColorMap = {
true: 'success',
@@ -28,7 +29,7 @@ export default function AdminTableCell({ user, columnKey, onTogglePay }) {
case 'major':
return (
- {user.major}
+ {formatMajorLabel(user.major)}
{user.studentId}
);
@@ -54,4 +55,3 @@ export default function AdminTableCell({ user, columnKey, onTogglePay }) {
}
}
-
diff --git a/src/components/admin/UserDetailsModal.tsx b/src/components/admin/UserDetailsModal.tsx
index 5787e14..6e50032 100644
--- a/src/components/admin/UserDetailsModal.tsx
+++ b/src/components/admin/UserDetailsModal.tsx
@@ -3,6 +3,7 @@
import React, { useEffect } from 'react';
import { Button } from '@nextui-org/react';
import clsx from 'clsx';
+import { formatMajorLabel } from '@/constant/majorOptions';
import { formatPhoneNumberDisplay } from '@/utils/phoneNumber';
const FIELD_LABELS = {
@@ -79,6 +80,9 @@ const formatFieldValue = (key, value) => {
if (key === 'isPayed' && typeof value === 'boolean') {
return value ? '입금 완료' : '미입금';
}
+ if (key === 'major' && typeof value === 'string') {
+ return formatMajorLabel(value);
+ }
return formatValue(value);
};
diff --git a/src/components/auth/screen/AuthFindId.jsx b/src/components/auth/screen/AuthFindId.jsx
index 7f1315d..9ebdc55 100644
--- a/src/components/auth/screen/AuthFindId.jsx
+++ b/src/components/auth/screen/AuthFindId.jsx
@@ -8,7 +8,7 @@ import axios from 'axios';
import TransparentInput from '@/components/ui/input/TransparentInput';
import { usePhoneNumber } from '@/hooks/usePhoneNumber';
-import { majorOptions } from '@/constant/majorOptions';
+import { majorOptions, normalizeMajorCode } from '@/constant/majorOptions';
export default function AuthFindId({ handleBackToLogin }) {
const [name, setName] = useState('');
@@ -92,14 +92,14 @@ export default function AuthFindId({ handleBackToLogin }) {
base: 'bg-[#1c1c1c] text-white',
},
}}
- selectedKeys={major}
- onSelectionChange={setMajor}
+ selectedKeys={normalizeMajorCode(major)}
+ onSelectionChange={(value) => setMajor(String(value ?? ''))}
>
{majorOptions.map((major) => (
{major.items.map((item) => (
-
- {item.value}
+
+ {item.label}
))}
diff --git a/src/components/study/ui/card/ApplicantInfoList.jsx b/src/components/study/ui/card/ApplicantInfoList.jsx
index 906c44e..34693ba 100644
--- a/src/components/study/ui/card/ApplicantInfoList.jsx
+++ b/src/components/study/ui/card/ApplicantInfoList.jsx
@@ -2,6 +2,7 @@
// components
import GreenTextButton from "@/components/ui/button/GreenTextButton";
+import { formatMajorLabel } from '@/constant/majorOptions';
export default function ApplicantInfoList({
applications,
@@ -57,7 +58,7 @@ export default function ApplicantInfoList({
onClick={() => handleApplicantDetailPopup(app.id)}
>
| {app.name} |
- {app.major} |
+ {formatMajorLabel(app.major)} |
{app.studentId} |
{/* 이미 처리된 지원자가 있으면 상태 뱃지 표시 */}
@@ -104,4 +105,4 @@ export default function ApplicantInfoList({
);
-}
\ No newline at end of file
+}
diff --git a/src/components/study/ui/modal/ApplicantDetailModal.jsx b/src/components/study/ui/modal/ApplicantDetailModal.jsx
index f5bc167..558bbe7 100644
--- a/src/components/study/ui/modal/ApplicantDetailModal.jsx
+++ b/src/components/study/ui/modal/ApplicantDetailModal.jsx
@@ -2,6 +2,7 @@
import { useEffect } from 'react';
import { Spinner } from "@nextui-org/react";
+import { formatMajorLabel } from '@/constant/majorOptions';
// API Services
import { useApplicantDetail } from '@/services/study/useApplicantDetail';
@@ -58,7 +59,7 @@ export default function ApplicantDetailModal({ apiClient, studyId, selectedAppli
| 학번 |
- | {applicantDetail.major} |
+ {formatMajorLabel(applicantDetail.major)} |
{applicantDetail.studentId} |
@@ -108,4 +109,4 @@ export default function ApplicantDetailModal({ apiClient, studyId, selectedAppli
)
);
-}
\ No newline at end of file
+}
diff --git a/src/components/ui/design-system/GdgMajorDropdown.tsx b/src/components/ui/design-system/GdgMajorDropdown.tsx
index ef73a9f..3f20937 100644
--- a/src/components/ui/design-system/GdgMajorDropdown.tsx
+++ b/src/components/ui/design-system/GdgMajorDropdown.tsx
@@ -1,6 +1,6 @@
'use client'
-import { majorOptions } from '@/constant/majorOptions'
+import { majorOptions, normalizeMajorCode } from '@/constant/majorOptions'
import { GdgDropdown, type GdgDropdownOptionGroup } from './GdgDropdown'
export type GdgMajorDropdownProps = {
@@ -23,8 +23,8 @@ export function GdgMajorDropdown({
const groupedOptions: GdgDropdownOptionGroup[] = majorOptions.map((group) => ({
title: group.title,
items: group.items.map((item) => ({
- id: item.value,
- label: item.value
+ id: item.code,
+ label: item.label
}))
}))
@@ -34,7 +34,7 @@ export function GdgMajorDropdown({
size="full"
placeholder="학과를 입력해 주세요."
optionGroups={groupedOptions}
- value={value}
+ value={normalizeMajorCode(value)}
onChange={onChangeAction}
autoFocus={autoFocus}
isInvalid={isInvalid ?? Boolean(errorMessage)}
diff --git a/src/constant/majorOptions.ts b/src/constant/majorOptions.ts
index 2808449..3f98996 100644
--- a/src/constant/majorOptions.ts
+++ b/src/constant/majorOptions.ts
@@ -1,148 +1,198 @@
-export const majorOptions = [
+export type MajorOptionItem = {
+ code: string
+ label: string
+}
+
+export type MajorOptionGroup = {
+ title: string
+ items: MajorOptionItem[]
+}
+
+export const majorOptions: MajorOptionGroup[] = [
{
- title: '프런티어창의대학',
+ title: '소프트웨어융합대학',
items: [
- { key: '자유전공융합학부', value: '자유전공융합학부' },
- { key: '공학융합학부', value: '공학융합학부' },
- { key: '자연과학융합학부', value: '자연과학융합학부' },
- { key: '경영융합학부', value: '경영융합학부' },
- { key: '사회과학융합학부', value: '사회과학융합학부' },
- { key: '인문융합학부', value: '인문융합학부' }
+ { code: 'AIE', label: '인공지능공학과' },
+ { code: 'DSE', label: '데이터사이언스학과' },
+ { code: 'SME', label: '스마트모빌리티공학과' },
+ { code: 'DTE', label: '디자인테크놀로지학과' },
+ { code: 'CSE', label: '컴퓨터공학과' }
]
},
{
title: '공과대학',
items: [
- { key: '기계공학과', value: '기계공학과' },
- { key: '항공우주공학과', value: '항공우주공학과' },
- { key: '조선해양공학과', value: '조선해양공학과' },
- { key: '산업경영공학과', value: '산업경영공학과' },
- { key: '화학공학과', value: '화학공학과' },
- { key: '고분자공학과', value: '고분자공학과' },
- { key: '신소재공학과', value: '신소재공학과' },
- { key: '사회인프라공학과', value: '사회인프라공학과' },
- { key: '환경공학과', value: '환경공학과' },
- { key: '공간정보공학과', value: '공간정보공학과' },
- { key: '건축학부(건축공학)', value: '건축학부(건축공학)' },
- { key: '건축학부(건축학)', value: '건축학부(건축학)' },
- { key: '에너지자원공학과', value: '에너지자원공학과' },
- { key: '융합기술경영학부', value: '융합기술경영학부' },
- { key: '전기전자공학부', value: '전기전자공학부' },
- { key: '반도체시스템공학과', value: '반도체시스템공학과' },
- { key: '이차전지융합학과', value: '이차전지융합학과' }
+ { code: 'ME', label: '기계공학과' },
+ { code: 'AAE', label: '항공우주공학과' },
+ { code: 'NAE', label: '조선해양공학과' },
+ { code: 'IME', label: '산업경영공학과' },
+ { code: 'CHE', label: '화학공학과' },
+ { code: 'PSE', label: '고분자공학과' },
+ { code: 'MSE', label: '신소재공학과' },
+ { code: 'CIE', label: '사회인프라공학과' },
+ { code: 'ENVE', label: '환경공학과' },
+ { code: 'GIE', label: '공간정보공학과' },
+ { code: 'ACE', label: '건축학부(건축공학)' },
+ { code: 'ARCH', label: '건축학부(건축학)' },
+ { code: 'ERE', label: '에너지자원공학과' },
+ { code: 'MOT', label: '융합기술경영학부' },
+ { code: 'EEE', label: '전기전자공학부' },
+ { code: 'SSE', label: '반도체시스템공학과' },
+ { code: 'BCE', label: '이차전지융합학과' }
]
},
{
title: '자연과학대학',
items: [
- { key: '수학과', value: '수학과' },
- { key: '통계학과', value: '통계학과' },
- { key: '물리학과', value: '물리학과' },
- { key: '화학과', value: '화학과' },
- { key: '해양과학과', value: '해양과학과' },
- { key: '식품영양학과', value: '식품영양학과' }
+ { code: 'MATH', label: '수학과' },
+ { code: 'STAT', label: '통계학과' },
+ { code: 'PHYS', label: '물리학과' },
+ { code: 'CHEM', label: '화학과' },
+ { code: 'OCS', label: '해양과학과' },
+ { code: 'FNS', label: '식품영양학과' }
]
},
{
title: '경영대학',
items: [
- { key: '경영학부(경영학과)', value: '경영학부(경영학과)' },
- { key: '경영학부(파이낸스경영학과)', value: '경영학부(파이낸스경영학과)' },
- { key: '아태물류학부', value: '아태물류학부' },
- { key: '국제통상학과', value: '국제통상학과' }
+ { code: 'BUS', label: '경영학부(경영학과)' },
+ { code: 'FIN', label: '경영학부(파이낸스경영학과)' },
+ { code: 'APL', label: '아태물류학부' },
+ { code: 'ITC', label: '국제통상학과' }
]
},
{
- title: '사범대학',
+ title: '예술체육대학',
items: [
- { key: '국어교육과', value: '국어교육과' },
- { key: '영어교육과', value: '영어교육과' },
- { key: '사회교육과', value: '사회교육과' },
- { key: '교육학과', value: '교육학과' },
- { key: '체육교육과', value: '체육교육과' },
- { key: '수학교육과', value: '수학교육과' }
+ { code: 'FINEART', label: '조형예술학과' },
+ { code: 'ID', label: '디자인융합학과' },
+ { code: 'SPORTS', label: '스포츠과학과' },
+ { code: 'TFA', label: '연극영화학과' },
+ { code: 'FD', label: '의류디자인학과' }
]
},
{
title: '사회과학대학',
items: [
- { key: '행정학과', value: '행정학과' },
- { key: '정치외교학과', value: '정치외교학과' },
- { key: '미디어커뮤니케이션학과', value: '미디어커뮤니케이션학과' },
- { key: '경제학과', value: '경제학과' },
- { key: '소비자학과', value: '소비자학과' },
- { key: '아동심리학과', value: '아동심리학과' },
- { key: '사회복지학과', value: '사회복지학과' }
+ { code: 'PAD', label: '행정학과' },
+ { code: 'POL', label: '정치외교학과' },
+ { code: 'MCS', label: '미디어커뮤니케이션학과' },
+ { code: 'ECON', label: '경제학과' },
+ { code: 'CONS', label: '소비자학과' },
+ { code: 'CPSY', label: '아동심리학과' },
+ { code: 'SW', label: '사회복지학과' }
]
},
{
- title: '문과대학',
+ title: '프런티어창의대학',
items: [
- { key: '한국어문학과', value: '한국어문학과' },
- { key: '사학과', value: '사학과' },
- { key: '철학과', value: '철학과' },
- { key: '중국학과', value: '중국학과' },
- { key: '일본언어문화학과', value: '일본언어문화학과' },
- { key: '영미유럽인문융합학부', value: '영미유럽인문융합학부' },
- { key: '문화콘텐츠문화경영학과', value: '문화콘텐츠문화경영학과' }
+ { code: 'ULS', label: '자유전공융합학부' },
+ { code: 'ECS', label: '공학융합학부' },
+ { code: 'NCS', label: '자연과학융합학부' },
+ { code: 'BCONV', label: '경영융합학부' },
+ { code: 'SCS', label: '사회과학융합학부' },
+ { code: 'HCS', label: '인문융합학부' }
]
},
{
- title: '의과대학',
+ title: '문과대학',
items: [
- { key: '의예과', value: '의예과' },
- { key: '의학과', value: '의학과' }
+ { code: 'KLL', label: '한국어문학과' },
+ { code: 'HIST', label: '사학과' },
+ { code: 'PHIL', label: '철학과' },
+ { code: 'CHIN', label: '중국학과' },
+ { code: 'JLC', label: '일본언어문화학과' },
+ { code: 'ELH', label: '영미유럽인문융합학부' },
+ { code: 'CCM', label: '문화콘텐츠문화경영학과' }
]
},
- {
- title: '간호대학',
- items: [{ key: '간호학과', value: '간호학과' }]
- },
{
title: '미래융합대학',
items: [
- { key: '메카트로닉스공학과', value: '메카트로닉스공학과' },
- { key: '소프트웨어융합공학과', value: '소프트웨어융합공학과' },
- { key: '산업경영학과', value: '산업경영학과' },
- { key: '금융투자학과', value: '금융투자학과' }
+ { code: 'MTE', label: '메카트로닉스공학과' },
+ { code: 'SWE', label: '소프트웨어융합공학과' },
+ { code: 'IMGT', label: '산업경영학과' },
+ { code: 'FI', label: '금융투자학과' }
]
},
{
- title: '예술체육대학',
+ title: '바이오시스템융합학부',
items: [
- { key: '조형예술학과', value: '조형예술학과' },
- { key: '디자인융합학과', value: '디자인융합학과' },
- { key: '스포츠과학과', value: '스포츠과학과' },
- { key: '연극영화학과', value: '연극영화학과' },
- { key: '의류디자인학과', value: '의류디자인학과' }
+ { code: 'BIOE', label: '생명공학과' },
+ { code: 'BPE', label: '바이오제약공학과' },
+ { code: 'BIOS', label: '생명과학과' },
+ { code: 'ABM', label: '첨단바이오의약학과' },
+ { code: 'BFE', label: '바이오식품공학과' }
]
},
{
title: '국제학부',
items: [
- { key: 'IBT학과', value: 'IBT학과' },
- { key: 'ISE학과', value: 'ISE학과' },
- { key: 'KLC학과', value: 'KLC학과' }
+ { code: 'IBT', label: 'IBT학과' },
+ { code: 'ISE', label: 'ISE학과' },
+ { code: 'KLC', label: 'KLC학과' }
]
},
{
- title: '소프트웨어융합대학',
+ title: '의과대학',
items: [
- { key: '인공지능공학과', value: '인공지능공학과' },
- { key: '데이터사이언스학과', value: '데이터사이언스학과' },
- { key: '스마트모빌리티공학과', value: '스마트모빌리티공학과' },
- { key: '디자인테크놀로지학과', value: '디자인테크놀로지학과' },
- { key: '컴퓨터공학과', value: '컴퓨터공학과' }
+ { code: 'PREMED', label: '의예과' },
+ { code: 'MED', label: '의학과' }
]
},
{
- title: '바이오시스템융합학부',
+ title: '간호대학',
+ items: [{ code: 'NURS', label: '간호학과' }]
+ },
+ {
+ title: '사범대학',
items: [
- { key: '생명공학과', value: '생명공학과' },
- { key: '바이오제약공학과', value: '바이오제약공학과' },
- { key: '생명과학과', value: '생명과학과' },
- { key: '첨단바이오의약학과', value: '첨단바이오의약학과' },
- { key: '바이오식품공학과', value: '바이오식품공학과' }
+ { code: 'KOR_EDU', label: '국어교육과' },
+ { code: 'ENG_EDU', label: '영어교육과' },
+ { code: 'SOC_EDU', label: '사회교육과' },
+ { code: 'EDU', label: '교육학과' },
+ { code: 'PE_EDU', label: '체육교육과' },
+ { code: 'MATH_EDU', label: '수학교육과' }
]
}
]
+
+const allMajorItems = majorOptions.flatMap((group) => group.items)
+
+export const majorLabelByCode = Object.freeze(
+ allMajorItems.reduce>((acc, item) => {
+ acc[item.code] = item.label
+ return acc
+ }, {})
+)
+
+const majorCodeByLabel = allMajorItems.reduce>((acc, item) => {
+ acc[item.label] = item.code
+ return acc
+}, {})
+
+const majorAliasToCode: Record = {
+ ...majorCodeByLabel,
+ 스마트모빌리티놀학과: 'SME',
+ 건축공학전공: 'ACE',
+ '건축학전공(5년제)': 'ARCH',
+ 경영학과: 'BUS',
+ 파이낸스경영학과: 'FIN',
+ '파이낸스경영학부(경영학과)': 'FIN',
+ '문화콘텐츠문화경영학부(경영학과)': 'CCM',
+ 문화컨텐츠경영학과: 'CCM'
+}
+
+export const normalizeMajorCode = (value?: string | null): string => {
+ if (!value) return ''
+ const trimmed = value.trim()
+ if (!trimmed) return ''
+ if (majorLabelByCode[trimmed]) return trimmed
+ return majorAliasToCode[trimmed] ?? trimmed
+}
+
+export const formatMajorLabel = (value?: string | null): string => {
+ if (!value) return '-'
+ const normalized = normalizeMajorCode(value)
+ return majorLabelByCode[normalized] ?? value
+}