github.com/quickfeed/quickfeed@v0.0.0-20240507093252-ed8ca812a09c/public/src/components/Members.tsx (about)

     1  import React, { useState } from "react"
     2  import { Color, EnrollmentSort, EnrollmentStatus, EnrollmentStatusBadge, getCourseID, getFormattedTime, isPending, isTeacher, sortEnrollments } from "../Helpers"
     3  import { useAppState, useActions } from "../overmind"
     4  import { Enrollment, Enrollment_UserStatus } from "../../proto/qf/types_pb"
     5  import Search from "./Search"
     6  import DynamicTable, { Row } from "./DynamicTable"
     7  import DynamicButton from "./DynamicButton"
     8  import Button, { ButtonType } from "./admin/Button"
     9  
    10  const Members = (): JSX.Element => {
    11      const state = useAppState()
    12      const actions = useActions()
    13      const courseID = getCourseID()
    14  
    15      const [sortBy, setSortBy] = useState<EnrollmentSort>(EnrollmentSort.Status)
    16      const [descending, setDescending] = useState<boolean>(false)
    17      const [edit, setEditing] = useState<boolean>(false)
    18  
    19  
    20      const setSort = (sort: EnrollmentSort) => {
    21          if (sortBy === sort) {
    22              setDescending(!descending)
    23          }
    24          setSortBy(sort)
    25      }
    26  
    27      let enrollments: Enrollment[] = []
    28      if (state.courseEnrollments[courseID.toString()]) {
    29          // Clone the enrollments so we can sort them
    30          enrollments = state.courseEnrollments[courseID.toString()].slice()
    31      }
    32  
    33      const pending = state.pendingEnrollments
    34  
    35      const header: Row = [
    36          { value: "Name", onClick: () => setSort(EnrollmentSort.Name) },
    37          { value: "Email", onClick: () => setSort(EnrollmentSort.Email) },
    38          { value: "Student ID", onClick: () => setSort(EnrollmentSort.StudentID) },
    39          { value: "Activity", onClick: () => setSort(EnrollmentSort.Activity) },
    40          { value: "Approved", onClick: () => setSort(EnrollmentSort.Approved) },
    41          { value: "Slipdays", onClick: () => { setSort(EnrollmentSort.Slipdays) } },
    42          { value: "Role", onClick: () => { setSort(EnrollmentSort.Status) } },
    43      ]
    44      const members = sortEnrollments(enrollments, sortBy, descending).map(enrollment => {
    45          const data: Row = []
    46          data.push(enrollment.user ? enrollment.user.Name : "")
    47          data.push(enrollment.user ? enrollment.user.Email : "")
    48          data.push(enrollment.user ? enrollment.user.StudentID : "")
    49          data.push(getFormattedTime(enrollment.lastActivityDate))
    50          data.push(enrollment.totalApproved.toString())
    51          data.push(enrollment.slipDaysRemaining.toString())
    52  
    53          if (isPending(enrollment)) {
    54              data.push(
    55                  <div className="d-flex">
    56                      <DynamicButton
    57                          text={"Accept"}
    58                          color={Color.GREEN}
    59                          type={ButtonType.BADGE}
    60                          className="mr-2"
    61                          onClick={() => actions.updateEnrollment({ enrollment, status: Enrollment_UserStatus.STUDENT })}
    62                      />
    63                      <DynamicButton
    64                          text={"Reject"}
    65                          color={Color.RED}
    66                          type={ButtonType.BADGE}
    67                          onClick={() => actions.updateEnrollment({ enrollment, status: Enrollment_UserStatus.NONE })}
    68                      />
    69                  </div>)
    70          } else {
    71              data.push(edit ? (
    72                  <div className="d-flex">
    73                      <DynamicButton
    74                          text={isTeacher(enrollment) ? "Demote" : "Promote"}
    75                          color={isTeacher(enrollment) ? Color.YELLOW : Color.BLUE}
    76                          type={ButtonType.BADGE}
    77                          className="mr-2"
    78                          onClick={() => actions.updateEnrollment({ enrollment, status: isTeacher(enrollment) ? Enrollment_UserStatus.STUDENT : Enrollment_UserStatus.TEACHER })}
    79                      />
    80                      <DynamicButton
    81                          text={"Reject"}
    82                          color={Color.RED}
    83                          type={ButtonType.BADGE}
    84                          onClick={() => actions.updateEnrollment({ enrollment, status: Enrollment_UserStatus.NONE })}
    85                      />
    86                  </div>) :
    87                  <i className={EnrollmentStatusBadge[enrollment.status]}>
    88                      {EnrollmentStatus[enrollment.status]}
    89                  </i>
    90              )
    91          }
    92          return data
    93      })
    94  
    95      return (
    96          <div className='container'>
    97              <div className="row no-gutters pb-2">
    98                  <div className="col-md-6">
    99                      <Search />
   100                  </div>
   101                  <div className="ml-auto">
   102                      <Button
   103                          text={edit ? "Done" : "Edit"}
   104                          color={edit ? Color.RED : Color.BLUE}
   105                          type={ButtonType.BUTTON}
   106                          onClick={() => setEditing(!edit)}
   107                      />
   108                  </div>
   109                  {pending?.length > 0 ?
   110                      <div style={{ marginLeft: "10px" }}>
   111                          <DynamicButton
   112                              text="Approve All"
   113                              color={Color.GREEN}
   114                              type={ButtonType.BUTTON}
   115                              onClick={() => actions.approvePendingEnrollments()}
   116                          />
   117                      </div> : null}
   118              </div>
   119  
   120              <div>
   121                  <DynamicTable header={header} data={members} />
   122              </div>
   123          </div>
   124      )
   125  }
   126  
   127  export default Members