Skip to content

Instantly share code, notes, and snippets.

@AlbionaHoti
Created October 22, 2020 12:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AlbionaHoti/e417c1374d7539e729c06f8bcd42e3bb to your computer and use it in GitHub Desktop.
Save AlbionaHoti/e417c1374d7539e729c06f8bcd42e3bb to your computer and use it in GitHub Desktop.
e-commerce-starter
import React, { useState, useContext } from 'react';
// React context
import { CartContext, TotalContext } from '../context/Context';
import { Col, Row } from 'antd';
// Components
import { BillingDetailsFields } from '../components/BillingDetailsField';
// styled components
import styled from 'styled-components';
import axios from 'axios';
// Ant design
import { Form, Button, Typography } from 'antd';
const { Title } = Typography;
// Stripe
import { CardElement, useStripe, useElements } from '@stripe/react-stripe-js';
const iframeStyles = {
base: {
color: '#ff748c',
fontSize: '16px',
iconColor: '#ff748c',
'::placeholder': {
color: '#87bbfd',
},
border: '1px solid gray',
},
invalid: {
iconColor: '#ff748c',
color: '#ff748c',
},
complete: {
iconColor: '#ff748c',
},
};
const cardElementOpts = {
iconStyle: 'solid',
style: iframeStyles,
hidePostalCode: true,
};
const CardElementContainer = styled.div`
height: 40px;
display: flex;
align-items: center;
& .StripeElement {
width: 100%;
padding: 15px;
}
`;
const CheckoutForm = () => {
const [form] = Form.useForm();
const [cart, setCart] = useContext(CartContext);
const [isProcessing, setProcessingTo] = useState(false);
const stripe = useStripe();
const elements = useElements();
console.log('stripe');
const [totalPrice, settotalPrice] = useContext(TotalContext);
const [checkoutError, setCheckoutError] = useState();
const [checkoutSuccess, setCheckoutSuccess] = useState();
const handleCardDetailsChange = (ev) => {
ev.error ? setCheckoutError(ev.error.message) : setCheckoutError();
};
const handleSubmit = async (e) => {
// e.preventDefault();
const billingDetails = {
name: e.name,
email: e.email,
address: {
city: e.city,
state: e.state,
postal_code: e.zip,
},
};
setProcessingTo(true);
const cardElement = elements.getElement('card');
try {
const { data: clientSecret } = await axios.post(
'/api/payment_intents',
{
amount: totalPrice * 100,
},
);
const paymentMethodReq = await stripe.createPaymentMethod({
type: 'card',
card: cardElement,
billing_details: billingDetails,
});
if (paymentMethodReq.error) {
setCheckoutError(paymentMethodReq.error.message);
setProcessingTo(false);
return;
}
const {
error,
paymentIntent: { status },
} = await stripe.confirmCardPayment(clientSecret, {
payment_method: paymentMethodReq.paymentMethod.id,
});
if (error) {
setCheckoutError(error.message);
return;
}
if (status === 'succeeded') {
setCheckoutSuccess(true);
setCart([]);
settotalPrice(0);
}
} catch (err) {
setCheckoutError(err.message);
}
};
if (checkoutSuccess)
return <Title level={4}>Payment was successfull!</Title>;
return (
<>
<Row>
<Col
xs={{ span: 10, offset: 4 }}
lg={{ span: 10, offset: 6 }}
span={24}
>
<Form
form={form}
name="checkout"
onFinish={handleSubmit}
scrollToFirstError
>
<BillingDetailsFields />
<CardElementContainer>
<CardElement
options={cardElementOpts}
onChange={handleCardDetailsChange}
/>
</CardElementContainer>{' '}
{checkoutError && (
<span style={{ color: 'red' }}>{checkoutError}</span>
)}
<br />
<Form.Item>
<Button
type="primary"
htmlType="submit"
disabled={isProcessing || !stripe}
>
{isProcessing ? 'Processing...' : `Pay $${totalPrice}`}
</Button>
</Form.Item>
</Form>
</Col>
</Row>
</>
);
};
export default CheckoutForm;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment