11import { addCourseByURL } from '@pages/background/lib/addCourseByURL' ;
2+ import { ArrowsClockwise , Check } from '@phosphor-icons/react' ;
23import { background } from '@shared/messages' ;
34import { Button } from '@views/components/common/Button' ;
45import ExtensionRoot from '@views/components/common/ExtensionRoot/ExtensionRoot' ;
5- import useSchedules from '@views/hooks/useSchedules' ;
6+ import { getScheduleById , switchSchedule } from '@views/hooks/useSchedules' ;
67import { useEffect , useState } from 'react' ;
78import ReactDOM from 'react-dom' ;
9+ import createSchedule from 'src/pages/background/lib/createSchedule' ;
810
911/**
1012 * InjectedButton component renders a button that adds courses to UTRP from official MyUT calendar
@@ -14,13 +16,17 @@ import ReactDOM from 'react-dom';
1416 */
1517export default function InjectedButton ( ) : JSX . Element | null {
1618 const [ container , setContainer ] = useState < HTMLDivElement | null > ( null ) ;
17- const [ activeSchedule , _ ] = useSchedules ( ) ;
19+ const [ importStatus , setImportStatus ] = useState < 'idle' | 'loading' | 'complete' > ( 'idle' ) ;
1820
1921 const extractCoursesFromCalendar = async ( ) => {
20- const calendarElement = document . querySelector ( '#kgoui_Rcontent_I3_Rprimary_I1_Rcontent_I1_Rcontent_I0_Ritems' ) ;
22+ setImportStatus ( 'loading' ) ;
23+
24+ const tableElements = document . querySelectorAll ( 'table' ) ;
25+ const calendarElement = Array . from ( tableElements ) . find ( el => el . textContent ?. includes ( '12PM' ) ) ;
2126
2227 if ( ! calendarElement ) {
2328 console . error ( 'Calendar element not found' ) ;
29+ setImportStatus ( 'idle' ) ;
2430 return [ ] ;
2531 }
2632
@@ -36,20 +42,55 @@ export default function InjectedButton(): JSX.Element | null {
3642 url : 'https://utdirect.utexas.edu/apps/registrar/course_schedule/utrp_login/' ,
3743 } ) ;
3844
39- if ( loggedInToUT ) {
40- for ( const a of uniqueAnchorTags ) {
41- await addCourseByURL ( activeSchedule , a ) ;
45+ try {
46+ if ( loggedInToUT ) {
47+ const scheduleId = await createSchedule ( 'Imported Schedule' ) ;
48+ switchSchedule ( scheduleId ) ;
49+ const newSchedule = await getScheduleById ( scheduleId ) ;
50+ if ( ! newSchedule ) {
51+ throw new Error ( 'Failed to retrieve new schedule' ) ;
52+ }
53+
54+ for ( const a of uniqueAnchorTags ) {
55+ await addCourseByURL ( newSchedule , a ) ;
56+ }
57+
58+ setImportStatus ( 'complete' ) ;
59+ return ;
4260 }
43- } else {
61+
4462 // We'll allow the alert for this WIP feature
4563 window . alert ( 'Logged into UT Registrar.' ) ;
64+ } catch ( error ) {
65+ console . error ( 'Failed to import courses from calendar' , error ) ;
4666 }
67+
68+ setImportStatus ( 'idle' ) ;
4769 } ;
4870
71+ const buttonText =
72+ importStatus === 'loading'
73+ ? 'Importing...'
74+ : importStatus === 'complete'
75+ ? 'Imported!'
76+ : 'Add Courses to UT Registration+' ;
77+
78+ const buttonIcon = importStatus === 'loading' ? ArrowsClockwise : importStatus === 'complete' ? Check : undefined ;
79+
80+ const buttonIconProps =
81+ importStatus === 'loading'
82+ ? {
83+ className : 'animate-spin animate-duration-800' ,
84+ }
85+ : undefined ;
86+
4987 useEffect ( ( ) => {
50- const targetElement = document . getElementById ( 'kgoui_Rcontent_I3_Rsecondary' ) ;
88+ const targetElements = document . querySelectorAll (
89+ 'div.kgoui_object_region.kgoui_container_responsive_asymmetric2_column_secondary'
90+ ) ;
91+ const targetElement = Array . from ( targetElements ) . find ( el => el . textContent ?. includes ( 'My Information' ) ) ;
5192
52- if ( targetElement ?. classList . contains ( 'kgoui_container_responsive_asymmetric2_column_secondary' ) ) {
93+ if ( targetElement ) {
5394 const buttonContainer = document . createElement ( 'div' ) ;
5495 targetElement . appendChild ( buttonContainer ) ;
5596 setContainer ( buttonContainer ) ;
@@ -66,8 +107,16 @@ export default function InjectedButton(): JSX.Element | null {
66107
67108 return ReactDOM . createPortal (
68109 < ExtensionRoot >
69- < Button variant = 'filled' color = 'ut-burntorange' onClick = { extractCoursesFromCalendar } >
70- Add Courses to UT Registration+
110+ < Button
111+ variant = 'filled'
112+ color = 'ut-burntorange'
113+ className = 'flex!'
114+ onClick = { extractCoursesFromCalendar }
115+ disabled = { importStatus !== 'idle' }
116+ icon = { buttonIcon }
117+ iconProps = { buttonIconProps }
118+ >
119+ { buttonText }
71120 </ Button >
72121 </ ExtensionRoot > ,
73122 container
0 commit comments