Skip to content

Commit e57d6fa

Browse files
authored
feat(TS-31): 날짜 설정 모드 추가 (#100)
* feat: 수강신청 안내 페이지 추가 - 수강신청 안내문과 본인 학과와 날짜를 설정할 수 있는 컴포넌트를 추가하였습니다. - 학과와 날짜 설정을 저장하기 위한 slice를 추가하였습니다. * feat: 날짜 설정 모드 - 본인학년 날짜 선택 시 타학과 전공과목을 신청할 수 없게 에러 타입을 추가하였습니다 - 교직은 교육학과만 신청할 수 있게 하였습니다 - 수강신청 탭을 닫으면 전역상태에 저장된 dateMode의 값을 초기화하도록 하였습니다
1 parent 1669b85 commit e57d6fa

File tree

16 files changed

+453
-42
lines changed

16 files changed

+453
-42
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import {styled} from 'styled-components';
2+
import {WarningWrap} from '../LectureList/Filters';
3+
4+
function InfoContent() {
5+
return (
6+
<>
7+
<Container>
8+
<SubTitle>2025-1학기 수강신청 연습 안내</SubTitle> <br />
9+
<p>
10+
<span>1. 시간표 업데이트 일정:</span> 1.24.(금)
11+
</p>
12+
<p>
13+
<span>2. 수강신청 주요일정</span>
14+
</p>
15+
<Table>
16+
<thead>
17+
<tr>
18+
<th>구분</th>
19+
<th>대상</th>
20+
<th>일정</th>
21+
<th>비고</th>
22+
</tr>
23+
</thead>
24+
<tbody>
25+
<tr>
26+
<td rowSpan={5}>수강신청</td>
27+
<td>
28+
4학년(7~8학기 등록 예정자), <br /> 건축학 5학년, 수업연한초과자
29+
</td>
30+
<td>2.17.(월) 10:00 ~ 17:00</td>
31+
<td rowSpan={4}>
32+
소속학부(과)의 주·복수·부
33+
<br />
34+
전공과목과 교양과목만 수강신청 <br />
35+
가능
36+
</td>
37+
</tr>
38+
<tr>
39+
<td>3학년(5~6학기 등록 예정자)</td>
40+
<td>2.18.(화) 10:00 ~ 17:00</td>
41+
</tr>
42+
<tr>
43+
<td>2학년(3~4학기 등록 예정자)</td>
44+
<td>2.19.(수) 10:00 ~ 17:00</td>
45+
</tr>
46+
<tr>
47+
<td>1학년(1~2학기 등록 예정자)</td>
48+
<td>2.20.(목) 10:00 ~ 17:00</td>
49+
</tr>
50+
<tr>
51+
<td>전학년</td>
52+
<td>2.21.(금) 10:00 ~ 17:00</td>
53+
<td>
54+
다른 학과 전공과목도 수강신청
55+
<br /> 가능
56+
</td>
57+
</tr>
58+
<tr>
59+
<td>
60+
수강신청과목 <br /> 확인 및 변경
61+
</td>
62+
<td>전학년</td>
63+
<td>2. 25.(화) ~ 2.28.(금) 10:00 ~ 17:00</td>
64+
<td>
65+
다른 학과 전공과목도 수강신청
66+
<br /> 가능
67+
</td>
68+
</tr>
69+
</tbody>
70+
</Table>
71+
<br />
72+
<p>
73+
<span>3. 수강신청 연습 방법 &nbsp; ※날짜 설정 모드※</span>
74+
</p>
75+
<p>본인의 학과를 선택하고, 수강신청 날짜를 지정합니다.</p>
76+
<p>
77+
- 본인 학년 선택 -&gt; 본인 소속학부(과)의 주·복수·부전공과목과
78+
교양과목만 수강신청 가능
79+
</p>
80+
<p>- 전학년 선택 -&gt; 다른 학과 전공과목도 수강신청가능</p>
81+
<p>
82+
학과를 선택하지 않을 경우, 학과 제한이 없는 전학년 수강신청 날짜로
83+
자동 설정됩니다.
84+
</p>
85+
<br />
86+
<WarningWrap>
87+
<p>
88+
※ 본 수강신청 연습 사이트는 학사정보시스템의 실제 수강신청과 다를 수
89+
있습니다. 수강 대상 및 유의사항을 반드시 확인하시고, 수강편람을
90+
숙지하여 주시기 바랍니다.
91+
</p>
92+
</WarningWrap>
93+
</Container>
94+
</>
95+
);
96+
}
97+
98+
const Container = styled.div`
99+
border: 0.1rem solid #714656;
100+
border-radius: 2px;
101+
padding: 1.5rem 1.5rem;
102+
margin-bottom: 2rem;
103+
104+
> p {
105+
font-weight: normal;
106+
font-size: 1.4rem;
107+
margin-bottom: 8px;
108+
line-height: 1.6;
109+
letter-spacing: 0.01em;
110+
111+
> span {
112+
font-weight: bold;
113+
font-size: 1.4rem;
114+
color: #333;
115+
}
116+
}
117+
`;
118+
119+
const SubTitle = styled.div`
120+
${props => props.theme.texts.subtitle};
121+
font-size: 1.6rem;
122+
margin-bottom: 15px;
123+
`;
124+
125+
const Table = styled.table`
126+
width: 90%;
127+
height: auto;
128+
max-width: 70rem;
129+
border-collapse: collapse;
130+
border: 1.6px solid #000;
131+
132+
th {
133+
${props => props.theme.texts.tableTitle};
134+
background-color: #e5e5e5;
135+
border: 1px solid #c3c3c3;
136+
padding: 0.8rem;
137+
text-align: center;
138+
}
139+
140+
td {
141+
${props => props.theme.texts.content};
142+
border: 1px solid #c3c3c3;
143+
padding: 0.8rem;
144+
text-align: center;
145+
vertical-align: middle;
146+
line-height: 1.4;
147+
letter-spacing: 0.01em;
148+
word-break: break-all;
149+
}
150+
`;
151+
152+
export default InfoContent;
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import {TableTitle, TableTitleWrap} from '../LectureList';
2+
import styled from 'styled-components';
3+
import SelectBox from '../common/SelectBox';
4+
import {major} from '@/assets/data/filter';
5+
import {useAppSelector} from '@/store/hooks';
6+
import {useDispatch} from 'react-redux';
7+
import {setSelectedDate, setUserMajor} from '@/store/modules/dateModeSlice';
8+
import InfoContent from './InfoContent';
9+
10+
interface RegisterInfoProps {
11+
onClickNext: () => void;
12+
}
13+
14+
function RegisterInfo({onClickNext}: RegisterInfoProps) {
15+
const userMajor = useAppSelector(state => state.dateMode.userMajor);
16+
const dispatch = useDispatch();
17+
18+
const handleSelectMajor = (value: string | undefined) => {
19+
dispatch(setUserMajor(value!.split('【')[0]));
20+
if (value === '-전체-') {
21+
dispatch(setSelectedDate('전학년 (학과 제한 없음)'));
22+
}
23+
};
24+
25+
const handleSelectDate = (value: string | undefined) => {
26+
dispatch(setSelectedDate(value!));
27+
};
28+
29+
return (
30+
<>
31+
<TableTitleWrap>
32+
<TableTitle>안내문</TableTitle>
33+
</TableTitleWrap>
34+
<InfoContent />
35+
<Container>
36+
<SelectArea>
37+
<SelectBoxWrap>
38+
<SelectWrap>
39+
<span>학과전공</span>
40+
<SelectBox
41+
options={major}
42+
sizes='xl'
43+
onSelect={value => handleSelectMajor(value)}
44+
/>
45+
</SelectWrap>
46+
<SelectWrap>
47+
<span>수강신청 날짜</span>
48+
<SelectBox
49+
options={[
50+
{id: 0, value: '전학년 (학과 제한 없음)'},
51+
{id: 1, value: '본인학년 (학과 제한 있음)'},
52+
]}
53+
disabled={userMajor === '-전체-' ? true : false}
54+
sizes='m'
55+
onSelect={value => handleSelectDate(value)}
56+
restricted={userMajor === '-전체-'}
57+
/>
58+
</SelectWrap>
59+
</SelectBoxWrap>
60+
<ButtonWrap onClick={onClickNext}>저장/NEXT</ButtonWrap>
61+
</SelectArea>
62+
</Container>
63+
</>
64+
);
65+
}
66+
67+
const Container = styled.div`
68+
border: 0.1rem solid #714656;
69+
border-radius: 2px;
70+
padding: 1.5rem 1.5rem;
71+
margin-bottom: 2rem;
72+
`;
73+
74+
export const SelectArea = styled.div`
75+
display: flex;
76+
align-items: flex-end;
77+
justify-content: space-between;
78+
gap: 0.7rem 3rem;
79+
80+
@media ${props => props.theme.device.mobile} {
81+
flex-wrap: wrap;
82+
}
83+
`;
84+
85+
export const SelectBoxWrap = styled.div`
86+
display: flex;
87+
flex-wrap: wrap;
88+
gap: 0.7rem 3rem;
89+
`;
90+
91+
export const SelectWrap = styled.div`
92+
${props => props.theme.texts.tableTitle};
93+
display: flex;
94+
flex-wrap: wrap;
95+
gap: 0.7rem 0;
96+
align-items: center;
97+
98+
> span {
99+
margin-right: 1rem;
100+
text-align: right;
101+
min-width: 7rem;
102+
flex-basis: 7rem;
103+
}
104+
`;
105+
106+
const ButtonWrap = styled.button`
107+
${props => props.theme.texts.content};
108+
background-color: ${props => props.theme.colors.primary};
109+
color: ${props => props.theme.colors.white};
110+
min-width: 8rem;
111+
height: 2.4rem;
112+
display: flex;
113+
align-items: center;
114+
justify-content: center;
115+
gap: 0.8rem;
116+
117+
&:hover {
118+
filter: grayscale(15%);
119+
}
120+
`;
121+
122+
export default RegisterInfo;

src/components/CourseRegister/index.tsx

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ import RegisteredList from './RegisteredList';
77
import {useDispatch} from 'react-redux';
88
import {
99
setCourseName,
10+
setCuriTypeCdNm,
1011
setModalName,
12+
setSchDeptAlias,
1113
setScheduleId,
1214
} from '@/store/modules/modalSlice';
1315
import StartButton from '@components/CourseRegister/StartButton.tsx';
1416
import {getCourseList, getRegisterdList, getWishlist} from '@/apis/api/course';
1517
import {useAppSelector} from '@/store/hooks';
1618
import {openModalHandler} from '../common/Modal/handlers/handler';
1719
import {setEndCount} from '@/store/modules/courseRegisteredSlice';
20+
import RegisterInfo from './RegisterInfo';
21+
import {setIsConfirm} from '@/store/modules/dateModeSlice';
1822

1923
const colData = [
2024
{name: 'action', value: '신청', initialWidth: 50, enableFilters: false},
@@ -44,6 +48,7 @@ function CourseRegister() {
4448

4549
const dispatch = useDispatch();
4650
const studentId = useAppSelector(state => state.userInfo.username);
51+
const isConfirm = useAppSelector(state => state.dateMode.isConfirm);
4752

4853
useEffect(() => {
4954
dispatch(setEndCount(false));
@@ -95,32 +100,42 @@ function CourseRegister() {
95100
_action: string,
96101
scheduleId: number | undefined,
97102
curiNm: string | undefined,
103+
schDeptAlias: string | undefined,
104+
curiTypeCdNm: string | undefined,
98105
) => {
99-
if (scheduleId && curiNm) {
106+
if (scheduleId && curiNm && schDeptAlias && curiTypeCdNm) {
100107
dispatch(setScheduleId(scheduleId));
101108
dispatch(setCourseName(curiNm));
102109
dispatch(setModalName('macro'));
110+
dispatch(setSchDeptAlias(schDeptAlias));
111+
dispatch(setCuriTypeCdNm(curiTypeCdNm));
103112
}
104113
};
105114

106115
return (
107116
<>
108-
<StartButton onClick={handleStartButtonClick} />
109-
<RegisterFilters
110-
onSearch={handleSearch}
111-
isRegistrationStarted={isRegistrationStarted}
112-
/>
113-
<TableTitleWrap>
114-
<TableTitle>수강대상교과목</TableTitle>
115-
</TableTitleWrap>
116-
<Table
117-
colData={colData}
118-
data={list}
119-
width='100%'
120-
height='35rem'
121-
onAction={handleAction}
122-
/>
123-
<RegisteredList list={registeredList} refreshAll={refreshAll} />
117+
{!isConfirm ? (
118+
<RegisterInfo onClickNext={() => dispatch(setIsConfirm())} />
119+
) : (
120+
<>
121+
<StartButton onClick={handleStartButtonClick} />
122+
<RegisterFilters
123+
onSearch={handleSearch}
124+
isRegistrationStarted={isRegistrationStarted}
125+
/>
126+
<TableTitleWrap>
127+
<TableTitle>수강대상교과목</TableTitle>
128+
</TableTitleWrap>
129+
<Table
130+
colData={colData}
131+
data={list}
132+
width='100%'
133+
height='35rem'
134+
onAction={handleAction}
135+
/>
136+
<RegisteredList list={registeredList} refreshAll={refreshAll} />
137+
</>
138+
)}
124139
</>
125140
);
126141
}

src/components/LectureList/Filters.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ function Filters({onSearch}: FiltersProps) {
119119
);
120120
}
121121

122-
const WarningWrap = styled.div`
122+
export const WarningWrap = styled.div`
123123
${props => props.theme.texts.warning};
124124
color: #c30e2e;
125125
margin-bottom: -1.5rem;

src/components/LoginForm/FormInput.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ const InputWrap = styled.input`
2424
height: 4rem;
2525
width: 38rem;
2626
font-size: 1.9rem;
27-
padding: 0 1rem;
2827
`;
2928

3029
export default FormInput;

src/components/TabMenu/Tab.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import styled, {css} from 'styled-components';
22
import close from '@assets/img/close-line-red.png';
33
import {useAppDispatch, useAppSelector} from '@/store/hooks';
44
import {delTab, setFocused} from '@/store/modules/tabSlice';
5+
import {resetDateMode} from '@/store/modules/dateModeSlice';
56

67
interface TabProps {
78
id: number;
@@ -23,6 +24,9 @@ function Tab({id, label, isActive, onClick}: TabProps) {
2324
dispatch(setFocused(tabs[idx - 1].id));
2425
}
2526
dispatch(delTab(id));
27+
if (label === '수강신청') {
28+
dispatch(resetDateMode());
29+
}
2630
};
2731

2832
return (

0 commit comments

Comments
 (0)