aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/auth
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2018-02-12 14:16:33 +0100
committerLibravatar GitHub <noreply@github.com>2018-02-12 14:16:33 +0100
commit7a1872e64262a76f17ac231a47fd8f57cd5a13ac (patch)
tree29ed8aa4dfcb9b179f4fe47c30fb33cf78c2e2ce /src/components/auth
parentMerge pull request #668 from meetfranz/fix/import-screen-toggles (diff)
parentfeat(App) Feature Invite Friends in Settings (diff)
downloadferdium-app-7a1872e64262a76f17ac231a47fd8f57cd5a13ac.tar.gz
ferdium-app-7a1872e64262a76f17ac231a47fd8f57cd5a13ac.tar.zst
ferdium-app-7a1872e64262a76f17ac231a47fd8f57cd5a13ac.zip
Merge pull request #654 from meetfranz/feature/invite-button
Invite Button in Settings
Diffstat (limited to 'src/components/auth')
-rw-r--r--src/components/auth/Invite.js121
1 files changed, 97 insertions, 24 deletions
diff --git a/src/components/auth/Invite.js b/src/components/auth/Invite.js
index c6dca3a65..f1c16986b 100644
--- a/src/components/auth/Invite.js
+++ b/src/components/auth/Invite.js
@@ -3,13 +3,20 @@ import PropTypes from 'prop-types';
3import { observer } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
5import { Link } from 'react-router'; 5import { Link } from 'react-router';
6import classnames from 'classnames';
6 7
8import Infobox from '../ui/Infobox';
9import Appear from '../ui/effects/Appear';
7import Form from '../../lib/Form'; 10import Form from '../../lib/Form';
8import { email } from '../../helpers/validation-helpers'; 11import { email } from '../../helpers/validation-helpers';
9import Input from '../ui/Input'; 12import Input from '../ui/Input';
10import Button from '../ui/Button'; 13import Button from '../ui/Button';
11 14
12const messages = defineMessages({ 15const messages = defineMessages({
16 settingsHeadline: {
17 id: 'settings.invite.headline',
18 defaultMessage: '!!!Invite Friends',
19 },
13 headline: { 20 headline: {
14 id: 'invite.headline.friends', 21 id: 'invite.headline.friends',
15 defaultMessage: '!!!Invite 3 of your friends or colleagues', 22 defaultMessage: '!!!Invite 3 of your friends or colleagues',
@@ -30,41 +37,77 @@ const messages = defineMessages({
30 id: 'invite.skip.label', 37 id: 'invite.skip.label',
31 defaultMessage: '!!!I want to do this later', 38 defaultMessage: '!!!I want to do this later',
32 }, 39 },
40 inviteSuccessInfo: {
41 id: 'invite.successInfo',
42 defaultMessage: '!!!Invitations sent successfully',
43 },
33}); 44});
34 45
35@observer 46@observer
36export default class Invite extends Component { 47export default class Invite extends Component {
37 static propTypes = { 48 static propTypes = {
38 onSubmit: PropTypes.func.isRequired, 49 onSubmit: PropTypes.func.isRequired,
50 embed: PropTypes.bool,
51 isInviteSuccessful: PropTypes.bool,
52 isLoadingInvite: PropTypes.bool,
53 };
54
55 static defaultProps = {
56 embed: false,
57 isInviteSuccessful: false,
58 isLoadingInvite: false,
39 }; 59 };
40 60
41 static contextTypes = { 61 static contextTypes = {
42 intl: intlShape, 62 intl: intlShape,
43 }; 63 };
44 64
45 form = new Form({ 65 state = { showSuccessInfo: false };
46 fields: { 66
47 invite: [...Array(3).fill({ 67 componentWillMount() {
48 fields: { 68 const handlers = {
49 name: { 69 onChange: () => {
50 label: this.context.intl.formatMessage(messages.nameLabel), 70 this.setState({ showSuccessInfo: false });
51 placeholder: this.context.intl.formatMessage(messages.nameLabel), 71 },
52 }, 72 };
53 email: { 73
54 label: this.context.intl.formatMessage(messages.emailLabel), 74 this.form = new Form({
55 placeholder: this.context.intl.formatMessage(messages.emailLabel), 75 fields: {
56 validators: [email], 76 invite: [...Array(3).fill({
77 fields: {
78 name: {
79 label: this.context.intl.formatMessage(messages.nameLabel),
80 placeholder: this.context.intl.formatMessage(messages.nameLabel),
81 handlers,
82 // related: ['invite.0.email'], // path accepted but does not work
83 },
84 email: {
85 label: this.context.intl.formatMessage(messages.emailLabel),
86 placeholder: this.context.intl.formatMessage(messages.emailLabel),
87 handlers,
88 validators: [email],
89 },
57 }, 90 },
58 }, 91 })],
59 })], 92 },
60 }, 93 }, this.context.intl);
61 }, this.context.intl); 94 }
95
96 componentDidMount() {
97 document.querySelector('input:first-child').focus();
98 }
62 99
63 submit(e) { 100 submit(e) {
64 e.preventDefault(); 101 e.preventDefault();
102
65 this.form.submit({ 103 this.form.submit({
66 onSuccess: (form) => { 104 onSuccess: (form) => {
67 this.props.onSubmit({ invites: form.values().invite }); 105 this.props.onSubmit({ invites: form.values().invite });
106
107 this.form.clear();
108 // this.form.$('invite.0.name').focus(); // path accepted but does not focus ;(
109 document.querySelector('input:first-child').focus();
110 this.setState({ showSuccessInfo: true });
68 }, 111 },
69 onError: () => {}, 112 onError: () => {},
70 }); 113 });
@@ -73,20 +116,38 @@ export default class Invite extends Component {
73 render() { 116 render() {
74 const { form } = this; 117 const { form } = this;
75 const { intl } = this.context; 118 const { intl } = this.context;
119 const { embed, isInviteSuccessful, isLoadingInvite } = this.props;
76 120
77 const atLeastOneEmailAddress = form.$('invite') 121 const atLeastOneEmailAddress = form.$('invite')
78 .map(invite => invite.$('email').value) 122 .map(invite => invite.$('email').value)
79 .some(emailValue => emailValue.trim() !== ''); 123 .some(emailValue => emailValue.trim() !== '');
80 124
81 return ( 125 const sendButtonClassName = classnames({
82 <div className="auth__container auth__container--signup"> 126 auth__button: true,
127 'invite__embed--button': embed,
128 });
129
130 const renderForm = (
131 <div>
132 {this.state.showSuccessInfo && isInviteSuccessful && (
133 <Appear>
134 <Infobox
135 type="success"
136 icon="checkbox-marked-circle-outline"
137 dismissable
138 >
139 {intl.formatMessage(messages.inviteSuccessInfo)}
140 </Infobox>
141 </Appear>
142 )}
143
83 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 144 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
84 <img 145 {!embed && (<img
85 src="./assets/images/logo.svg" 146 src="./assets/images/logo.svg"
86 className="auth__logo" 147 className="auth__logo"
87 alt="" 148 alt=""
88 /> 149 />)}
89 <h1> 150 <h1 className={embed && 'invite__embed'}>
90 {intl.formatMessage(messages.headline)} 151 {intl.formatMessage(messages.headline)}
91 </h1> 152 </h1>
92 {form.$('invite').map(invite => ( 153 {form.$('invite').map(invite => (
@@ -99,18 +160,30 @@ export default class Invite extends Component {
99 ))} 160 ))}
100 <Button 161 <Button
101 type="submit" 162 type="submit"
102 className="auth__button" 163 className={sendButtonClassName}
103 disabled={!atLeastOneEmailAddress} 164 disabled={!atLeastOneEmailAddress}
104 label={intl.formatMessage(messages.submitButtonLabel)} 165 label={intl.formatMessage(messages.submitButtonLabel)}
166 loaded={!isLoadingInvite}
105 /> 167 />
106 <Link 168 {!embed && (<Link
107 to="/" 169 to="/"
108 className="franz-form__button franz-form__button--secondary auth__button auth__button--skip" 170 className="franz-form__button franz-form__button--secondary auth__button auth__button--skip"
109 > 171 >
110 {intl.formatMessage(messages.skipButtonLabel)} 172 {intl.formatMessage(messages.skipButtonLabel)}
111 </Link> 173 </Link>)}
112 </form> 174 </form>
113 </div> 175 </div>
114 ); 176 );
177
178 return (
179 <div className={!embed ? 'auth__container auth__container--signup' : 'settings__main'}>
180 {embed && (
181 <div className="settings__header">
182 <h1>{this.context.intl.formatMessage(messages.settingsHeadline)}</h1>
183 </div>
184 )}
185 {!embed ? <div>{renderForm}</div> : <div className="settings__body invite__form">{renderForm}</div>}
186 </div>
187 );
115 } 188 }
116} 189}