204 lines
5.7 KiB
JavaScript
204 lines
5.7 KiB
JavaScript
import { useElements, useStripe, CardElement } from "@stripe/react-stripe-js";
|
|
import { Form, Modal, notification } from "antd";
|
|
import React, { useState, useEffect } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { connect } from "react-redux";
|
|
import { createStructuredSelector } from "reselect";
|
|
import { toggleModalVisible } from "../../redux/modals/modals.actions";
|
|
import { selectPayment } from "../../redux/modals/modals.selectors";
|
|
import {
|
|
selectBodyshop,
|
|
selectCurrentUser,
|
|
} from "../../redux/user/user.selectors";
|
|
import PaymentForm from "../payment-form/payment-form.container";
|
|
import axios from "axios";
|
|
import { useMutation } from "@apollo/react-hooks";
|
|
import { INSERT_NEW_PAYMENT } from "../../graphql/payments.queries";
|
|
import { TemplateList } from "../../utils/TemplateConstants";
|
|
import RenderTemplate, {
|
|
displayTemplateInWindow,
|
|
} from "../../utils/RenderTemplate";
|
|
import { setEmailOptions } from "../../redux/email/email.actions";
|
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
|
|
|
const mapStateToProps = createStructuredSelector({
|
|
paymentModal: selectPayment,
|
|
bodyshop: selectBodyshop,
|
|
currentUser: selectCurrentUser,
|
|
});
|
|
|
|
const mapDispatchToProps = (dispatch) => ({
|
|
setEmailOptions: (e) => dispatch(setEmailOptions(e)),
|
|
toggleModalVisible: () => dispatch(toggleModalVisible("payment")),
|
|
});
|
|
|
|
function InvoiceEnterModalContainer({
|
|
paymentModal,
|
|
toggleModalVisible,
|
|
bodyshop,
|
|
currentUser,
|
|
setEmailOptions,
|
|
}) {
|
|
const [form] = Form.useForm();
|
|
const [insertPayment] = useMutation(INSERT_NEW_PAYMENT);
|
|
const stripe = useStripe();
|
|
const elements = useElements();
|
|
const { t } = useTranslation();
|
|
const { context, actions, visible } = paymentModal;
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
const stripeStateArr = useState({
|
|
error: null,
|
|
cardComplete: false,
|
|
});
|
|
const stripeState = stripeStateArr[0];
|
|
|
|
const cardValid = !!!stripeState.error && stripeState.cardComplete;
|
|
|
|
const handleFinish = async (values) => {
|
|
const { useStripe, sendby, ...paymentObj } = values;
|
|
if (useStripe && !cardValid) return;
|
|
|
|
if ((useStripe && !stripe) || !elements) {
|
|
// Stripe.js has not yet loaded.
|
|
// Make sure to disable form submission until Stripe.js has loaded.
|
|
return;
|
|
}
|
|
|
|
setLoading(true);
|
|
|
|
try {
|
|
let stripePayment;
|
|
if (useStripe && bodyshop.stripe_acct_id) {
|
|
logImEXEvent("payment_stripe_attempt");
|
|
|
|
const secretKey = await axios.post("/stripe/payment", {
|
|
amount: Math.round(values.amount * 100),
|
|
stripe_acct_id: bodyshop.stripe_acct_id,
|
|
});
|
|
|
|
stripePayment = await stripe.confirmCardPayment(
|
|
secretKey.data.clientSecret,
|
|
{
|
|
payment_method: {
|
|
card: elements.getElement(CardElement),
|
|
billing_details: {
|
|
name: "Jenny Rosen",
|
|
},
|
|
},
|
|
}
|
|
);
|
|
console.log("handleFinish -> stripePayment", stripePayment);
|
|
|
|
if (stripePayment.paymentIntent.status === "succeeded") {
|
|
notification["success"]({ message: t("payments.successes.stripe") });
|
|
} else {
|
|
notification["error"]({ message: t("payments.errors.stripe") });
|
|
throw new Error();
|
|
}
|
|
}
|
|
logImEXEvent("payment_insert");
|
|
|
|
const newPayment = await insertPayment({
|
|
variables: {
|
|
paymentInput: {
|
|
...paymentObj,
|
|
stripeid:
|
|
stripePayment &&
|
|
stripePayment.paymentIntent &&
|
|
stripePayment.paymentIntent.id,
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!!!newPayment.errors) {
|
|
notification["success"]({ message: t("payments.successes.payment") });
|
|
} else {
|
|
notification["error"]({ message: t("payments.errors.payment") });
|
|
}
|
|
|
|
if (sendby === "email") {
|
|
setEmailOptions({
|
|
messageOptions: {
|
|
// to: appData.email,
|
|
replyTo: bodyshop.email,
|
|
},
|
|
template: {
|
|
name: TemplateList.payment_receipt.key,
|
|
variables: {
|
|
id: newPayment.data.insert_payments.returning[0].id,
|
|
},
|
|
},
|
|
});
|
|
} else {
|
|
displayTemplateInWindow(
|
|
await RenderTemplate(
|
|
{
|
|
name: TemplateList.payment_receipt.key,
|
|
variables: {
|
|
id: newPayment.data.insert_payments.returning[0].id,
|
|
},
|
|
},
|
|
bodyshop
|
|
)
|
|
);
|
|
}
|
|
|
|
if (actions.refetch) actions.refetch();
|
|
toggleModalVisible();
|
|
} catch (error) {
|
|
console.log("error", error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleCancel = () => {
|
|
toggleModalVisible();
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (visible) form.resetFields();
|
|
}, [visible, form]);
|
|
|
|
return (
|
|
<Modal
|
|
title={t("payments.labels.new")}
|
|
visible={visible}
|
|
okText={t("general.actions.save")}
|
|
onOk={() => form.submit()}
|
|
onCancel={handleCancel}
|
|
afterClose={() => form.resetFields()}
|
|
okButtonProps={{
|
|
loading: loading,
|
|
}}
|
|
destroyOnClose>
|
|
<Form
|
|
onFinish={handleFinish}
|
|
autoComplete={"off"}
|
|
form={form}
|
|
layout='vertical'
|
|
initialValues={{ jobid: context.jobId }}>
|
|
<PaymentForm form={form} stripeStateArr={stripeStateArr} />
|
|
</Form>
|
|
</Modal>
|
|
);
|
|
}
|
|
|
|
export default connect(
|
|
mapStateToProps,
|
|
mapDispatchToProps
|
|
)(InvoiceEnterModalContainer);
|
|
|
|
// const pr = stripe.paymentRequest({
|
|
// country: "CA",
|
|
// currency: "CAD",
|
|
// total: {
|
|
// label: "Demo total",
|
|
// amount: 1099,
|
|
// },
|
|
// requestPayerName: true,
|
|
// requestPayerEmail: true,
|
|
// });
|
|
// console.log("handleFinish -> pr", pr);
|