diff --git a/packages/app/src/app/pages/common/Modals/FeedbackModal/Feedback.tsx b/packages/app/src/app/pages/common/Modals/FeedbackModal/Feedback.tsx index e084d4c1add..67b917ddf45 100644 --- a/packages/app/src/app/pages/common/Modals/FeedbackModal/Feedback.tsx +++ b/packages/app/src/app/pages/common/Modals/FeedbackModal/Feedback.tsx @@ -1,129 +1,135 @@ -import * as React from 'react'; -import { useOvermind } from 'app/overmind'; import Margin from '@codesandbox/common/lib/components/spacing/Margin'; -import { Button } from '@codesandbox/common/lib/components/Button'; import { CurrentUser } from '@codesandbox/common/lib/types'; +import React, { + ChangeEvent, + FormEvent, + FunctionComponent, + useState, +} from 'react'; -import AutosizeTextArea from '@codesandbox/common/lib/components/AutosizeTextArea'; -import Input from '@codesandbox/common/lib/components/Input'; +import { useOvermind } from 'app/overmind'; import pushToAirtable from 'app/store/utils/pushToAirtable'; -import { EmojiButton } from './elements'; +import { + AutosizeTextArea, + Button, + ButtonContainer, + EmojiButton, + Input, +} from './elements'; -interface ICollectionInfoProps { +type Props = { id: string; - user: CurrentUser; -} - -const Feedback: React.FC = ({ id, user }) => { + user?: CurrentUser; +}; +const Feedback: FunctionComponent = ({ id, user }) => { const { - actions: { modalClosed, notificationAdded }, + actions: { notificationAdded, modalClosed }, } = useOvermind(); + const [email, setEmail] = useState((user || {}).email); + const [emoji, setEmoji] = useState(null); + const [feedback, setFeedback] = useState(''); + const [loading, setLoading] = useState(false); - const [feedback, setFeedback] = React.useState(''); - const [email, setEmail] = React.useState((user || {}).email); - const [emoji, setEmoji] = React.useState(null); - const [loading, setLoading] = React.useState(false); + const onChange = ({ + target: { name, value }, + }: ChangeEvent) => { + const noop = () => undefined; + const settersByInputName = { + email: setEmail, + feedback: setFeedback, + }; - const setHappy = () => setEmoji('happy'); + (settersByInputName[name] || noop)(value); + }; - const setSad = () => setEmoji('sad'); + const onSubmit = ({ preventDefault }: FormEvent) => { + preventDefault(); - const onSubmit = async evt => { - evt.preventDefault(); setLoading(true); - try { - await pushToAirtable({ - sandboxId: id, - feedback, - emoji, - username: (user || {}).username, - email, - }); - setFeedback(''); - setEmoji(null); - setLoading(false); - - modalClosed(); - notificationAdded({ - title: `Thanks for your feedback!`, - notificationType: 'success', - }); - } catch (e) { - notificationAdded({ - title: `Something went wrong while sending feedback: ${e.message}`, - notificationType: 'error', + + pushToAirtable({ + sandboxId: id, + feedback, + emoji, + username: (user || {}).username, + email, + }) + .then(() => { + setEmoji(null); + setFeedback(''); + setLoading(false); + + modalClosed(); + notificationAdded({ + notificationType: 'success', + title: 'Thanks for your feedback!', + }); + }) + .catch(({ message }) => { + notificationAdded({ + notificationType: 'error', + title: `Something went wrong while sending feedback: ${message}`, + }); + + setLoading(false); }); - setLoading(false); - } }; + const setHappy = () => setEmoji('happy'); + const setSad = () => setEmoji('sad'); + return (
setFeedback(e.target.value)} + onChange={onChange} placeholder="What are your thoughts?" - minRows={3} required + value={feedback} /> + {!user && ( setEmail(e.target.value)} + onChange={onChange} placeholder="Email if you wish to be contacted" + type="email" + value={email} /> )} - + 😊 - - + + 😞 -
- -
+
); diff --git a/packages/app/src/app/pages/common/Modals/FeedbackModal/elements.ts b/packages/app/src/app/pages/common/Modals/FeedbackModal/elements.ts index 12018954abb..0492a1944bf 100644 --- a/packages/app/src/app/pages/common/Modals/FeedbackModal/elements.ts +++ b/packages/app/src/app/pages/common/Modals/FeedbackModal/elements.ts @@ -1,44 +1,60 @@ +import AutosizeTextAreaBase from '@codesandbox/common/lib/components/AutosizeTextArea'; +import { Button as ButtonBase } from '@codesandbox/common/lib/components/Button'; +import InputBase from '@codesandbox/common/lib/components/Input'; import styled, { css } from 'styled-components'; -interface Props { - active: boolean; -} - -export const EmojiButton = styled.button` - transition: 0.3s ease all; - border: 2px solid rgba(0, 0, 0, 0.2); - background-color: rgba(0, 0, 0, 0.3); - border-radius: 4px; - padding: 0.1rem; - outline: 0; - margin-right: 1rem; - width: 32px; - height: 32px; - line-height: 28px; - display: inline-flex; - align-items: center; - justify-content: center; - - cursor: pointer; - - span { - display: inline; - line-height: initial; - width: 15px; - } - - &:hover { - border: 2px solid rgba(255, 255, 255, 0.2); - background-color: ${props => props.theme.secondary}; - } - &:focus { - border: 2px solid rgba(255, 255, 255, 0.2); - } - - ${props => - props.active && - css` +export const AutosizeTextArea = styled(AutosizeTextAreaBase)` + width: 100%; +`; + +export const Button = styled(ButtonBase)` + float: right; +`; + +export const ButtonContainer = styled.div` + flex: 1; +`; + +export const EmojiButton = styled.button<{ active: boolean }>` + ${({ active, theme }) => css` + transition: 0.3s ease all; + border: 2px solid rgba(0, 0, 0, 0.2); + background-color: rgba(0, 0, 0, 0.3); + border-radius: 4px; + padding: 0.1rem; + outline: 0; + margin-right: 1rem; + width: 32px; + height: 32px; + line-height: 28px; + display: inline-flex; + align-items: center; + justify-content: center; + + cursor: pointer; + + span { + display: inline; + line-height: initial; + width: 15px; + } + + &:hover { + border: 2px solid rgba(255, 255, 255, 0.2); + background-color: ${theme.secondary}; + } + &:focus { border: 2px solid rgba(255, 255, 255, 0.2); - background-color: ${props.theme.secondary}; - `}; + } + + ${active && + css` + border: 2px solid rgba(255, 255, 255, 0.2); + background-color: ${theme.secondary}; + `}; + `}; +`; + +export const Input = styled(InputBase)` + width: 100%; `; diff --git a/packages/app/src/app/pages/common/Modals/FeedbackModal/index.tsx b/packages/app/src/app/pages/common/Modals/FeedbackModal/index.tsx index 28216dfc5e3..c498050c1c7 100644 --- a/packages/app/src/app/pages/common/Modals/FeedbackModal/index.tsx +++ b/packages/app/src/app/pages/common/Modals/FeedbackModal/index.tsx @@ -1,19 +1,19 @@ -import React from 'react'; +import React, { FunctionComponent } from 'react'; import { useOvermind } from 'app/overmind'; import Loadable from 'app/utils/Loadable'; -import { Heading, Container } from '../elements'; +import { Container, Heading } from '../elements'; const Feedback = Loadable(() => import(/* webpackChunkName: 'feedback' */ './Feedback') ); -export const FeedbackModal: React.FC = () => { +export const FeedbackModal: FunctionComponent = () => { const { state: { - user, editor: { currentId }, + user, }, } = useOvermind();