<commit_before>// beginning to alphabetize imports for best practices
import { Button } from 'semantic-ui-react';
import Career from './Profile/Preferences/Career';
import Certifications from './Profile/Preferences/Certifications';
import Collaboration from './Profile/Preferences/Collaboration';
import { connect } from 'react-redux';
import { connectScreenSize } from 'react-screen-size';
import { countryCodes } from '../../assets/dropdowns/countries';
import ERROR from '../../assets/helpers/errors';
import { findIndex } from 'lodash';
import interests, { INTERESTS_MAP } from '../../assets/dropdowns/interests';
import { isEmpty } from 'lodash';
import { mapScreenSizeToProps } from '../Navbar';
import Mentorship from './Profile/Preferences/Mentorship';
import Modal from './Profile/Preferences/common/SaveModal';
import PersonalInfo from './Profile/Preferences/PersonalInfo';
import propTypes from 'prop-types';
import React from 'react';
import { savePreferencesViewState } from '../../actions/views';
import { saveUser, updateUser, updateUserPartial } from '../../actions/user';
import skills, { SKILLS_MAP } from '../../assets/dropdowns/skills';
import SkillsAndInterests from './Profile/Preferences/SkillsAndInterests';
import Social from './Profile/Preferences/Social';
import styled from 'styled-components';
import swearjar from '../../assets/helpers/swearjar-lite';
import { ThickPaddedBottom } from '../../styles/style-utils';
import UserLabel from '../dashboard/common/UserLabel';
import validate from '../../assets/helpers/validations';

/*
TODO:
  - PERSONAL INFO: validation to require user to enter country to collect data for D3 map?
  - GENERAL: Refactor validation code, kind of reduntant and could be improved (isPageValid && isSectionValid)
*/

const BottomButton = styled(Button)`
  right: 0;
  bottom: 35px;
`;

const Container = styled(ThickPaddedBottom)`
  @media (max-width: 770px) {
    padding: 0 10px 50px 10px !important;
  }
`;

const TopButton = styled(Button)`
  height: 42px !important;
  padding: 10px !important;
  @media (max-width: 959px) {
    margin-top: 10px !important;
  }
  @media (min-width: 959px) {
    float: right !important;
  }
`;

class Preferences extends React.Component {
  constructor(props) {
    super(props);
    const { user, viewState } = this.props;
    this.state = {
      user,
      viewState,
      errors: {},
      modalOpen: false,
      isPageValid: true,
      profileWarning: '',
      socialPopUp: false,
      careerPopUp: false,
      projectsPopUp: false,
      personalPopUp: false,
      mentorshipPopUp: false,
      showBottomButton: false,
      skillsAndInterestsPopUp: false,
      interestsOptions: [],
      skillsOptions: [],
    }
  }

  componentDidMount() {
    document.addEventListener('scroll', this.handleScroll);
    var { user } = this.state;
    /* add user-added, non-default skills to skillsOptions for
    correct rendering of multi-select dropdown component... */
    let skillsOptions = skills;
    user.skillsAndInterests.coreSkills.forEach(value => {
      if (findIndex(skillsOptions, { text: value, value }) === -1) {
        skillsOptions = [{ text: value, value }, ...skillsOptions];
      }
    });
    // ...then add non-default interests
    let interestsOptions = interests;
    user.skillsAndInterests.codingInterests.forEach(value => {
      if (findIndex(interestsOptions, { text: value, value }) === -1) {
        interestsOptions = [{ text: value, value }, ...interestsOptions];
      }
    });
    this.setState({ skillsOptions, interestsOptions });
  }

  componentWillUnmount() {
    this.props.savePreferencesViewState(this.state.viewState);
    document.removeEventListener('scroll', this.handleScroll);
  }

  handleScroll = (e) => {
    if (e.target.scrollingElement.scrollTop >= 60) {
      this.setState({ showBottomButton: true });
    } else {
      this.setState({ showBottomButton: false });
    }
  }

  /**********************
  HANDLE CHANGE FUNCTIONS
  **********************/

  handleSkillsChange = (e, { value }) => {
    /* extra logic here and in sister function
    to make sure same skills with different cases
    are not added to the list */
    var { user } = this.state;
    user.skillsAndInterests.coreSkills = value
      .map(el => el.toLowerCase())
      .filter((el, idx, arr) => arr.indexOf(el) === idx)
      .map(el => SKILLS_MAP[el]);
    this.setState({ user });
  }

