saleor-dashboard/src/orders/components/OrderChangeWarehouseDialog/OrderChangeWarehouseDialog.tsx

214 lines
6.9 KiB
TypeScript
Raw Normal View History

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 09:16:58 +00:00
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;