diff --git a/modules/core/client/less/global-variables.less b/modules/core/client/less/global-variables.less
index 7a99dcfebb..6d3c643639 100644
--- a/modules/core/client/less/global-variables.less
+++ b/modules/core/client/less/global-variables.less
@@ -159,6 +159,15 @@
@text-highlight: lighten(@brand-primary, 40%);
@text-highlight-color: @text-color;
+// Reference colors
+// ---------------------------------------
+@reference-recommend-yes-bg: #5cb85c;
+@reference-recommend-yes-color: #fff;
+@reference-recommend-no-bg: #d9534f;
+@reference-recommend-no-color: #fff;
+@reference-recommend-unknown-bg: lighten(#000, 98%);
+@reference-recommend-unknown-color: @btn-default-color;
+
// Offer colors
// ---------------------------------------
@offer-hosting-yes: #5cb85c;
diff --git a/modules/references/client/components/ReferencesNew.component.js b/modules/references/client/components/ReferencesNew.component.js
new file mode 100644
index 0000000000..53979b1a38
--- /dev/null
+++ b/modules/references/client/components/ReferencesNew.component.js
@@ -0,0 +1,344 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+function Interaction(props) {
+
+ const { reference: { interactions } } = props;
+ const isInteraction = [...Object.keys(interactions)].reduce((accumulator, current) => accumulator || interactions[current], false);
+ return (
+
+
+
How do you know them?
+
+
+
+ );
+}
+
+Interaction.propTypes = {
+ onChange: PropTypes.func,
+ reference: PropTypes.object
+};
+
+function Recommend(props) {
+
+ const { hostedMe, hostedThem } = props.reference.interactions;
+ const maxInteraction = (hostedMe) ? 'hostedMe' : (hostedThem) ? 'hostedThem' : 'met';
+ const recommendQuestions = {
+ hostedMe: 'Would you recommend others to stay with them?',
+ hostedThem: 'Would you recommend others to host them?',
+ met: 'Would you recommend others to meet them?'
+ };
+
+ return (
+
+
+
{recommendQuestions[maxInteraction]}
+
+
+
+ );
+}
+
+Recommend.propTypes = {
+ reference: PropTypes.object,
+ onChange: PropTypes.func,
+ onChangeReportMessage: PropTypes.func,
+ onChangeReport: PropTypes.func,
+ onChangeReportMessage: PropTypes.func,
+ report: PropTypes.bool,
+ reportMessage: PropTypes.string
+};
+
+function Report(props) {
+ return (
+
+
+
+ We're sad to hear you didn't have great experience using Trustroots! 😞
+
+
+
+ {(props.report) ?
+
+
+
+
+ Please write in English if possible.
+
+
: null
+ }
+
+ );
+}
+
+Report.propTypes = {
+ report: PropTypes.bool,
+ reportMessage: PropTypes.string,
+ onChangeReport: PropTypes.func,
+ onChangeReportMessage: PropTypes.func
+};
+
+function Navigation(props) {
+ const back = (
+
+ );
+
+ const next = (
+
+ );
+
+ const submit = (
+
+ );
+
+ return (
+
+ {(props.tab > 0) ? back : null}
+ {(props.tab < props.tabs - 1) ? next : null}
+ {/* */}
+ {(props.tab === props.tabs - 1) ? submit : null}
+
+
+ );
+}
+
+Navigation.propTypes = {
+ onBack: PropTypes.func,
+ onNext: PropTypes.func,
+ onSubmit: PropTypes.func,
+ tab: PropTypes.number, // current tab index - indexed from 0
+ tabs: PropTypes.number, // amount of tabs to display
+ tabDone: PropTypes.number // which tab is already filled
+};
+
+export default class ReferencesNew extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ tab: 0,
+ reference: {
+ interactions: {
+ met: false,
+ hostedThem: false,
+ hostedMe: false
+ },
+ recommend: null
+ },
+ report: false,
+ reportMessage: ''
+ };
+ }
+
+ handleTabSwitch(move) {
+ this.setState({
+ ...this.state,
+ tab: this.state.tab + move
+ });
+ }
+
+ handleChange(field, ...data) {
+ if (field === 'interactions') {
+ const interaction = { };
+ interaction[data[0]] = !this.state.reference.interactions[data[0]];
+ this.setState({
+ ...this.state,
+ reference: {
+ ...this.state.reference,
+ interactions: {
+ ...this.state.reference.interactions,
+ ...interaction
+ }
+ }
+ });
+ }
+
+ if (field === 'recommend') {
+ this.setState({
+ ...this.state,
+ reference: {
+ ...this.state.reference,
+ recommend: data[0]
+ }
+ });
+ }
+ }
+
+ handleChangeReport() {
+ this.setState({
+ ...this.state,
+ report: !this.state.report
+ });
+ }
+
+ handleChangeReportMessage(reportMessage) {
+ this.setState({
+ ...this.state,
+ reportMessage
+ });
+ }
+
+ handleSubmit() {
+ /* do something with the provided data
+ {
+ reference: this.state.reference,
+ report: this.state.report,
+ reportMessage: this.state.reportMessage
+ };
+ */
+ }
+
+ render() {
+ const tabs = [
+ this.handleChange(...data)} />,
+ this.handleChange(...data)}
+ report={this.state.report}
+ reportMessage={this.state.reportMessage}
+ onChangeReport={() => this.handleChangeReport()}
+ onChangeReportMessage={(reportMessage) => this.handleChangeReportMessage(reportMessage)}
+ />
+ ];
+
+ const { interactions: { hostedMe, hostedThem, met }, recommend } = this.state.reference;
+
+ const tabDone = (recommend) ? 1 :
+ (hostedMe || hostedThem || met) ? 0 : -1;
+
+ return (
+
+
+ {tabs[this.state.tab]}
+ {/* */}
+ this.handleTabSwitch(-1)}
+ onNext={() => this.handleTabSwitch(+1)}
+ onSubmit={() => this.handleSubmit()}
+ />
+
+ );
+ }
+}
+
+ReferencesNew.propTypes = {};
diff --git a/modules/references/client/less/reference-new.less b/modules/references/client/less/reference-new.less
new file mode 100644
index 0000000000..0e1b6031fb
--- /dev/null
+++ b/modules/references/client/less/reference-new.less
@@ -0,0 +1,116 @@
+.reference-new-tabs {
+ .nav-pills {
+ margin-bottom: @padding-base-horizontal;
+ margin-right: 1px;
+ > li {
+ clear: both;
+ width: 100%;
+ opacity: 0.5;
+ &.active,
+ &.reference-new-tabs-tab-processed {
+ opacity: 1;
+ }
+ + li {
+ margin-left: 0;
+ }
+ // This is here just so that we can apply `text-decoration:none` to it later
+ > a:before {
+ display: none;
+ }
+ &.active > a {
+ color: @brand-primary;
+ background: transparent;
+ }
+ &.disabled > a {
+ text-decoration: line-through;
+ color: @gray-light;
+ &:before {
+ text-decoration: none;
+ }
+ }
+ > a {
+ color: @gray;
+ background: transparent;
+ font-style: italic;
+ padding: 3px 6px;
+ cursor: default;
+ &:hover {
+ background: none;
+ }
+ }
+ &.reference-new-tabs-tab-processed > a {
+ cursor: pointer;
+ }
+ }
+ @media (min-width: @screen-xs-min) {
+ > li {
+ clear: none;
+ width: auto;
+ margin: 0;
+ > a {
+ padding: 0;
+ &:before {
+ display: inline-block;
+ content: '›';
+ margin: 0 10px;
+ color: @gray-light;
+ }
+ }
+ &:first-child a:before {
+ display: none;
+ }
+ }
+ }
+ }
+}
+
+.btn-group {
+ > .btn-reference-recommend {
+ &, &:hover {
+ border-color: transparent;
+ }
+ span {
+ border-bottom: 2px solid transparent;
+ padding: 1px 2px;
+ margin: 0 5px;
+ }
+ }
+ > .btn-reference-recommend-unknown {
+ .button-variant(@reference-recommend-unknown-color; @reference-recommend-unknown-bg; @reference-recommend-unknown-bg);
+ &.active {
+ span {
+ border-color: @reference-recommend-unknown-color;
+ }
+ }
+ }
+ > .btn-reference-recommend-no {
+ .button-variant(@reference-recommend-no-color; @reference-recommend-no-bg; @reference-recommend-no-bg);
+ &.active {
+ span {
+ border-color: @reference-recommend-no-color;
+ }
+ }
+ }
+ > .btn-reference-recommend-yes {
+ .button-variant(@reference-recommend-yes-color; @reference-recommend-yes-bg; @reference-recommend-yes-bg);
+ &.active {
+ span {
+ border-color: @reference-recommend-yes-color;
+ }
+ }
+ }
+}
+
+.reference-new-tabs-alert {
+ margin-top: @padding-base-horizontal;
+}
+
+.reference-new-endorsement-selector {
+ button.list-group-item {
+ width: 50%;
+ float: left;
+ &[disabled] {
+ color: @gray-light;
+ }
+ }
+}
diff --git a/modules/users/client/config/users.client.routes.js b/modules/users/client/config/users.client.routes.js
index b88213305b..cdd59089ec 100644
--- a/modules/users/client/config/users.client.routes.js
+++ b/modules/users/client/config/users.client.routes.js
@@ -235,6 +235,34 @@
pageTitle: 'Profile contacts'
}
}).
+ state('profile.references', {
+ url: '/references',
+ templateUrl: '/modules/users/views/profile/profile-view-references.client.view.html',
+ requiresAuth: true,
+ noScrollingTop: true,
+ abstract: true,
+ data: {
+ pageTitle: 'Profile references'
+ }
+ }).
+ state('profile.references.list', {
+ url: '',
+ templateUrl: '/modules/users/views/profile/profile-view-references-list.client.view.html',
+ requiresAuth: true,
+ noScrollingTop: true,
+ data: {
+ pageTitle: 'Profile references'
+ }
+ }).
+ state('profile.references.new', {
+ url: '/new',
+ template: '',
+ requiresAuth: true,
+ noScrollingTop: true,
+ data: {
+ pageTitle: 'Leave a reference'
+ }
+ }).
state('profile.tribes', {
url: '/tribes',
templateUrl: '/modules/users/views/profile/profile-view-tribes.client.view.html',
diff --git a/modules/users/client/views/profile/profile-view-references.client.view.html b/modules/users/client/views/profile/profile-view-references.client.view.html
new file mode 100644
index 0000000000..740d8f27b3
--- /dev/null
+++ b/modules/users/client/views/profile/profile-view-references.client.view.html
@@ -0,0 +1,8 @@
+
diff --git a/modules/users/client/views/profile/profile-view.client.view.html b/modules/users/client/views/profile/profile-view.client.view.html
index 573c10610f..8e8ebe7654 100644
--- a/modules/users/client/views/profile/profile-view.client.view.html
+++ b/modules/users/client/views/profile/profile-view.client.view.html
@@ -20,6 +20,11 @@
Send a message
+
+
+ Write a reference
+
+
@@ -129,13 +134,7 @@ Don't panic!