saleor-dashboard/src/orders/components/OrderChangeWarehouseDialog/OrderChangeWarehouseDialog.tsx
Michał Droń 6cf148c4c3
Fulfillment creation refactor (#1896)
* Create change warehouse dialog (#1850)

* Add allocations & variant stocks to order details query

* Add asc sorting to warehouse search query

* Add OrderChangeWarehouseDialog component

* Add key to warehouse list in dialog

* Update snapshots

* Remove debug directive

* Remove IDs from messages

* Fix typo in method name & extract messages

* Add quantity to allocations in order details query

* Add types to functions

* Move functions to local utils file

* Add utility type WithOptional

* Fix warehouse types

* Change multiple items unavailable message name

* Fix fetching onScroll

* Fix types in utils

* Add backdrop click support

* Add id to stocks and allocations

* Change unavailableLines from .map to .filter

Co-authored-by: Wojciech Mista <wojciech.mista@hotmail.com>

* Fix linter issue

Co-authored-by: Wojciech Mista <wojciech.mista@hotmail.com>

* Refactor order cards headers (#1875)

* Add keys to TableLines

* Bump macaw

* Move & rename CardTitle used in Cards with order lines

* Improve OrderCardTitle typography

* Replace StatusLabels with CircleIndicators

* Fix card title divs placement

* Add warehouse selection button to OrderUnfulfilledCard

* Fix fulfill button placement

* Update snapshots

* Make warehouse in order details view optional so that it works with uncofirmed orders

* Fix undefined lines in warehouse dialog

* Fix spacing in warehouse change button

* Fix macaw dependency

* Bump macaw-ui

* Extract messages

* Implement default warehouse selection logic

* Move CircleIndicator render condition to wrapper

* Fix failing reduce on orders with no lines

* Improve warehousesAvailable early return

* Drop counter in favor of filter().length

* Fix tests post-rebase

* Refactor fulfillment details page (#1915)

* Add shipment information card

* Refactor multiple warehouse fulfilling to one warehouse

* Fix fulfill button navigation

* Remove redundant code from OrderFulfill view

* Fix OrderFulfill story

* Move styling to seperate file & remove unused classes

* Replace colQuantityTotal class with colStock

* Add warehouse label under page header

* Fix preorder cases

* Change default values to maximum

* Simplify logic

* Add badge for preorder & deleted variant cases

* Remove unused data

* Add yellow outline for exceeding stock

* Fix failing tests

* Extract messages

* Fix tests post-rebase

* Add support for tracking number

* Block fulfilling no items

* Fix deleted variant order details bug

* Fix preorder & deleted variant cases

* Update snapshots

* Remove redundant import

* Fix linter issue

* Extract fulfillment lines as separate component

* Fix types

* Export styles & messages to seperate files

* Simplify formset changes

* Fix warning input styling

* Fix shouldEnableSave for overfulfillment cases

* Simplify preorder rendering

* Move empty line rendering

* Change Warehouse prop to just id of it

* Add endAdornment for deleted variant cases

* Update snapshots

* Fix linter issue

* Extract messages

* Fix incorrect operator precedence resulting in NaN values

* Extract fulfillment lines to fragment

* Replace nested types with fragment type

* Match fragment names

* Update snapshots

* Create exceeding stock confirmation dialog (#1970)

* Cherry-pick OrderFulfillStockExceededDialog

* Fix types to graphql-codegen

* Unify names in OrderFulfillStockExceededDialogLines

* Fix types in OrderFulfillStockExceededDialogLines

* Fix types in util

* Change utils for usage with single warehouse context

* Refactor OrderFulfillStockExceededDialogLine for usage with single warehouse context

* Fix deleted variant cases in OrderFulfillStockExceededDialogLine

* Include only exceeded lines

* Display stock exceeded dialog on error

* Add confirm button state

* Change fixed height in OrderFulfillStockExceededDialog to responsive

* Extract messages

* Move initial form data after interfaces

* Change nested type to fragment

* Reuse logic

* Remove unused import

* Remove redundant isStockError

* Remove unused imports

* Fix minor bugs in fulfillment creation refactor (#1972)

* Fix unfulfilled card header quantity calculation

* Fix formset default value for deleted variants

* Update snapshots

* Fix default warehouse selection in order draft (#1971)

* Fix default warehouse selection

* Replace Skeleton with circular progress

* Reuse logic

* Reuse logic

* Apply CR fixes

* Remove unused imports

* Fix canceled order header status

* Update snapshots

* Revert CircularProgress & change to Skeleton

* Change complex types to fragments

* Extract default warehouse logic to hook

* Fix linter issue

* Remove type assertion from OrderFulfillPage story

* Handle exceeding stock fulfillment approvals (#1988)

* wip Add OrderFulfillStockExceeded modal for fulfillment approvals

* wip Fix types & imports

* wip Fix union typing in stock exceeded dialog for both views

* Add allowStockToBeExceeded flag on submit

* Fix lines keys in FulfilledCard

* Remove redundant import

* Extract attributes caption function

* Use getById util

* Fix deleted warehouse cases in approvals

* Fix typo

* Fix styling for long warehouse names (#2019)

* Fix styling in change warehouse dialog

* Fix styling in warehouse selection button

* Add extra margin in button

* Update snapshots

Co-authored-by: Wojciech Mista <wojciech.mista@hotmail.com>
2022-04-29 11:16:58 +02:00

213 lines
6.9 KiB
TypeScript

import {
Dialog,
DialogActions,
DialogContent,
FormControlLabel,
InputAdornment,
Radio,
RadioGroup,
TableCell,
TableRow,
TextField,
Typography
} from "@material-ui/core";
import Debounce from "@saleor/components/Debounce";
import Skeleton from "@saleor/components/Skeleton";
import { OrderLineFragment, WarehouseFragment } from "@saleor/graphql";
import { buttonMessages } from "@saleor/intl";
import {
Button,
DialogHeader,
DialogTable,
isScrolledToBottom,
isScrolledToTop,
ScrollShadow,
SearchIcon,
useElementScroll
} from "@saleor/macaw-ui";
import { isLineAvailableInWarehouse } from "@saleor/orders/utils/data";
import useWarehouseSearch from "@saleor/searches/useWarehouseSearch";
import { mapEdgesToItems } from "@saleor/utils/maps";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
import { getById } from "../OrderReturnPage/utils";
import { changeWarehouseDialogMessages as messages } from "./messages";
import { useStyles } from "./styles";
export interface OrderChangeWarehouseDialogProps {
open: boolean;
lines: OrderLineFragment[];
currentWarehouse: WarehouseFragment;
onConfirm: (warehouse: WarehouseFragment) => void;
onClose();
}
export const OrderChangeWarehouseDialog: React.FC<OrderChangeWarehouseDialogProps> = ({
open,
lines,
currentWarehouse,
onConfirm,
onClose
}) => {
const classes = useStyles();
const intl = useIntl();
const { anchor, position, setAnchor } = useElementScroll();
const topShadow = isScrolledToTop(anchor, position, 20) === false;
const bottomShadow = isScrolledToBottom(anchor, position, 20) === false;
const [query, setQuery] = React.useState<string>("");
const [selectedWarehouseId, setSelectedWarehouseId] = React.useState<
string | null
>(null);
React.useEffect(() => {
if (currentWarehouse?.id) {
setSelectedWarehouseId(currentWarehouse.id);
}
}, [currentWarehouse]);
const { result: warehousesOpts, loadMore, search } = useWarehouseSearch({
variables: {
after: null,
first: 20,
query: ""
}
});
const filteredWarehouses = mapEdgesToItems(warehousesOpts?.data?.search);
const selectedWarehouse = filteredWarehouses?.find(
getById(selectedWarehouseId ?? "")
);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setSelectedWarehouseId(e.target.value);
};
const handleSubmit = () => {
onConfirm(selectedWarehouse);
onClose();
};
React.useEffect(() => {
if (!bottomShadow) {
loadMore();
}
}, [bottomShadow]);
return (
<Dialog fullWidth open={open} onClose={onClose}>
<ScrollShadow variant="top" show={topShadow}>
<DialogHeader onClose={onClose}>
<FormattedMessage {...messages.dialogTitle} />
</DialogHeader>
<DialogContent className={classes.container}>
<FormattedMessage {...messages.dialogDescription} />
<Debounce debounceFn={search}>
{debounceSearchChange => {
const handleSearchChange = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const value = event.target.value;
setQuery(value);
debounceSearchChange(value);
};
return (
<TextField
className={classes.searchBox}
value={query}
variant="outlined"
onChange={handleSearchChange}
placeholder={intl.formatMessage(
messages.searchFieldPlaceholder
)}
fullWidth
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
)
}}
inputProps={{ className: classes.searchInput }}
/>
);
}}
</Debounce>
<Typography className={classes.supportHeader}>
<FormattedMessage {...messages.warehouseListLabel} />
</Typography>
</DialogContent>
</ScrollShadow>
<DialogTable ref={setAnchor}>
{filteredWarehouses ? (
<RadioGroup value={selectedWarehouseId} onChange={handleChange}>
{filteredWarehouses.map(warehouse => {
const unavailableLines = lines?.filter(
line => !isLineAvailableInWarehouse(line, warehouse)
);
const someLinesUnavailable = unavailableLines?.length > 0;
return (
<TableRow key={warehouse.id}>
<TableCell>
<FormControlLabel
value={warehouse.id}
control={<Radio color="primary" />}
label={
<div className={classes.radioLabelContainer}>
<span className={classes.warehouseName}>
{warehouse.name}
</span>
{someLinesUnavailable && (
<Typography className={classes.supportText}>
{unavailableLines.length === 1
? intl.formatMessage(
messages.productUnavailable,
{
productName:
unavailableLines[0].productName
}
)
: intl.formatMessage(
messages.multipleProductsUnavailable,
{ productCount: unavailableLines.length }
)}
</Typography>
)}
</div>
}
/>
{currentWarehouse?.id === warehouse?.id && (
<Typography className={classes.helpText}>
{intl.formatMessage(messages.currentSelection)}
</Typography>
)}
</TableCell>
</TableRow>
);
})}
</RadioGroup>
) : (
<Skeleton />
)}
</DialogTable>
<ScrollShadow variant="bottom" show={bottomShadow}>
<DialogActions>
<Button
onClick={handleSubmit}
color="primary"
variant="primary"
disabled={!selectedWarehouse}
>
{intl.formatMessage(buttonMessages.select)}
</Button>
</DialogActions>
</ScrollShadow>
</Dialog>
);
};
OrderChangeWarehouseDialog.displayName = "OrderChangeWarehouseDialog";
export default OrderChangeWarehouseDialog;