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.
86 lines
3.1 KiB
JavaScript
86 lines
3.1 KiB
JavaScript
4 years ago
|
import React, {useReducer} from 'react'
|
||
|
import Router from 'next/router'
|
||
|
import axios from 'axios'
|
||
|
import ActionBar from '~/components/admin/actionBar'
|
||
|
import Table from '~/components/table'
|
||
|
import {Button} from '~/components/form'
|
||
|
|
||
|
ManualOrder.getInitialProps = async ({ctx}) => {
|
||
|
const {data: items} = await ctx.axios.get('/api/items?showUnpublished=true')
|
||
|
return {items}
|
||
|
}
|
||
|
|
||
|
export default function ManualOrder({items}) {
|
||
|
const [itemState, dispatch] = useReducer(itemCountReducer, {})
|
||
|
const totalNumber = Object.values(itemState).reduce((a,b) => (b+a), 0)
|
||
|
|
||
|
const add = (item) => () => dispatch({type: 'add', item: item.uuid})
|
||
|
const subtract = (item) => () => dispatch({type: 'subtract', item: item.uuid})
|
||
|
const remove = (item) => () => dispatch({type: 'remove', item: item.uuid})
|
||
|
const clear = () => dispatch({type: 'clear'})
|
||
|
|
||
|
async function createOrder(){
|
||
|
const items = Object.keys(itemState)
|
||
|
.map(uuid => ({ uuid, count: itemState[uuid] }))
|
||
|
|
||
|
const {data: order} = await axios.put(`/api/orders/manual`, {items})
|
||
|
|
||
|
Router.push(`/admin/orders/new/${order.uuid}/address`)
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
<>
|
||
|
<ActionBar title="New Order" actions={[
|
||
|
{label: 'Cancel', url: `/admin/orders`}
|
||
|
]}/>
|
||
|
<Table
|
||
|
columns={[
|
||
|
{name: 'Name', extractor: item => item.name},
|
||
|
{name: 'Price', extractor: item => `$${(item.price_cents / 100).toFixed(2)}`},
|
||
|
{name: 'Number in stock', extractor: item => item.number_in_stock},
|
||
|
{name: 'Number in order', extractor: item => (
|
||
|
<span style={{display: 'flex', flexDirection: 'row', width: 120, justifyContent: 'space-between', alignItems: 'center'}}>
|
||
|
<Button enabled={itemState[item.uuid] > 0} style={{width: 30}} onClick={subtract(item)}>-</Button>
|
||
|
{itemState[item.uuid] || 0}
|
||
|
<Button enabled={(itemState[item.uuid] || 0) < item.number_in_stock} style={{width: 30}} onClick={add(item)}>+</Button>
|
||
|
</span>
|
||
|
)},
|
||
|
{name: 'Actions', extractor: item => (
|
||
|
<span>
|
||
|
<button className="buttonLink" onClick={remove(item)}>Remove all</button>
|
||
|
</span>
|
||
|
)}
|
||
|
]}
|
||
|
// Map in an id property so the table can use array.map
|
||
|
rows={items.map(item => ({id: item.uuid, ...item}))}
|
||
|
/>
|
||
|
<p style={{textAlign: 'center'}}>
|
||
|
<button className="buttonLink" onClick={clear}>Reset order</button>
|
||
|
</p>
|
||
|
<p style={{maxWidth: 400, margin: '0 auto'}}>
|
||
|
<Button enabled={totalNumber > 0} onClick={createOrder}>Create Order</Button>
|
||
|
</p>
|
||
|
</>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
function itemCountReducer(state, action) {
|
||
|
switch(action.type) {
|
||
|
case 'add':
|
||
|
if (state[action.item])
|
||
|
return {...state, [action.item]: state[action.item] + 1}
|
||
|
else
|
||
|
return {...state, [action.item]: 1}
|
||
|
case 'subtract':
|
||
|
if (state[action.item])
|
||
|
return {...state, [action.item]: state[action.item] - 1}
|
||
|
else
|
||
|
return state
|
||
|
case 'remove':
|
||
|
const newState = {...state}
|
||
|
delete newState[action.item]
|
||
|
return newState;
|
||
|
case 'clear':
|
||
|
return {};
|
||
|
}
|
||
|
}
|