import NotFoundPage from "@saleor/components/NotFoundPage"; import { WindowTitle } from "@saleor/components/WindowTitle"; import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config"; import { Task } from "@saleor/containers/BackgroundTasks/types"; import useBackgroundTask from "@saleor/hooks/useBackgroundTask"; import useNavigator from "@saleor/hooks/useNavigator"; import useUser from "@saleor/hooks/useUser"; import OrderCannotCancelOrderDialog from "@saleor/orders/components/OrderCannotCancelOrderDialog"; import OrderInvoiceEmailSendDialog from "@saleor/orders/components/OrderInvoiceEmailSendDialog"; import { InvoiceRequest } from "@saleor/orders/types/InvoiceRequest"; import useCustomerSearch from "@saleor/searches/useCustomerSearch"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; import { useWarehouseList } from "@saleor/warehouses/queries"; import React from "react"; import { useIntl } from "react-intl"; import { customerUrl } from "../../../customers/urls"; import { getStringOrPlaceholder, maybe, transformAddressToForm } from "../../../misc"; import { productUrl } from "../../../products/urls"; import { FulfillmentStatus, JobStatusEnum, OrderStatus } from "../../../types/globalTypes"; import OrderAddressEditDialog from "../../components/OrderAddressEditDialog"; import OrderCancelDialog from "../../components/OrderCancelDialog"; import OrderDetailsPage from "../../components/OrderDetailsPage"; import OrderDraftCancelDialog from "../../components/OrderDraftCancelDialog/OrderDraftCancelDialog"; import OrderDraftFinalizeDialog, { OrderDraftFinalizeWarning } from "../../components/OrderDraftFinalizeDialog"; import OrderDraftPage from "../../components/OrderDraftPage"; import OrderFulfillmentCancelDialog from "../../components/OrderFulfillmentCancelDialog"; import OrderFulfillmentTrackingDialog from "../../components/OrderFulfillmentTrackingDialog"; import OrderMarkAsPaidDialog from "../../components/OrderMarkAsPaidDialog/OrderMarkAsPaidDialog"; import OrderPaymentDialog from "../../components/OrderPaymentDialog"; import OrderPaymentVoidDialog from "../../components/OrderPaymentVoidDialog"; import OrderProductAddDialog from "../../components/OrderProductAddDialog"; import OrderShippingMethodEditDialog from "../../components/OrderShippingMethodEditDialog"; import OrderOperations from "../../containers/OrderOperations"; import { TypedOrderDetailsQuery, useOrderVariantSearch } from "../../queries"; import { OrderDetails_order } from "../../types/OrderDetails"; import { orderFulfillUrl, orderListUrl, orderUrl, OrderUrlDialog, OrderUrlQueryParams } from "../../urls"; import { OrderDetailsMessages } from "./OrderDetailsMessages"; const orderDraftFinalizeWarnings = (order: OrderDetails_order) => { const warnings = [] as OrderDraftFinalizeWarning[]; if (!(order && order.shippingAddress)) { warnings.push(OrderDraftFinalizeWarning.NO_SHIPPING); } if (!(order && order.billingAddress)) { warnings.push(OrderDraftFinalizeWarning.NO_BILLING); } if (!(order && (order.user || order.userEmail))) { warnings.push(OrderDraftFinalizeWarning.NO_USER); } if ( order && order.lines && order.lines.filter(line => line.isShippingRequired).length > 0 && order.shippingMethod === null ) { warnings.push(OrderDraftFinalizeWarning.NO_SHIPPING_METHOD); } if ( order && order.lines && order.lines.filter(line => line.isShippingRequired).length === 0 && order.shippingMethod !== null ) { warnings.push(OrderDraftFinalizeWarning.UNNECESSARY_SHIPPING_METHOD); } return warnings; }; interface OrderDetailsProps { id: string; params: OrderUrlQueryParams; } export const OrderDetails: React.FC = ({ id, params }) => { const navigate = useNavigator(); const { user } = useUser(); const { loadMore: loadMoreCustomers, search: searchUsers, result: users } = useCustomerSearch({ variables: DEFAULT_INITIAL_SEARCH_DATA }); const { loadMore, search: variantSearch, result: variantSearchOpts } = useOrderVariantSearch({ variables: DEFAULT_INITIAL_SEARCH_DATA }); const warehouses = useWarehouseList({ displayLoader: true, variables: { first: 30 } }); const { queue } = useBackgroundTask(); const intl = useIntl(); const [openModal, closeModal] = createDialogActionHandlers< OrderUrlDialog, OrderUrlQueryParams >(navigate, params => orderUrl(id, params), params); const handleBack = () => navigate(orderListUrl()); return ( {({ data, loading }) => { const order = data?.order; if (order === null) { return ; } return ( {orderMessages => ( { if ( data.invoiceRequest.invoice.status === JobStatusEnum.SUCCESS ) { orderMessages.handleInvoiceGenerateFinished(data); } else { orderMessages.handleInvoiceGeneratePending(data); queue(Task.INVOICE_GENERATE, { generateInvoice: { invoiceId: data.invoiceRequest.invoice.id, orderId: id } }); } }} onInvoiceSend={orderMessages.handleInvoiceSend} > {({ orderAddNote, orderCancel, orderDraftUpdate, orderLinesAdd, orderLineDelete, orderLineUpdate, orderPaymentCapture, orderPaymentRefund, orderVoid, orderShippingMethodUpdate, orderUpdate, orderFulfillmentCancel, orderFulfillmentUpdateTracking, orderDraftCancel, orderDraftFinalize, orderPaymentMarkAsPaid, orderInvoiceRequest, orderInvoiceSend }) => ( <> {order?.status !== OrderStatus.DRAFT ? ( <> orderAddNote.mutate({ input: variables, order: id }) } onBack={handleBack} order={order} shippingMethods={maybe( () => data.order.availableShippingMethods, [] )} userPermissions={user?.userPermissions || []} onOrderCancel={() => openModal("cancel")} onOrderFulfill={() => navigate(orderFulfillUrl(id))} onFulfillmentCancel={fulfillmentId => navigate( orderUrl(id, { action: "cancel-fulfillment", id: fulfillmentId }) ) } onFulfillmentTrackingNumberUpdate={fulfillmentId => navigate( orderUrl(id, { action: "edit-fulfillment", id: fulfillmentId }) ) } onPaymentCapture={() => openModal("capture")} onPaymentVoid={() => openModal("void")} onPaymentRefund={() => openModal("refund")} onProductClick={id => () => navigate(productUrl(id))} onBillingAddressEdit={() => openModal("edit-billing-address") } onShippingAddressEdit={() => openModal("edit-shipping-address") } onPaymentPaid={() => openModal("mark-paid")} onProfileView={() => navigate(customerUrl(order.user.id)) } onInvoiceClick={id => window.open( order.invoices.find(invoice => invoice.id === id) ?.url, "_blank" ) } onInvoiceGenerate={() => orderInvoiceRequest.mutate({ orderId: id }) } onInvoiceSend={id => openModal("invoice-send", { id }) } /> fulfillment.status === FulfillmentStatus.FULFILLED ) } /> orderCancel.mutate({ id }) } /> orderPaymentMarkAsPaid.mutate({ id }) } open={params.action === "mark-paid"} /> orderVoid.mutate({ id })} /> orderPaymentCapture.mutate({ ...variables, id }) } /> orderPaymentRefund.mutate({ ...variables, id }) } /> edge.node ) || [] } onConfirm={variables => orderFulfillmentCancel.mutate({ id: params.id, input: variables }) } onClose={closeModal} /> fulfillment.id === params.id )?.trackingNumber )} onConfirm={variables => orderFulfillmentUpdateTracking.mutate({ id: params.id, input: { ...variables, notifyCustomer: true } }) } onClose={closeModal} /> invoice.id === params.id )} onClose={closeModal} onSend={() => orderInvoiceSend.mutate({ id: params.id }) } /> ) : ( <> orderAddNote.mutate({ input: variables, order: id }) } users={maybe( () => users.data.search.edges.map(edge => edge.node), [] )} hasMore={maybe( () => users.data.search.pageInfo.hasNextPage, false )} onFetchMore={loadMoreCustomers} fetchUsers={searchUsers} loading={users.loading} usersLoading={users.loading} onCustomerEdit={data => orderDraftUpdate.mutate({ id, input: data }) } onDraftFinalize={() => openModal("finalize")} onDraftRemove={() => openModal("cancel")} onOrderLineAdd={() => openModal("add-order-line")} onBack={() => navigate(orderListUrl())} order={order} countries={maybe(() => data.shop.countries, []).map( country => ({ code: country.code, label: country.country }) )} onProductClick={id => () => navigate(productUrl(encodeURIComponent(id)))} onBillingAddressEdit={() => openModal("edit-billing-address") } onShippingAddressEdit={() => openModal("edit-shipping-address") } onShippingMethodEdit={() => openModal("edit-shipping") } onOrderLineRemove={id => orderLineDelete.mutate({ id }) } onOrderLineChange={(id, data) => orderLineUpdate.mutate({ id, input: data }) } saveButtonBarState="default" onProfileView={() => navigate(customerUrl(order.user.id)) } userPermissions={user?.userPermissions || []} /> orderDraftCancel.mutate({ id })} open={params.action === "cancel"} orderNumber={getStringOrPlaceholder(order?.number)} /> orderDraftFinalize.mutate({ id })} open={params.action === "finalize"} orderNumber={getStringOrPlaceholder(order?.number)} warnings={orderDraftFinalizeWarnings(order)} /> orderShippingMethodUpdate.mutate({ id, input: { shippingMethod: variables.shippingMethod } }) } /> edge.node )} onClose={closeModal} onFetch={variantSearch} onFetchMore={loadMore} onSubmit={variants => orderLinesAdd.mutate({ id, input: variants.map(variant => ({ quantity: 1, variantId: variant.id })) }) } /> )} ({ code: country.code, label: country.country })) || [] } errors={orderUpdate.opts.data?.orderUpdate.errors || []} open={params.action === "edit-shipping-address"} variant="shipping" onClose={closeModal} onConfirm={shippingAddress => orderUpdate.mutate({ id, input: { shippingAddress } }) } /> ({ code: country.code, label: country.country })) || [] } errors={orderUpdate.opts.data?.orderUpdate.errors || []} open={params.action === "edit-billing-address"} variant="billing" onClose={closeModal} onConfirm={billingAddress => orderUpdate.mutate({ id, input: { billingAddress } }) } /> )} )} ); }} ); }; export default OrderDetails;