The following is a quick reference to the StudentDegreePlannerPage.
Sticky State# We are using three StickyState
variables to share state across the Degree Experience Planner components. The three state names are defined in the DegreePlannerStateNames
enum.
Copy export enum DegreePlannerStateNames {
selectedCiID = 'Planner.selectedCiID' ,
selectedOiID = 'Planner.selectedOiID' ,
selectedProfileTab = 'Planner.selectedProfileTab' ,
}
StudentDegreePlannerPage# The StudentDegreePlannerPage.tsx
just uses the set methods. It doesn't actually care what the state values are.
Copy const [ , setSelectedCiID ] = useStickyState ( DegreePlannerStateNames . selectedCiID , '' ) ;
const [ , setSelectedOiID ] = useStickyState ( DegreePlannerStateNames . selectedOiID , '' ) ;
const [ , setSelectedProfileTab ] = useStickyState ( DegreePlannerStateNames . selectedProfileTab , '' ) ;
We pass these set methods are passed into the onDragEnd
method by using a higher order method.
Copy const onDragEnd = ( onDragEndProps ) => ( result ) => {
const { match , setSelectedCiID , setSelectedOiID , setSelectedProfileTab } = onDragEndProps ;
...
}
We use the setSelectedCiID
, setSelectedOiID
, and setSelectedProfileTab
in the onDragEnd method to tell the TabbedProfileEntries.tsx
what to display.
DegreeExperiencePlanner# The DegreeExperiencePlanner
also uses the StickyState set methods to tell the TabbedProfileEntries
what is selected.
Copy const [ , setSelectedCiID ] = useStickyState ( DegreePlannerStateNames . selectedCiID , '' ) ;
const [ , setSelectedOiID ] = useStickyState ( DegreePlannerStateNames . selectedOiID , '' ) ;
const [ , setSelectedProfileTab ] = useStickyState ( DegreePlannerStateNames . selectedProfileTab , '' ) ;
TabbedProfileEntries# The TabbedProfileEntries
defines the names of the individual tabs in an exported enum TabbedProfileEntryNames
.
Copy export enum TabbedProfileEntryNames {
profileCourses = 'PROFILE_COURSES' ,
profileOpportunities = 'PROFILE_OPPORTUNITIES' ,
profileDetails = 'PROFILE_DETAILS' ,
}
It only cares about the selected tab state.
Copy const [ selectedTab , setSelectedTab ] = useStickyState ( DegreePlannerStateNames . selectedProfileTab , TabbedProfileEntryNames . profileOpportunities ) ;
When the student clicks on a tab we use the setSelectedTab
method to update the selectedTab.
DepDetailsCard# Uses the selectedCourse
and selectedOpportunity
state to decide what to show.
Copy const [ selectedCourse ] = useStickyState ( DegreePlannerStateNames . selectedCiID , '' ) ;
const [ selectedOpportunity ] = useStickyState ( DegreePlannerStateNames . selectedOiID , '' ) ;
const courseP = selectedCourse !== '' ;
...
return courseP ? < DetailCourseCard instance = { instance as CourseInstance } / > : < DetailOpportunityCard instance = { instance as OpportunityInstance } verificationRequests = { verificationRequests } / > ;
Drag and Drop# We are using react-beautiful-dnd for our drag and drop needs.
StudentDegreePlannerPage# The StudentDegreePlannerPage
wraps the entire page in a DragDropContext
.
Copy return (
< DragDropContext onDragEnd = { onDragEnd ( onDragEndProps ) } >
...
< / DragDropContext >
) ;
The onDragEnd
is our higher order function that passes in the sticky state set methods. By wrapping the entire page in the DragDropContext
, we can drag items between the different components on the page. The onDragEnd
method handles all the drop events. It stops the students from doing incorrect things to their degree plan. It creates the CourseInstances and OpportunityInstances on a valid drop. See onDragEnd for the current code.
AcademicTermView# The AcademicTermView
defines the Droppable
that allow students to drop course or opportunities into an academic term.
Copy < Droppable droppableId = { ` ${ termSlug } ` } >
{ ( provided , snapshot ) => (
< div ref = { provided . innerRef } style = { getDroppableListStyle ( snapshot . isDraggingOver ) } >
{ courseInstancesToShow . map ( ( ci , index ) => (
< DraggableCourseInstancePill key = { ci . _id } instance = { ci } index = { index } inPast = { inPast }
handleClickCourseInstance = { handleClickCourseInstance } / >
) ) }
{ opportunityInstancesToShow . map ( ( oi , index ) => (
< DraggableOpportunityInstancePill key = { oi . _id } instance = { oi }
index = { courseInstancesToShow . length + index }
handleClickOpportunityInstance = { handleClickOpportunityInstance } / >
) ) }
{ provided . placeholder }
< Icon name = "plus circle" color = "grey" / > Drag Here
< / div >
) }
< / Droppable >
DraggableCourseInstancePill and DraggableOpportunityInstancePill# The DraggableCourseInstancePill and DraggableOpportunityInstancePill define the Draggable
elements.
Copy < Draggable key = { instance . _id } draggableId = { instance . _id } index = { index } >
{ ( prov , snap ) => (
< div ref = { prov . innerRef } { ... prov . draggableProps } { ... prov . dragHandleProps } style = { getDraggablePillStyle ( snap . isDragging , prov . draggableProps . style ) } >
< Grid >
< Grid . Row style = { { paddingTop : 7 , paddingBottom : 7 } } >
< Grid . Column width = { 13 } onClick = { handleClick ( instance , handleClickCourseInstance ) } >
< NamePill name = { instance . note } / >
< / Grid . Column >
< Grid . Column width = { 2 } > { inPast ? '' : < RemoveItWidget collectionName = "CourseInstanceCollection" id = { instance . _id } name = { getName ( instance ) } courseNumber = { instance . note } / > } < / Grid . Column >
< / Grid . Row >
< / Grid >
< / div >
) }
< / Draggable >