Added stripe integration and donation modal

This commit is contained in:
Mitchell McCaffrey 2020-04-15 12:51:03 +10:00
parent d662f5e107
commit 0015144d1a
4 changed files with 154 additions and 1 deletions

View File

@ -4,6 +4,7 @@
"private": true,
"homepage": "https://owlbear.rodeo",
"dependencies": {
"@stripe/stripe-js": "^1.3.2",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",

133
src/modals/DonationModal.js Normal file
View File

@ -0,0 +1,133 @@
import React, { useState, useEffect } from "react";
import { loadStripe } from "@stripe/stripe-js";
import { Box, Label, Button, Flex, Radio, Text } from "theme-ui";
import { useLocation, useHistory } from "react-router-dom";
import Modal from "../components/Modal";
import LoadingOverlay from "../components/LoadingOverlay";
import Banner from "../components/Banner";
const skus = [
{ sku: "sku_H6DhHS1MimRPR9", price: "$5.00 AUD", name: "Small" },
{ sku: "sku_H6DhiQfHUkYUKd", price: "$15.00 AUD", name: "Medium" },
{ sku: "sku_H6DhbO2oUn9Sda", price: "$30.00 AUD", name: "Large" },
];
function DonationModal({ isOpen, onRequestClose }) {
// Handle callback from stripe
const location = useLocation();
const history = useHistory();
const query = new URLSearchParams(location.search);
const hasDonated = query.has("donated");
const showDonationForm = isOpen || query.get("donated") === "false";
const [loading, setLoading] = useState(showDonationForm);
const [error, setError] = useState(null);
const [stripe, setStripe] = useState();
useEffect(() => {
if (showDonationForm) {
loadStripe("pk_live_MJjzi5djj524Y7h3fL5PNh4e00a852XD51")
.then((stripe) => {
setStripe(stripe);
setLoading(false);
})
.catch((err) => {
setError(err.message);
setLoading(false);
});
}
}, [showDonationForm]);
function handleClose() {
if (hasDonated) {
history.push(location.pathname);
}
onRequestClose();
}
function handleSubmit(event) {
event.preventDefault();
if (!stripe) {
return;
}
setLoading(true);
stripe
.redirectToCheckout({
items: [{ sku: selectedSku, quantity: 1 }],
successUrl: `${window.location.href}?donated=true`,
cancelUrl: `${window.location.href}?donated=false`,
submitType: "donate",
})
.then((response) => {
setLoading(false);
if (response.error) {
setError(response.error.message);
}
});
}
const [selectedSku, setSelectedSku] = useState("sku_H6DhiQfHUkYUKd");
function handleSkuChange(event) {
setSelectedSku(event.target.value);
}
const donationSuccessful = (
<Box>
<Text my={2} variant="heading" as="h1" sx={{ fontSize: 3 }}>
Thanks for donating! ʕʔ
</Text>
</Box>
);
const donationForm = (
<Box as="form" onSubmit={handleSubmit}>
<Label py={2}>Support us with a donation</Label>
<Text as="p" mb={2} variant="caption">
One time donation
</Text>
{skus.map((sku) => (
<Label key={sku.sku}>
<Radio
name="donation"
checked={selectedSku === sku.sku}
value={sku.sku}
onChange={handleSkuChange}
/>
{sku.name} - {sku.price}
</Label>
))}
<Flex mt={3}>
<Button sx={{ flexGrow: 1 }} disabled={!stripe || loading}>
Donate
</Button>
</Flex>
</Box>
);
return (
<Modal isOpen={isOpen || hasDonated} onRequestClose={handleClose}>
<Flex
sx={{
flexDirection: "column",
justifyContent: "center",
maxWidth: "300px",
flexGrow: 1,
}}
m={2}
>
{query.get("donated") === "true" ? donationSuccessful : donationForm}
{loading && <LoadingOverlay />}
<Banner isOpen={!!error} onRequestClose={() => setError(null)}>
<Box p={1}>
<Text as="p" variant="body2">
{error}
</Text>
</Box>
</Banner>
</Flex>
</Modal>
);
}
export default DonationModal;

View File

@ -1,10 +1,11 @@
import React, { useState, useEffect, useContext } from "react";
import { Flex, Button, Image, Text } from "theme-ui";
import { Flex, Button, Image, Text, Box } from "theme-ui";
import Footer from "../components/Footer";
import StartModal from "../modals/StartModal";
import JoinModal from "../modals/JoinModal";
import DonateModal from "../modals/DonationModal";
import AuthContext from "../contexts/AuthContext";
@ -13,6 +14,7 @@ import owlington from "../images/Owlington.png";
function Home() {
const [isStartModalOpen, setIsStartModalOpen] = useState(false);
const [isJoinModalOpen, setIsJoinModalOpen] = useState(false);
const [isDonateModalOpen, setIsDonateModalOpen] = useState(false);
// Reset password on visiting home
const { setPassword } = useContext(AuthContext);
@ -51,6 +53,14 @@ function Home() {
<Text variant="caption" as="p" sx={{ textAlign: "center" }}>
Alpha v0.10.2
</Text>
<Button
m={2}
onClick={() => setIsDonateModalOpen(true)}
variant="secondary"
>
Support Us
</Button>
<JoinModal
isOpen={isJoinModalOpen}
onRequestClose={() => setIsJoinModalOpen(false)}
@ -59,6 +69,10 @@ function Home() {
isOpen={isStartModalOpen}
onRequestClose={() => setIsStartModalOpen(false)}
/>
<DonateModal
isOpen={isDonateModalOpen}
onRequestClose={() => setIsDonateModalOpen(false)}
/>
</Flex>
<Footer />
</Flex>

View File

@ -1408,6 +1408,11 @@
resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz#5405ee8e444ed212db44e79351f0c70a582aae25"
integrity sha512-DetpxZw1fzPD5xUBrIAoplLChO2VB8DlL5Gg+I1IR9b2wPqYIca2WSUxL5g1vLeR4MsQq1NeWriXAVffV+U1Fw==
"@stripe/stripe-js@^1.3.2":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@stripe/stripe-js/-/stripe-js-1.3.2.tgz#ddd9a34f732604909e0362b8b31d5584c5c8387a"
integrity sha512-m8WogAMX0EzGRfKhuXTTTxfet8G+UozoCs6gEhGlzvDIhteQUuuuESzWEhlEAlEJXJCa1l6qqa20uWR4jqCl3g==
"@styled-system/background@^5.1.2":
version "5.1.2"
resolved "https://registry.yarnpkg.com/@styled-system/background/-/background-5.1.2.tgz#75c63d06b497ab372b70186c0bf608d62847a2ba"