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.

159 lines
4.5 KiB
JavaScript

import React, {useMemo} from 'react'
import {DateTime} from 'luxon'
import Link from 'next/link'
import styles from './style.module.css'
export default function OrderSummary({order, isAdmin}) {
const items = useMemo(() => coalesceItems(order), [order])
const totalShipping = useMemo(() => sumShippingPrice(order), [order])
return (
<>
<section className={styles.summaryRow}>
{items.length && (
<div className={styles.summaryRowSection}>
<h3>Contents:</h3>
<section>
<ul>
{items.map(({count, item}) => (
<li key={item.uuid}>{count}x - {item.name}</li>
))}
</ul>
</section>
</div>
)}
{order.address && (
<div className={styles.summaryRowSection}>
<h3>Address:</h3>
<section>
<pre>
{order.address.name || order.address.company}<br/>
{order.address.street1}<br/>
{order.address.street2 && (<>{order.address.street2}<br/></>)}
{order.address.city}, {order.address.state}, {order.address.zip}<br/>
{order.address.country !== 'US' && order.address.country}
</pre>
</section>
</div>
)}
<div className={styles.summaryRowSection}>
<h3>Shipping:</h3>
<section>
<ShippingStatus order={order} totalShipping={totalShipping} delivery={order.delivery} isAdmin={isAdmin}/>
</section>
</div>
</section>
</>
)
}
function coalesceItems(order) {
const {transactions} = order
let items = {}
for(const trans of transactions)
for(const {count, item} of trans.cart.items) {
if(!items[item.uuid])
items[item.uuid] = {
count, item
}
else
items[item.uuid].count += count
}
return Object.values(items)
}
function sumShippingPrice(order) {
return order.transactions.map(trans => trans.shipping_price).reduce((a,b) => (b+a), 0)
}
const formatMoney = money => {
if (money === undefined || money === null) return null;
return '$' + (money / 100).toFixed(2)
}
function formatTime(time){
return DateTime.fromISO(time).setZone('local').toFormat('LLLL dd')
}
function ShippingStatus({order, totalShipping, delivery, isAdmin}) {
const preorderDates = order.transactions.filter(t => t.has_preorder).map(t => DateTime.fromISO(t.preorder_fulfill_date))
preorderDates.sort((b, a) => a < b ? -1 : a > b ? 1 : 0)
const latestPreorder = preorderDates[0]?.toLocaleString(DateTime.DATE_FULL)
if(!delivery && latestPreorder)
return (
<>
{isAdmin && (<p>{formatMoney(totalShipping)} charged to customer</p>)}
<p>Preorder - awaiting stock.</p>
<p>Expected to be in stock {latestPreorder}</p>
</>
)
if(!delivery)
return (
<>
{isAdmin && (<p>{formatMoney(totalShipping)} charged to customer</p>)}
<p>Not yet shipped</p>
</>
)
switch (delivery.type) {
case 'easypost':
case 'hand_shipped':
return (
<>
{isAdmin && (
<p>
{formatMoney(totalShipping)} charged to customer<br/>
{(delivery.price_cents && !delivery.easypost) && (<>{formatMoney(parseInt(delivery.price_cents, 10))} paid to ship<br/></>)}
{delivery.easypost && (<>{formatMoney(parseFloat(delivery.easypost.selected_rate.rate) * 100)} paid to EasyPost</>)}
</p>
)}
<p>
Shipped
{isAdmin && delivery.type === 'hand_shipped' && ' by hand '}
{' '} on {formatTime(delivery.date_shipped)}
</p>
<p>
Tracking number:<br/>
<a href={`https://tools.usps.com/go/TrackConfirmAction?tLabels=${delivery.tracking_number}`}>{delivery.tracking_number}</a>
</p>
4 years ago
{isAdmin && delivery.type === 'easypost' && (
<p>
<Link href={`/admin/orders/${order.uuid}/label`}><a>View/print shipping label</a></Link>
</p>
)}
</>
)
case 'hand_delivered':
return (
<>
<p>Delivered {isAdmin && ' in person '} on {formatTime(delivery.date_delivered)}</p>
{isAdmin && (
<>
<h4>Note:</h4>
<pre>
{delivery.description}
</pre>
</>
)}
</>
)
default:
return <p>Error displaying shipment information</p>
}
}