Admin order list

main
Ashelyn Dawn 5 years ago
parent d0b5b67025
commit ee4f291db2

@ -0,0 +1,15 @@
module.exports = async (req, res) => {
if(!req.user) {
const err = new Error('Unauthorized')
err.status = 401
throw err;
}
if(!req.user.is_admin) {
const err = new Error('Forbidden')
err.status = 401
throw err;
}
return 'next'
}

@ -2,6 +2,7 @@ const router = module.exports = require('express-promise-router')()
const parseJSON = require('body-parser').json() const parseJSON = require('body-parser').json()
const db = require('../db') const db = require('../db')
const stripe = require('stripe')(process.env.STRIPE_PRIVATE_KEY); const stripe = require('stripe')(process.env.STRIPE_PRIVATE_KEY);
const ensureAdmin = require('./middleware/ensureAdmin')
const validate = require('./middleware/validators') const validate = require('./middleware/validators')
@ -13,6 +14,16 @@ router.get('/', async (req, res) => {
return res.json(await db.order.findAllForSession(req.session.uuid)) return res.json(await db.order.findAllForSession(req.session.uuid))
}) })
router.get('/all', ensureAdmin, async (req, res) => {
const orders = await db.order.findAllComplete()
res.json(orders)
})
router.get('/:uuid', ensureAdmin, async (req, res) => {
const order = await db.order.findByUUID(req.params.uuid)
res.json(order)
})
router.use(require('./middleware/ensureCart')) router.use(require('./middleware/ensureCart'))
router.put('/', async (req, res) => { router.put('/', async (req, res) => {

@ -2,9 +2,12 @@ import styles from './actionBar.module.css'
export default function AdminActionBar({title, children}) { export default function AdminActionBar({title, children}) {
return ( return (
<>
<div className={styles.actionBar}> <div className={styles.actionBar}>
<h2>{title}</h2> <h2>{title}</h2>
{children} {children}
</div> </div>
<span className={styles.spacer}/>
</>
) )
} }

@ -1,10 +1,11 @@
.actionBar { .actionBar {
position: fixed;
width: 100%;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
height: 60px; height: 60px;
align-items: center; align-items: center;
margin-top: -15px; margin-top: -15px;
margin-bottom: 24px;
background: rgb(66, 66, 66); background: rgb(66, 66, 66);
color: white; color: white;
padding: 0 15px; padding: 0 15px;
@ -24,3 +25,9 @@
.actionBar button:global(.mdc-button--outlined):not(:disabled) { .actionBar button:global(.mdc-button--outlined):not(:disabled) {
border-color: rgba(255,255,255,.44); border-color: rgba(255,255,255,.44);
} }
.spacer {
display: block;
height: 60px;
margin-bottom: 24px;
}

@ -57,6 +57,24 @@ order.findForTransaction = transaction_uuid =>
single: true single: true
}) })
// TODO: Perhaps pagination?
order.findAllComplete = () =>
dbUtil.executeQuery({
query: 'select * from sos.v_order where transaction_payment_state = \'completed\'',
returnType: 'order',
single: false
})
order.findByUUID = uuid =>
dbUtil.executeQuery({
query: {
text: 'select * from sos.v_order where order_uuid = $1',
values: [uuid]
},
returnType: 'order',
single: true
})
order.addAddress = async function (transaction, address){ order.addAddress = async function (transaction, address){
// Get parcel size // Get parcel size
const parcel = { const parcel = {

@ -0,0 +1,19 @@
import React from 'react'
import Router from 'next/router'
import ActionBar from '~/components/admin/actionBar'
import Table from '~/components/table'
import {DateTime} from 'luxon'
Order.getInitialProps = async ({ctx: {axios, query: {id}}}) => {
const {data: order} = await axios.get(`/api/orders/${id}`)
return {order}
}
export default function Order({order}){
return (
<>
<ActionBar title="Order Details"/>
<pre>{JSON.stringify(order, null, 2)}</pre>
</>
)
}

@ -0,0 +1,78 @@
import React from 'react'
import Router from 'next/router'
import ActionBar from '~/components/admin/actionBar'
import Table from '~/components/table'
import {DateTime} from 'luxon'
Orders.getInitialProps = async ({ctx}) => {
const {data: orders} = await ctx.axios.get('/api/orders/all')
return {orders}
}
export default function Orders({orders}){
return (
<>
<ActionBar title="Orders"/>
<Table
columns={[
{name: 'Purchased', extractor: getPurchaseTime},
{name: 'Items', extractor: getNumberItems},
{name: 'Price', extractor: getItemPrice},
{name: 'Shipping', extractor: getShippingEstimate},
{name: 'Amount Paid', extractor: getAmountPaid},
{name: '', extractor: row =>
<button className="buttonLink" onClick={() => Router.push(`/admin/orders/${row.id}`)}>Details</button>
}
]}
rows={orders.map(order => ({id: order.uuid, ...order}))}
/>
</>
)
}
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(({payment}) => payment.value_cents)
.reduce((a,b)=>(a+b)))
}
function parsePaymentTime({payment}){
if(typeof payment.time === 'string')
payment.time = DateTime.fromISO(payment.time)
return payment.time
}
function sortTransactions(a,b){
const timeA = parsePaymentTime(a)
const timeB = parsePaymentTime(b)
return timeB.diff(timeA).as('seconds')
}
const formatMoney = money => {
if (money === undefined || money === null) return null;
return '$' + (money / 100).toFixed(2)
}
Loading…
Cancel
Save