From 87d6cbf72ad58cbf82c96796a47250971758ca61 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 9 Oct 2020 08:18:18 -0700 Subject: [PATCH] Feedback form sends req to stubbed API endpoint Okay, now the UI can handle the loading/success/error status! Next we need to actually send :3 --- api/sendFeedback.js | 16 +++++++++++ src/app/HomePage.js | 66 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 api/sendFeedback.js diff --git a/api/sendFeedback.js b/api/sendFeedback.js new file mode 100644 index 0000000..6ebeaf6 --- /dev/null +++ b/api/sendFeedback.js @@ -0,0 +1,16 @@ +const beeline = require("honeycomb-beeline")({ + writeKey: process.env["HONEYCOMB_WRITE_KEY"], + dataset: + process.env["NODE_ENV"] === "production" + ? "Dress to Impress (2020)" + : "Dress to Impress (2020, dev)", + serviceName: "impress-2020-gql-server", +}); + +async function handle(req, res) { + res.status(500).send("TODO! This is a fake error case."); +} + +export default async (req, res) => { + beeline.withTrace({ name: "uploadLayerImage" }, () => handle(req, res)); +}; diff --git a/src/app/HomePage.js b/src/app/HomePage.js index 589a202..c9dcd45 100644 --- a/src/app/HomePage.js +++ b/src/app/HomePage.js @@ -16,7 +16,7 @@ import { CloseIcon } from "@chakra-ui/icons"; import { useHistory, useLocation } from "react-router-dom"; import { useLazyQuery } from "@apollo/client"; -import { Heading1, usePageTitle } from "./util"; +import { Heading1, useLocalStorage, usePageTitle } from "./util"; import OutfitPreview from "./components/OutfitPreview"; import SpeciesColorPicker from "./components/SpeciesColorPicker"; @@ -390,8 +390,58 @@ function FeedbackFormPitch({ isDisabled, onClick, openButtonRef }) { function FeedbackForm({ isDisabled, onClose, emailFieldRef }) { const [content, setContent] = React.useState(""); + const [email, setEmail] = useLocalStorage("DTIFeedbackFormEmail", ""); + const [isSending, setIsSending] = React.useState(false); const toast = useToast(); + const onSubmit = React.useCallback( + (e) => { + e.preventDefault(); + + const formData = new FormData(); + formData.set("content", content); + formData.set("email", email); + + fetch("/api/sendFeedback", { + method: "POST", + body: formData, + }) + .then((res) => { + if (!res.ok) { + throw new Error(`/api/sendFeedback returned status ${res.status}`); + } + + setIsSending(false); + setContent(""); + onClose(); + toast({ + status: "success", + title: "Got it! We'll take a look soon.", + description: + "Thanks for helping us get better! Best wishes to you and your " + + "pets!!", + }); + }) + .catch((e) => { + setIsSending(false); + console.error(e); + toast({ + status: "warning", + title: "Oops, we had an error sending this, sorry!", + description: + "We'd still love to hear from you! Please reach out to " + + "matchu@openneo.net with whatever's on your mind. Thanks and " + + "enjoy the site!", + duration: null, + isClosable: true, + }); + }); + + setIsSending(true); + }, + [content] + ); + return ( { - e.preventDefault(); - toast({ - title: "Ah, well, this form isn't hooked up yet!", - description: - "That's coming soon! 😅 For now, please send an email to matchu@openneo.net. Sorry and thanks!", - duration: null, - isClosable: true, - }); - }} + onSubmit={onSubmit} onKeyDown={(e) => { if (e.key === "Escape") { onClose(); @@ -423,6 +464,8 @@ function FeedbackForm({ isDisabled, onClose, emailFieldRef }) { placeholder="Email address (optional)" size="sm" gridArea="email" + value={email} + onChange={(e) => setEmail(e.target.value)} ref={emailFieldRef} isDisabled={isDisabled} /> @@ -440,6 +483,7 @@ function FeedbackForm({ isDisabled, onClose, emailFieldRef }) { colorScheme="blue" gridArea="send" isDisabled={isDisabled || content.trim().length === 0} + isLoading={isSending} > Send