1
- import React , { useState , useCallback , useMemo , useEffect } from 'react' ;
1
+ import React , { useState , useMemo , useEffect } from 'react' ;
2
2
import { useSelector } from 'react-redux' ;
3
3
import { getSemesterTimetableColors , getSemesterTimetableLessons } from 'selectors/timetables' ;
4
4
import { State } from 'types/state' ;
@@ -16,10 +16,10 @@ import {
16
16
isSaturdayInOptions ,
17
17
} from 'utils/optimiser' ;
18
18
import { FreeDayConflict , LessonOption } from 'types/optimiser' ;
19
- import { DayText } from 'types/modules ' ;
19
+ import useOptimiserForm from 'views/hooks/useOptimiserForm ' ;
20
20
import styles from './OptimiserContent.scss' ;
21
21
import OptimiserHeader from './OptimiserHeader' ;
22
- import OptimiserForm from './OptimiserForm' ;
22
+ import OptimiserForm from './OptimiserForm/OptimiserForm ' ;
23
23
import OptimiserButton from './OptimiserButton' ;
24
24
import OptimiserResults from './OptimiserResults' ;
25
25
@@ -30,16 +30,19 @@ const OptimiserContent: React.FC = () => {
30
30
const modulesMap = useSelector ( ( { moduleBank } : State ) => moduleBank . modules ) ;
31
31
const acadYear = useSelector ( ( state : State ) => state . timetables . academicYear ) ;
32
32
33
- const [ selectedLessons , setSelectedLessons ] = useState < LessonOption [ ] > ( [ ] ) ;
34
- const [ selectedFreeDays , setSelectedFreeDays ] = useState < Set < DayText > > ( new Set ( ) ) ;
35
- const [ earliestTime , setEarliestTime ] = useState < string > ( '0800' ) ;
36
- const [ latestTime , setLatestTime ] = useState < string > ( '1900' ) ;
37
- const [ earliestLunchTime , setEarliestLunchTime ] = useState < string > ( '1200' ) ;
38
- const [ latestLunchTime , setLatestLunchTime ] = useState < string > ( '1400' ) ;
39
- const [ unAssignedLessons , setUnAssignedLessons ] = useState < LessonOption [ ] > ( [ ] ) ;
33
+ const optimiserFormFields = useOptimiserForm ( ) ;
34
+ const {
35
+ physicalLessonOptions,
36
+ setPhysicalLessonOptions,
37
+ freeDays,
38
+ lessonTimeRange,
39
+ lunchTimeRange,
40
+ maxConsecutiveHours,
41
+ } = optimiserFormFields ;
42
+
43
+ const [ hasSaturday , setHasSaturday ] = useState ( false ) ;
44
+ const [ unassignedLessons , setUnassignedLessons ] = useState < LessonOption [ ] > ( [ ] ) ;
40
45
const [ shareableLink , setShareableLink ] = useState < string > ( '' ) ;
41
- const [ hasSaturday , setHasSaturday ] = useState < boolean > ( false ) ;
42
- const [ maxConsecutiveHours , setMaxConsecutiveHours ] = useState < number > ( 4 ) ;
43
46
const [ isOptimising , setIsOptimising ] = useState < boolean > ( false ) ;
44
47
const [ error , setError ] = useState < Error | null > ( null ) ;
45
48
@@ -48,48 +51,23 @@ const OptimiserContent: React.FC = () => {
48
51
return getLessonOptions ( modules , activeSemester , colors ) ;
49
52
} , [ timetable , modulesMap , activeSemester , colors ] ) ;
50
53
51
- const recordedLessonOptions : LessonOption [ ] = useMemo (
52
- ( ) => getRecordedLessonOptions ( lessonOptions , selectedLessons ) ,
53
- [ lessonOptions , selectedLessons ] ,
54
- ) ;
55
-
56
54
const freeDayConflicts : FreeDayConflict [ ] = useMemo ( ( ) => {
57
55
const modules = getSemesterModules ( timetable , modulesMap ) ;
58
- return getFreeDayConflicts ( modules , activeSemester , selectedLessons , selectedFreeDays ) ;
59
- } , [ timetable , modulesMap , activeSemester , selectedLessons , selectedFreeDays ] ) ;
56
+ return getFreeDayConflicts ( modules , activeSemester , physicalLessonOptions , freeDays ) ;
57
+ } , [ timetable , modulesMap , activeSemester , physicalLessonOptions , freeDays ] ) ;
58
+
59
+ const recordedLessonOptions : LessonOption [ ] = useMemo (
60
+ ( ) => getRecordedLessonOptions ( lessonOptions , physicalLessonOptions ) ,
61
+ [ lessonOptions , physicalLessonOptions ] ,
62
+ ) ;
60
63
61
64
useEffect ( ( ) => {
62
65
const availableKeys = new Set ( lessonOptions . map ( ( option ) => option . lessonKey ) ) ;
63
- setSelectedLessons ( ( prev ) => prev . filter ( ( lesson ) => availableKeys . has ( lesson . lessonKey ) ) ) ;
66
+ setPhysicalLessonOptions ( ( prev ) =>
67
+ prev . filter ( ( lesson ) => availableKeys . has ( lesson . lessonKey ) ) ,
68
+ ) ;
64
69
setHasSaturday ( isSaturdayInOptions ( lessonOptions ) ) ;
65
- } , [ lessonOptions ] ) ;
66
-
67
- const toggleLessonSelection = useCallback (
68
- ( option : LessonOption ) => {
69
- const isSelected = selectedLessons . some ( ( lesson ) => lesson . lessonKey === option . lessonKey ) ;
70
-
71
- if ( isSelected ) {
72
- setSelectedLessons ( ( prev ) =>
73
- prev . filter ( ( lesson ) => lesson . lessonKey !== option . lessonKey ) ,
74
- ) ;
75
- } else {
76
- setSelectedLessons ( ( prev ) => [ ...prev , option ] ) ;
77
- }
78
- } ,
79
- [ selectedLessons ] ,
80
- ) ;
81
-
82
- const toggleFreeDay = useCallback ( ( day : DayText ) => {
83
- setSelectedFreeDays ( ( prev ) => {
84
- const newSet = new Set ( prev ) ;
85
- if ( newSet . has ( day ) ) {
86
- newSet . delete ( day ) ;
87
- } else {
88
- newSet . add ( day ) ;
89
- }
90
- return newSet ;
91
- } ) ;
92
- } , [ ] ) ;
70
+ } , [ lessonOptions , setHasSaturday , setPhysicalLessonOptions ] ) ;
93
71
94
72
const buttonOnClick = async ( ) => {
95
73
setShareableLink ( '' ) ; // Reset shareable link
@@ -98,18 +76,17 @@ const OptimiserContent: React.FC = () => {
98
76
99
77
const modulesList = Object . keys ( timetable ) ;
100
78
const acadYearFormatted = `${ acadYear . split ( '/' ) [ 0 ] } -${ acadYear . split ( '/' ) [ 1 ] } ` ;
101
- const recordings = recordedLessonOptions . map ( ( lessonOption ) => lessonOption . displayText ) ;
102
79
103
80
const params : OptimiseRequest = {
104
81
modules : modulesList ,
105
82
acadYear : acadYearFormatted ,
106
83
acadSem : activeSemester ,
107
- freeDays : Array . from ( selectedFreeDays ) ,
108
- earliestTime,
109
- latestTime,
110
- recordings,
111
- lunchStart : earliestLunchTime ,
112
- lunchEnd : latestLunchTime ,
84
+ freeDays : Array . from ( freeDays ) ,
85
+ earliestTime : lessonTimeRange . earliest ,
86
+ latestTime : lessonTimeRange . latest ,
87
+ recordings : recordedLessonOptions . map ( ( lessonOption ) => lessonOption . displayText ) ,
88
+ lunchStart : lunchTimeRange . earliest ,
89
+ lunchEnd : lunchTimeRange . latest ,
113
90
maxConsecutiveHours,
114
91
} ;
115
92
@@ -127,42 +104,26 @@ const OptimiserContent: React.FC = () => {
127
104
setShareableLink ( link ) ;
128
105
129
106
const unassignedLessonOptions = getUnassignedLessonOptions ( lessonOptions , data ) ;
130
- setUnAssignedLessons ( unassignedLessonOptions ) ;
107
+ setUnassignedLessons ( unassignedLessonOptions ) ;
131
108
} ;
132
109
133
110
return (
134
111
< div className = { styles . container } >
135
112
< Title > Optimiser</ Title >
136
113
137
- { /* Optimiser header */ }
138
114
< OptimiserHeader />
139
115
140
- { /* All the form elements */ }
141
116
< OptimiserForm
142
117
lessonOptions = { lessonOptions }
143
- selectedLessons = { selectedLessons }
144
- selectedFreeDays = { selectedFreeDays }
145
- earliestTime = { earliestTime }
146
- latestTime = { latestTime }
147
- earliestLunchTime = { earliestLunchTime }
148
- latestLunchTime = { latestLunchTime }
149
118
freeDayConflicts = { freeDayConflicts }
150
119
hasSaturday = { hasSaturday }
151
- maxConsecutiveHours = { maxConsecutiveHours }
152
- onToggleLessonSelection = { toggleLessonSelection }
153
- onToggleFreeDay = { toggleFreeDay }
154
- onEarliestTimeChange = { setEarliestTime }
155
- onLatestTimeChange = { setLatestTime }
156
- onEarliestLunchTimeChange = { setEarliestLunchTime }
157
- onLatestLunchTimeChange = { setLatestLunchTime }
158
- onMaxConsecutiveHoursChange = { setMaxConsecutiveHours }
120
+ optimiserFormFields = { optimiserFormFields }
159
121
/>
160
122
161
- { /* Optimiser button */ }
162
123
< OptimiserButton
163
- freeDayConflicts = { freeDayConflicts }
164
- lessonOptions = { lessonOptions }
165
124
isOptimising = { isOptimising }
125
+ lessonOptions = { lessonOptions }
126
+ freeDayConflicts = { freeDayConflicts }
166
127
onClick = { buttonOnClick }
167
128
/>
168
129
@@ -173,8 +134,7 @@ const OptimiserContent: React.FC = () => {
173
134
/>
174
135
) }
175
136
176
- { /* Optimiser results */ }
177
- < OptimiserResults shareableLink = { shareableLink } unassignedLessons = { unAssignedLessons } />
137
+ < OptimiserResults shareableLink = { shareableLink } unassignedLessons = { unassignedLessons } />
178
138
</ div >
179
139
) ;
180
140
} ;
0 commit comments