Lambda-School-Labs/Labs26-StorySquad-BE-TeamB

View on GitHub
lib/formatHelpers.js

Summary

Maintainability
A
1 hr
Test Coverage
A
100%
/**
 * Formats an array of cohort submissions into an object that maps submission ids (page.ID)
 * to the submission info (...page)
 * @param {Array} submissions an array of all submissions in a given cohort
 * @returns {Object} returns an object that maps submission info for a cohort to each submission ID
 */
const formatCohortSubmissions = (submissions) => {
  const res = {};
  // Iterate over each submission
  submissions.forEach((page) => {
    // Initialize an entry in the hash table the first time you see a given Submission ID
    if (!res[page.ID]) {
      res[page.ID] = {
        Image: page.DrawingURL,
        Inappropriate: page.Inappropriate,
        Sensitive: page.Sensitive,
        Status: page.Status,
        Complexity: page.Complexity,
        Pages: {},
      };
    }
    // Add the current page to the pages object as pages: { [pageNum]: pageURL }
    res[page.ID].Pages[page.PageNum] = page.WritingURL;
  });
  return res;
};

/**
 * Formats the amalgamized array of child/parent data into separate, readble profiles each denoted
 * by a specific type tag for the GET /profiles router endpoint
 * @param {Array} profiles an array of children objects returned from Parents.getProfilesByEmail(),
 *                         each of which has parent data, to be parsed into separate profiles
 * @returns {Array} an array of child/parent profiles with type values
 */
const formatProfiles = (profiles) => {
  // Initialize response array
  const res = [];
  // Pull the parent data out of the first entry and add it to the response
  res.push(makeParent(profiles[0]));
  // Iterate over all of the entries
  profiles.forEach((child) => {
    // If the entry includes data for a child, add a formatted child to the response - note:
    // this conditional is in place to handle situations where profiles are being returned
    // for a parent that has no children
    if (child.ChildID) {
      res.push(makeChild(child));
    }
  });
  return res;
};

/**
 * Takes an object returned by Parents.getProfilesByEmail(), strips it of the excess child
 * data, and adds a type 'Parent' to it for the GET /profiles endpoint
 * @param {Object} param0 a parent object with values ID, Name, Email, PIN
 * @returns {Object} a formatted parent with the added field { type: 'Parent' }
 */
const makeParent = ({ ID, Name, Email, PIN }) => ({
  ID,
  Name,
  Email,
  PIN,
  type: 'Parent',
});

/**
 * Takes an object returned by Parents.getProfilesByEmail(), strips it of the excess parent
 * data, formats the child data into proper field names, and adds a type 'Child' to it for
 * the GET /profiles endpoint
 * @param {Object} param0 a child object returned by Parents.getProfilesByEmail()
 * @returns {Object} a formatted child object with added field { type: 'Child' }
 */
const makeChild = ({
  IsDyslexic,
  GradeLevel,
  AvatarURL,
  CohortID,
  ...child
}) => ({
  ID: child.ChildID,
  PIN: child.ChildPIN,
  Name: child.ChildName,
  IsDyslexic,
  GradeLevel,
  AvatarURL,
  CohortID,
  ParentID: child.ID,
  type: 'Child',
});

/**
 * A function that takes an array of students' submissions, organizes them by childId, and sorts the written
 * pages into an array.
 * @param {Array} submissions an array of all pages for a team's submission (two children, 1-5 pages each)
 * @returns {Object} returns a formatted team object documented at GET /game/team
 */
const formatTeam = (submissions) => {
  // Initialize response object
  const team = {};
  // Iterate over submission pages
  submissions.forEach(
    ({
      MemberID,
      ChildID,
      SubmissionID,
      Name,
      ImgURL,
      PageURL,
      PageNum,
      AvatarURL,
      ChildName,
    }) => {
      // If the team name hasn't been set yet, set it here
      if (!team.name) team.name = Name;
      // Initialize an object for each child
      if (!team[ChildID])
        team[ChildID] = {
          ChildID,
          MemberID,
          SubmissionID,
          ImgURL,
          ChildName,
          AvatarURL,
          Pages: [],
        };
      // Add each page to the child's Pages array
      team[ChildID].Pages.push({ PageURL, PageNum });
    }
  );
  return team;
};

/**
 * This function formats an array of submission objects from the databaSe into a single submission object
 * @param {Array} pages an array of page objects for a given submission
 * @returns {Object} retruns a formatted submission object with an array of Pages
 */
const formatSubForMatchups = (pages) => {
  const res = {};
  // Iterate over the page objects
  pages.forEach(({ ID, PageNum, PageURL, ImgURL, AvatarURL, Name }) => {
    // Set the ID and ImgURL of the response object if it hasn't yet been set
    if (!res.ID) res.ID = ID;
    if (!res.Name) res.Name = Name;
    if (!res.ImgURL) res.ImgURL = ImgURL;
    if (!res.AvatarURL) res.AvatarURL = AvatarURL;
    // Initialize the Pages array on the response object
    if (!res.Pages) res.Pages = [];
    // Add each page to the Pages array
    res.Pages.push({ PageNum, PageURL });
  });
  return res;
};

/**
 * Takes the results of a query joining children with their submissions and parses them into
 * the proper format for the ds api
 * @param {Array} complexities an array of complexity scores/child name
 * @returns {Object} returns a formatted object:\{ StudentName: '', ScoreHistory: [] }
 */
const formatLineGraphBody = (complexities) => {
  const res = {};
  complexities.forEach((score) => {
    if (!res.StudentName) res.StudentName = score.Name;
    if (!res.ScoreHistory) res.ScoreHistory = [];
    res.ScoreHistory.push(score.Complexity);
  });
  return res;
};

module.exports = {
  formatCohortSubmissions,
  formatProfiles,
  formatTeam,
  formatSubForMatchups,
  formatLineGraphBody,
};