department-of-veterans-affairs/vets-website

View on GitHub
src/applications/gi/containers/CompareLayout.jsx

Summary

Maintainability
D
2 days
Test Coverage
import React from 'react';
import { connect } from 'react-redux';
import classNames from 'classnames';
import _ from 'lodash';
import environment from 'platform/utilities/environment';
import CompareGrid from '../components/CompareGrid';
import {
  boolYesNo,
  convertRatingToStars,
  formatCurrency,
  isShowVetTec,
  naIfNull,
  schoolSize,
  upperCaseFirstLetterOnly,
} from '../utils/helpers';
import { MINIMUM_RATING_COUNT } from '../constants';
import RatingsStars from '../components/profile/schoolRatings/RatingsStars';
import { showModal } from '../actions';
import { religiousAffiliations } from '../utils/data/religiousAffiliations';
import {
  AccreditationModalContent,
  GiBillStudentsModalContent,
  SizeOfInstitutionsModalContent,
  SpecializedMissionModalContent,
  TuitionAndFeesModalContent,
  HousingAllowanceSchoolModalContent,
  BookStipendInfoModalContent,
  CautionFlagsModalContent,
  StudentComplaintsModalContent,
  MilitaryTrainingCreditModalContent,
  YellowRibbonModalContent,
  StudentVeteranGroupModalContent,
  PrinciplesOfExcellenceModalContent,
  EightKeysModalContent,
  MilitaryTuitionAssistanceModalContent,
  PriorityEnrollmentModalContent,
} from '../components/content/modals';

export const renFieldData = (programHours, automatedTest = false) => {
  if (isShowVetTec(automatedTest)) {
    return [
      {
        label: 'Length of VET TEC programs',
        mapper: institution => programHours(institution.programLengthInHours),
      },
      {
        label: 'Credit for military training',
        mapper: institution => boolYesNo(institution.creditForMilTraining),
      },
    ];
  }
  return [
    {
      label: 'Credit for military training',
      mapper: institution => boolYesNo(institution.creditForMilTraining),
    },
  ];
};

