Create fulfillment page

This commit is contained in:
dominik-zeglen 2020-04-20 18:23:54 +02:00
parent 9812277e9a
commit a5c1c9d544
2 changed files with 91 additions and 27 deletions

View file

@ -1,20 +1,19 @@
import React from "react"; import React from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import Card from "@material-ui/core/Card"; import Card from "@material-ui/core/Card";
import Typography from "@material-ui/core/Typography"; import CardActions from "@material-ui/core/CardActions";
import TableBody from "@material-ui/core/TableBody"; import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell"; import TableCell from "@material-ui/core/TableCell";
import TableHead from "@material-ui/core/TableHead"; import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow"; import TableRow from "@material-ui/core/TableRow";
import TextField from "@material-ui/core/TextField"; import TextField from "@material-ui/core/TextField";
import classNames from "classnames"; import classNames from "classnames";
import Typography from "@material-ui/core/Typography";
import useFormset, { FormsetData } from "@saleor/hooks/useFormset"; import useFormset, { FormsetData } from "@saleor/hooks/useFormset";
import { StockInput } from "@saleor/types/globalTypes"; import { StockInput } from "@saleor/types/globalTypes";
import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment"; import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment";
import TableCellAvatar, { import TableCellAvatar from "@saleor/components/TableCellAvatar";
AVATAR_MARGIN
} from "@saleor/components/TableCellAvatar";
import Container from "@saleor/components/Container"; import Container from "@saleor/components/Container";
import PageHeader from "@saleor/components/PageHeader"; import PageHeader from "@saleor/components/PageHeader";
import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SaveButtonBar from "@saleor/components/SaveButtonBar";
@ -24,18 +23,21 @@ import { OrderFulfillData_order } from "@saleor/orders/types/OrderFulfillData";
import CardTitle from "@saleor/components/CardTitle"; import CardTitle from "@saleor/components/CardTitle";
import ResponsiveTable from "@saleor/components/ResponsiveTable"; import ResponsiveTable from "@saleor/components/ResponsiveTable";
import makeStyles from "@material-ui/core/styles/makeStyles"; import makeStyles from "@material-ui/core/styles/makeStyles";
import { update } from "@saleor/utils/lists";
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
const useStyles = makeStyles( const useStyles = makeStyles(
theme => ({ theme => ({
actionBar: {
flexDirection: "row",
paddingLeft: theme.spacing(2) + 2
},
colName: { colName: {
width: 300 width: 300
}, },
colNameLabel: {
marginLeft: AVATAR_MARGIN
},
colQuantity: { colQuantity: {
textAlign: "right", textAlign: "right",
width: 200 width: 210
}, },
colQuantityContent: { colQuantityContent: {
alignItems: "center", alignItems: "center",
@ -52,12 +54,17 @@ const useStyles = makeStyles(
error: { error: {
color: theme.palette.error.main color: theme.palette.error.main
}, },
full: {
fontWeight: 600
},
quantityInnerInput: {
padding: "16px 0 14px 12px"
},
quantityInput: { quantityInput: {
width: "4rem" width: 100
}, },
remainingQuantity: { remainingQuantity: {
marginLeft: theme.spacing(), marginLeft: theme.spacing()
paddingTop: 14
}, },
table: { table: {
"&&": { "&&": {
@ -98,7 +105,10 @@ const OrderFulfillPage: React.FC<OrderFulfillPageProps> = ({
const intl = useIntl(); const intl = useIntl();
const classes = useStyles({}); const classes = useStyles({});
const { change, data: formsetData } = useFormset<null, StockInput[]>( const { change: formsetChange, data: formsetData } = useFormset<
null,
StockInput[]
>(
order?.lines.map(line => ({ order?.lines.map(line => ({
data: null, data: null,
id: line.id, id: line.id,
@ -149,9 +159,7 @@ const OrderFulfillPage: React.FC<OrderFulfillPageProps> = ({
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell className={classes.colName}> <TableCell className={classes.colName}>
<span className={classes.colNameLabel}> <FormattedMessage defaultMessage="Product name" />
<FormattedMessage defaultMessage="Product name" />
</span>
</TableCell> </TableCell>
<TableCell className={classes.colSku}> <TableCell className={classes.colSku}>
<FormattedMessage <FormattedMessage
@ -179,6 +187,14 @@ const OrderFulfillPage: React.FC<OrderFulfillPageProps> = ({
{order?.lines.map((line, lineIndex) => { {order?.lines.map((line, lineIndex) => {
const remainingQuantity = const remainingQuantity =
line.quantity - line.quantityFulfilled; line.quantity - line.quantityFulfilled;
const quantityToFulfill = formsetData[
lineIndex
].value.reduce(
(quantityToFulfill, lineInput) =>
quantityToFulfill + lineInput.quantity,
0
);
const overfulfill = remainingQuantity < quantityToFulfill;
return ( return (
<TableRow key={line.id}> <TableRow key={line.id}>
@ -187,6 +203,15 @@ const OrderFulfillPage: React.FC<OrderFulfillPageProps> = ({
thumbnail={line?.thumbnail?.url} thumbnail={line?.thumbnail?.url}
> >
{line.productName} {line.productName}
<Typography color="textSecondary" variant="caption">
{line.variant.attributes
.map(attribute =>
attribute.values
.map(attributeValue => attributeValue.name)
.join(", ")
)
.join(" / ")}
</Typography>
</TableCellAvatar> </TableCellAvatar>
<TableCell className={classes.colSku}> <TableCell className={classes.colSku}>
{line.variant.sku} {line.variant.sku}
@ -195,6 +220,10 @@ const OrderFulfillPage: React.FC<OrderFulfillPageProps> = ({
const warehouseStock = line.variant.stocks.find( const warehouseStock = line.variant.stocks.find(
stock => stock.warehouse.id === warehouse.id stock => stock.warehouse.id === warehouse.id
); );
const formsetStock = formsetData[
lineIndex
].value.find(line => line.warehouse === warehouse.id);
if (!warehouseStock) { if (!warehouseStock) {
return ( return (
<TableCell <TableCell
@ -217,19 +246,32 @@ const OrderFulfillPage: React.FC<OrderFulfillPageProps> = ({
<TextField <TextField
type="number" type="number"
inputProps={{ inputProps={{
className: classes.quantityInnerInput,
max: warehouseStock.quantity, max: warehouseStock.quantity,
min: 0,
style: { textAlign: "right" } style: { textAlign: "right" }
}} }}
className={classes.quantityInput} className={classes.quantityInput}
value={ value={formsetStock.quantity}
formsetData[lineIndex].value[0].quantity onChange={event =>
formsetChange(
line.id,
update(
{
quantity: parseInt(
event.target.value,
10
),
warehouse: warehouse.id
},
formsetData[lineIndex].value,
(a, b) => a.warehouse === b.warehouse
)
)
} }
onChange={event => undefined}
error={ error={
remainingQuantity < overfulfill ||
formsetData[lineIndex].value[0] formsetStock.quantity >
.quantity ||
formsetData[lineIndex].value[0].quantity >
warehouseStock.quantity warehouseStock.quantity
} }
/> />
@ -241,10 +283,15 @@ const OrderFulfillPage: React.FC<OrderFulfillPageProps> = ({
); );
})} })}
<TableCell className={classes.colQuantityTotal}> <TableCell className={classes.colQuantityTotal}>
{formsetData[lineIndex].value.reduce( <span
(acc, stock) => acc + stock.quantity, className={classNames({
0 [classes.error]: overfulfill,
)}{" "} [classes.full]:
remainingQuantity <= quantityToFulfill
})}
>
{quantityToFulfill}
</span>{" "}
/ {remainingQuantity} / {remainingQuantity}
</TableCell> </TableCell>
</TableRow> </TableRow>
@ -252,9 +299,26 @@ const OrderFulfillPage: React.FC<OrderFulfillPageProps> = ({
})} })}
</TableBody> </TableBody>
</ResponsiveTable> </ResponsiveTable>
<CardActions className={classes.actionBar}>
<ControlledCheckbox
checked={data.sendInfo}
label={intl.formatMessage({
defaultMessage: "Send shipment details to customer",
description: "checkbox"
})}
name="sendInfo"
onChange={change}
/>
</CardActions>
</Card> </Card>
<SaveButtonBar <SaveButtonBar
disabled={disabled} disabled={disabled}
labels={{
save: intl.formatMessage({
defaultMessage: "Fulfill",
description: "fulfill order, button"
})
}}
state={saveButtonBar} state={saveButtonBar}
onSave={submit} onSave={submit}
onCancel={onBack} onCancel={onBack}

View file

@ -54,7 +54,7 @@ const useStyles = makeStyles(
width: 120 width: 120
}, },
quantityInput: { quantityInput: {
width: "4rem" width: 100
}, },
remainingQuantity: { remainingQuantity: {
marginLeft: theme.spacing(), marginLeft: theme.spacing(),