MetaPhase-Consulting/State-TalentMAP

View on GitHub
src/Components/PositionDetailsItem/PositionDetailsItem.jsx

Summary

Maintainability
A
55 mins
Test Coverage
A
100%
import PropTypes from 'prop-types';
import { get } from 'lodash';
import Differentials from 'Components/Differentials';
import BidCount from 'Components/BidCount';
import PositionSkillCodeList from 'Components/PositionSkillCodeList';
import { checkFlag } from 'flags';
import { COMMON_PROPERTIES } from '../../Constants/EndpointParams';
import LanguageList from '../../Components/LanguageList/LanguageList';
import CondensedCardDataPoint from '../CondensedCardData/CondensedCardDataPoint';
import PositionDetailsDescription from './PositionDetailsDescription';
import PositionDetailsContact from './PositionDetailsContact';
import ServiceNeededToggle from './ServiceNeededToggle';
import GlossaryTermTrigger from '../GlossaryTermTrigger';
import { Handshake, HistDiffToStaff, IsHardToFill, ServiceNeedDifferential } from '../Ribbon';
import {
  formatDate,
  getAccessiblePositionNumber,
  getBidStatisticsObject,
  propOrDefault,
} from '../../utilities';

import { DEFAULT_HIGHLIGHT_POSITION } from '../../Constants/DefaultProps';
import {
  EMPTY_FUNCTION,
  HIGHLIGHT_POSITION,
  POSITION_DETAILS,
  USER_PROFILE,
} from '../../Constants/PropTypes';
import {
  NO_BUREAU,
  NO_END_DATE,
  NO_GRADE,
  NO_TOUR_OF_DUTY,
  NO_UPDATE_DATE,
  NO_USER_LISTED,
} from '../../Constants/SystemMessages';

export const renderHandshake = (stats, ribbonClass) => (
  get(stats, 'has_handshake_offered', false) && <Handshake cutSide="both" className={ribbonClass} />
);

export const renderHistDiffToStaff = (details, ribbonClass) => (
  get(details, 'isDifficultToStaff', false) && <HistDiffToStaff cutSide="both" className={ribbonClass} />
);

export const renderServiceNeedDifferential = (details, ribbonClass) => (
  get(details, 'isServiceNeedDifferential', false) && <ServiceNeedDifferential cutSide="both" className={ribbonClass} />
);

export const renderIsHardToFill = (details, ribbonClass) => (
  get(details, 'isHardToFill', false) && <IsHardToFill cutSide="both" className={ribbonClass} />
);

const DETO_RWA_FLAG = () => checkFlag('flags.deto_rwa');

