Preorder - Admin UI for setting pre-order fields on an item

main
Ashelyn Dawn 3 years ago
parent be32530b40
commit bfddebfe23

@ -90,3 +90,19 @@ router.post('/:uuid/unpublish', ensureAdmin, async (req, res) => {
const item = await db.item.unpublish(req.params.uuid)
res.json(item)
})
router.get('/:uuid/preorder/count', ensureAdmin, async (req, res) => {
const count = await db.item.getPreorderCount(req.params.uuid);
res.json(count)
})
router.post('/:uuid/preorder', ensureAdmin, parseJSON, async (req, res) => {
const item = await db.item.setPreorder(
req.params.uuid,
req.body.availability_date,
req.body.preorder_maximum
)
res.json(item);
})

@ -86,7 +86,7 @@ export const FormController = function FormController({children, className, url,
// Update initial state
React.Children.forEach(children, child => {
if(!child.props.name) return;
if(!child?.props?.name) return;
initialState.fields[child.props.name] = {
name: child.props.name,
@ -149,6 +149,8 @@ export const FormController = function FormController({children, className, url,
// Map children
const _children = React.Children.map(children, child => {
if(!child) return null;
if(child.type === Button && child.props.type?.toLowerCase() === 'submit')
return React.cloneElement(child, {
// Allow enabled prop to disable, but not solely enable

@ -22,6 +22,8 @@ module.exports = [{
'price_cents',
'published',
'number_in_stock',
'preorder_availability_date',
'preorder_maximum',
'hs_tariff_number',
'customs_description',
'customs_origin_country',

@ -52,7 +52,7 @@ item.findBySlug = async (item_slug) => {
return joinjs.map(rows, mappings, 'itemMap', 'item_')[0];
}
item.create = async (name, urlslug, description, price_cents, published, hs_tariff_number, customs_description, origin_country, weight) =>
item.create = async (name, urlslug, description, price_cents, published, hs_tariff_number, customs_description, origin_country, weight) =>
dbUtil.executeFunction({
name: 'create_item',
params: [
@ -89,6 +89,21 @@ item.update = async (uuid, name, urlslug, description, price_cents, published) =
return joinjs.map(rows, mappings, 'itemMap', 'item_')[0]
}
item.setPreorder = (uuid, estimated_delivery, max_preorders) =>
dbUtil.executeFunction({
name: 'set_preorder',
params: [uuid, estimated_delivery, max_preorders],
returnType: 'item',
single: true
})
item.getPreorderCount = (uuid) =>
dbUtil.executeFunction({
name: 'get_number_of_preorder_reservations',
params: [uuid],
returnType: 'raw'
})
item.addImage = async (item_uuid, image_buffer, uploader_uuid) => {
// Default param chain: output as png
const source = sharp(image_buffer).png()

@ -1336,4 +1336,44 @@ begin
);
return query select * from sos.v_config;
end; $function$;
create or replace function sos.get_number_of_preorder_reservations(_item_uuid uuid)
returns integer
language plpgsql
as $function$
begin
return (
select
count(*)
from sos.item_stockchange_preorder
left join sos.item_stockchange
on item_stockchange.stockchange_uuid = item_stockchange_preorder.stockchange_uuid
where stockchange_preorder_ready_to_ship = false
and stockchange_item_uuid = _item_uuid
);
end; $function$;
create or replace function sos.set_preorder(_item_uuid uuid, _estimated_delivery timestamptz, _max_preorders integer)
returns setof sos.v_item
language plpgsql
as $function$
declare
_num_reserved integer := sos.get_number_of_preorder_reservations(_item_uuid);
begin
if _num_reserved > _max_preorders then
raise 'Cannot lower preorder limit past the number of reservations';
end if;
update sos.item
set (
item_preorder_availability_date,
item_preorder_maximum
) = (
_estimated_delivery,
_max_preorders
)
where item_uuid = _item_uuid;
return query select * from sos.v_item where item_uuid = _item_uuid;
end; $function$;

@ -12,6 +12,9 @@ util.executeQuery = async function({query, returnType, tablePrefix, single = fal
const {rows} = await pg.query(query)
if(returnType === 'raw')
return rows
const mappedObjs = joinjs.map(rows, mappings, returnType + 'Map', tablePrefix || (returnType + '_'))
if(single)
@ -27,5 +30,10 @@ util.executeFunction = async function({name, params, returnType, single, tablePr
values: params
}
return util.executeQuery({query, returnType, single, tablePrefix})
const result = await util.executeQuery({query, returnType, single, tablePrefix})
if(returnType === 'raw' && result[0][name] !== undefined)
return result[0][name]
return result
}

@ -27,6 +27,11 @@ export default function EditItem({item}) {
return (
<>
<ActionBar title={`Editing "${item.name}"`}>
{
item.preorder_availability_date
? <RMWCButton outlined onClick={()=>router.push(`/admin/items/${item.urlslug}/preorder`)}>Edit Pre-order</RMWCButton>
: <RMWCButton outlined onClick={()=>router.push(`/admin/items/${item.urlslug}/preorder`)}>Set Pre-order</RMWCButton>
}
<RMWCButton outlined onClick={()=>router.push(`/admin/items/${item.urlslug}/images`)}>Edit Images ({item.images.length})</RMWCButton>
</ActionBar>
<FormController url={`/api/items/${item.uuid}`} afterSubmit={afterUpdate}>

@ -0,0 +1,50 @@
import React from 'react'
import router from 'next/router'
import axios from 'axios'
import ActionBar from '~/components/admin/actionBar'
import {Button as RMWCButton} from '@rmwc/button'
import {FormController, IntegerInput, Button, DateInput} from '~/components/form'
EditItem.getInitialProps = async ({ctx: {axios, query: {slug}}}) => {
const {data: item} = await axios.get(`/api/items/by-slug/${slug}`)
const {data: numPreorders} = await axios.get(`/api/items/${item.uuid}/preorder/count`)
return {item, numPreorders}
}
export default function EditItem({item, numPreorders}) {
const minimum = Math.max(numPreorders, 1)
const initial = Math.max(minimum, item.preorder_maximum);
const afterUpdate = () => {
router.push(`/admin/items/${item.urlslug}`)
}
const deletePreorder = async () => {
await axios.post(`/api/items/${item.uuid}/preorder`, {availability_date: null, preorder_maximum: null})
router.push(`/admin/items/${item.urlslug}`)
}
return (
<>
{
item.preorder_availability_date
? <ActionBar title={`Updating pre-order for "${item.name}"`}>
{numPreorders < 1 &&
<RMWCButton outlined onClick={deletePreorder}>Remove pre-order</RMWCButton>
}
</ActionBar>
: <ActionBar title={`Adding pre-order for "${item.name}"`}/>
}
<FormController url={`/api/items/${item.uuid}/preorder`} afterSubmit={afterUpdate}>
<DateInput label="Estimated Delivery" initialValue={item.preorder_availability_date} minDate={new Date()} name="availability_date" />
<IntegerInput label="Max pre-orders" initialValue={initial.toFixed(0)} name="preorder_maximum" minimum={minimum.toFixed(0)} validate={i => i > 0} />
{item.preorder_availability_date &&
<p>There are currently {numPreorders} pre-orders for this item</p>
}
<Button type="submit">Create</Button>
</FormController>
</>
)
}
Loading…
Cancel
Save