All files / components/Staff StaffTabComponent.jsx

100% Statements 88/88
100% Branches 13/13
100% Functions 11/11
100% Lines 88/88

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 1171x 1x 1x 1x 1x 1x 1x   1x 1x 1x 1x 47x 47x   47x   47x 47x 47x 47x 47x   47x   47x 1x 1x 1x 1x   47x 1x 1x 1x   47x 47x 47x 47x     47x 1x 1x   47x 2x 2x 2x 2x 2x 2x 2x 2x 2x   47x 2x 2x 1x 1x 2x 2x   2x 2x   47x 47x 47x 47x     47x 2x 2x   47x 47x 47x 47x 47x   47x 47x     47x 47x 47x   47x 47x     47x 47x 47x 47x 47x 47x     47x 47x 47x 47x 47x 47x     47x     47x  
import { toast } from "react-toastify";
import { useBackend, useBackendMutation } from "main/utils/useBackend";
import React, { useState } from "react";
import { Button, Modal } from "react-bootstrap";
import StaffCSVUploadForm from "main/components/Staff/StaffCSVUploadForm";
import StaffForm from "main/components/Staff/StaffForm";
import StaffTable from "main/components/Staff/StaffTable";
 
// The Staff tab of a course's admin page: adding staff (individually or via
// CSV roster upload) is scoped to this courseId, not a free-standing admin
// page with a course-picker. See issue #251.
export default function StaffTabComponent({ courseId, currentUser }) {
  const [showAddModal, setShowAddModal] = useState(false);
  const [showCsvModal, setShowCsvModal] = useState(false);
 
  const queryKey = [`/api/staff/course/${courseId}`];
 
  // Stryker disable all
  const { data: staff } = useBackend(
    queryKey,
    { method: "GET", url: `/api/staff/course/${courseId}` },
    [],
  );
  // Stryker restore all
 
  const objectToAxiosParamsAdd = (staffMember) => ({
    url: "/api/staff",
    method: "POST",
    data: { ...staffMember, courseId },
  });
 
  const onAddSuccess = () => {
    toast("Staff member added successfully.");
    setShowAddModal(false);
  };
 
  const addMutation = useBackendMutation(
    objectToAxiosParamsAdd,
    { onSuccess: onAddSuccess },
    queryKey,
  );
 
  const submitAddForm = (data) => {
    addMutation.mutate(data);
  };
 
  const objectToAxiosParamsCsv = (formData) => {
    const file = new FormData();
    file.append("file", formData.upload[0]);
    return {
      url: "/api/staff/upload/csv",
      method: "POST",
      params: { courseId },
      data: file,
    };
  };
 
  const onCsvSuccess = (result) => {
    const skipped = result.skippedEmails.length;
    const skippedMessage = skipped
      ? `, ${skipped} skipped (already on roster)`
      : "";
    toast(
      `Roster uploaded: ${result.created} staff member(s) added${skippedMessage}.`,
    );
    setShowCsvModal(false);
  };
 
  const csvMutation = useBackendMutation(
    objectToAxiosParamsCsv,
    { onSuccess: onCsvSuccess },
    queryKey,
  );
 
  const submitCsvForm = (formData) => {
    csvMutation.mutate(formData);
  };
 
  return (
    <div data-testid="StaffTabComponent">
      <Modal show={showAddModal} onHide={() => setShowAddModal(false)}>
        <Modal.Header closeButton>
          <Modal.Title>Add Individual Staff Member</Modal.Title>
        </Modal.Header>
        <Modal.Body>
          <StaffForm submitAction={submitAddForm} cancelDisabled={true} />
        </Modal.Body>
      </Modal>
      <Modal show={showCsvModal} onHide={() => setShowCsvModal(false)}>
        <Modal.Header closeButton>
          <Modal.Title>Upload CSV Roster</Modal.Title>
        </Modal.Header>
        <Modal.Body>
          <StaffCSVUploadForm submitAction={submitCsvForm} />
        </Modal.Body>
      </Modal>
      <Button
        variant="primary"
        className="mb-3 me-2"
        data-testid="StaffTabComponent-add-button"
        onClick={() => setShowAddModal(true)}
      >
        Add Individual Staff Member
      </Button>
      <Button
        variant="secondary"
        className="mb-3"
        data-testid="StaffTabComponent-csv-button"
        onClick={() => setShowCsvModal(true)}
      >
        Upload CSV Roster
      </Button>
      <StaffTable staff={staff} currentUser={currentUser} courseId={courseId} />
    </div>
  );
}