|
1 | | -import * as React from 'react'; |
2 | | -import { useOvermind } from 'app/overmind'; |
3 | 1 | import Margin from '@codesandbox/common/lib/components/spacing/Margin'; |
4 | | -import { Button } from '@codesandbox/common/lib/components/Button'; |
5 | 2 | import { CurrentUser } from '@codesandbox/common/lib/types'; |
| 3 | +import React, { |
| 4 | + ChangeEvent, |
| 5 | + FormEvent, |
| 6 | + FunctionComponent, |
| 7 | + useState, |
| 8 | +} from 'react'; |
6 | 9 |
|
7 | | -import AutosizeTextArea from '@codesandbox/common/lib/components/AutosizeTextArea'; |
8 | | -import Input from '@codesandbox/common/lib/components/Input'; |
| 10 | +import { useOvermind } from 'app/overmind'; |
9 | 11 | import pushToAirtable from 'app/store/utils/pushToAirtable'; |
10 | 12 |
|
11 | | -import { EmojiButton } from './elements'; |
| 13 | +import { |
| 14 | + AutosizeTextArea, |
| 15 | + Button, |
| 16 | + ButtonContainer, |
| 17 | + EmojiButton, |
| 18 | + Input, |
| 19 | +} from './elements'; |
12 | 20 |
|
13 | | -interface ICollectionInfoProps { |
| 21 | +type Props = { |
14 | 22 | id: string; |
15 | | - user: CurrentUser; |
16 | | -} |
17 | | - |
18 | | -const Feedback: React.FC<ICollectionInfoProps> = ({ id, user }) => { |
| 23 | + user?: CurrentUser; |
| 24 | +}; |
| 25 | +const Feedback: FunctionComponent<Props> = ({ id, user }) => { |
19 | 26 | const { |
20 | | - actions: { modalClosed, notificationAdded }, |
| 27 | + actions: { notificationAdded, modalClosed }, |
21 | 28 | } = useOvermind(); |
| 29 | + const [email, setEmail] = useState((user || {}).email); |
| 30 | + const [emoji, setEmoji] = useState(null); |
| 31 | + const [feedback, setFeedback] = useState(''); |
| 32 | + const [loading, setLoading] = useState(false); |
22 | 33 |
|
23 | | - const [feedback, setFeedback] = React.useState(''); |
24 | | - const [email, setEmail] = React.useState((user || {}).email); |
25 | | - const [emoji, setEmoji] = React.useState(null); |
26 | | - const [loading, setLoading] = React.useState(false); |
| 34 | + const onChange = ({ |
| 35 | + target: { name, value }, |
| 36 | + }: ChangeEvent<HTMLInputElement>) => { |
| 37 | + const noop = () => undefined; |
| 38 | + const settersByInputName = { |
| 39 | + email: setEmail, |
| 40 | + feedback: setFeedback, |
| 41 | + }; |
27 | 42 |
|
28 | | - const setHappy = () => setEmoji('happy'); |
| 43 | + (settersByInputName[name] || noop)(value); |
| 44 | + }; |
29 | 45 |
|
30 | | - const setSad = () => setEmoji('sad'); |
| 46 | + const onSubmit = ({ preventDefault }: FormEvent<HTMLFormElement>) => { |
| 47 | + preventDefault(); |
31 | 48 |
|
32 | | - const onSubmit = async evt => { |
33 | | - evt.preventDefault(); |
34 | 49 | setLoading(true); |
35 | | - try { |
36 | | - await pushToAirtable({ |
37 | | - sandboxId: id, |
38 | | - feedback, |
39 | | - emoji, |
40 | | - username: (user || {}).username, |
41 | | - email, |
42 | | - }); |
43 | | - setFeedback(''); |
44 | | - setEmoji(null); |
45 | | - setLoading(false); |
46 | | - |
47 | | - modalClosed(); |
48 | | - notificationAdded({ |
49 | | - title: `Thanks for your feedback!`, |
50 | | - notificationType: 'success', |
51 | | - }); |
52 | | - } catch (e) { |
53 | | - notificationAdded({ |
54 | | - title: `Something went wrong while sending feedback: ${e.message}`, |
55 | | - notificationType: 'error', |
| 50 | + |
| 51 | + pushToAirtable({ |
| 52 | + sandboxId: id, |
| 53 | + feedback, |
| 54 | + emoji, |
| 55 | + username: (user || {}).username, |
| 56 | + email, |
| 57 | + }) |
| 58 | + .then(() => { |
| 59 | + setEmoji(null); |
| 60 | + setFeedback(''); |
| 61 | + setLoading(false); |
| 62 | + |
| 63 | + modalClosed(); |
| 64 | + notificationAdded({ |
| 65 | + notificationType: 'success', |
| 66 | + title: 'Thanks for your feedback!', |
| 67 | + }); |
| 68 | + }) |
| 69 | + .catch(({ message }) => { |
| 70 | + notificationAdded({ |
| 71 | + notificationType: 'error', |
| 72 | + title: `Something went wrong while sending feedback: ${message}`, |
| 73 | + }); |
| 74 | + |
| 75 | + setLoading(false); |
56 | 76 | }); |
57 | | - setLoading(false); |
58 | | - } |
59 | 77 | }; |
60 | 78 |
|
| 79 | + const setHappy = () => setEmoji('happy'); |
| 80 | + const setSad = () => setEmoji('sad'); |
| 81 | + |
61 | 82 | return ( |
62 | 83 | <form onSubmit={onSubmit}> |
63 | 84 | <AutosizeTextArea |
64 | | - css={` |
65 | | - width: 100%; |
66 | | - `} |
| 85 | + minRows={3} |
67 | 86 | name="feedback" |
68 | | - value={feedback} |
69 | | - onChange={e => setFeedback(e.target.value)} |
| 87 | + onChange={onChange} |
70 | 88 | placeholder="What are your thoughts?" |
71 | | - minRows={3} |
72 | 89 | required |
| 90 | + value={feedback} |
73 | 91 | /> |
| 92 | + |
74 | 93 | {!user && ( |
75 | 94 | <Margin top={0.5}> |
76 | 95 | <Input |
77 | | - css={` |
78 | | - width: 100%; |
79 | | - `} |
80 | | - type="email" |
81 | 96 | name="email" |
82 | | - value={email} |
83 | | - onChange={e => setEmail(e.target.value)} |
| 97 | + onChange={onChange} |
84 | 98 | placeholder="Email if you wish to be contacted" |
| 99 | + type="email" |
| 100 | + value={email} |
85 | 101 | /> |
86 | 102 | </Margin> |
87 | 103 | )} |
88 | 104 |
|
89 | 105 | <Margin |
90 | | - top={0.5} |
91 | 106 | css={` |
92 | 107 | display: flex; |
93 | 108 | align-items: center; |
94 | 109 | `} |
| 110 | + top={0.5} |
95 | 111 | > |
96 | 112 | <EmojiButton |
97 | | - type="button" |
98 | 113 | active={emoji === 'happy'} |
99 | 114 | onClick={setHappy} |
| 115 | + type="button" |
100 | 116 | > |
101 | | - <span role="img" aria-label="happy"> |
| 117 | + <span aria-label="happy" role="img"> |
102 | 118 | 😊 |
103 | 119 | </span> |
104 | 120 | </EmojiButton> |
105 | 121 |
|
106 | | - <EmojiButton type="button" active={emoji === 'sad'} onClick={setSad}> |
107 | | - <span role="img" aria-label="sad"> |
| 122 | + <EmojiButton active={emoji === 'sad'} onClick={setSad} type="button"> |
| 123 | + <span aria-label="sad" role="img"> |
108 | 124 | 😞 |
109 | 125 | </span> |
110 | 126 | </EmojiButton> |
111 | 127 |
|
112 | | - <div |
113 | | - css={` |
114 | | - flex: 1; |
115 | | - `} |
116 | | - > |
117 | | - <Button |
118 | | - disabled={loading} |
119 | | - small |
120 | | - css={` |
121 | | - float: right; |
122 | | - `} |
123 | | - > |
| 128 | + <ButtonContainer> |
| 129 | + <Button disabled={loading} small> |
124 | 130 | {loading ? 'Sending...' : 'Submit'} |
125 | 131 | </Button> |
126 | | - </div> |
| 132 | + </ButtonContainer> |
127 | 133 | </Margin> |
128 | 134 | </form> |
129 | 135 | ); |
|
0 commit comments