const PositionDetailsItem = (props) => {
  const {
    details,
    editDescriptionContent,
    resetDescriptionEditMessages,
    editPocContent,
    editWebsiteContent,
    userProfile,
    highlightPosition,
    onHighlight,
    isProjectedVacancy,
    hideHeader,
    hideContact,
  } = props;

  const { position } = details;

  const ribbonClass = 'ribbon-position-details';

  const isHighlightLoading = highlightPosition.loading;
  const tourEndDate = propOrDefault(details, 'ted');
  const formattedTourEndDate = tourEndDate ? formatDate(tourEndDate) : NO_END_DATE;

  const formattedBureau = get(position, 'bureau', NO_BUREAU);
  const formattedTOD = propOrDefault(position, 'post.tour_of_duty') || NO_TOUR_OF_DUTY;

  const dangerPay = get(position, 'post.danger_pay');
  const postDifferential = get(position, 'post.differential_rate');
  const obcUrl = get(position, 'post.post_bidding_considerations_url');
  const diffProps = { dangerPay, postDifferential, obcUrl };
  const differentials = <Differentials {...diffProps} />;

  const incumbent = get(position, 'current_assignment.user') || NO_USER_LISTED;
  const assignee = get(position, 'assignee') || NO_USER_LISTED;
  const cycle = get(position, 'latest_bidcycle.name', 'None Listed');
  const deto = position?.availTeleworkPos ? 'Eligible' : 'Not Eligible';

  const getPostedDate = () => {
    const posted = get(position, COMMON_PROPERTIES.posted);
    if (posted) {
      return formatDate(posted);
    }
    return NO_UPDATE_DATE;
  };
  const postedDate = getPostedDate();

  const stats = getBidStatisticsObject(get(details, 'bid_statistics', [{}]));

  const formattedDate = formatDate(get(details, 'position.description.date_updated'));

  const isHighlighted = get(position, 'is_highlighted');
  return (
    <div className="usa-grid-full padded-main-content position-details-outer-container">
      <div className="handshake-offset-container">
        {renderHandshake(stats, position, ribbonClass)}
        {renderHistDiffToStaff(details, ribbonClass)}
        {renderServiceNeedDifferential(details, ribbonClass)}
        {renderIsHardToFill(details, ribbonClass)}
      </div>
      <div className="usa-grid-full position-details-description-container positions-details-about-position">
        <div className={`usa-width-${hideContact ? 'one-whole' : 'two-thirds'} about-section-left`}>
          { !hideHeader && <h2>About the Position</h2> }
          <PositionDetailsDescription
            details={position}
            editDescriptionContent={editDescriptionContent}
            resetDescriptionEditMessages={resetDescriptionEditMessages}
            updatedDate={hideContact ? formattedDate : null}
          />
          {
            isHighlighted &&
            <div className="featured-description-container">
              {`
                This is a featured position. To learn more about the benefits of filling a featured position, click on each term:
              `}
              <GlossaryTermTrigger className="featured-description--link" text="volunteer" term="Vol Cable - Volunteer Cable" />
              {', '}
              <GlossaryTermTrigger className="featured-description--link" text="hard-to-fill" term="HDS - Historically Difficult to Staff" />
              {', or '}
              <GlossaryTermTrigger className="featured-description--link" text="urgent vacancies" term="UV - Urgent Vacancy" />
              {'.'}
            </div>
          }
          <div className="usa-grid-full data-point-section">
            {hideContact && <BidCount bidStatistics={stats} altStyle isCondensed />}
            <CondensedCardDataPoint ariaLabel={getAccessiblePositionNumber(get(position, 'position_number'))} title="Position number" content={get(position, 'position_number')} />
            <CondensedCardDataPoint title="Skill" content={<PositionSkillCodeList primarySkill={get(position, 'skill')} secondarySkill={get(position, 'skill_secondary')} />} />
            <CondensedCardDataPoint title="Grade" content={get(position, 'grade', NO_GRADE)} />
            <CondensedCardDataPoint title="Bureau" content={formattedBureau} />
            <CondensedCardDataPoint title="Tour of Duty" content={formattedTOD} />
            <CondensedCardDataPoint title="Language" content={<LanguageList languages={get(position, 'languages')} propToUse="representation" />} />
            <CondensedCardDataPoint title="Post Differential | Danger Pay" content={differentials} />
            <CondensedCardDataPoint title={isProjectedVacancy ? 'Bid Season' : 'Bid Cycle'} content={cycle} />
            <CondensedCardDataPoint title="TED" content={formattedTourEndDate} />
            <CondensedCardDataPoint title="Incumbent" content={incumbent} />
            { isProjectedVacancy && <CondensedCardDataPoint title="Assignee" content={assignee} /> }
            { !isProjectedVacancy && <CondensedCardDataPoint title="Posted" content={postedDate} />}
            { DETO_RWA_FLAG() && <CondensedCardDataPoint title="RWA/DETO Eligible" content={deto} /> }
          </div>
        </div>
        {
          !hideContact &&
          <div className="usa-width-one-third position-details-contact-container">
            <PositionDetailsContact
              details={{
                ...position,
                bidStatistics: get(details, 'bid_statistics', [{}]),
              }}
              editWebsiteContent={editWebsiteContent}
              editPocContent={editPocContent}
              resetDescriptionEditMessages={resetDescriptionEditMessages}
              isProjectedVacancy={isProjectedVacancy}
            />
            {
              !isProjectedVacancy &&
              <ServiceNeededToggle
                userProfile={userProfile}
                position={details}
                loading={isHighlightLoading}
                onChange={onHighlight}
              />
            }
          </div>
        }
      </div>
    </div>
  );
};

PositionDetailsItem.propTypes = {
  details: POSITION_DETAILS,
  editDescriptionContent: PropTypes.func.isRequired,
  resetDescriptionEditMessages: PropTypes.func.isRequired,
  editWebsiteContent: PropTypes.func.isRequired,
  editPocContent: PropTypes.func.isRequired,
  userProfile: USER_PROFILE,
  highlightPosition: HIGHLIGHT_POSITION,
  onHighlight: PropTypes.func.isRequired,
  isProjectedVacancy: PropTypes.bool,
  hideHeader: PropTypes.bool,
  hideContact: PropTypes.bool,
};

PositionDetailsItem.defaultProps = {
  details: null,
  userProfile: {},
  highlightPosition: DEFAULT_HIGHLIGHT_POSITION,
  onHighlight: EMPTY_FUNCTION,
  isProjectedVacancy: false,
  hideHeader: false,
  hideContact: false,
};

export default PositionDetailsItem;