@@ -41,9 +41,11 @@ import SearchFilters from "./SearchFilters";
4141import Calendar from "./Calendar" ;
4242import { Timetable } from "@/utils/type-utils" ;
4343import { useSearchParams } from "react-router-dom" ;
44+
4445type FormContextType = UseFormReturn < z . infer < typeof TimetableFormSchema > > ;
4546export const FormContext = createContext < FormContextType | null > ( null ) ;
4647const SEARCH_LIMIT = 1000 ;
48+
4749/**
4850 * TimetableBuilder Component
4951 *
@@ -79,31 +81,37 @@ const SEARCH_LIMIT = 1000;
7981 *
8082 * @returns {JSX.Element } The rendered timetable builder.
8183 */
84+
8285const TimetableBuilder = ( ) => {
8386 const form = useForm < z . infer < typeof TimetableFormSchema > > ( {
8487 resolver : zodResolver ( TimetableFormSchema ) ,
8588 defaultValues : baseTimetableForm ,
8689 } ) ;
90+
8791 const filterForm = useForm < z . infer < typeof FilterFormSchema > > ( {
8892 resolver : zodResolver ( FilterFormSchema ) ,
8993 } ) ;
94+
9095 const [ queryParams , setQueryParams ] = useSearchParams ( ) ;
9196 const isEditingTimetable = queryParams . has ( "edit" ) ;
9297 const editingTimetableId = queryParams . get ( "edit" ) ;
98+
9399 const selectedCourses = form . watch ( "courses" ) || [ ] ;
94100 const enabledRestrictions = form . watch ( "restrictions" ) || [ ] ;
95101 const searchQuery = form . watch ( "search" ) ;
96102 const debouncedSearchQuery = useDebounceValue ( searchQuery , 250 ) ;
103+
97104 const [ isCustomSettingsOpen , setIsCustomSettingsOpen ] = useState ( false ) ;
98105 const [ filters , setFilters ] = useState < FilterForm | null > ( null ) ;
99106 const [ showFilters , setShowFilters ] = useState ( false ) ;
100107 const [ timetableId , setTimetableId ] = useState (
101- editingTimetableId ? parseInt ( editingTimetableId ) : 0 ,
108+ editingTimetableId ? parseInt ( editingTimetableId ) : 0
102109 ) ;
103110
104111 const noSearchAndFilter = ( ) => {
105112 return ! searchQuery && ! filters ;
106113 } ;
114+
107115 // limit search number if no search query or filters for performance purposes.
108116 // Otherwise, limit is 10k, which effectively gets all results.
109117 const { data, isLoading, error, refetch } = useGetCoursesQuery ( {
@@ -112,32 +120,38 @@ const TimetableBuilder = () => {
112120 semester : form . getValues ( "semester" ) ,
113121 ...filters ,
114122 } ) ;
123+
115124 const { data : eventsData , isLoading : eventsLoading } = useGetEventsQuery (
116- timetableId ,
125+ timetableId
117126 ) as {
118127 data : { courseEvents : unknown [ ] ; userEvents : unknown [ ] } ;
119128 isLoading : boolean ;
120129 } ;
121130 const courseEvents = eventsData ?. courseEvents || [ ] ;
122131 const userEvents = eventsData ?. userEvents || [ ] ;
132+
123133 const { data : timetablesData } = useGetTimetablesQuery ( ) as {
124134 data : Timetable [ ] ;
125135 } ;
126136 const timetables = timetablesData || [ ] ;
137+
127138 useEffect ( ( ) => {
128139 if ( searchQuery ) {
129140 refetch ( ) ;
130141 }
131142 } , [ debouncedSearchQuery ] ) ;
143+
132144 const createTimetable = ( values : z . infer < typeof TimetableFormSchema > ) => {
133145 console . log ( values ) ;
134146 // TODO Send request to /api/timetable/create
135147 } ;
148+
136149 const handleReset = ( ) => {
137150 form . reset ( ) ;
138151 filterForm . reset ( ) ;
139152 setFilters ( null ) ;
140153 } ;
154+
141155 const handleRemoveCourse = ( course : {
142156 id : number ;
143157 code : string ;
@@ -147,20 +161,24 @@ const TimetableBuilder = () => {
147161 const newList = currentList . filter ( ( item ) => item . id !== course . id ) ;
148162 form . setValue ( "courses" , newList ) ;
149163 } ;
164+
150165 const handleAddRestriction = ( values : z . infer < typeof RestrictionSchema > ) => {
151166 const currentList = form . getValues ( "restrictions" ) ;
152167 const newList = [ ...currentList , values ] ;
153168 form . setValue ( "restrictions" , newList ) ;
154169 } ;
170+
155171 const handleRemoveRestriction = ( index : number ) => {
156172 const currentList = form . getValues ( "restrictions" ) ;
157173 const newList = currentList . filter ( ( _ , i ) => i !== index ) ;
158174 form . setValue ( "restrictions" , newList ) ;
159175 } ;
176+
160177 const applyFilters = ( values : z . infer < typeof FilterFormSchema > ) => {
161178 setFilters ( values ) ;
162179 console . log ( "Apply filters" , values ) ;
163180 } ;
181+
164182 return (
165183 < >
166184 < div className = "w-full" >
@@ -207,6 +225,7 @@ const TimetableBuilder = () => {
207225 </ div >
208226 < hr />
209227 </ div >
228+
210229 < div className = "m-8 flex gap-12" >
211230 < div className = "w-2/5" >
212231 < Form { ...form } >
@@ -237,7 +256,7 @@ const TimetableBuilder = () => {
237256 < SelectItem key = { value } value = { value } >
238257 { value }
239258 </ SelectItem >
240- ) ,
259+ )
241260 ) }
242261 </ SelectContent >
243262 </ Select >
@@ -246,6 +265,7 @@ const TimetableBuilder = () => {
246265 </ FormItem >
247266 ) }
248267 />
268+
249269 < FormField
250270 control = { form . control }
251271 name = "search"
@@ -292,6 +312,7 @@ const TimetableBuilder = () => {
292312 ) ) }
293313 </ div >
294314 </ div >
315+
295316 < div className = "flex gap-12 items-end" >
296317 < div className = "flex flex-col gap-2" >
297318 < h2 className = "text-lg" > Custom Settings</ h2 >
@@ -309,6 +330,7 @@ const TimetableBuilder = () => {
309330 + Add new
310331 </ Button >
311332 </ div >
333+
312334 < div className = "flex flex-col" >
313335 < FormField
314336 control = { form . control }
@@ -346,6 +368,7 @@ const TimetableBuilder = () => {
346368 { restric . numDays } days off
347369 </ p >
348370 ) }
371+
349372 < X
350373 size = { 16 }
351374 className = "hover:text-red-500 cursor-pointer"
@@ -355,6 +378,7 @@ const TimetableBuilder = () => {
355378 ) ) }
356379 </ div >
357380 </ div >
381+
358382 < Button type = "submit" > Generate</ Button >
359383 </ form >
360384
@@ -370,6 +394,7 @@ const TimetableBuilder = () => {
370394 < div className = "w-3/5" >
371395 < Calendar courseEvents = { courseEvents } userEvents = { userEvents } />
372396 </ div >
397+
373398 { showFilters && (
374399 < SearchFilters
375400 submitHandler = { applyFilters }
@@ -387,4 +412,5 @@ const TimetableBuilder = () => {
387412 </ >
388413 ) ;
389414} ;
415+
390416export default TimetableBuilder ;
0 commit comments