github.com/quickfeed/quickfeed@v0.0.0-20240507093252-ed8ca812a09c/public/src/components/dashboard/SubmissionsTable.tsx (about) 1 import React from "react" 2 import { useHistory } from "react-router" 3 import { assignmentStatusText, getFormattedTime, SubmissionStatus, timeFormatter } from "../../Helpers" 4 import { useAppState } from "../../overmind" 5 import { Assignment, Submission, Submission_Status } from "../../../proto/qf/types_pb" 6 import ProgressBar, { Progress } from "../ProgressBar" 7 8 9 /* SubmissionsTable is a component that displays a table of assignments and their submissions for all courses. */ 10 const SubmissionsTable = (): JSX.Element => { 11 const state = useAppState() 12 const history = useHistory() 13 14 const sortedAssignments = () => { 15 const assignments: Assignment[] = [] 16 for (const courseID in state.assignments) { 17 assignments.push(...state.assignments[courseID]) 18 } 19 assignments.sort((a, b) => { 20 if (a.deadline && b.deadline) { 21 return a.deadline.toDate().getTime() - b.deadline.toDate().getTime() 22 } 23 return 0 24 }) 25 return assignments 26 } 27 28 const NewSubmissionsTable = (): JSX.Element[] => { 29 const table: JSX.Element[] = [] 30 sortedAssignments().forEach(assignment => { 31 const courseID = assignment.CourseID 32 const submissions = state.submissions[courseID.toString()] 33 if (!submissions) { 34 return 35 } 36 // Submissions are indexed by the assignment order - 1. 37 const submission = submissions[assignment.order - 1] ?? new Submission() 38 if (submission.status !== Submission_Status.APPROVED && assignment.deadline) { 39 const deadline = timeFormatter(assignment.deadline) 40 if (deadline.daysUntil > 3 && submission.score >= assignment.scoreLimit) { 41 deadline.className = "table-success" 42 } 43 if (!deadline.message) { 44 return 45 } 46 const course = state.courses.find(c => c.ID === courseID) 47 table.push( 48 <tr key={assignment.ID.toString()} className={`clickable-row ${deadline.className}`} 49 onClick={() => history.push(`/course/${courseID}/lab/${assignment.ID}`)}> 50 <th scope="row">{course?.code}</th> 51 <td> 52 {assignment.name} 53 {assignment.isGroupLab ? 54 <span className="badge ml-2 float-right"><i className="fa fa-users" title="Group Assignment" /></span> : null} 55 </td> 56 <td><ProgressBar assignmentIndex={assignment.order - 1} courseID={courseID.toString()} submission={submission} type={Progress.OVERVIEW} /></td> 57 <td>{getFormattedTime(assignment.deadline)}</td> 58 <td>{deadline.message ? deadline.message : '--'}</td> 59 <td className={SubmissionStatus[submission.status]}> 60 {assignmentStatusText(assignment, submission)} 61 </td> 62 </tr> 63 ) 64 } 65 }) 66 return table 67 } 68 69 return ( 70 <div> 71 <table className="table rounded-lg table-bordered table-hover" id="LandingPageTable"> 72 <thead > 73 <tr> 74 <th scope="col">Course</th> 75 <th scope="col">Assignment</th> 76 <th scope="col">Progress</th> 77 <th scope="col">Deadline</th> 78 <th scope="col">Due in</th> 79 <th scope="col">Status</th> 80 </tr> 81 </thead> 82 <tbody> 83 {NewSubmissionsTable()} 84 </tbody> 85 </table> 86 </div> 87 ) 88 } 89 90 export default SubmissionsTable