const CompareLayout = ({
  calculated,
  estimated,
  institutions,
  showDifferences,
  smallScreen,
}) => {
  // environment variable to keep ratings out of production until ready
  const isProduction = !environment.isProduction();
  const mapRating = institution => {
    const { type } = institution; // used to identify if the training is OJT
    let ratingAverage = false;
    let ratingCount = -1;
    let institutionRatingIsNotNull = false;
    let institutionCountIsNotNull = false;
    let institutionOverallAvgIsNotNull = false;
    const ratingsAriaLabel = `Overall rating for ${
      institution.name
    } has not yet been rated by veterans`;
    /** ***CHECK IF INSTITUTION.INSTITUTIONRATING IS NULL**** */
    if (institution.institutionRating != null) {
      institutionRatingIsNotNull = true;
    }
    if (
      institutionRatingIsNotNull &&
      institution.institutionRating.institutionRatingCount != null
    ) {
      institutionCountIsNotNull = true;
    }
    if (
      institutionRatingIsNotNull &&
      institutionCountIsNotNull &&
      institution.institutionRating.overallAvg != null
    ) {
      institutionOverallAvgIsNotNull = true;
    }
    if (
      institutionRatingIsNotNull &&
      institutionCountIsNotNull &&
      institutionOverallAvgIsNotNull
    ) {
      const {
        institutionRatingCount,
        overallAvg,
      } = institution.institutionRating;
      ratingAverage = overallAvg;
      ratingCount = institutionRatingCount;
    }
    /// /////////////////////////////////////////////////////////////////////

    if (ratingAverage && ratingCount >= MINIMUM_RATING_COUNT) {
      const stars = convertRatingToStars(ratingAverage);
      return (
        <div>
          <div
            aria-label={`Overall Rating for ${institution.name} is ${
              stars.display
            } out of 4.`}
          >
            {stars.display} out of a possible 4 stars
          </div>
          <div>
            <RatingsStars rating={ratingAverage} />{' '}
          </div>
        </div>
      );
    }
    if (type.toUpperCase() === 'OJT') {
      return (
        <div
          aria-label={`Overall rating not applicable for ${institution.name}`}
        >
          N/A
        </div>
      );
    }

    return <div aria-label={ratingsAriaLabel}>Not yet rated by Veterans</div>;
  };

  const formatEstimate = ({ qualifier, value }) => {
    if (qualifier === '% of instate tuition') {
      return <span>{value}% in-state</span>;
    }
    if (qualifier === null) {
      return value;
    }
    return <span>{formatCurrency(value)}</span>;
  };

  const programHours = programLength => {
    if (!programLength) return 'N/A';

    const maxHours = Math.max(...programLength);
    const minHours = Math.min(...programLength);
    if (
      programLength &&
      programLength.length > 0 &&
      maxHours + minHours !== 0
    ) {
      return `${
        minHours === maxHours ? minHours : `${minHours} - ${maxHours}`
      } hours`;
    }
    return 'N/A';
  };

  const fieldDataSummary = [
    {
      label: 'Location',
      className: 'capitalize-value',
      mapper: institution => {
        return institution.country === 'USA'
          ? `${institution.city}, ${institution.state}`
          : `${institution.city}, ${institution.country}`;
      },
    },
    {
      label: 'Overall rating',
      mapper: institution => mapRating(institution),
    },
    {
      label: 'Accreditation',
      className: 'capitalize-value',
      mapper: institution => naIfNull(institution.accreditationType),
    },
    {
      label: 'GI Bill students',
      className: 'capitalize-value',
      mapper: institution => naIfNull(institution.studentCount),
    },
    {
      label: 'Length of program',
      mapper: institution => {
        if (!institution.highestDegree) {
          return 'N/A';
        }

        return _.isFinite(institution.highestDegree)
          ? `${institution.highestDegree} year`
          : `${institution.highestDegree} program`;
      },
    },
    {
      label: 'Type of institution',
      mapper: institution => {
        if (institution.vetTecProvider) {
          return 'VET TEC';
        }
        if (institution.type.toLowerCase() === 'ojt') {
          return 'Employer';
        }
        return `${upperCaseFirstLetterOnly(institution.type)} school`;
      },
    },
    {
      label: 'Institution locale',
      className: 'capitalize-value',
      mapper: institution => naIfNull(institution.localeType),
    },
    {
      label: 'Size of institution',
      className: 'capitalize-value',
      mapper: institution => schoolSize(institution.undergradEnrollment),
    },
    {
      label: 'Community focus',
      className: 'capitalize-value',
      mapper: institution => {
        const specialMission = [];
        if (institution.hbcu) {
          specialMission.push('Historically Black Colleges and Universities');
        }
        if (institution.relaffil) {
          specialMission.push(religiousAffiliations[institution.relaffil]);
        }
        if (institution.womenonly) {
          specialMission.push('Women’s colleges and universities');
          // specialMission.push('Women-only');
        }
        if (institution.menonly) {
          specialMission.push('Men’s colleges and universities');
        }
        return specialMission.length > 0 ? specialMission.join(', ') : 'N/A';
      },
    },
  ];

  return (
    <div className={classNames({ 'row vads-l-grid-container': !smallScreen })}>
      <CompareGrid
        sectionLabel="Summary"
        institutions={institutions}
        showDifferences={showDifferences}
        smallScreen={smallScreen}
        fieldData={
          isProduction
            ? fieldDataSummary
            : fieldDataSummary.filter(
                value => value.label.toUpperCase() !== 'OVERALL RATING',
              )
        }
      />
      <va-additional-info trigger="Additional information on comparison summary fields">
        <AccreditationModalContent />
        <GiBillStudentsModalContent />
        <SizeOfInstitutionsModalContent />
        <SpecializedMissionModalContent />
      </va-additional-info>

      <CompareGrid
        sectionLabel="Your estimated benefits"
        subSectionLabel="Payments made to institution"
        institutions={institutions}
        showDifferences={showDifferences}
        smallScreen={smallScreen}
        fieldData={[
          {
            label: 'Tuition and fees',
            mapper: institution =>
              formatCurrency(
                calculated[institution.facilityCode].outputs
                  .tuitionAndFeesCharged.value,
              ),
          },
          {
            label: 'GI Bill pays to institution',
            mapper: institution =>
              formatCurrency(
                calculated[institution.facilityCode].outputs.giBillPaysToSchool
                  .value,
              ),
          },
          {
            label: 'Out of pocket tuition',
            mapper: institution =>
              formatCurrency(
                calculated[institution.facilityCode].outputs.outOfPocketTuition
                  .value,
              ),
          },
        ]}
      />

      <va-additional-info trigger="Additional information on payments made to institution fields">
        <TuitionAndFeesModalContent />
      </va-additional-info>

      <CompareGrid
        subSectionLabel="Payments made to you"
        institutions={institutions}
        showDifferences={showDifferences}
        smallScreen={smallScreen}
        fieldData={[
          {
            label: 'Housing allowance',
            mapper: institution =>
              formatEstimate(estimated[institution.facilityCode].housing),
          },
          {
            label: 'Book stipend',
            mapper: institution =>
              formatEstimate(estimated[institution.facilityCode].books),
          },
        ]}
      />
      <va-additional-info trigger="Additional information on payments made to you fields">
        <HousingAllowanceSchoolModalContent />
        <BookStipendInfoModalContent />
      </va-additional-info>

      {/* ////////////////////////////////////////////////////////////////////////////////////////////////////// */}
      {/* LEAVING CODE IN UNTIL EDU APPROVES DELETION */}
      {/* {//gibctSchoolRatings && used for toggle, rework this before pushing to staging
        (
          <>
            <CompareGrid
              sectionLabel="Veteran ratings"
              institutions={institutions}
              showDifferences={showDifferences}
              smallScreen={smallScreen}
              fieldData={[
                {
                  label: 'Overall rating',
                  className: 'vads-u-text-align--center rating-value',
                  mapper: institution => {
                    const stars = convertRatingToStars(
                      // institution.ratingAverage,
                      ratingAverage
                    );
                    const aboveMinimumRatingCount =
                      // institution.ratingCount >= MINIMUM_RATING_COUNT;
                      ratingCount >= MINIMUM_RATING_COUNT;

                    return (
                      <div className="vads-u-display--inline-block vads-u-text-align--center main-rating">
                        <div className="vads-u-font-weight--bold vads-u-font-size--2xl vads-u-font-family--serif">
                          {aboveMinimumRatingCount && stars && stars.display}
                          {(!aboveMinimumRatingCount || !stars) && (
                            <span>N/A</span>
                          )}
                        </div>
                        <div className="vads-u-font-size--sm vads-u-padding-bottom--1">
                          {aboveMinimumRatingCount &&
                            stars && <span>out of a possible 4 stars</span>}
                          {(!aboveMinimumRatingCount || !stars) && (
                            <span>not yet rated</span>
                          )}
                        </div>
                        {aboveMinimumRatingCount &&
                          stars && (
                            <div className="vads-u-font-size--lg">
                              <RatingsStars
                                rating={institution.ratingAverage}
                              />
                            </div>
                          )}
                      </div>
                    );
                  },
                },
                {
                  label: '# of Veteran ratings',
                  className: () =>
                    !smallScreen ? 'vads-u-text-align--center' : '',
                  mapper: institution =>
                    // institution.ratingCount >= MINIMUM_RATING_COUNT
                    //   ? institution.ratingCount
                    ratingCount >= MINIMUM_RATING_COUNT
                      ? ratingCount
                      : '0',
                },
              ]}
            /> */}
      {/* <CompareGrid
              subSectionLabel="Education ratings"
              institutions={institutions}
              showDifferences={showDifferences}
              smallScreen={smallScreen}
              fieldData={[
                {
                  label: 'Overall experience',
                  mapper: institution =>
                    mapRating(institution, 'overall_experience'),
                },
                {
                  label: 'Quality of classes',
                  mapper: institution =>
                    mapRating(institution, 'quality_of_classes'),
                },
                {
                  label: 'Online instruction',
                  mapper: institution =>
                    mapRating(institution, 'online_instruction'),
                },
                {
                  label: 'Job preparation',
                  mapper: institution =>
                    mapRating(institution, 'job_preparation'),
                },
              ]}
            />S

            <CompareGrid
              subSectionLabel="Veteran friendliness"
              institutions={institutions}
              showDifferences={showDifferences}
              smallScreen={smallScreen}
              fieldData={[
                {
                  label: 'GI Bill support',
                  mapper: institution =>
                    mapRating(institution, 'gi_bill_support'),
                },
                {
                  label: 'Veteran community',
                  mapper: institution =>
                    mapRating(institution, 'veteran_community'),
                },
                {
                  label: 'True to expectations',
                  mapper: institution =>
                    mapRating(institution, 'marketing_practices'),
                },
              ]}
            />
          </>
        )} */}
      {/* ////////////////////////////////////////////////////////////////////////////////////////////////////// */}

      <CompareGrid
        sectionLabel="Cautionary information"
        institutions={institutions}
        smallScreen={smallScreen}
        fieldData={[
          {
            label: 'Caution flags',
            className: institution =>
              classNames('caution-flag-display', {
                none: institution.cautionFlags.length === 0,
              }),
            mapper: institution => {
              const hasFlags = institution.cautionFlags.length > 0;
              return (
                <div className="vads-u-display--flex">
                  <div className="caution-flag-icon vads-u-flex--1">
                    {!hasFlags && (
                      <va-icon size={4} icon="check" class="display-none" />
                    )}
                    {hasFlags && <va-icon size={3} icon="warning" />}
                  </div>
                  <div className="vads-u-flex--4">
                    {!hasFlags && (
                      <div className="caution-header">
                        <span>This school doesn’t have any caution flags</span>
                      </div>
                    )}
                    {hasFlags && (
                      <div className="caution-header">
                        <span>
                          This school has {institution.cautionFlags.length}{' '}
                          cautionary warning
                          {institution.cautionFlags.length > 1 && 's'}
                        </span>
                      </div>
                    )}
                    {hasFlags && (
                      <div>
                        <ul>
                          {institution.cautionFlags.map(
                            (cautionFlag, index) => {
                              return <li key={index}>{cautionFlag.title}</li>;
                            },
                          )}
                        </ul>
                      </div>
                    )}
                  </div>
                </div>
              );
            },
          },
        ]}
      />

      <CompareGrid
        sectionLabel=""
        className={classNames({ 'vads-u-margin-top--4': !smallScreen })}
        institutions={institutions}
        showDifferences={showDifferences}
        smallScreen={smallScreen}
        fieldData={[
          {
            label: 'Student complaints',
            mapper: institution => +institution.complaints.mainCampusRollUp,
          },
        ]}
      />
      <va-additional-info trigger="Additional information on cautionary information fields">
        <CautionFlagsModalContent />
        <StudentComplaintsModalContent />
      </va-additional-info>

      <CompareGrid
        sectionLabel="Academics"
        institutions={institutions}
        showDifferences={showDifferences}
        smallScreen={smallScreen}
        fieldData={renFieldData(programHours)}
      />
      <va-additional-info trigger="Additional information on academics fields">
        <MilitaryTrainingCreditModalContent />
      </va-additional-info>

      <CompareGrid
        sectionLabel="Veteran programs"
        institutions={institutions}
        showDifferences={showDifferences}
        smallScreen={smallScreen}
        fieldData={[
          {
            label: 'Yellow Ribbon',
            mapper: institution => boolYesNo(institution.yr),
          },
          {
            label: 'Student Veteran Group',
            mapper: institution => boolYesNo(institution.studentVeteran),
          },
          {
            label: 'Principles of Excellence',
            mapper: institution => boolYesNo(institution.poe),
          },
          {
            label: '8 Keys to Veteran Success',
            mapper: institution => boolYesNo(institution.eightKeys),
          },
          {
            label: 'Military Tuition Assistance (TA)',
            mapper: institution => boolYesNo(institution.dodmou),
          },
          {
            label: 'Priority Enrollment',
            mapper: institution => boolYesNo(institution.priorityEnrollment),
          },
        ]}
      />
      <va-additional-info trigger="Additional information on veteran programs fields">
        <YellowRibbonModalContent />
        <StudentVeteranGroupModalContent />
        <PrinciplesOfExcellenceModalContent />
        <EightKeysModalContent />
        <MilitaryTuitionAssistanceModalContent />
        <PriorityEnrollmentModalContent />
      </va-additional-info>
    </div>
  );
};

const mapDispatchToProps = {
  dispatchShowModal: showModal,
};

export default connect(
  null,
  mapDispatchToProps,
)(CompareLayout);