diff --git a/src/components/CourseRegister/InfoContent.tsx b/src/components/CourseRegister/InfoContent.tsx
new file mode 100644
index 0000000..915a99e
--- /dev/null
+++ b/src/components/CourseRegister/InfoContent.tsx
@@ -0,0 +1,152 @@
+import {styled} from 'styled-components';
+import {WarningWrap} from '../LectureList/Filters';
+
+function InfoContent() {
+ return (
+ <>
+
+ 2025-1학기 수강신청 연습 안내
+
+ 1. 시간표 업데이트 일정: 1.24.(금)
+
+
+ 2. 수강신청 주요일정
+
+
+
+
+ | 구분 |
+ 대상 |
+ 일정 |
+ 비고 |
+
+
+
+
+ | 수강신청 |
+
+ 4학년(7~8학기 등록 예정자), 건축학 5학년, 수업연한초과자
+ |
+ 2.17.(월) 10:00 ~ 17:00 |
+
+ 소속학부(과)의 주·복수·부
+
+ 전공과목과 교양과목만 수강신청
+ 가능
+ |
+
+
+ | 3학년(5~6학기 등록 예정자) |
+ 2.18.(화) 10:00 ~ 17:00 |
+
+
+ | 2학년(3~4학기 등록 예정자) |
+ 2.19.(수) 10:00 ~ 17:00 |
+
+
+ | 1학년(1~2학기 등록 예정자) |
+ 2.20.(목) 10:00 ~ 17:00 |
+
+
+ | 전학년 |
+ 2.21.(금) 10:00 ~ 17:00 |
+
+ 다른 학과 전공과목도 수강신청
+ 가능
+ |
+
+
+
+ 수강신청과목 확인 및 변경
+ |
+ 전학년 |
+ 2. 25.(화) ~ 2.28.(금) 10:00 ~ 17:00 |
+
+ 다른 학과 전공과목도 수강신청
+ 가능
+ |
+
+
+
+
+
+ 3. 수강신청 연습 방법 ※날짜 설정 모드※
+
+ 본인의 학과를 선택하고, 수강신청 날짜를 지정합니다.
+
+ - 본인 학년 선택 -> 본인 소속학부(과)의 주·복수·부전공과목과
+ 교양과목만 수강신청 가능
+
+ - 전학년 선택 -> 다른 학과 전공과목도 수강신청가능
+
+ 학과를 선택하지 않을 경우, 학과 제한이 없는 전학년 수강신청 날짜로
+ 자동 설정됩니다.
+
+
+
+
+ ※ 본 수강신청 연습 사이트는 학사정보시스템의 실제 수강신청과 다를 수
+ 있습니다. 수강 대상 및 유의사항을 반드시 확인하시고, 수강편람을
+ 숙지하여 주시기 바랍니다.
+
+
+
+ >
+ );
+}
+
+const Container = styled.div`
+ border: 0.1rem solid #714656;
+ border-radius: 2px;
+ padding: 1.5rem 1.5rem;
+ margin-bottom: 2rem;
+
+ > p {
+ font-weight: normal;
+ font-size: 1.4rem;
+ margin-bottom: 8px;
+ line-height: 1.6;
+ letter-spacing: 0.01em;
+
+ > span {
+ font-weight: bold;
+ font-size: 1.4rem;
+ color: #333;
+ }
+ }
+`;
+
+const SubTitle = styled.div`
+ ${props => props.theme.texts.subtitle};
+ font-size: 1.6rem;
+ margin-bottom: 15px;
+`;
+
+const Table = styled.table`
+ width: 90%;
+ height: auto;
+ max-width: 70rem;
+ border-collapse: collapse;
+ border: 1.6px solid #000;
+
+ th {
+ ${props => props.theme.texts.tableTitle};
+ background-color: #e5e5e5;
+ border: 1px solid #c3c3c3;
+ padding: 0.8rem;
+ text-align: center;
+ }
+
+ td {
+ ${props => props.theme.texts.content};
+ border: 1px solid #c3c3c3;
+ padding: 0.8rem;
+ text-align: center;
+ vertical-align: middle;
+ line-height: 1.4;
+ letter-spacing: 0.01em;
+ word-break: break-all;
+ }
+`;
+
+export default InfoContent;
diff --git a/src/components/CourseRegister/RegisterInfo.tsx b/src/components/CourseRegister/RegisterInfo.tsx
new file mode 100644
index 0000000..a5b2de2
--- /dev/null
+++ b/src/components/CourseRegister/RegisterInfo.tsx
@@ -0,0 +1,122 @@
+import {TableTitle, TableTitleWrap} from '../LectureList';
+import styled from 'styled-components';
+import SelectBox from '../common/SelectBox';
+import {major} from '@/assets/data/filter';
+import {useAppSelector} from '@/store/hooks';
+import {useDispatch} from 'react-redux';
+import {setSelectedDate, setUserMajor} from '@/store/modules/dateModeSlice';
+import InfoContent from './InfoContent';
+
+interface RegisterInfoProps {
+ onClickNext: () => void;
+}
+
+function RegisterInfo({onClickNext}: RegisterInfoProps) {
+ const userMajor = useAppSelector(state => state.dateMode.userMajor);
+ const dispatch = useDispatch();
+
+ const handleSelectMajor = (value: string | undefined) => {
+ dispatch(setUserMajor(value!.split('【')[0]));
+ if (value === '-전체-') {
+ dispatch(setSelectedDate('전학년 (학과 제한 없음)'));
+ }
+ };
+
+ const handleSelectDate = (value: string | undefined) => {
+ dispatch(setSelectedDate(value!));
+ };
+
+ return (
+ <>
+
+ 안내문
+
+
+
+
+
+
+ 학과전공
+ handleSelectMajor(value)}
+ />
+
+
+ 수강신청 날짜
+ handleSelectDate(value)}
+ restricted={userMajor === '-전체-'}
+ />
+
+
+ 저장/NEXT
+
+
+ >
+ );
+}
+
+const Container = styled.div`
+ border: 0.1rem solid #714656;
+ border-radius: 2px;
+ padding: 1.5rem 1.5rem;
+ margin-bottom: 2rem;
+`;
+
+export const SelectArea = styled.div`
+ display: flex;
+ align-items: flex-end;
+ justify-content: space-between;
+ gap: 0.7rem 3rem;
+
+ @media ${props => props.theme.device.mobile} {
+ flex-wrap: wrap;
+ }
+`;
+
+export const SelectBoxWrap = styled.div`
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.7rem 3rem;
+`;
+
+export const SelectWrap = styled.div`
+ ${props => props.theme.texts.tableTitle};
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.7rem 0;
+ align-items: center;
+
+ > span {
+ margin-right: 1rem;
+ text-align: right;
+ min-width: 7rem;
+ flex-basis: 7rem;
+ }
+`;
+
+const ButtonWrap = styled.button`
+ ${props => props.theme.texts.content};
+ background-color: ${props => props.theme.colors.primary};
+ color: ${props => props.theme.colors.white};
+ min-width: 8rem;
+ height: 2.4rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.8rem;
+
+ &:hover {
+ filter: grayscale(15%);
+ }
+`;
+
+export default RegisterInfo;
diff --git a/src/components/CourseRegister/index.tsx b/src/components/CourseRegister/index.tsx
index a32241f..8414842 100644
--- a/src/components/CourseRegister/index.tsx
+++ b/src/components/CourseRegister/index.tsx
@@ -7,7 +7,9 @@ import RegisteredList from './RegisteredList';
import {useDispatch} from 'react-redux';
import {
setCourseName,
+ setCuriTypeCdNm,
setModalName,
+ setSchDeptAlias,
setScheduleId,
} from '@/store/modules/modalSlice';
import StartButton from '@components/CourseRegister/StartButton.tsx';
@@ -15,6 +17,8 @@ import {getCourseList, getRegisterdList, getWishlist} from '@/apis/api/course';
import {useAppSelector} from '@/store/hooks';
import {openModalHandler} from '../common/Modal/handlers/handler';
import {setEndCount} from '@/store/modules/courseRegisteredSlice';
+import RegisterInfo from './RegisterInfo';
+import {setIsConfirm} from '@/store/modules/dateModeSlice';
const colData = [
{name: 'action', value: '신청', initialWidth: 50, enableFilters: false},
@@ -44,6 +48,7 @@ function CourseRegister() {
const dispatch = useDispatch();
const studentId = useAppSelector(state => state.userInfo.username);
+ const isConfirm = useAppSelector(state => state.dateMode.isConfirm);
useEffect(() => {
dispatch(setEndCount(false));
@@ -95,32 +100,42 @@ function CourseRegister() {
_action: string,
scheduleId: number | undefined,
curiNm: string | undefined,
+ schDeptAlias: string | undefined,
+ curiTypeCdNm: string | undefined,
) => {
- if (scheduleId && curiNm) {
+ if (scheduleId && curiNm && schDeptAlias && curiTypeCdNm) {
dispatch(setScheduleId(scheduleId));
dispatch(setCourseName(curiNm));
dispatch(setModalName('macro'));
+ dispatch(setSchDeptAlias(schDeptAlias));
+ dispatch(setCuriTypeCdNm(curiTypeCdNm));
}
};
return (
<>
-
-
-
- 수강대상교과목
-
-
-
+ {!isConfirm ? (
+ dispatch(setIsConfirm())} />
+ ) : (
+ <>
+
+
+
+ 수강대상교과목
+
+
+
+ >
+ )}
>
);
}
diff --git a/src/components/LectureList/Filters.tsx b/src/components/LectureList/Filters.tsx
index ccae9dd..d180956 100644
--- a/src/components/LectureList/Filters.tsx
+++ b/src/components/LectureList/Filters.tsx
@@ -119,7 +119,7 @@ function Filters({onSearch}: FiltersProps) {
);
}
-const WarningWrap = styled.div`
+export const WarningWrap = styled.div`
${props => props.theme.texts.warning};
color: #c30e2e;
margin-bottom: -1.5rem;
diff --git a/src/components/LoginForm/FormInput.tsx b/src/components/LoginForm/FormInput.tsx
index 8684065..a05cdc0 100644
--- a/src/components/LoginForm/FormInput.tsx
+++ b/src/components/LoginForm/FormInput.tsx
@@ -24,7 +24,6 @@ const InputWrap = styled.input`
height: 4rem;
width: 38rem;
font-size: 1.9rem;
- padding: 0 1rem;
`;
export default FormInput;
diff --git a/src/components/TabMenu/Tab.tsx b/src/components/TabMenu/Tab.tsx
index 13d7ce9..3f03285 100644
--- a/src/components/TabMenu/Tab.tsx
+++ b/src/components/TabMenu/Tab.tsx
@@ -2,6 +2,7 @@ import styled, {css} from 'styled-components';
import close from '@assets/img/close-line-red.png';
import {useAppDispatch, useAppSelector} from '@/store/hooks';
import {delTab, setFocused} from '@/store/modules/tabSlice';
+import {resetDateMode} from '@/store/modules/dateModeSlice';
interface TabProps {
id: number;
@@ -23,6 +24,9 @@ function Tab({id, label, isActive, onClick}: TabProps) {
dispatch(setFocused(tabs[idx - 1].id));
}
dispatch(delTab(id));
+ if (label === '수강신청') {
+ dispatch(resetDateMode());
+ }
};
return (
diff --git a/src/components/Wishlist/Filters.tsx b/src/components/Wishlist/Filters.tsx
index fd5f0f3..eb7cfaa 100644
--- a/src/components/Wishlist/Filters.tsx
+++ b/src/components/Wishlist/Filters.tsx
@@ -202,7 +202,7 @@ const WishFilterWrap = styled(FilterWrap)`
display: inline-block;
margin-right: 1rem;
text-align: right;
- min-width: 4.5rem;
+ min-width: 5rem;
}
`;
diff --git a/src/components/common/Modal/ErrorModal.tsx b/src/components/common/Modal/ErrorModal.tsx
index 2045e7d..64d442e 100644
--- a/src/components/common/Modal/ErrorModal.tsx
+++ b/src/components/common/Modal/ErrorModal.tsx
@@ -34,6 +34,8 @@ function ErrorModal() {
default:
return '422 알 수 없는 오류';
}
+ case 500:
+ return '대상학년 또는 대상학과가 아니므로 수강신청할 수 없습니다!';
default:
return '알 수 없는 오류';
}
@@ -95,12 +97,12 @@ const ModalHeader = styled.div`
const CloseImage = styled.img.attrs({
src: `${close}`,
})`
- display: block;
- width: 25px;
- height: 25px;
- cursor: pointer;
- margin-top: 10px;
- margin-right: 10px;
+ display: block;
+ width: 25px;
+ height: 25px;
+ cursor: pointer;
+ margin-top: 10px;
+ margin-right: 10px;
`;
const WarningImage = styled.img.attrs({
diff --git a/src/components/common/Modal/LoadingModal.tsx b/src/components/common/Modal/LoadingModal.tsx
index 3733f51..9209f5a 100644
--- a/src/components/common/Modal/LoadingModal.tsx
+++ b/src/components/common/Modal/LoadingModal.tsx
@@ -7,9 +7,20 @@ import {useAppSelector} from '@store/hooks';
import {postCourse} from '@apis/api/course.ts';
import {setType} from '@/store/modules/errorSlice';
-function LoadingModal({scheduleId}: {scheduleId: number}) {
- const dispatch = useDispatch();
+interface LoadingModalProps {
+ scheduleId: number;
+ schDeptAlias: string;
+ curiTypeCdNm: string;
+}
+function LoadingModal({
+ scheduleId,
+ schDeptAlias,
+ curiTypeCdNm,
+}: LoadingModalProps) {
+ const dispatch = useDispatch();
+ const userMajor = useAppSelector(state => state.dateMode.userMajor);
+ const selectedDate = useAppSelector(state => state.dateMode.selectedDate);
const endCount = useAppSelector(state => state.courseRegistered.endCount);
useEffect(() => {
@@ -26,8 +37,27 @@ function LoadingModal({scheduleId}: {scheduleId: number}) {
return;
}
- // 수강신청 요청
+ // 본인학년 (학과 제한 있음) 선택 시 학과 제한
+ if (
+ selectedDate === '본인학년 (학과 제한 있음)' &&
+ schDeptAlias !== '대양휴머니티칼리지' &&
+ schDeptAlias !== userMajor
+ ) {
+ dispatch(setType(500));
+ openModalHandler(dispatch, 'fail');
+ return;
+ }
+
+ //교직은 교육학과만 수강가능
+ if (curiTypeCdNm === '교직') {
+ if (schDeptAlias !== '교육학과') {
+ dispatch(setType(500));
+ openModalHandler(dispatch, 'fail');
+ return;
+ }
+ }
+ // 수강신청 요청
try {
const res = await postCourse(scheduleId);
if (res === 'Course already registered') {
diff --git a/src/components/common/SelectBox.tsx b/src/components/common/SelectBox.tsx
index ed8842a..db169f5 100644
--- a/src/components/common/SelectBox.tsx
+++ b/src/components/common/SelectBox.tsx
@@ -12,9 +12,16 @@ interface SelectProps {
disabled?: boolean;
sizes: string;
onSelect: (value: string) => void;
+ restricted?: boolean;
}
-function SelectBox({options, disabled = false, sizes, onSelect}: SelectProps) {
+function SelectBox({
+ options,
+ disabled = false,
+ sizes,
+ onSelect,
+ restricted = false,
+}: SelectProps) {
const [open, setOpen] = useState(false);
const [input, setInput] = useState(options[0].value);
const [selected, setSelected] = useState(options[0].value);
@@ -65,7 +72,11 @@ function SelectBox({options, disabled = false, sizes, onSelect}: SelectProps) {
return (
-
+
{open && (
@@ -138,8 +149,8 @@ const InputContainer = styled.div<{disabled: boolean}>`
const InputWrap = styled.input`
${props => props.theme.texts.content};
- width: calc(100% - 1rem);
- height: inherit;
+ width: 100%;
+ height: 100%;
padding: 0 0 0 1rem;
&:hover {
diff --git a/src/components/common/Table/index.tsx b/src/components/common/Table/index.tsx
index e3168af..a6b0b11 100644
--- a/src/components/common/Table/index.tsx
+++ b/src/components/common/Table/index.tsx
@@ -13,6 +13,8 @@ interface TableProps {
action: string,
scheduleId: number | undefined,
curiNm: string | undefined,
+ schDeptAlias: string | undefined,
+ curiTypeCdNm: string | undefined,
) => void;
}
@@ -84,7 +86,13 @@ function Table({data, colData, width, height, onAction}: TableProps) {
const handleActionClick = (row: CourseTypes, action: string) => {
if (onAction) {
- onAction(action, row.scheduleId, row.curiNm);
+ onAction(
+ action,
+ row.scheduleId,
+ row.curiNm,
+ row.schDeptAlias,
+ row.curiTypeCdNm,
+ );
} else {
console.log(`${action} action for scheduleId: ${row.scheduleId}`);
}
@@ -189,7 +197,6 @@ const TableBox = styled.div<{width: string; height: string}>`
border-bottom: 1px solid #c3c3c3;
border-top: 1px solid ${props => props.theme.colors.black};
white-space: nowrap;
- overflow:;
`;
const RowWrap = styled.div`
diff --git a/src/pages/index/Home.tsx b/src/pages/index/Home.tsx
index 17c6517..a5bb274 100644
--- a/src/pages/index/Home.tsx
+++ b/src/pages/index/Home.tsx
@@ -22,9 +22,8 @@ function Home() {
const {tab, focused} = useAppSelector(state => state.tabs);
const [barOpen, setBarOpen] = useState(isPc);
- const {modalName, scheduleId, courseName} = useAppSelector(
- state => state.modalInfo,
- );
+ const {modalName, scheduleId, courseName, schDeptAlias, curiTypeCdNm} =
+ useAppSelector(state => state.modalInfo);
const focusedTab = tab.find(tab => tab.id === focused);
const focusedTabName = focusedTab ? focusedTab.name : '선택된 탭이 없습니다.';
@@ -57,7 +56,13 @@ function Home() {
case 'check':
return ;
case 'loading':
- return ;
+ return (
+
+ );
case 'reload':
return ;
case 'fail':
diff --git a/src/store/modules/dateModeSlice.ts b/src/store/modules/dateModeSlice.ts
new file mode 100644
index 0000000..3ac75c4
--- /dev/null
+++ b/src/store/modules/dateModeSlice.ts
@@ -0,0 +1,40 @@
+import {createSlice} from '@reduxjs/toolkit';
+
+export interface dateMode {
+ isConfirm: boolean;
+ userMajor: string;
+ selectedDate: string;
+}
+
+const dateMode = createSlice({
+ name: 'dateMode',
+ initialState: {
+ isConfirm: false,
+ userMajor: '-전체-',
+ selectedDate: '전학년 (학과 제한 없음)',
+ },
+ reducers: {
+ setIsConfirm(state: dateMode) {
+ state.isConfirm = true;
+ },
+
+ setUserMajor(state: dateMode, {payload}: {payload: string}) {
+ state.userMajor = payload;
+ },
+
+ setSelectedDate(state: dateMode, {payload}: {payload: string}) {
+ state.selectedDate = payload;
+ },
+
+ resetDateMode(state: dateMode) {
+ state.isConfirm = false;
+ state.userMajor = '-전체-';
+ state.selectedDate = '전학년 (학과 제한 없음)';
+ },
+ },
+});
+
+export const {setIsConfirm, setUserMajor, setSelectedDate, resetDateMode} =
+ dateMode.actions;
+
+export default dateMode.reducer;
diff --git a/src/store/modules/modalSlice.ts b/src/store/modules/modalSlice.ts
index 86e12f7..8b108d4 100644
--- a/src/store/modules/modalSlice.ts
+++ b/src/store/modules/modalSlice.ts
@@ -4,6 +4,8 @@ export interface ModalInfo {
modalName: string;
scheduleId: number;
courseName: string;
+ schDeptAlias: string;
+ curiTypeCdNm: string;
}
const modalInfo = createSlice({
@@ -12,6 +14,8 @@ const modalInfo = createSlice({
modalName: '',
scheduleId: 0,
courseName: '',
+ schDeptAlias: '',
+ curiTypeCdNm: '',
},
reducers: {
setModalName(state: ModalInfo, {payload}: {payload: string}) {
@@ -26,14 +30,31 @@ const modalInfo = createSlice({
state.courseName = payload;
},
+ setSchDeptAlias(state: ModalInfo, {payload}: {payload: string}) {
+ state.schDeptAlias = payload;
+ },
+
+ setCuriTypeCdNm(state: ModalInfo, {payload}: {payload: string}) {
+ state.curiTypeCdNm = payload;
+ },
+
clearModalInfo(state: ModalInfo) {
state.modalName = '';
state.scheduleId = 0;
state.courseName = '';
+ state.schDeptAlias = '';
+ state.curiTypeCdNm = '';
},
},
});
-export const {setModalName, setScheduleId, setCourseName, clearModalInfo} = modalInfo.actions;
+export const {
+ setModalName,
+ setScheduleId,
+ setCourseName,
+ setSchDeptAlias,
+ setCuriTypeCdNm,
+ clearModalInfo,
+} = modalInfo.actions;
-export default modalInfo.reducer;
\ No newline at end of file
+export default modalInfo.reducer;
diff --git a/src/store/store.ts b/src/store/store.ts
index 6f05a2e..7892493 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -7,6 +7,7 @@ import modalSlice from '@/store/modules/modalSlice';
import courseRegisteredSlice from '@/store/modules/courseRegisteredSlice';
import tabSlice from './modules/tabSlice';
import errorSlice from './modules/errorSlice';
+import dateModeSlice from './modules/dateModeSlice';
const reducers = combineReducers({
userInfo: userSlice,
@@ -14,6 +15,7 @@ const reducers = combineReducers({
courseRegistered: courseRegisteredSlice,
tabs: tabSlice,
error: errorSlice,
+ dateMode: dateModeSlice,
});
const persistConfig = {
diff --git a/src/styles/FilterLayout.tsx b/src/styles/FilterLayout.tsx
index 22e202b..7bedbe3 100644
--- a/src/styles/FilterLayout.tsx
+++ b/src/styles/FilterLayout.tsx
@@ -34,6 +34,7 @@ export const FilterWrap = styled.div`
> span {
margin-right: 1rem;
text-align: right;
- min-width: 4.5rem;
+ min-width: 5rem;
+ flex-basis: 5rem;
}
`;