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.button}
+
+
+ {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)}
+
+
+
+
+
+
+
+
Historical Information
+
+
+
+ Benefit
+ Recipients
+ Total 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 (
+
+ );
+ };
+
+ return (
+
+
+
+
+
{it.complaints.main_campus_roll_up} student complaints
+
(Source )
+
+
+
+ Complaint type
+ This campus
+ All campuses
+
+
+
+ {complaints.map((c) => )}
+
+
+
+
+
+
This campus
+ {complaints.map((c) =>
)}
+
+
+
+
{it.complaints.facility_code}
+
+
+ All campuses
+ {complaints.map((c) => )}
+
+
+
+
{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 (
+
+ );
+ }
+}
+// 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 (
);
}
}
-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;
+ }
+ }
+ }
+
+
}