  // lets user add skill not in dropdown
  handleAddSkill = (e, { value }) => {
    if (!swearjar.profane(value)) {
      var { user, skillsOptions } = this.state;
      /* if skill not already in dropdown options, ignoring case,
      temporarily add it to options list so that semantic-ui-react
      will display it as choice and add new choice to user object */
      if (findIndex(skillsOptions, { key: value.toLowerCase() }) === -1) {
        skillsOptions = [{ text: value, key: value, value }, ...skillsOptions];
        user.skillsAndInterests.coreSkills.push(value);
      }
      this.setState({ skillsOptions, user });
    }
  }

  handleInterestsChange = (e, { value }) => {
    var { user } = this.state;
    user.skillsAndInterests.codingInterests = value
      .map(el => el.toLowerCase())
      .filter((el, idx, arr) => arr.indexOf(el) === idx)
      .map(el => INTERESTS_MAP[el]);
    this.setState({ user });
  }

  // lets user add interest not in dropdown
  handleAddInterest = (e, { value }) => {
    if (!swearjar.profane(value)) {
      var { user, interestsOptions } = this.state;
      /* if interest not already in dropdown options, temporarily
      add it to options list so that semantic-ui-react component
      will display it as choice and add new choice to user object */
      if (findIndex(interestsOptions, { key: value.toLowerCase() }) === -1) {
        interestsOptions = [{ text: value, key: value, value }, ...interestsOptions];
        user.skillsAndInterests.codingInterests.push(value);
      }
      this.setState({ interestsOptions, user });
    }
  }

  handleCountryChange = (e, { value }) => {
    var { user } = this.state;
    user.personal.flag = value;
    user.personal.country = countryCodes[value.replace(' ', '_')];
    this.setState({ user });
  }

  handleTenureChange = (e, { value }) => {
    var { user } = this.state;
    user.career.tenure = value;
    this.setState({ user });
  }

