You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
6.8 KiB
JavaScript

import {useState, useRef} from 'react'
import Link from 'next/link'
import Router from 'next/router'
import styles from './style.module.css'
import {Input, Button} from '~/components/form'
import useUser from '~/hooks/useUser'
import axios from 'axios'
import { loadStripe } from '@stripe/stripe-js';
const stripePromise = loadStripe(process.env.STRIPE_PUBLIC_KEY);
import PaypalIcon from '../../../images/icons/paypal.svg'
// TODO: Load previous addresses
CheckoutSummary.getInitialProps = async function({ctx: {axios}}){
const {data: order} = await axios.get(`/api/orders/current`)
return {order}
}
export default function CheckoutSummary({order: _order}){
const user = useUser();
const [order, updateOrder] = useState(_order)
const currentTransaction = order
.transactions.find(transaction => (
transaction.payment_state === 'started'
))
const {item_total_price, shipping_price, tax_price, coupon_effective_discount} = currentTransaction
const {free_shipping} = currentTransaction.coupon || {}
const total_price =
(item_total_price && shipping_price && tax_price)
? item_total_price + (free_shipping ? 0 : shipping_price) + tax_price - (coupon_effective_discount || 0)
: null
const formatMoney = money => {
if (money === undefined || money === null) return null;
return '$' + (money / 100).toFixed(2)
}
// For coupon input
const couponRef = useRef()
const onCouponSubmit = async ev => {
if(ev) ev.preventDefault()
const code = couponRef.current?.value
const {data: updatedOrder} = await axios.post(`/api/orders/current/coupon`, {code})
updateOrder(updatedOrder)
}
// For Stripe checkout
const handleStripeButton = async ev => {
if(ev) ev.preventDefault()
// Create a stripe session on server
const {data: sessionId} = await axios.post('/api/orders/current/checkout/stripe')
// Allow Stripe to finish initializing
const stripe = await stripePromise;
const {error} = await stripe.redirectToCheckout({sessionId})
if(error)
alert(error.message)
}
return (
<>
<h2>Checkout</h2>
<div className={styles.checkoutSection}>
<h3>Address</h3>
<div className={styles.horizContainer}>
{
order.address
? (
<div>
<p style={{margin: 0}}>{order.address.name}</p>
<p style={{margin: 0}}>{order.address.street1}</p>
<p style={{margin: 0}}>{order.address.street2}</p>
<p style={{margin: 0}}>{order.address.city}, {order.address.state}, {order.address.zip}</p>
<p style={{marginBottom: '-20px'}}><Link href="/store/checkout/address"><a>(Edit Address)</a></Link></p>
</div>
)
: (
user
?(
<div style={{textAlign: 'center'}}>
<p>
TODO: Load previous addresses
</p>
</div>
):(
<>
<div style={{textAlign: 'center'}}>
<p>
<Link href="/login"><a>Log in</a></Link> to use your<br/>saved addresses
</p>
</div>
<span className={styles.horizDivider}>
OR
</span>
<div>
<Button style={{width: '100px'}} onClick={()=>Router.push('/store/checkout/address')}>Input Address</Button>
</div>
</>
)
)
}
</div>
</div>
<div className={styles.checkoutSection}>
<h3>Coupon (optional)</h3>
{
currentTransaction.coupon
? (
<>
<p style={{textAlign: 'center'}}>
Using coupon code: <strong>{currentTransaction.coupon.code}</strong><br/>
(
{coupon_effective_discount > 0 && `Discounting by ${formatMoney(coupon_effective_discount)}`}
{coupon_effective_discount > 0 && free_shipping && ' & '}
{free_shipping && `${coupon_effective_discount > 0 ? 'f' : 'F'}ree shipping`}
)
</p>
</>
)
: (
<div className={styles.horizContainer} style={{maxWidth:'400px', margin: '0 auto'}}>
<Input inputRef={couponRef} label="" name="coupon" />
<div style={{maxWidth: '120px', marginLeft: '8px'}}>
<Button onClick={onCouponSubmit} outline>Save Coupon</Button>
</div>
</div>
)
}
</div>
<div className={styles.checkoutSection}>
<h3>Total</h3>
<div className={styles.horizContainer}>
<div>
<table>
<tbody>
{currentTransaction.cart.items.map(({uuid, count, item}) => (
<tr key={uuid}>
<td>{item.name} {count > 1 ? `(${count})` : ''}:</td>
<td>{formatMoney(count * item.price_cents)}</td>
</tr>
))}
{coupon_effective_discount > 0 && (
<tr>
<td>Coupon:</td>
<td>- {formatMoney(coupon_effective_discount)}</td>
</tr>
)}
<tr className={free_shipping ? 'strikethrough' : undefined}>
<td>Shipping:</td>
<td>{formatMoney(shipping_price) || '-'}</td>
</tr>
{tax_price && (
<tr>
<td>Sales tax:</td>
<td>{formatMoney(tax_price)}</td>
</tr>
)}
<tr style={{fontWeight: 'bold'}}>
<td>Total:</td>
<td>{formatMoney(total_price) || '-'}</td>
</tr>
</tbody>
</table>
</div>
<div className={styles.paymentButtons}>
{
total_price
? (
<div>
<Button outline icon="credit_card" onClick={handleStripeButton}>Pay with Card</Button>
<Button outline icon={<PaypalIcon/>}>Pay with Paypal</Button>
</div>
) : (
<div style={{pointerEvents: 'none', opacity: .4}}>
<Button outline icon="credit_card">Pay with Card</Button> {/* Hit API endpoint to get Stripe session, and then redirect */}
<Button outline icon={<PaypalIcon/>}>Pay with Paypal</Button>
</div>
)
}
</div>
</div>
</div>
</>
)
}