Skip to content

Commit cf3314e

Browse files
MichaelDeBoeySaraVieira
authored andcommitted
🔨 Switch FeedbackModal to use useOvermind (#2846)
1 parent 44f99df commit cf3314e

File tree

3 files changed

+139
-117
lines changed

3 files changed

+139
-117
lines changed

‎packages/app/src/app/pages/common/Modals/FeedbackModal/Feedback.tsx‎

Lines changed: 79 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,135 @@
1-
import * as React from 'react';
2-
import { useOvermind } from 'app/overmind';
31
import Margin from '@codesandbox/common/lib/components/spacing/Margin';
4-
import { Button } from '@codesandbox/common/lib/components/Button';
52
import { CurrentUser } from '@codesandbox/common/lib/types';
3+
import React, {
4+
ChangeEvent,
5+
FormEvent,
6+
FunctionComponent,
7+
useState,
8+
} from 'react';
69

7-
import AutosizeTextArea from '@codesandbox/common/lib/components/AutosizeTextArea';
8-
import Input from '@codesandbox/common/lib/components/Input';
10+
import { useOvermind } from 'app/overmind';
911
import pushToAirtable from 'app/store/utils/pushToAirtable';
1012

11-
import { EmojiButton } from './elements';
13+
import {
14+
AutosizeTextArea,
15+
Button,
16+
ButtonContainer,
17+
EmojiButton,
18+
Input,
19+
} from './elements';
1220

13-
interface ICollectionInfoProps {
21+
type Props = {
1422
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 }) => {
1926
const {
20-
actions: { modalClosed, notificationAdded },
27+
actions: { notificationAdded, modalClosed },
2128
} = 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);
2233

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+
};
2742

28-
const setHappy = () => setEmoji('happy');
43+
(settersByInputName[name] || noop)(value);
44+
};
2945

30-
const setSad = () => setEmoji('sad');
46+
const onSubmit = ({ preventDefault }: FormEvent<HTMLFormElement>) => {
47+
preventDefault();
3148

32-
const onSubmit = async evt => {
33-
evt.preventDefault();
3449
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);
5676
});
57-
setLoading(false);
58-
}
5977
};
6078

79+
const setHappy = () => setEmoji('happy');
80+
const setSad = () => setEmoji('sad');
81+
6182
return (
6283
<form onSubmit={onSubmit}>
6384
<AutosizeTextArea
64-
css={`
65-
width: 100%;
66-
`}
85+
minRows={3}
6786
name="feedback"
68-
value={feedback}
69-
onChange={e => setFeedback(e.target.value)}
87+
onChange={onChange}
7088
placeholder="What are your thoughts?"
71-
minRows={3}
7289
required
90+
value={feedback}
7391
/>
92+
7493
{!user && (
7594
<Margin top={0.5}>
7695
<Input
77-
css={`
78-
width: 100%;
79-
`}
80-
type="email"
8196
name="email"
82-
value={email}
83-
onChange={e => setEmail(e.target.value)}
97+
onChange={onChange}
8498
placeholder="Email if you wish to be contacted"
99+
type="email"
100+
value={email}
85101
/>
86102
</Margin>
87103
)}
88104

89105
<Margin
90-
top={0.5}
91106
css={`
92107
display: flex;
93108
align-items: center;
94109
`}
110+
top={0.5}
95111
>
96112
<EmojiButton
97-
type="button"
98113
active={emoji === 'happy'}
99114
onClick={setHappy}
115+
type="button"
100116
>
101-
<span role="img" aria-label="happy">
117+
<span aria-label="happy" role="img">
102118
😊
103119
</span>
104120
</EmojiButton>
105121

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">
108124
😞
109125
</span>
110126
</EmojiButton>
111127

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>
124130
{loading ? 'Sending...' : 'Submit'}
125131
</Button>
126-
</div>
132+
</ButtonContainer>
127133
</Margin>
128134
</form>
129135
);
Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,60 @@
1+
import AutosizeTextAreaBase from '@codesandbox/common/lib/components/AutosizeTextArea';
2+
import { Button as ButtonBase } from '@codesandbox/common/lib/components/Button';
3+
import InputBase from '@codesandbox/common/lib/components/Input';
14
import styled, { css } from 'styled-components';
25

3-
interface Props {
4-
active: boolean;
5-
}
6-
7-
export const EmojiButton = styled.button<Props>`
8-
transition: 0.3s ease all;
9-
border: 2px solid rgba(0, 0, 0, 0.2);
10-
background-color: rgba(0, 0, 0, 0.3);
11-
border-radius: 4px;
12-
padding: 0.1rem;
13-
outline: 0;
14-
margin-right: 1rem;
15-
width: 32px;
16-
height: 32px;
17-
line-height: 28px;
18-
display: inline-flex;
19-
align-items: center;
20-
justify-content: center;
21-
22-
cursor: pointer;
23-
24-
span {
25-
display: inline;
26-
line-height: initial;
27-
width: 15px;
28-
}
29-
30-
&:hover {
31-
border: 2px solid rgba(255, 255, 255, 0.2);
32-
background-color: ${props => props.theme.secondary};
33-
}
34-
&:focus {
35-
border: 2px solid rgba(255, 255, 255, 0.2);
36-
}
37-
38-
${props =>
39-
props.active &&
40-
css`
6+
export const AutosizeTextArea = styled(AutosizeTextAreaBase)`
7+
width: 100%;
8+
`;
9+
10+
export const Button = styled(ButtonBase)`
11+
float: right;
12+
`;
13+
14+
export const ButtonContainer = styled.div`
15+
flex: 1;
16+
`;
17+
18+
export const EmojiButton = styled.button<{ active: boolean }>`
19+
${({ active, theme }) => css`
20+
transition: 0.3s ease all;
21+
border: 2px solid rgba(0, 0, 0, 0.2);
22+
background-color: rgba(0, 0, 0, 0.3);
23+
border-radius: 4px;
24+
padding: 0.1rem;
25+
outline: 0;
26+
margin-right: 1rem;
27+
width: 32px;
28+
height: 32px;
29+
line-height: 28px;
30+
display: inline-flex;
31+
align-items: center;
32+
justify-content: center;
33+
34+
cursor: pointer;
35+
36+
span {
37+
display: inline;
38+
line-height: initial;
39+
width: 15px;
40+
}
41+
42+
&:hover {
43+
border: 2px solid rgba(255, 255, 255, 0.2);
44+
background-color: ${theme.secondary};
45+
}
46+
&:focus {
4147
border: 2px solid rgba(255, 255, 255, 0.2);
42-
background-color: ${props.theme.secondary};
43-
`};
48+
}
49+
50+
${active &&
51+
css`
52+
border: 2px solid rgba(255, 255, 255, 0.2);
53+
background-color: ${theme.secondary};
54+
`};
55+
`};
56+
`;
57+
58+
export const Input = styled(InputBase)`
59+
width: 100%;
4460
`;

‎packages/app/src/app/pages/common/Modals/FeedbackModal/index.tsx‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
import React from 'react';
1+
import React, { FunctionComponent } from 'react';
22

33
import { useOvermind } from 'app/overmind';
44
import Loadable from 'app/utils/Loadable';
55

6-
import { Heading, Container } from '../elements';
6+
import { Container, Heading } from '../elements';
77

88
const Feedback = Loadable(() =>
99
import(/* webpackChunkName: 'feedback' */ './Feedback')
1010
);
1111

12-
export const FeedbackModal: React.FC = () => {
12+
export const FeedbackModal: FunctionComponent = () => {
1313
const {
1414
state: {
15-
user,
1615
editor: { currentId },
16+
user,
1717
},
1818
} = useOvermind();
1919

0 commit comments

Comments
 (0)