  handleRadioChange = ({ target: { name, id }}) => {
    var { user } = this.state;<commit_msg>fix user defined skills/interests (#202)<commit_after>// beginning to alphabetize imports for best practices
import { Button } from 'semantic-ui-react';
import Career from './Profile/Preferences/Career';
import Certifications from './Profile/Preferences/Certifications';
import Collaboration from './Profile/Preferences/Collaboration';
import { connect } from 'react-redux';
import { connectScreenSize } from 'react-screen-size';
import { countryCodes } from '../../assets/dropdowns/countries';
import ERROR from '../../assets/helpers/errors';
import { findIndex } from 'lodash';
import interests, { INTERESTS_MAP } from '../../assets/dropdowns/interests';
import { isEmpty } from 'lodash';
import { mapScreenSizeToProps } from '../Navbar';
import Mentorship from './Profile/Preferences/Mentorship';
import Modal from './Profile/Preferences/common/SaveModal';
import PersonalInfo from './Profile/Preferences/PersonalInfo';
import propTypes from 'prop-types';
import React from 'react';
import { savePreferencesViewState } from '../../actions/views';
import { saveUser, updateUser, updateUserPartial } from '../../actions/user';
import skills, { SKILLS_MAP } from '../../assets/dropdowns/skills';
import SkillsAndInterests from './Profile/Preferences/SkillsAndInterests';
import Social from './Profile/Preferences/Social';
import styled from 'styled-components';
import swearjar from '../../assets/helpers/swearjar-lite';
import { ThickPaddedBottom } from '../../styles/style-utils';
import UserLabel from '../dashboard/common/UserLabel';
import validate from '../../assets/helpers/validations';

/*
TODO:
  - PERSONAL INFO: validation to require user to enter country to collect data for D3 map?
  - GENERAL: Refactor validation code, kind of reduntant and could be improved (isPageValid && isSectionValid)
*/

const BottomButton = styled(Button)`
  right: 0;
  bottom: 35px;
`;

const Container = styled(ThickPaddedBottom)`
  @media (max-width: 770px) {
    padding: 0 10px 50px 10px !important;
  }
`;

const TopButton = styled(Button)`
  height: 42px !important;
  padding: 10px !important;
  @media (max-width: 959px) {
    margin-top: 10px !important;
  }
  @media (min-width: 959px) {
    float: right !important;
  }
`;

class Preferences extends React.Component {
  constructor(props) {
    super(props);
    const { user, viewState } = this.props;
    this.state = {
      user,
      viewState,
      errors: {},
      modalOpen: false,
      isPageValid: true,
      profileWarning: '',
      socialPopUp: false,
      careerPopUp: false,
      projectsPopUp: false,
      personalPopUp: false,
      mentorshipPopUp: false,
      showBottomButton: false,
      skillsAndInterestsPopUp: false,
      interestsOptions: [],
      skillsOptions: [],
    }
  }

  componentDidMount() {
    document.addEventListener('scroll', this.handleScroll);
    var { user } = this.state;
    /* add user-added, non-default skills to skillsOptions for
    correct rendering of multi-select dropdown component... */
    let skillsOptions = skills;
    user.skillsAndInterests.coreSkills.forEach(value => {
      if (findIndex(skillsOptions, { text: value, value }) === -1) {
        skillsOptions = [{ text: value, value }, ...skillsOptions];
      }
    });
    // ...then add non-default interests
    let interestsOptions = interests;
    user.skillsAndInterests.codingInterests.forEach(value => {
      if (findIndex(interestsOptions, { text: value, value }) === -1) {
        interestsOptions = [{ text: value, value }, ...interestsOptions];
      }
    });
    this.setState({ skillsOptions, interestsOptions });
  }

  componentWillUnmount() {
    this.props.savePreferencesViewState(this.state.viewState);
    document.removeEventListener('scroll', this.handleScroll);
  }

  handleScroll = (e) => {
    if (e.target.scrollingElement.scrollTop >= 60) {
      this.setState({ showBottomButton: true });
    } else {
      this.setState({ showBottomButton: false });
    }
  }

  /**********************
  HANDLE CHANGE FUNCTIONS
  **********************/

  handleSkillsChange = (e, { value }) => {
    /* extra logic here and in sister function
    to make sure same skills with different cases
    are not added to the list (e.g. javascript
    should automatically map to JavaScript dropdown
    option). If custom skill, simply add to the list -
    duplication prevention happens in handleAddSkill */
    var { user } = this.state;

    let CURRENT_MAP = {};
    value.forEach(el => {
      CURRENT_MAP[el.toLowerCase()] = el;
    });

    user.skillsAndInterests.coreSkills = value
      .map(el => el.toLowerCase())
      .filter((el, idx, arr) => arr.indexOf(el) === idx)
      .map(el => {
        if (SKILLS_MAP[el])
          return SKILLS_MAP[el];
        else {
          return CURRENT_MAP[el];
        }
      });

    this.setState({ user });
  }

  // lets user add skill not in dropdown
  handleAddSkill = (e, { value }) => {
    if (!swearjar.profane(value)) {
      var { user, skillsOptions } = this.state;
      /* if skill not already in dropdown options, ignoring case,
      temporarily add it to options list so that semantic-ui-react
      will display it as choice and add new choice to user object */
      if (findIndex(skillsOptions, { key: value.toLowerCase() }) === -1) {
        skillsOptions = [{ text: value, key: value.toLowerCase(), value }, ...skillsOptions];
        user.skillsAndInterests.coreSkills.push(value);
      }
      this.setState({ skillsOptions, user });
    }
  }

  handleInterestsChange = (e, { value }) => {
    // see comment in handleSkillsChange
    var { user } = this.state;
    
    let CURRENT_MAP = {};
    value.forEach(el => {
      CURRENT_MAP[el.toLowerCase()] = el;
    });

    user.skillsAndInterests.codingInterests = value
    .map(el => el.toLowerCase())
    .filter((el, idx, arr) => arr.indexOf(el) === idx)
    .map(el => {
      if (INTERESTS_MAP[el])
        return INTERESTS_MAP[el];
      else {
        return CURRENT_MAP[el];
      }
    });
    this.setState({ user });
  }

  // lets user add interest not in dropdown
  handleAddInterest = (e, { value }) => {
    if (!swearjar.profane(value)) {
      var { user, interestsOptions } = this.state;
      /* if interest not already in dropdown options, ignoring case,
      temporarily add it to options list so that semantic-ui-react
      will display it as choice and add new choice to user object */
      if (findIndex(interestsOptions, { key: value.toLowerCase() }) === -1) {
        interestsOptions = [{ text: value, key: value.toLowerCase(), value }, ...interestsOptions];
        user.skillsAndInterests.codingInterests.push(value);
      }
      this.setState({ interestsOptions, user });
    }
  }

  handleCountryChange = (e, { value }) => {
    var { user } = this.state;
    user.personal.flag = value;
    user.personal.country = countryCodes[value.replace(' ', '_')];
    this.setState({ user });
  }

  handleTenureChange = (e, { value }) => {
    var { user } = this.state;
    user.career.tenure = value;
    this.setState({ user });
  }

  handleRadioChange = ({ target: { name, id }}) => {
    var { user } = this.state;
{'fraction_non_alphanumeric': 0.14197802197802198, 'fraction_numerical': 0.004908424908424909, 'mean_word_length': 3.1416868932038833, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1076452', 'n_tokens_mistral': 4047, 'n_tokens_neox': 3992, 'n_words': 1072}