@@ -29,8 +29,6 @@ import LoadingPage from "./components/loading-page";
2929import {
3030 addPlannedCourse as addCourse ,
3131 moveCourseToSemester ,
32- removePlannedCourse as removeCourse ,
33- wipePlannedCourses ,
3432} from "./audit-mutations" ;
3533
3634type SemesterInfo = Record < StringSemester , Course [ ] > ;
@@ -161,95 +159,72 @@ export function AuditContextProvider({
161159 } ;
162160 } , [ currentAuditId ] ) ;
163161
164- async function persist (
165- auditId : string ,
166- updated : CachedAuditData ,
167- ) : Promise < void > {
168- await saveAuditData ( auditId , updated ) ;
169- setAuditData ( updated ) ;
170- }
171-
172- async function addPlannedCourse (
173- course : PlannedCourseOutline ,
174- requirementTitle : string ,
175- ruleTitle : string ,
176- ) : Promise < CourseId | null > {
177- if ( ! auditData || ! currentAuditId ) return null ;
178- const result = addCourse ( auditData , course , requirementTitle , ruleTitle ) ;
179- if ( ! result ) return null ;
180- await persist ( currentAuditId , result . audit ) ;
181- return result . courseId ;
182- }
183-
184- async function removePlannedCourse ( courseId : CourseId ) : Promise < boolean > {
185- if ( ! auditData || ! currentAuditId ) return false ;
186- const updated = removeCourse ( auditData , courseId ) ;
187- if ( ! updated ) return false ;
188- await persist ( currentAuditId , updated ) ;
189- return true ;
190- }
191-
192- async function wipeAllPlannedCourses ( ) : Promise < number > {
193- if ( ! auditData || ! currentAuditId ) return 0 ;
194- const result = wipePlannedCourses ( auditData ) ;
195- if ( result . removed ) await persist ( currentAuditId , result . audit ) ;
196- return result . removed ;
197- }
198-
199- async function moveCourseToNewSemester (
200- courseId : CourseId ,
201- semester : StringSemester ,
202- ) : Promise < boolean > {
203- if ( ! auditData || ! currentAuditId ) return false ;
204- const updated = moveCourseToSemester ( auditData , courseId , semester ) ;
205- if ( ! updated ) return false ;
206- await persist ( currentAuditId , updated ) ;
207- return true ;
208- }
162+ const value = useMemo < AuditContextValue > ( ( ) => {
163+ const persist = async ( auditId : string , updated : CachedAuditData ) => {
164+ await saveAuditData ( auditId , updated ) ;
165+ setAuditData ( updated ) ;
166+ } ;
209167
210- async function renameAuditTitle (
211- auditId : string ,
212- title : string ,
213- ) : Promise < boolean > {
214- const cleanTitle = title . trim ( ) ;
215- if ( ! cleanTitle ) return false ;
216- const updatedHistory = await renameAudit ( auditId , cleanTitle ) ;
217- if ( ! updatedHistory ) return false ;
218- setHistory ( updatedHistory ) ;
219- return true ;
220- }
168+ // currentAuditId and history are guaranteed non-null past the loading
169+ // guard below, which is the only path that renders this provider's value.
170+ return {
171+ sections,
172+ history : history as AuditHistoryData ,
173+ semesters,
174+ currentAuditId : currentAuditId as string ,
175+ currentAudit,
176+ currentAuditName,
177+ progresses,
178+ courseMap,
179+ getCourseById : ( id ) => {
180+ const course = courseMap [ id ] ;
181+ if ( ! course ) throw new Error ( `Course ${ id } not found` ) ;
182+ return course ;
183+ } ,
184+ setCurrentAuditId : ( id ) => {
185+ window . history . pushState ( { } , "" , `?auditId=${ id } ` ) ;
186+ setCurrentAuditIdState ( id ) ;
187+ updateLastAuditId ( id ) ;
188+ } ,
189+ renameAuditTitle : async ( auditId , title ) => {
190+ const cleanTitle = title . trim ( ) ;
191+ if ( ! cleanTitle ) return false ;
192+ const updatedHistory = await renameAudit ( auditId , cleanTitle ) ;
193+ if ( ! updatedHistory ) return false ;
194+ setHistory ( updatedHistory ) ;
195+ return true ;
196+ } ,
197+ moveCourseToNewSemester : async ( courseId , semester ) => {
198+ if ( ! auditData || ! currentAuditId ) return false ;
199+ const updated = moveCourseToSemester ( auditData , courseId , semester ) ;
200+ if ( ! updated ) return false ;
201+ await persist ( currentAuditId , updated ) ;
202+ return true ;
203+ } ,
204+ addPlannedCourse : async ( course , requirementTitle , ruleTitle ) => {
205+ if ( ! auditData || ! currentAuditId ) return null ;
206+ const result = addCourse ( auditData , course , requirementTitle , ruleTitle ) ;
207+ if ( ! result ) return null ;
208+ await persist ( currentAuditId , result . audit ) ;
209+ return result . courseId ;
210+ } ,
211+ } ;
212+ } , [
213+ sections ,
214+ history ,
215+ semesters ,
216+ currentAuditId ,
217+ currentAudit ,
218+ currentAuditName ,
219+ progresses ,
220+ courseMap ,
221+ auditData ,
222+ updateLastAuditId ,
223+ ] ) ;
221224
222225 if ( ! loaded || ! currentAuditId || ! history ) return < LoadingPage /> ;
223226
224- return (
225- < AuditContext . Provider
226- value = { {
227- sections,
228- history,
229- semesters,
230- currentAuditId,
231- currentAudit,
232- currentAuditName,
233- setCurrentAuditId : ( id ) => {
234- window . history . pushState ( { } , "" , `?auditId=${ id } ` ) ;
235- setCurrentAuditIdState ( id ) ;
236- updateLastAuditId ( id ) ;
237- } ,
238- renameAuditTitle,
239- moveCourseToNewSemester,
240- progresses,
241- getCourseById : ( id ) => {
242- const course = courseMap [ id ] ;
243- if ( ! course ) throw new Error ( `Course ${ id } not found` ) ;
244- return course ;
245- } ,
246- courseMap,
247- addPlannedCourse,
248- } }
249- >
250- { children }
251- </ AuditContext . Provider >
252- ) ;
227+ return < AuditContext . Provider value = { value } > { children } </ AuditContext . Provider > ;
253228}
254229
255230export function useAuditContext ( ) : AuditContextValue {
0 commit comments