import { ReturnItem } from "@medusajs/medusa" import { useAdminCancelReturn, useAdminCancelSwap, useAdminOrder, useAdminStore, } from "medusa-react" import React, { useEffect, useState } from "react" import CreateFulfillmentModal from "../../../domain/orders/details/create-fulfillment" import { ReceiveReturnMenu } from "../../../domain/orders/details/receive-return" import useOrdersExpandParam from "../../../domain/orders/details/utils/use-admin-expand-paramter" import { ExchangeEvent } from "../../../hooks/use-build-timeline" import useNotification from "../../../hooks/use-notification" import Medusa from "../../../services/api" import { getErrorMessage } from "../../../utils/error-messages" import CopyToClipboard from "../../atoms/copy-to-clipboard" import Button from "../../fundamentals/button" import CancelIcon from "../../fundamentals/icons/cancel-icon" import DollarSignIcon from "../../fundamentals/icons/dollar-sign-icon" import RefreshIcon from "../../fundamentals/icons/refresh-icon" import TruckIcon from "../../fundamentals/icons/truck-icon" import DeletePrompt from "../../organisms/delete-prompt" import { ActionType } from "../actionables" import IconTooltip from "../icon-tooltip" import { FulfillmentStatus, PaymentStatus, ReturnStatus } from "../order-status" import EventActionables from "./event-actionables" import EventContainer, { EventIconColor } from "./event-container" import EventItemContainer from "./event-item-container" type ExchangeProps = { event: ExchangeEvent refetch: () => void } type ExchangeStatusProps = { event: ExchangeEvent } const ExchangeStatus: React.FC = ({ event }) => { const divider =
return (
Payment:
{divider}
Return:
{divider}
Fulfillment:
) } const Exchange: React.FC = ({ event, refetch }) => { const [showCancel, setShowCancel] = useState(false) const [showCancelReturn, setShowCancelReturn] = useState(false) const [showReceiveReturn, setShowReceiveReturn] = useState(false) const [showCreateFulfillment, setShowCreateFulfillment] = useState(false) const cancelExchange = useAdminCancelSwap(event.orderId) const cancelReturn = useAdminCancelReturn(event.returnId) const [differenceCardId, setDifferenceCardId] = useState( undefined ) const [paymentFormatWarning, setPaymentFormatWarning] = useState< string | undefined >(undefined) const [payable, setPayable] = useState(true) const { store } = useAdminStore() const { orderRelations } = useOrdersExpandParam() const { order } = useAdminOrder(event.orderId, { expand: orderRelations, }) const notification = useNotification() useEffect(() => { if (!store) { return } if (event.paymentStatus !== "not_paid") { setPayable(false) return } if (store.swap_link_template?.indexOf("{cart_id}") === -1) { setPaymentFormatWarning( "Store payment link does not have the default format, as it does not contain '{cart_id}'. Either update the payment link to include '{cart_id}' or update this method to reflect the format of your payment link." ) } if (!store.swap_link_template) { setPaymentFormatWarning( "No payment link has been set for this store. Please update store settings." ) } if (event.exchangeCartId) { setDifferenceCardId( store.swap_link_template?.replace(/\{cart_id\}/, event.exchangeCartId) ) } }, [ store?.swap_link_template, event.exchangeCartId, event.paymentStatus, store, ]) const paymentLink = getPaymentLink( payable, differenceCardId, paymentFormatWarning, event.exchangeCartId ) const handleCancelExchange = async () => { await cancelExchange.mutateAsync(event.id) refetch() } const handleCancelReturn = async () => { await cancelReturn.mutateAsync() refetch() } const handleProcessSwapPayment = () => { Medusa.orders .processSwapPayment(event.orderId, event.id) .then((_res) => { notification("Success", "Payment processed successfully", "success") refetch() }) .catch((err) => { notification("Error", getErrorMessage(err), "error") }) } const returnItems = getReturnItems(event) const newItems = getNewItems(event) const actions: ActionType[] = [] if (event.paymentStatus === "awaiting") { actions.push({ label: "Capture payment", icon: , onClick: handleProcessSwapPayment, }) } if (event.returnStatus === "requested") { actions.push({ label: "Cancel return", icon: , onClick: () => setShowCancelReturn(!showCancelReturn), }) } if ( !event.isCanceled && !event.canceledAt && event.fulfillmentStatus !== "fulfilled" && event.fulfillmentStatus !== "shipped" ) { actions.push({ label: "Cancel exchange", icon: , onClick: () => setShowCancel(!showCancel), variant: "danger", }) } const args = { title: event.canceledAt ? "Exchange Cancelled" : "Exchange Requested", icon: event.canceledAt ? ( ) : ( ), expandable: !!event.canceledAt, iconColor: event.canceledAt ? EventIconColor.DEFAULT : EventIconColor.ORANGE, time: event.time, noNotification: event.noNotification, topNode: getActions(event, actions), children: [
{event.canceledAt && (
Requested on: {new Date(event.time).toUTCString()}
)} {!event.canceledAt && } {!event.canceledAt && paymentLink} {returnItems} {newItems}
{event.returnStatus === "requested" && ( )} {event.fulfillmentStatus === "not_fulfilled" && ( )}
, ], } return ( <> {showCancel && ( setShowCancel(!showCancel)} onDelete={handleCancelExchange} confirmText="Yes, cancel" heading="Cancel exchange" text="Are you sure you want to cancel this exchange?" successText="Exchange cancelled" /> )} {showCancelReturn && ( setShowCancelReturn(!showCancelReturn)} onDelete={handleCancelReturn} confirmText="Yes, cancel" heading="Cancel return" text="Are you sure you want to cancel this return?" successText="Return cancelled" /> )} {showReceiveReturn && order && ( setShowReceiveReturn(false)} /> )} {showCreateFulfillment && ( setShowCreateFulfillment(false)} /> )} ) } function getNewItems(event: ExchangeEvent) { return (
New Items
{event.newItems.map((i, index) => ( ))}
) } function getPaymentLink( payable: boolean, differenceCardId: string | undefined, paymentFormatWarning: string | undefined, exchangeCartId: string | undefined ) { return payable ? (
{paymentFormatWarning && } Payment link:
{differenceCardId && ( )}
) : null } function getReturnItems(event: ExchangeEvent) { return (
Return Items
{event.returnItems .filter((i) => !!i) .map((i: ReturnItem) => ( ))}
) } function getActions(event: ExchangeEvent, actions: ActionType[]) { if (actions.length === 0) { return null } return } export default Exchange