aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/auth/Invite.tsx
diff options
context:
space:
mode:
authorLibravatar muhamedsalih-tw <104364298+muhamedsalih-tw@users.noreply.github.com>2022-11-02 06:31:36 +0530
committerLibravatar GitHub <noreply@github.com>2022-11-02 01:01:36 +0000
commit302d595f7c289387e53a0ef7df4d574ed4e25d70 (patch)
tree2385e59eaca9c78921d9b0b3681cfba1b3eef168 /src/components/auth/Invite.tsx
parentRe-enable editing of the address bar to manually access a different url withi... (diff)
downloadferdium-app-302d595f7c289387e53a0ef7df4d574ed4e25d70.tar.gz
ferdium-app-302d595f7c289387e53a0ef7df4d574ed4e25d70.tar.zst
ferdium-app-302d595f7c289387e53a0ef7df4d574ed4e25d70.zip
Transform to TS and refactored components w.r.t deletion if duplicated Input component (#729)
Diffstat (limited to 'src/components/auth/Invite.tsx')
-rw-r--r--src/components/auth/Invite.tsx213
1 files changed, 213 insertions, 0 deletions
diff --git a/src/components/auth/Invite.tsx b/src/components/auth/Invite.tsx
new file mode 100644
index 000000000..7723ea1ac
--- /dev/null
+++ b/src/components/auth/Invite.tsx
@@ -0,0 +1,213 @@
1import { Component } from 'react';
2import { observer } from 'mobx-react';
3import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
4import { Link } from 'react-router-dom';
5import classnames from 'classnames';
6import { noop } from 'lodash';
7import Infobox from '../ui/Infobox';
8import Appear from '../ui/effects/Appear';
9import Form from '../../lib/Form';
10import { email, required } from '../../helpers/validation-helpers';
11import Input from '../ui/input/index';
12import Button from '../ui/button';
13import { H1 } from '../ui/headline';
14
15const messages = defineMessages({
16 settingsHeadline: {
17 id: 'settings.invite.headline',
18 defaultMessage: 'Invite Friends',
19 },
20 headline: {
21 id: 'invite.headline.friends',
22 defaultMessage: 'Invite 3 of your friends or colleagues',
23 },
24 nameLabel: {
25 id: 'invite.name.label',
26 defaultMessage: 'Name',
27 },
28 emailLabel: {
29 id: 'invite.email.label',
30 defaultMessage: 'Email address',
31 },
32 submitButtonLabel: {
33 id: 'invite.submit.label',
34 defaultMessage: 'Send invites',
35 },
36 skipButtonLabel: {
37 id: 'invite.skip.label',
38 defaultMessage: 'I want to do this later',
39 },
40 inviteSuccessInfo: {
41 id: 'invite.successInfo',
42 defaultMessage: 'Invitations sent successfully',
43 },
44});
45
46interface IProps extends WrappedComponentProps {
47 onSubmit: (...args: any[]) => void;
48 embed?: boolean;
49 isInviteSuccessful?: boolean;
50 isLoadingInvite?: boolean;
51}
52
53interface IState {
54 showSuccessInfo: boolean;
55}
56
57@observer
58class Invite extends Component<IProps, IState> {
59 form: Form;
60
61 constructor(props: IProps) {
62 super(props);
63
64 this.state = { showSuccessInfo: false };
65 this.form = new Form({
66 fields: {
67 invite: [
68 ...Array.from({ length: 3 }).fill({
69 fields: {
70 name: {
71 label: this.props.intl.formatMessage(messages.nameLabel),
72 placeholder: this.props.intl.formatMessage(messages.nameLabel),
73 onChange: () => {
74 this.setState({ showSuccessInfo: false });
75 },
76 validators: [required],
77 // related: ['invite.0.email'], // path accepted but does not work
78 },
79 email: {
80 label: this.props.intl.formatMessage(messages.emailLabel),
81 placeholder: this.props.intl.formatMessage(messages.emailLabel),
82 onChange: () => {
83 this.setState({ showSuccessInfo: false });
84 },
85 validators: [email],
86 },
87 },
88 }),
89 // TODO - [TS DEBT] need to fix this type once mobx-react-form is updated to next version
90 ] as any,
91 },
92 });
93 }
94
95 componentDidMount() {
96 const selector: HTMLElement | null =
97 document.querySelector('input:first-child');
98 if (selector) {
99 selector.focus();
100 }
101 }
102
103 submit(e) {
104 e.preventDefault();
105
106 this.form?.submit({
107 onSuccess: form => {
108 this.props.onSubmit({ invites: form.values().invite });
109 this.form?.clear();
110 // this.form.$('invite.0.name').focus(); // path accepted but does not focus ;(
111
112 const selector: HTMLElement | null =
113 document.querySelector('input:first-child');
114 if (selector) {
115 selector.focus();
116 }
117
118 this.setState({ showSuccessInfo: true });
119 },
120 onError: () => {},
121 });
122 }
123
124 render() {
125 const { form } = this;
126 const { intl } = this.props;
127 const {
128 embed = false,
129 isInviteSuccessful = false,
130 isLoadingInvite = false,
131 } = this.props;
132
133 const atLeastOneEmailAddress = form
134 .$('invite')
135 .map(invite => invite.$('email').value)
136 .some(emailValue => emailValue.trim() !== '');
137
138 const sendButtonClassName = classnames({
139 auth__button: true,
140 'invite__embed--button': embed,
141 });
142
143 const renderForm = (
144 <>
145 {this.state.showSuccessInfo && isInviteSuccessful && (
146 <Appear>
147 <Infobox
148 type="success"
149 icon="checkbox-marked-circle-outline"
150 dismissible
151 >
152 {intl.formatMessage(messages.inviteSuccessInfo)}
153 </Infobox>
154 </Appear>
155 )}
156
157 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}>
158 {!embed && (
159 <img src="./assets/images/logo.svg" className="auth__logo" alt="" />
160 )}
161 <H1 className={embed ? 'invite__embed' : ''}>
162 {intl.formatMessage(messages.headline)}
163 </H1>
164 {form.$('invite').map(invite => (
165 <div className="grid" key={invite.key}>
166 <div className="grid__row">
167 <Input {...invite.$('name').bind()} showLabel={false} />
168 <Input {...invite.$('email').bind()} showLabel={false} />
169 </div>
170 </div>
171 ))}
172 <Button
173 type="submit"
174 className={sendButtonClassName}
175 disabled={!atLeastOneEmailAddress}
176 label={intl.formatMessage(messages.submitButtonLabel)}
177 loaded={!isLoadingInvite}
178 onClick={noop}
179 />
180 {!embed && (
181 <Link
182 to="/"
183 className="franz-form__button franz-form__button--secondary auth__button auth__button--skip"
184 >
185 {intl.formatMessage(messages.skipButtonLabel)}
186 </Link>
187 )}
188 </form>
189 </>
190 );
191
192 return (
193 <div
194 className={
195 !embed ? 'auth__container auth__container--signup' : 'settings__main'
196 }
197 >
198 {embed && (
199 <div className="settings__header">
200 <H1>{intl.formatMessage(messages.settingsHeadline)}</H1>
201 </div>
202 )}
203 {!embed ? (
204 <div>{renderForm}</div>
205 ) : (
206 <div className="settings__body invite__form">{renderForm}</div>
207 )}
208 </div>
209 );
210 }
211}
212
213export default injectIntl(Invite);