diff --git a/src/js/gi/components/AccordionItem.jsx b/src/js/gi/components/AccordionItem.jsx new file mode 100644 index 000000000000..1abb4ad8a3a1 --- /dev/null +++ b/src/js/gi/components/AccordionItem.jsx @@ -0,0 +1,42 @@ +import React from 'react'; + +class AccordionItem extends React.Component { + + constructor(props) { + super(props); + this.state = { + expanded: props.expanded, + } + } + + toggle() { + this.setState({expanded: !this.state.expanded}); + } + + render() { + const expanded = this.state.expanded; + return ( +
  • + +
    + {this.props.children} +
    +
  • + ); + } + +} + +AccordionItem.propTypes = { + expanded: React.PropTypes.bool.isRequired, + children: React.PropTypes.node.isRequired, + button: React.PropTypes.string.isRequired, +}; + +AccordionItem.defaultProps = { + expanded: true +}; + +export default AccordionItem; diff --git a/src/js/gi/components/profile/AdditionalInformation.jsx b/src/js/gi/components/profile/AdditionalInformation.jsx new file mode 100644 index 000000000000..c7338f6775d5 --- /dev/null +++ b/src/js/gi/components/profile/AdditionalInformation.jsx @@ -0,0 +1,166 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import * as actions from '../../actions'; + +export class AdditionalInformation extends React.Component { + + render() { + const it = this.props.profile.attributes; + const accredited = !!it.cross; + const TypeOfAccreditation = () => { + if (!accredited) return null; + return ( +

    + Type of accreditation:  + {it.accreditation_type.toUpperCase()} +

    + ); + }; + const VetTuitionPolicy = () => { + if (!it.vet_tuition_policy_url) return null; + return ( +

    + Veterans tuition policy:  + View policy +

    + ); + }; + + // Formats positive and negative currency values in USD + const formatCurrency = (num) => { + const str = Number(num).toFixed(2).toString().split('.'); + // Match a digit if it's followed by 3 other digits, + // appending a comma to each match. + const regex = /\d(?=(\d{3})+$)/g; + return [ + '$', + [str[0].replace(regex, '$&,'), str[1]].join('.') + ].join('').replace('$-', '-$'); + }; + + const formatNumber = (num) => { + const str = Math.round(Number(num)).toString(); + // Match a digit if it's followed by 3 other digits, + // appending a comma to each match. + const regex = /\d(?=(\d{3})+$)/g; + return str.replace(regex, '$&,'); + }; + + return ( +
    +
    +
    +

    Institution summary

    +

    + Accredited:  + {accredited ? 'Yes' : 'No'} +

    + + +

    + Single point of contact for veterans:  + {!!it.vet_poc ? 'Yes' : 'No'} +

    +

    + Credit for military training:  + {!!it.credit_for_mil_training ? 'Yes' : 'No'} +

    +
    +
    +

    Historical Information

    +
    +

    + Benefit:  + Post-9/11 GI Bill +

    +

    + Recipients:  + {formatNumber(it.p911_recipients)} +

    +

    + Total paid (2014):  + {formatCurrency(it.p911_tuition_fees)} +

    +
    +
    +

    + Benefit:  + Yellow Ribbon +

    +

    + Recipients:  + {formatNumber(it.p911_yr_recipients)} +

    +

    + Total paid (2014):  + {formatCurrency(it.p911_yellow_ribbon)} +

    +
    +
    +
    +

    Institution codes

    +

    + + VA facility code: +   + + {+it.facility_code} +

    +

    + + ED IPEDS code: +   + + {+it.cross} +

    +

    + + ED OPE code: +   + + {+it.ope6} +

    +
    +
    +
    +
    +

    Historical Information

    + + + + + + + + + + + + + + + + + + + + +
    BenefitRecipientsTotal paid (2014)
    Post-9/11 GI Bill{formatNumber(it.p911_recipients)}{formatCurrency(it.p911_tuition_fees)}
    Yellow Ribbon{formatNumber(it.p911_yr_recipients)}{formatCurrency(it.p911_yellow_ribbon)}
    +
    +
    +
    + ); + } +} + +const mapStateToProps = (state, props) => state; + +const mapDispatchToProps = (dispatch) => { + return { + showModal: (name) => { + dispatch(actions.displayModal(name)); + }, + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(AdditionalInformation); diff --git a/src/js/gi/components/profile/Calculator.jsx b/src/js/gi/components/profile/Calculator.jsx new file mode 100644 index 000000000000..e8baaf262a51 --- /dev/null +++ b/src/js/gi/components/profile/Calculator.jsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import * as actions from '../../actions'; + +export class Calculator extends React.Component { + render() { + const it = this.props.profile.attributes; + return ( +
    + Calculator +
    + ); + } +} + +const mapStateToProps = (state, props) => state; + +const mapDispatchToProps = (dispatch) => { + return { + showModal: (name) => { + dispatch(actions.displayModal(name)); + }, + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(Calculator); diff --git a/src/js/gi/components/profile/CautionaryInformation.jsx b/src/js/gi/components/profile/CautionaryInformation.jsx new file mode 100644 index 000000000000..180ffc87ce7e --- /dev/null +++ b/src/js/gi/components/profile/CautionaryInformation.jsx @@ -0,0 +1,128 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import * as actions from '../../actions'; +import AlertBox from '../../../common/components/AlertBox'; + +export class CautionaryInformation extends React.Component { + render() { + const it = this.props.profile.attributes; + if (!it.complaints) { return null; } + + const flagContent = ( +

    + {it.caution_flag_reason} +
    + Learn more about these warnings +

    + ); + const complaintData = [ + {type: 'Financial Issues (e.g., Tuition/Fee charges)', key: 'financial'}, + {type: 'Quality of Education', key: 'quality'}, + {type: 'Refund Issues', key: 'refund'}, + {type: 'Recruiting/Marketing Practices', key: 'marketing'}, + {type: 'Accreditation', key: 'accreditation'}, + {type: 'Change in degree plan/requirements', key: 'degree_requirements'}, + {type: 'Student Loans', key: 'student_loans'}, + {type: 'Grade Policy', key: 'grades'}, + {type: 'Transfer of Credits', key: 'credit_transfer'}, + {type: 'Post-Graduation Job Opportunities', key: 'job', totalKey: 'jobs'}, + {type: 'Release of Transcripts', key: 'transcript'}, + {type: 'Other', key: 'other'}, + {type: 'Student Complaints', totals: ['facility_code', 'main_campus_roll_up']} + ]; + const complaints = complaintData.reduce((complaints, complaint) => { + const totals = complaint.totals || {}; + const { type, key, totalKey } = complaint; + const hydratedComplaint = { + description: type, + thisCampus: (complaint.totals ? it.complaints[totals[0]] : it.complaints[`${key}_by_fac_code`]), + allCampuses: (complaint.totals ? it.complaints[totals[1]] : it.complaints[`${totalKey || key}_by_ope_id_do_not_sum`]), + }; + return [...complaints, hydratedComplaint]; + }, []); + + const TableRow = ({description, thisCampus, allCampuses}) => { + return ( + + {description} + {thisCampus} + {allCampuses} + + ); + }; + + const ListRow = ({description, value}) => { + if (value < 1) return null; + return ( +
    +
    +

    {description}:

    +
    +
    +

    {value}

    +
    +
    + ); + }; + + return ( +
    + + +
    +

    {it.complaints.main_campus_roll_up} student complaints

    +

    (Source)

    + + + + + + + + + + {complaints.map((c) => )} + +
    Complaint typeThis campusAll campuses
    +
    + +
    +

    This campus

    + {complaints.map((c) => )} +
    +
    +

    Total complaints:

    +
    +
    +

    {it.complaints.facility_code}

    +
    +
    +

    All campuses

    + {complaints.map((c) => )} +
    +
    +

    Total complaints:

    +
    +
    +

    {it.complaints.main_campus_roll_up}

    +
    +
    +
    + +

    *Each complaint can have multiple types

    +
    + ); + } +} + +const mapStateToProps = (state, props) => state; + +const mapDispatchToProps = (dispatch) => { + return { + showModal: (name) => { + dispatch(actions.displayModal(name)); + }, + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(CautionaryInformation); diff --git a/src/js/gi/components/profile/Graph.jsx b/src/js/gi/components/profile/Graph.jsx new file mode 100644 index 000000000000..c89ecc6bd5c6 --- /dev/null +++ b/src/js/gi/components/profile/Graph.jsx @@ -0,0 +1,121 @@ +import React from 'react'; + +class Graph extends React.Component { + + constructor(props) { + super(props); + this.format = this.format.bind(this); + } + + format(d) { + let val = d.value; + if (val === null || val === undefined) { + return 'No Data'; + } else { + val = val.toFixed(this.props.decimals); + while (/(\d+)(\d{3})/.test(val.toString())) { + val = val.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); + } + val = typeof d.percent !== 'undefined' ? '$' + val.replace('.0','') : val + '%'; + return val; + } + } + + render() { + const { width, height, padding, split } = this.props; + const viewBoxString = ['0', '0', width, height].join(' '); + const BarLabel = (props) => ( + + {props.text} + + ); + const HollowUnderbar = ({top}) => ; + const SolidUnderbar = ({top}) => ; + const Underbar = ({top, value, children}) => { + return !!value ? {children} : ; + }; + const ValueBar = ({top, color, percent}) => { + if (isNaN(percent)) { return null } + const width = 134 * (percent / this.props.max); + return ; + }; + const ValueLabel = ({y, text}) => ( + + {text} + + ); + const AverageMark = ({percent, text}) => { + const position = 75 + (134 * (percent / 100)); + const x = position - 10; + return ( + + + + {text} + + + ); + }; + + let averagePercent, averageObject; + const bars = [ + { name: 'vet', value: this.props.veterans }, + { name: 'all', value: this.props.all } + ]; + // handle non-percentage data + if (this.props.max !== 100) { + for (var i in bars) { + bars[i].percent = (bars[i].value / this.props.max) * 100; + } + // handle non-percentage average line + averagePercent = (this.props.average / this.props.max) * 100; + averageObject = {value: this.props.average, percent: true} + } else { + averagePercent = this.props.average; + averageObject = {value: this.props.average}; + } + const veterans = bars[0]; + const all = bars[1]; + + return ( +
    + + + + + + + + + + + + + + + + + +
    + ); + } +} + +Graph.propTypes = { + max: React.PropTypes.number, + average: React.PropTypes.number, + veterans: React.PropTypes.number, + all: React.PropTypes.number, + decimals: React.PropTypes.number +}; + +Graph.defaultProps = { + max: 100, + veterans: null, + width: 300, + height: 100, + split: 1.8, + decimals: 2 +}; + +export default Graph; diff --git a/src/js/gi/components/profile/HeadingSummary.jsx b/src/js/gi/components/profile/HeadingSummary.jsx new file mode 100644 index 000000000000..ddf2377819f4 --- /dev/null +++ b/src/js/gi/components/profile/HeadingSummary.jsx @@ -0,0 +1,77 @@ +import React from 'react'; +import _ from 'lodash'; +import { connect } from 'react-redux'; +import * as actions from '../../actions'; +import AlertBox from '../../../common/components/AlertBox'; +import If from '../If'; + +export class AdditionalInformation extends React.Component { + + render() { + const it = this.props.profile.attributes; + const schoolSize = (enrollment) => { + if (!enrollment) return 'Unknown'; + if (enrollment <= 2000) { + return 'Small'; + } else if (enrollment <= 15000) { + return 'Medium'; + } else { + return 'Large'; + } + }; + const domestic = {it.city}, {it.state}; + const foreign = {it.city}, {it.country}; + const place = (it.country === 'usa' ? domestic : foreign); + const link = it.website ? {it.website} : null; + return ( +
    +
    +

    {it.name}

    + VA has concerns about this school. View warnings

    )} + isVisible={!!it.caution_flag} + status="warning"/> +

    + {it.student_count} GI Bill students + (Learn more) +

    +
    +
    +

    {place}

    +

    {link}

    + +

    {it.highest_degree} year program

    +
    +
    +
    + +

    +
    + + +

    {_.capitalize(it.type)} institution

    +

    {_.capitalize(it.locale_type)} locale

    +

    {schoolSize(it.undergrad_enrollment)} size

    +
    +
    +
    +
    +
    +
    +
    + ); + } + +} + +const mapStateToProps = (state, props) => state; + +const mapDispatchToProps = (dispatch) => { + return { + showModal: (name) => { + dispatch(actions.displayModal(name)); + }, + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(AdditionalInformation); diff --git a/src/js/gi/components/profile/Outcomes.jsx b/src/js/gi/components/profile/Outcomes.jsx new file mode 100644 index 000000000000..49d5c4715361 --- /dev/null +++ b/src/js/gi/components/profile/Outcomes.jsx @@ -0,0 +1,70 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import * as actions from '../../actions'; + +import { Link } from 'react-router'; +import { outcomeNumbers } from '../../selectors/outcomes'; +import Graph from './Graph'; +import If from '../If'; + +export class Outcomes extends React.Component { + + render() { + const { retention, graduation, salary, repayment } = this.props.graphing; + const download = { + info: 'Excel | 14.4 MB', + link: 'http://www.benefits.va.gov/gibill/docs/OutcomeMeasuresDashboard.xlsx' + }; + return ( +
    +
    +

    Retention rate

    +

    (Learn more)

    + +
    + +
    +

    Graduation rate

    +

    (Learn more)

    + +
    + +
    +

    Average salaries

    +

    (Learn more)

    + +
    + +
    +

    Repayment rate

    +

    (Learn more)

    + +
    + +
    +

    + Access a comprehensive spreadsheet of Veteran Outcome Measures ({download.info}) +

    +
    +
    + ); + } +} +// const mapStateToProps = (state, props) => state; + +const mapStateToProps = (state, props) => { + return { + graphing: outcomeNumbers(state, props) + }; +}; + +const mapDispatchToProps = (dispatch) => { + return { + showModal: (name) => { + dispatch(actions.displayModal(name)); + }, + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(Outcomes); diff --git a/src/js/gi/components/profile/Programs.jsx b/src/js/gi/components/profile/Programs.jsx new file mode 100644 index 000000000000..df7af1b11e22 --- /dev/null +++ b/src/js/gi/components/profile/Programs.jsx @@ -0,0 +1,102 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import * as actions from '../../actions'; +import If from '../../components/If'; + +export class Programs extends React.Component { + + programs(institution) { + return { + yr: { + modal: 'yribbon', + text: 'Yellow Ribbon', + link: { + href: `http://www.benefits.va.gov/gibill/yellow_ribbon/2015/states/${institution.state}.asp`, + text: 'See rates', + } + }, + student_veteran: { + modal: 'vetgroups', + text: 'Student Veteran Group', + link: { + href: institution.student_veteran_link, + text: 'Site', + } + }, + poe: { + modal: 'poe', + text: 'Principles of Excellence', + link: false + }, + eight_keys: { + modal: 'eightKeys', + text: '8 Keys to Veteran Success', + link: false + }, + vet_success_name: { + modal: false, + text: 'VetSuccess on Campus', + link: { + href: institution.vet_success_email ? `mailto:${institution.vet_success_email}` : false, + text: `Email ${institution.vet_success_name}`, + } + }, + dodmou: { + modal: 'ta', + text: 'Military Tuition Assistance (TA)', + link: false + }, + }; + } + + renderProgramLabel(programKey, available) { + const program = this.programs(this.props.profile.attributes)[programKey]; + const icon = available ? 'fa fa-check' : 'fa fa-remove'; + let link = ''; + if (program.link && program.link.href) { + link =  ({program.link.text}); + } + let label = ''; + if (program.modal) { + label = {program.text}; + } else { + label = program.text; + } + return

    {label} {link}

    ; + } + + render() { + const it = this.props.profile.attributes; + const available = Object.keys(this.programs(it)).filter((key) => !!it[key] === true); + const notAvailable = Object.keys(this.programs(it)).filter((key) => !!it[key] === false); + return ( +
    + 0}> +
    +

    Veteran programs available at this campus

    + {available.map(( (program) => this.renderProgramLabel.bind(this, program, true)() ))} +
    +
    +
    + 0}> +
    +

    Not available at this campus

    + {notAvailable.map(( (program) => this.renderProgramLabel.bind(this, program, false)() ))} +
    +
    +
    + ); + } +} + +const mapStateToProps = (state, props) => state; + +const mapDispatchToProps = (dispatch) => { + return { + showModal: (name) => { + dispatch(actions.displayModal(name)); + }, + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(Programs); diff --git a/src/js/gi/containers/Modals.jsx b/src/js/gi/containers/Modals.jsx index ca71cbf8ce7e..fd1649a2991b 100644 --- a/src/js/gi/containers/Modals.jsx +++ b/src/js/gi/containers/Modals.jsx @@ -89,10 +89,9 @@ export class Modals extends React.Component {

    Student Veterans Group

    Does this school have a student-led Veterans group on campus?

    - If a school has a student Veterans group that's not represented here, please email - - 224A.VBAVACO@va.gov - . + If a school has a student Veterans group that's not represented here, + please email 224A.VBAVACO@va.gov. We make quarterly updates to this tool.

    @@ -103,7 +102,7 @@ export class Modals extends React.Component { -

    Yellow Ribbon (See rates)

    +

    Yellow Ribbon

    The diff --git a/src/js/gi/containers/ProfilePage.jsx b/src/js/gi/containers/ProfilePage.jsx index 16ad04c17122..8f5f37072b8c 100644 --- a/src/js/gi/containers/ProfilePage.jsx +++ b/src/js/gi/containers/ProfilePage.jsx @@ -1,8 +1,15 @@ import React from 'react'; import { connect } from 'react-redux'; +import _ from 'lodash'; import * as actions from '../actions'; - -import { calculatedBenefits } from '../selectors/calculator'; +import AccordionItem from '../components/AccordionItem'; +import If from '../components/If'; +import HeadingSummary from '../components/profile/HeadingSummary'; +import Programs from '../components/profile/Programs'; +import Outcomes from '../components/profile/Outcomes'; +import Calculator from '../components/profile/Calculator'; +import CautionaryInformation from '../components/profile/CautionaryInformation'; +import AdditionalInformation from '../components/profile/AdditionalInformation'; export class ProfilePage extends React.Component { @@ -10,39 +17,48 @@ export class ProfilePage extends React.Component { this.props.fetch(this.props.params.facility_code); } - setPageTitleOnce() { - const profileName = this.props.profile.attributes.name; - const title = `${profileName} - GI Bill Comparison Tool`; - if (profileName && window.document.title !== title) { - this.props.setPageTitle(title); - } - } - render() { - // this.setPageTitleOnce(); + const constants = this.props.constants.constants; + const profile = this.props.profile; + // TODO - set page title + // const title = `${profile.attributes.name} - GI Bill Comparison Tool`; + // this.props.setPageTitle(title); return (

    - this.props.showModal('cautionInfo')}>Caution Modal + +
      + + + + + + + + + + + + + + + + + + +
    ); } } -const mapStateToProps = (state, props) => { - return { - calc: null //calculatedBenefits(state, props) - }; -}; +const mapStateToProps = (state, props) => state; const mapDispatchToProps = (dispatch) => { return { showModal: (name) => { dispatch(actions.displayModal(name)); }, - hideModal: () => { - dispatch(actions.displayModal(null)); - }, setPageTitle: (title) => { dispatch(actions.setPageTitle(title)); }, @@ -52,5 +68,4 @@ const mapDispatchToProps = (dispatch) => { }; }; - export default connect(mapStateToProps, mapDispatchToProps)(ProfilePage); diff --git a/src/js/gi/reducers/index.js b/src/js/gi/reducers/index.js index 84baf4d4a6d8..a9532cbe0b63 100644 --- a/src/js/gi/reducers/index.js +++ b/src/js/gi/reducers/index.js @@ -1,4 +1,5 @@ import { combineReducers } from 'redux'; + import ModalDisplayReducer from './modals'; import PageTitleReducer from './title'; import PreviewModeReducer from './preview'; diff --git a/src/js/gi/reducers/profile.js b/src/js/gi/reducers/profile.js index 3c6782f79d59..708ba1d8f5e8 100644 --- a/src/js/gi/reducers/profile.js +++ b/src/js/gi/reducers/profile.js @@ -1,5 +1,4 @@ import { FETCH_PROFILE_STARTED, FETCH_PROFILE_FAILED, FETCH_PROFILE_SUCCEEDED } from '../actions'; -import { setPageTitle } from '../actions'; const INITIAL_STATE = { attributes: {}, @@ -7,6 +6,18 @@ const INITIAL_STATE = { inProgress: false, }; +function normalizedAttributes(attributes) { + const name = attributes.name ? attributes.name.toUpperCase() : attributes.name; + const city = attributes.city ? attributes.city.toUpperCase() : attributes.city; + const state = attributes.state ? attributes.state.toUpperCase() : attributes.state; + return { + ...attributes, + name, + city, + state, + }; +} + export default function (state = INITIAL_STATE, action) { switch (action.type) { case FETCH_PROFILE_STARTED: @@ -21,7 +32,11 @@ export default function (state = INITIAL_STATE, action) { inProgress: false }; case FETCH_PROFILE_SUCCEEDED: - const attributes = action.payload.data.attributes; + const attributes = normalizedAttributes({ + ...action.payload.data.attributes, + ...action.payload.data.links + }); + // delete attributes.self; const version = action.payload.meta.version; return { ...state, diff --git a/src/js/gi/selectors/calculator.js b/src/js/gi/selectors/calculator.js index 53ddfe9d5cc5..7bfc8956766b 100644 --- a/src/js/gi/selectors/calculator.js +++ b/src/js/gi/selectors/calculator.js @@ -9,7 +9,7 @@ const getEligibilityDetails = (state) => { }; const getRequiredAttributes = (_state, props) => { - const { type, bah } = props; + const { type, bah } = props.attributes; return { type, bah }; }; diff --git a/src/js/gi/selectors/outcomes.js b/src/js/gi/selectors/outcomes.js new file mode 100644 index 000000000000..8ecc8af7ef85 --- /dev/null +++ b/src/js/gi/selectors/outcomes.js @@ -0,0 +1,99 @@ +import { createSelector } from 'reselect'; + +const getConstants = (state) => state.constants.constants; + +const getRequiredAttributes = (state) => { + const {graduation_rate_veteran, graduation_rate_all_students, salary_all_students} = state.profile.attributes; + return { + graduation_rate_veteran, + graduation_rate_all_students, + salary_all_students + }; +}; + +export const outcomeNumbers = createSelector( + [getConstants, getRequiredAttributes], + (constant, institution) => { + const retention = { + rate: 30, + all: 97.83, + average: constant.AVERETENTIONRATE, + }; + const graduation = { + rate: Number(institution.graduation_rate_veteran * 100), + all: Number(institution.graduation_rate_all_students * 100), + average: constant.AVEGRADRATE, + }; + const salary = { + all: institution.salary_all_students, + average: constant.AVESALARY, + } + const repayment = { + rate: Number(institution.graduation_rate_veteran * 100), + all: Number(institution.graduation_rate_all_students * 100), + average: constant.AVEGRADRATE, + }; + return { + retention, + graduation, + salary, + repayment + }; + } +); + + + + + +// const getVeteranRetentionRate = (it) => { +// const a = [3, 4].includes(it.pred_degree_awarded); +// const b = String(it.va_highest_degree_offered).toLowerCase() === '4-year'; +// const upperClass = a || b; +// if (upperClass) { +// return it.retentation_rate_veteran_ba || it.retention_rate_veteran_otb; +// } else { +// return it.retentation_rate_veteran_otb || it.retention_rate_veteran_ba; +// } +// }; +// const getAllStudentRetentionRate = (it) => { +// const a = [3, 4].includes(it.pred_degree_awarded); +// const b = String(it.va_highest_degree_offered).toLowerCase() === '4-year'; +// const upperClass = a || b; +// if (upperClass) { +// return it.retention_all_students_ba || it.retention_all_students_otb; +// } else { +// return it.retention_all_students_otb || it.retention_all_students_ba; +// } +// }; +// const isNumeric = (n) => { return !Number.isNaN(parseFloat(n)); }; +// +// const retention = { +// rate: isNumeric(getVeteranRetentionRate(institution)) ? Number(getVeteranRetentionRate(institution) * 100) : null, +// all: isNumeric(getAllStudentRetentionRate(institution)) ? Number(getAllStudentRetentionRate(institution) * 100) : null, +// average: constant.AVERETENTIONRATE, +// }; +// const repayment = { +// rate: null, +// all: Number(institution.repayment_rate_all_students * 100), +// average: constant.AVEREPAYMENTRATE, +// }; +// // const graduation = { +// // rate: () => { +// // console.log(graduationRate: institution.graduation_rate_veteran) +// // isNumeric(institution.graduation_rate_veteran) ? Number(institution.graduation_rate_veteran* 100) : null +// // }, +// // all: () => { +// // console.log({graduationAll: institution.graduation_rate_all_students}) +// // isNumeric(institution.graduation_rate_all_students) ? Number(institution.graduation_rate_all_students* 100) : null +// // }, +// // average: constant.AVEGRADRATE, +// // }; +// +// const graduation = function(){ +// return { +// rate: Number(institution.graduation_rate_veteran* 100), +// all: Number(institution.graduation_rate_all_students* 100), +// average: constant.AVEGRADRATE +// }; +// }(); diff --git a/src/sass/gi/gi.scss b/src/sass/gi/gi.scss index c133675c34ac..3f7e1da20c14 100644 --- a/src/sass/gi/gi.scss +++ b/src/sass/gi/gi.scss @@ -1,5 +1,7 @@ @import "../style"; @import "../modules/m-modal"; +@import "../modules/m-loading-indicator"; + @import "../modules/va-pagination"; @import "partials/gi-breadcrumbs"; @@ -9,6 +11,7 @@ @import "partials/gi-landing-page"; @import "partials/gi-search-page"; @import "partials/gi-profile-page"; +@import "partials/gi-graphs"; .gi-app { diff --git a/src/sass/gi/partials/_gi-graphs.scss b/src/sass/gi/partials/_gi-graphs.scss new file mode 100644 index 000000000000..ab1f3348e23b --- /dev/null +++ b/src/sass/gi/partials/_gi-graphs.scss @@ -0,0 +1,4 @@ + +div.graph-component { + margin: 1em; +} diff --git a/src/sass/gi/partials/_gi-profile-page.scss b/src/sass/gi/partials/_gi-profile-page.scss index 4db86a583242..3dcee5d81cf8 100644 --- a/src/sass/gi/partials/_gi-profile-page.scss +++ b/src/sass/gi/partials/_gi-profile-page.scss @@ -1,3 +1,121 @@ .gi-app .profile-page { - + + ul.usa-accordion { + margin: 0; + list-style-type: none; + padding: 0; + } + + li button.usa-accordion-button { + text-align: left; + + h2 { + font-size: 1em; + } + } + + .programs.row { + h3 { + font-size: 1.35em; + } + .fa-check { + color: $color-green; + } + .fa-remove { + color: $color-gray-medium; + } + } + + .usa-alert { + background-size: 3rem; + } + + .outcomes.row { + h3 { + font-size: 1.35em; + } + } + + .outcomes .lml { + display: block; + float: left; + margin-left: 0.5em; + margin-top: 0.2em; + } + .outcomes .column > h3 { + display: block; + float: left; + } + .outcomes .graph-component { + clear: both; + } + + .cautionary-information { + .table > h3 { + padding-top: 1em !important; + float: left; + } + + .table > p { + padding-top: 2.25em !important; + float: left; + margin-left: 0.5em; + margin-top: 0.2em; + } + + .table .number { + text-align: left; + } + + .list { + h4 { + padding: 0.5em 0 !important; + } + .number { + text-align: right; + } + margin-bottom: 1em; + } + + @media screen and (min-width: 600px) { + .list { + display: none; + visibility: hidden; + } + } + @media screen and (max-width: 600px) { + .table { + display: none; + visibility: hidden; + } + } + } + + .additional-information { + h3 { + font-size: 1.35em; + padding-top: 1.5em !important; + } + + .historical-information.list { + div { + margin-bottom: 0.5em; + } + } + + @media screen and (min-width: 600px) { + .historical-information.list { + display: none; + visibility: hidden; + } + } + @media screen and (max-width: 600px) { + .historical-information.table { + display: none; + visibility: hidden; + } + } + } + + }