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.

102 lines
3.1 KiB
JavaScript

import router from 'next/router'
import {DateTime} from 'luxon'
import AdminToolbar from '~/components/admin/actionBar'
import Table from '~/components/table'
UserDetails.getInitialProps = async ({ctx: {axios, query: {uuid}}}) => {
const {data: user} = await axios.get(`/api/users/${uuid}`)
const {data: orders} = await axios.get(`/api/users/${uuid}/orders`)
return {user, orders: orders.sort(sortOrders)}
}
export default function UserDetails({user, orders}) {
return (
<>
<AdminToolbar title={`User Details: ${user.email}`}/>
<h3>User details</h3>
<div style={{maxWidth: 700, margin: '0 auto'}}>
<p><strong>Registered:</strong> {DateTime.fromISO(user.time_registered).toLocal().toFormat('LLLL dd, h:mm a')}</p>
<p><strong>Email:</strong> {user.email}</p>
<p><strong>Password:</strong> {!user.password_hash ? 'Unset' : <>Set.</>}</p>
</div>
<h3>Their Orders</h3>
<Table
columns={[
{name: 'Purchased', extractor: getPurchaseTime},
{name: 'Items', extractor: getNumberItems},
{name: 'Item Price', extractor: getItemPrice},
{name: 'Shipping', extractor: getShippingEstimate},
{name: 'Total', extractor: getAmountPaid},
{name: '', extractor: order =>
<button className="buttonLink" onClick={() => router.push(`/admin/orders/${order.uuid}`)}>Details</button>
}
]}
rows={orders}
/>
</>
)
}
function getPurchaseTime(order){
const mostRecentTransaction = order.transactions.sort(sortTransactions)[0]
const time = parsePaymentTime(mostRecentTransaction)
return time.setZone('local').toFormat('LLLL dd, h:mm a')
}
function getNumberItems(order){
return order.transactions.map(transaction =>
transaction.cart.items.map(item => item.count)
).reduce((a,b)=>(a+b))
}
function getItemPrice(order){
return formatMoney(order.transactions.map(transaction => transaction.item_total_price)
.reduce((a,b)=>(a+b)))
}
function getShippingEstimate(order){
return formatMoney(order.transactions.map(transaction => transaction.shipping_price)
.reduce((a,b)=>(a+b)))
}
function getAmountPaid(order){
return formatMoney(order.transactions.map(({payments}) => payments.map(payment => payment.value_cents))
.flat()
.reduce((a,b)=>(a+b)))
}
function parsePaymentTime({payments}){
for(const payment of payments) {
if(typeof payment.time === 'string')
payment.time = DateTime.fromISO(payment.time)
}
payments.sort((a,b) => b.time.diff(a.time))
return payments[0].time
}
function sortTransactions(a,b){
const timeA = parsePaymentTime(a)
const timeB = parsePaymentTime(b)
return timeB.diff(timeA).as('seconds')
}
function sortOrders(a,b){
const timePaidA = parsePaymentTime(a.transactions.sort(sortTransactions)[0])
const timePaidB = parsePaymentTime(b.transactions.sort(sortTransactions)[0])
return timePaidB.diff(timePaidA).as('seconds')
}
const formatMoney = money => {
if (money === undefined || money === null) return null;
return '$' + (money / 100).toFixed(2)
}