-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Table View #163
base: main
Are you sure you want to change the base?
Added Table View #163
Changes from all commits
a23fba6
b1b3583
b2e2365
8ee007c
75798b4
2560207
0f55da3
fc2ad6f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
import React from 'react' | ||
import Table from '@mui/material/Table' | ||
import { | ||
StyledTextBox, | ||
StyledSmallText, | ||
StyledClassesContainer, | ||
StyledNoClasses, | ||
} from 'Dashboard/Styles/Groups.style' | ||
import { | ||
Paper, | ||
TableBody, | ||
TableCell, | ||
TableContainer, | ||
TableHead, | ||
TableRow, | ||
} from '@mui/material' | ||
import { Course } from '@core/Types' | ||
import { useHistory } from 'react-router-dom' | ||
import Link from '@mui/material/Link' | ||
import { colors, EDIT_ZING_PATH } from '@core' | ||
import { | ||
defaultSortingOrder, | ||
defaultFilterOption, | ||
defaultView, | ||
} from './Dashboard' | ||
import { Box, Typography } from '@mui/material' | ||
import { ReactComponent as NewlyMatchableIcon } from '@assets/img/newlymatchable.svg' | ||
import { ReactComponent as GroupsIcon } from '@assets/img/groupsicon.svg' | ||
import { ReactComponent as PlusIcon } from '@assets/img/plusicon.svg' | ||
import { ReactComponent as WarningIcon } from '@assets/img/warning.svg' | ||
|
||
export const CourseTable = ({ courses }: CourseGridProps) => { | ||
const history = useHistory() | ||
// returns color of background, button, and if newly matchable | ||
function getColor(students: number, groups: number) { | ||
//all students are matched | ||
if (students === 0 && groups > 0) { | ||
return { color: colors.white, new_match: 'no' } | ||
} | ||
//students are ready to be matched | ||
else if (students > 0 && groups > 0) { | ||
return { color: colors.lightgreen, new_match: 'no' } | ||
} | ||
//NEWLY MATCHABLE | ||
else if (students > 1 && groups === 0) { | ||
return { color: colors.lightgreen, new_match: 'yes' } | ||
} | ||
//only 1 student & 0 groups formed | ||
else return { color: colors.yellow, new_match: 'no' } | ||
} | ||
|
||
return ( | ||
<Box | ||
sx={{ | ||
display: 'flex', | ||
flexDirection: 'column', | ||
alignItems: 'center', | ||
overflow: 'auto', | ||
}} | ||
> | ||
{courses.length === 0 ? ( | ||
<> | ||
<StyledTextBox> | ||
<h2>No Courses to Show</h2> | ||
</StyledTextBox> | ||
<StyledSmallText> | ||
Once students request study partners, they'll automatically be | ||
placed into courses on this page! | ||
</StyledSmallText> | ||
<StyledClassesContainer> | ||
{[...Array(8)].map((_, i) => ( | ||
<StyledNoClasses key={i} /> | ||
))} | ||
</StyledClassesContainer> | ||
</> | ||
) : ( | ||
<Box | ||
sx={{ | ||
width: '100%', | ||
justifyContent: 'center', | ||
px: 10, | ||
py: 4, | ||
}} | ||
> | ||
<TableContainer component={Paper}> | ||
<Table sx={{ minWidth: 650 }} aria-label="simple table"> | ||
<TableHead sx={{ background: '#EDEDEE' }}> | ||
<TableRow> | ||
<TableCell>Course </TableCell> | ||
<TableCell align="left">Students</TableCell> | ||
<TableCell align="left">Groups</TableCell> | ||
<TableCell align="left">Recent Date</TableCell> | ||
</TableRow> | ||
</TableHead> | ||
<TableBody> | ||
{courses.map((c) => ( | ||
<TableRow key={c.courseId}> | ||
<TableCell> | ||
<Box | ||
sx={{ | ||
display: 'flex', | ||
alignItems: 'center', | ||
gap: 2, | ||
}} | ||
> | ||
<Link | ||
sx={{ | ||
color: 'black', | ||
fontWeight: 'bold', | ||
textDecorationColor: 'black', | ||
}} | ||
component="button" | ||
variant="body1" | ||
onClick={() => { | ||
const state = history.location.state as any | ||
history.push({ | ||
pathname: `${EDIT_ZING_PATH}/${c.courseId}`, | ||
state: { | ||
sortedOrder: state?.sortedOrder | ||
? state.sortedOrder | ||
: defaultSortingOrder, | ||
filterOption: state?.filterOption | ||
? state.filterOption | ||
: defaultFilterOption, | ||
tableView: !defaultView, | ||
}, | ||
}) | ||
}} | ||
> | ||
{c.names[0]} | ||
</Link> | ||
{getColor(c.unmatched.length, c.lastGroupNumber) | ||
.new_match === 'yes' && <NewlyMatchableIcon />} | ||
</Box> | ||
</TableCell> | ||
<TableCell align="right"> | ||
<Box | ||
sx={{ | ||
display: 'flex', | ||
alignItems: 'center', | ||
gap: 2, | ||
background: getColor( | ||
c.unmatched.length, | ||
c.lastGroupNumber | ||
).color, | ||
}} | ||
> | ||
{c.unmatched.length === 1 ? ( | ||
<WarningIcon /> | ||
) : ( | ||
<PlusIcon /> | ||
)} | ||
<Typography> | ||
{c.unmatched.length}{' '} | ||
{c.unmatched.length === 1 | ||
? 'New Student' | ||
: 'New Students'} | ||
</Typography> | ||
</Box> | ||
</TableCell> | ||
<TableCell align="right"> | ||
<Box | ||
sx={{ | ||
display: 'flex', | ||
alignItems: 'center', | ||
gap: 2, | ||
}} | ||
> | ||
<GroupsIcon /> | ||
<Typography> | ||
{c.lastGroupNumber}{' '} | ||
{c.lastGroupNumber === 1 | ||
? 'Group Formed' | ||
: 'Groups Formed'} | ||
</Typography> | ||
</Box> | ||
</TableCell> | ||
<TableCell> | ||
<Typography> | ||
{c.latestSubmissionTime.getMonth() + 1} | ||
{'-'} | ||
{c.latestSubmissionTime.getDate()} | ||
{'-'} | ||
{c.latestSubmissionTime.getFullYear()} | ||
</Typography> | ||
</TableCell> | ||
</TableRow> | ||
))} | ||
</TableBody> | ||
</Table> | ||
</TableContainer> | ||
</Box> | ||
)} | ||
</Box> | ||
) | ||
} | ||
|
||
interface CourseGridProps { | ||
courses: Course[] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,14 +7,17 @@ import { | |
StyledHeaderMenu, | ||
} from 'Dashboard/Styles/Dashboard.style' | ||
import { CourseGrid } from 'Dashboard/Components/CourseGrid' | ||
import { Box, IconButton, SelectChangeEvent } from '@mui/material' | ||
import { Box, IconButton, SelectChangeEvent, Typography } from '@mui/material' | ||
import { DropdownSelect } from '@core/Components' | ||
import { useCourseValue } from '@context/CourseContext' | ||
import { useStudentValue } from '@context/StudentContext' | ||
import { Course } from '@core/Types' | ||
import { useHistory } from 'react-router-dom' | ||
import { AccountMenu } from 'Dashboard/Components/AccountMenu' | ||
import ClearIcon from '@mui/icons-material/Clear' | ||
import { CourseTable } from './CourseTable' | ||
import ViewWeekOutlinedIcon from '@mui/icons-material/ViewWeekOutlined' | ||
import ViewHeadlineIcon from '@mui/icons-material/ViewHeadline' | ||
|
||
import axios from 'axios' | ||
import { API_ROOT, COURSE_API } from '@core/Constants' | ||
|
@@ -36,7 +39,7 @@ type FilterOption = | |
|
||
export const defaultSortingOrder = 'newest-requests-first' | ||
export const defaultFilterOption = 'no-filter' | ||
|
||
export const defaultView = false | ||
const filterOptionDisplay = [ | ||
['no-filter', 'All Classes'], | ||
['unmatchable', 'Unmatchable'], | ||
|
@@ -59,13 +62,18 @@ export const Dashboard = () => { | |
const state = history.location.state as { | ||
sortedOrder: SortOrder | ||
filterOption: FilterOption | ||
tableView: boolean | ||
} | ||
const [sortedOrder, setSortedOrder] = useState<SortOrder>(() => | ||
state?.sortedOrder ? state.sortedOrder : defaultSortingOrder | ||
) | ||
const [filteredOption, setFilteredOption] = useState<FilterOption>(() => | ||
state?.filterOption ? state.filterOption : defaultFilterOption | ||
) | ||
const [tableView, setTableView] = useState(() => | ||
state?.tableView === undefined || state?.tableView ? true : defaultView | ||
) | ||
|
||
//Helper function to check if a given course has any groups without check-in emails | ||
function hasUnsentCheckIns(c: Course) { | ||
return c.groups.some((group) => !group.templateTimestamps['check-in']) | ||
|
@@ -160,6 +168,7 @@ export const Dashboard = () => { | |
state: { | ||
sortedOrder: event.target.value as SortOrder, | ||
filterOption: state?.filterOption ? state.filterOption : 'no-filter', | ||
tableView: state?.tableView ? state.tableView : defaultView, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. change this line to |
||
}, | ||
}) | ||
} | ||
|
@@ -171,6 +180,28 @@ export const Dashboard = () => { | |
? state.sortedOrder | ||
: 'newest-requests-first', | ||
filterOption: event.target.value as FilterOption, | ||
tableView: state?.tableView ? state.tableView : defaultView, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
}, | ||
}) | ||
} | ||
|
||
//helper function to change view | ||
const handleClickTable = () => { | ||
setTableView( | ||
state?.tableView === undefined || state?.tableView ? false : !defaultView | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. change this line to |
||
) | ||
history.replace({ | ||
state: { | ||
sortedOrder: state?.sortedOrder | ||
? state.sortedOrder | ||
: defaultSortingOrder, | ||
filterOption: state?.filterOption | ||
? state.filterOption | ||
: defaultFilterOption, | ||
tableView: | ||
state?.tableView === undefined || state?.tableView | ||
? false | ||
: !defaultView, | ||
Comment on lines
+202
to
+204
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
}, | ||
}) | ||
} | ||
|
@@ -311,7 +342,78 @@ export const Dashboard = () => { | |
/> | ||
</Box> | ||
</StyledHeaderMenu> | ||
<CourseGrid courses={filteredSortedCourses} /> | ||
|
||
<Box | ||
sx={{ | ||
display: 'flex', | ||
alignItems: 'center', | ||
justifyContent: 'right', | ||
flexDirection: 'row', | ||
gap: 1, | ||
paddingRight: '80px', | ||
}} | ||
> | ||
<Typography sx={{ paddingRight: '5px' }}> | ||
{filteredSortedCourses.length} | ||
{' classes'} | ||
</Typography> | ||
<IconButton | ||
onClick={handleClickTable} | ||
disabled={ | ||
state?.tableView || state?.tableView === undefined ? false : true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. change this to |
||
} | ||
color="default" | ||
sx={{ | ||
'&.Mui-disabled': { | ||
background: '#939393', | ||
color: 'white', | ||
}, | ||
boxSizing: 'border-box', | ||
display: 'flex', | ||
flexDirection: 'row', | ||
padding: '8px', | ||
gap: '10px', | ||
width: '40px', | ||
height: '40px', | ||
background: '#F3F3F3', | ||
border: '1px solid #939393', | ||
borderRadius: '6px', | ||
}} | ||
> | ||
<ViewWeekOutlinedIcon /> | ||
</IconButton>{' '} | ||
<IconButton | ||
onClick={handleClickTable} | ||
disabled={ | ||
state?.tableView || state?.tableView === undefined ? true : false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change to |
||
} | ||
color="default" | ||
sx={{ | ||
'&.Mui-disabled': { | ||
background: '#939393', | ||
color: 'white', | ||
}, | ||
boxSizing: 'border-box', | ||
display: 'flex', | ||
flexDirection: 'row', | ||
padding: '8px', | ||
gap: '10px', | ||
width: '40px', | ||
height: '40px', | ||
background: '#F3F3F3', | ||
border: '1px solid #939393', | ||
borderRadius: '6px', | ||
}} | ||
> | ||
<ViewHeadlineIcon /> | ||
</IconButton> | ||
</Box> | ||
|
||
{(state?.tableView ? state.tableView : defaultView) ? ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
<CourseTable courses={filteredSortedCourses} /> | ||
) : ( | ||
<CourseGrid courses={filteredSortedCourses} /> | ||
)} | ||
</StyledContainer> | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change this line to
state?.tableView === undefined ? defaultView : state?.tableView