Add fulfillment view

This commit is contained in:
dominik-zeglen 2020-04-20 19:18:20 +02:00
parent a5c1c9d544
commit dca0208173
6 changed files with 87 additions and 42 deletions

View file

@ -25,6 +25,8 @@ 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 { update } from "@saleor/utils/lists";
import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
import { renderCollection } from "@saleor/misc";
import Skeleton from "@saleor/components/Skeleton";
const useStyles = makeStyles( const useStyles = makeStyles(
theme => ({ theme => ({
@ -86,7 +88,7 @@ export interface OrderFulfillPageProps {
order: OrderFulfillData_order; order: OrderFulfillData_order;
saveButtonBar: ConfirmButtonTransitionState; saveButtonBar: ConfirmButtonTransitionState;
warehouses: WarehouseFragment[]; warehouses: WarehouseFragment[];
onBack: () => undefined; onBack: () => void;
onSubmit: (data: OrderFulfillSubmitData) => void; onSubmit: (data: OrderFulfillSubmitData) => void;
} }
@ -167,7 +169,7 @@ const OrderFulfillPage: React.FC<OrderFulfillPageProps> = ({
description="product's sku" description="product's sku"
/> />
</TableCell> </TableCell>
{warehouses.map(warehouse => ( {warehouses?.map(warehouse => (
<TableCell <TableCell
key={warehouse.id} key={warehouse.id}
className={classes.colQuantity} className={classes.colQuantity}
@ -184,7 +186,29 @@ const OrderFulfillPage: React.FC<OrderFulfillPageProps> = ({
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>
{order?.lines.map((line, lineIndex) => { {renderCollection(order?.lines, (line, lineIndex) => {
if (!line) {
return (
<TableRow>
<TableCellAvatar className={classes.colName}>
<Skeleton />
</TableCellAvatar>
<TableCell className={classes.colSku}>
<Skeleton />
</TableCell>
{warehouses?.map(() => (
<TableCell className={classes.colQuantity}>
<Skeleton />
</TableCell>
))}
<TableCell className={classes.colQuantityTotal}>
{" "}
<Skeleton />
</TableCell>
</TableRow>
);
}
const remainingQuantity = const remainingQuantity =
line.quantity - line.quantityFulfilled; line.quantity - line.quantityFulfilled;
const quantityToFulfill = formsetData[ const quantityToFulfill = formsetData[
@ -216,7 +240,7 @@ const OrderFulfillPage: React.FC<OrderFulfillPageProps> = ({
<TableCell className={classes.colSku}> <TableCell className={classes.colSku}>
{line.variant.sku} {line.variant.sku}
</TableCell> </TableCell>
{warehouses.map(warehouse => { {warehouses?.map(warehouse => {
const warehouseStock = line.variant.stocks.find( const warehouseStock = line.variant.stocks.find(
stock => stock.warehouse.id === warehouse.id stock => stock.warehouse.id === warehouse.id
); );

View file

@ -14,9 +14,11 @@ import {
orderPath, orderPath,
OrderUrlQueryParams, OrderUrlQueryParams,
OrderDraftListUrlSortField, OrderDraftListUrlSortField,
OrderListUrlSortField OrderListUrlSortField,
orderFulfillPath
} from "./urls"; } from "./urls";
import OrderDetailsComponent from "./views/OrderDetails"; import OrderDetailsComponent from "./views/OrderDetails";
import OrderFulfillComponent from "./views/OrderFulfill";
import OrderDraftListComponent from "./views/OrderDraftList"; import OrderDraftListComponent from "./views/OrderDraftList";
import OrderListComponent from "./views/OrderList"; import OrderListComponent from "./views/OrderList";
@ -57,6 +59,10 @@ const OrderDetails: React.FC<RouteComponentProps<any>> = ({
); );
}; };
const OrderFulfill: React.FC<RouteComponentProps<any>> = ({ match }) => (
<OrderFulfillComponent orderId={decodeURIComponent(match.params.id)} />
);
const Component = () => { const Component = () => {
const intl = useIntl(); const intl = useIntl();
@ -66,6 +72,7 @@ const Component = () => {
<Switch> <Switch>
<Route exact path={orderDraftListPath} component={OrderDraftList} /> <Route exact path={orderDraftListPath} component={OrderDraftList} />
<Route exact path={orderListPath} component={OrderList} /> <Route exact path={orderListPath} component={OrderList} />
<Route path={orderFulfillPath(":id")} component={OrderFulfill} />
<Route path={orderPath(":id")} component={OrderDetails} /> <Route path={orderPath(":id")} component={OrderDetails} />
</Switch> </Switch>
</> </>

View file

@ -97,10 +97,14 @@ export type OrderUrlDialog =
| "edit-shipping" | "edit-shipping"
| "edit-shipping-address" | "edit-shipping-address"
| "finalize" | "finalize"
| "fulfill"
| "mark-paid" | "mark-paid"
| "refund" | "refund"
| "void"; | "void";
export type OrderUrlQueryParams = Dialog<OrderUrlDialog> & SingleAction; export type OrderUrlQueryParams = Dialog<OrderUrlDialog> & SingleAction;
export const orderUrl = (id: string, params?: OrderUrlQueryParams) => export const orderUrl = (id: string, params?: OrderUrlQueryParams) =>
orderPath(encodeURIComponent(id)) + "?" + stringifyQs(params); orderPath(encodeURIComponent(id)) + "?" + stringifyQs(params);
export const orderFulfillPath = (id: string) =>
urlJoin(orderPath(id), "fulfill");
export const orderFulfillUrl = (id: string) =>
orderFulfillPath(encodeURIComponent(id));

View file

@ -26,7 +26,6 @@ import OrderDraftFinalizeDialog, {
} from "../../components/OrderDraftFinalizeDialog"; } from "../../components/OrderDraftFinalizeDialog";
import OrderDraftPage from "../../components/OrderDraftPage"; import OrderDraftPage from "../../components/OrderDraftPage";
import OrderFulfillmentCancelDialog from "../../components/OrderFulfillmentCancelDialog"; import OrderFulfillmentCancelDialog from "../../components/OrderFulfillmentCancelDialog";
import OrderFulfillmentDialog from "../../components/OrderFulfillmentDialog";
import OrderFulfillmentTrackingDialog from "../../components/OrderFulfillmentTrackingDialog"; import OrderFulfillmentTrackingDialog from "../../components/OrderFulfillmentTrackingDialog";
import OrderMarkAsPaidDialog from "../../components/OrderMarkAsPaidDialog/OrderMarkAsPaidDialog"; import OrderMarkAsPaidDialog from "../../components/OrderMarkAsPaidDialog/OrderMarkAsPaidDialog";
import OrderPaymentDialog from "../../components/OrderPaymentDialog"; import OrderPaymentDialog from "../../components/OrderPaymentDialog";
@ -40,7 +39,8 @@ import {
orderListUrl, orderListUrl,
orderUrl, orderUrl,
OrderUrlQueryParams, OrderUrlQueryParams,
OrderUrlDialog OrderUrlDialog,
orderFulfillUrl
} from "../../urls"; } from "../../urls";
import { OrderDetailsMessages } from "./OrderDetailsMessages"; import { OrderDetailsMessages } from "./OrderDetailsMessages";
@ -154,7 +154,6 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
{({ {({
orderAddNote, orderAddNote,
orderCancel, orderCancel,
orderCreateFulfillment,
orderDraftUpdate, orderDraftUpdate,
orderLinesAdd, orderLinesAdd,
orderLineDelete, orderLineDelete,
@ -201,7 +200,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
)} )}
userPermissions={user?.userPermissions || []} userPermissions={user?.userPermissions || []}
onOrderCancel={() => openModal("cancel")} onOrderCancel={() => openModal("cancel")}
onOrderFulfill={() => openModal("fulfill")} onOrderFulfill={() => navigate(orderFulfillUrl(id))}
onFulfillmentCancel={fulfillmentId => onFulfillmentCancel={fulfillmentId =>
navigate( navigate(
orderUrl(id, { orderUrl(id, {
@ -305,38 +304,6 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
}) })
} }
/> />
<OrderFulfillmentDialog
confirmButtonState={
orderCreateFulfillment.opts.status
}
errors={
orderCreateFulfillment.opts.data
?.orderFulfillmentCreate.errors || []
}
open={params.action === "fulfill"}
lines={maybe(() => order.lines, []).filter(
line => line.quantityFulfilled < line.quantity
)}
onClose={closeModal}
onSubmit={variables =>
orderCreateFulfillment.mutate({
input: {
...variables,
lines: maybe(() => order.lines, [])
.filter(
line =>
line.quantityFulfilled < line.quantity
)
.map((line, lineIndex) => ({
orderLineId: line.id,
quantity: variables.lines[lineIndex]
}))
.filter(line => line.quantity > 0)
},
order: order.id
})
}
/>
<OrderFulfillmentCancelDialog <OrderFulfillmentCancelDialog
confirmButtonState={ confirmButtonState={
orderFulfillmentCancel.opts.status orderFulfillmentCancel.opts.status

View file

@ -0,0 +1,41 @@
import React from "react";
import { useOrderFulfillData } from "@saleor/orders/queries";
import OrderFulfillPage from "@saleor/orders/components/OrderFulfillPage";
import useNavigator from "@saleor/hooks/useNavigator";
import { orderUrl } from "@saleor/orders/urls";
import { useWarehouseList } from "@saleor/warehouses/queries";
export interface OrderFulfillProps {
orderId: string;
}
const OrderFulfill: React.FC<OrderFulfillProps> = ({ orderId }) => {
const navigate = useNavigator();
const { data, loading } = useOrderFulfillData({
displayLoader: true,
variables: {
orderId
}
});
const { data: warehouseData, loading: warehousesLoading } = useWarehouseList({
displayLoader: true,
variables: {
first: 20
}
});
return (
<OrderFulfillPage
disabled={loading || warehousesLoading}
onBack={() => navigate(orderUrl(orderId))}
onSubmit={() => undefined}
order={data?.order}
saveButtonBar="default"
warehouses={warehouseData?.warehouses.edges.map(edge => edge.node)}
/>
);
};
OrderFulfill.displayName = "OrderFulfill";
export default OrderFulfill;

View file

@ -0,0 +1,2 @@
export * from "./OrderFulfill";
export { default } from "./OrderFulfill";