fix(admin): Add skus to claim menus (#3368)
**What** - Adds SKU to all tables in claim flow, allowing admins to easily copy them to their clipboard.
This commit is contained in:
committed by
GitHub
parent
d4e3e119de
commit
67ba8be02b
@@ -32,14 +32,15 @@ const CopyToClipboard: React.FC<CopyToClipboardProps> = ({
|
||||
if (isCopied) {
|
||||
notification("Success", "Copied!", "success")
|
||||
}
|
||||
}, [isCopied])
|
||||
}, [isCopied, notification])
|
||||
|
||||
return (
|
||||
<div className="flex items-center inter-small-regular text-grey-50 gap-x-xsmall">
|
||||
<div className="inter-small-regular text-grey-50 gap-x-xsmall flex items-center">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="small"
|
||||
className={clsx("p-0 text-grey-50", {
|
||||
type="button"
|
||||
className={clsx("text-grey-50 p-0", {
|
||||
["text-violet-60"]: isCopied,
|
||||
})}
|
||||
onClick={handleCopy}
|
||||
|
||||
+12
-12
@@ -104,14 +104,14 @@ const Claim = ({ event }: Props) => {
|
||||
topNode: Actions,
|
||||
children: [
|
||||
<Fragment key={event.id}>
|
||||
<div className="flex flex-col gap-y-base">
|
||||
<div className="gap-y-base flex flex-col">
|
||||
<ClaimStatus event={event} />
|
||||
{renderClaimItems(event)}
|
||||
{event.claim?.additional_items?.length > 0 &&
|
||||
renderReplacementItems(event)}
|
||||
{shouldHaveButtonActions && (
|
||||
<div className="flex items-center gap-x-xsmall">
|
||||
{event.claim.return_order.status === "requested" && (
|
||||
<div className="gap-x-xsmall flex items-center">
|
||||
{event.claim.return_order?.status === "requested" && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="small"
|
||||
@@ -157,7 +157,7 @@ const Claim = ({ event }: Props) => {
|
||||
export default Claim
|
||||
|
||||
const ClaimStatus = ({ event }: Props) => {
|
||||
const divider = <div className="h-11 w-px bg-grey-20" />
|
||||
const divider = <div className="bg-grey-20 h-11 w-px" />
|
||||
|
||||
const shouldHaveFulfillment =
|
||||
!!event.claim?.fulfillment_status &&
|
||||
@@ -168,7 +168,7 @@ const ClaimStatus = ({ event }: Props) => {
|
||||
|
||||
if (event.claim?.type === "replace") {
|
||||
refundStatus =
|
||||
event.claim?.return_order.status === "received"
|
||||
event.claim?.return_order?.status === "received"
|
||||
? "refunded"
|
||||
: event.claim?.payment_status
|
||||
}
|
||||
@@ -178,15 +178,15 @@ const ClaimStatus = ({ event }: Props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="inter-small-regular flex items-center gap-x-base">
|
||||
<div className="flex flex-col gap-y-2xsmall">
|
||||
<div className="inter-small-regular gap-x-base flex items-center">
|
||||
<div className="gap-y-2xsmall flex flex-col">
|
||||
<span className="text-grey-50">Refund:</span>
|
||||
<RefundStatus refundStatus={refundStatus} />
|
||||
</div>
|
||||
{shouldHaveReturnStatus && (
|
||||
<>
|
||||
{divider}
|
||||
<div className="flex flex-col gap-y-2xsmall">
|
||||
<div className="gap-y-2xsmall flex flex-col">
|
||||
<span className="text-grey-50">Return:</span>
|
||||
<ReturnStatus returnStatus={event.returnStatus} />
|
||||
</div>
|
||||
@@ -195,7 +195,7 @@ const ClaimStatus = ({ event }: Props) => {
|
||||
{shouldHaveFulfillment && (
|
||||
<>
|
||||
{divider}
|
||||
<div className="flex flex-col gap-y-2xsmall">
|
||||
<div className="gap-y-2xsmall flex flex-col">
|
||||
<span className="text-grey-50">Fulfillment:</span>
|
||||
<FulfillmentStatus
|
||||
fulfillmentStatus={event.claim?.fulfillment_status}
|
||||
@@ -209,7 +209,7 @@ const ClaimStatus = ({ event }: Props) => {
|
||||
|
||||
const renderClaimItems = (event: ClaimEvent) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-y-small">
|
||||
<div className="gap-y-small flex flex-col">
|
||||
<span className="inter-small-regular text-grey-50">Claim Items</span>
|
||||
<div>
|
||||
{event.claimItems.map((i, index) => (
|
||||
@@ -222,7 +222,7 @@ const renderClaimItems = (event: ClaimEvent) => {
|
||||
|
||||
const renderReplacementItems = (event: ClaimEvent) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-y-small">
|
||||
<div className="gap-y-small flex flex-col">
|
||||
<span className="inter-small-regular text-grey-50">
|
||||
Replacement Items
|
||||
</span>
|
||||
@@ -245,7 +245,7 @@ const renderClaimActions = (
|
||||
if (!event.canceledAt && !event.isCanceled) {
|
||||
if (
|
||||
event.claim.return_order &&
|
||||
event.claim.return_order.status === "requested"
|
||||
event.claim.return_order?.status === "requested"
|
||||
) {
|
||||
actions.push({
|
||||
icon: <TrashIcon size={20} />,
|
||||
|
||||
+17
-3
@@ -1,6 +1,7 @@
|
||||
import { createColumnHelper } from "@tanstack/react-table"
|
||||
import React, { ChangeEvent, useCallback, useMemo } from "react"
|
||||
import { Controller, useWatch } from "react-hook-form"
|
||||
import CopyToClipboard from "../../../../components/atoms/copy-to-clipboard"
|
||||
import Thumbnail from "../../../../components/atoms/thumbnail"
|
||||
import IndeterminateCheckbox from "../../../../components/molecules/indeterminate-checkbox"
|
||||
import { NestedForm } from "../../../../utils/nested-form"
|
||||
@@ -91,14 +92,27 @@ export const useItemsToReceiveColumns = ({ form, orderCurrency }: Props) => {
|
||||
columnHelper.accessor("variant_title", {
|
||||
header: "Product",
|
||||
cell: ({ getValue, row: { original } }) => {
|
||||
const value = getValue()
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-x-base py-xsmall">
|
||||
<div className="gap-x-base py-xsmall flex items-center">
|
||||
<div>
|
||||
<Thumbnail src={original.thumbnail} />
|
||||
</div>
|
||||
<div className="inter-small-regular">
|
||||
<p>{original.product_title}</p>
|
||||
<p className="text-grey-50">{getValue()}</p>
|
||||
<div className="gap-x-2xsmall flex items-center">
|
||||
<p>{original.product_title}</p>
|
||||
{value && <p className="text-grey-50">({value})</p>}
|
||||
</div>
|
||||
{original.sku && (
|
||||
<span>
|
||||
<CopyToClipboard
|
||||
value={original.sku}
|
||||
displayValue={original.sku}
|
||||
iconSize={14}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -22,6 +22,7 @@ export type ReturnItem = {
|
||||
thumbnail?: string | null
|
||||
product_title: string
|
||||
variant_title: string
|
||||
sku?: string | null
|
||||
quantity: number
|
||||
original_quantity: number
|
||||
total: number
|
||||
@@ -75,7 +76,7 @@ const ItemsToReturnForm = ({ form, order, isClaim = false }: Props) => {
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-y-base">
|
||||
<div className="gap-y-base flex flex-col">
|
||||
<h2 className="inter-base-semibold">
|
||||
Items to {isClaim ? "claim" : "return"}
|
||||
</h2>
|
||||
|
||||
+17
-3
@@ -2,6 +2,7 @@ import { createColumnHelper } from "@tanstack/react-table"
|
||||
import React, { useCallback, useMemo } from "react"
|
||||
import { Controller, useWatch } from "react-hook-form"
|
||||
import { ItemsToReturnFormType, ReturnItemObject } from "."
|
||||
import CopyToClipboard from "../../../../components/atoms/copy-to-clipboard"
|
||||
import { Thumbnail } from "../../../../components/atoms/thumbnail/thumbnail"
|
||||
import IndeterminateCheckbox from "../../../../components/molecules/indeterminate-checkbox"
|
||||
import { NestedForm } from "../../../../utils/nested-form"
|
||||
@@ -98,14 +99,27 @@ export const useItemsToReturnColumns = ({ form, orderCurrency }: Props) => {
|
||||
columnHelper.accessor("variant_title", {
|
||||
header: "Product",
|
||||
cell: ({ getValue, row: { original } }) => {
|
||||
const value = getValue()
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-x-base py-xsmall">
|
||||
<div className="gap-x-base py-xsmall flex items-center">
|
||||
<div>
|
||||
<Thumbnail src={original.thumbnail} />
|
||||
</div>
|
||||
<div className="inter-small-regular">
|
||||
<p>{original.product_title}</p>
|
||||
<p className="text-grey-50">{getValue()}</p>
|
||||
<div className="gap-x-2xsmall flex items-center">
|
||||
<p>{original.product_title}</p>
|
||||
{value && <p className="text-grey-50">({value})</p>}
|
||||
</div>
|
||||
{original.sku && (
|
||||
<span>
|
||||
<CopyToClipboard
|
||||
value={original.sku}
|
||||
displayValue={original.sku}
|
||||
iconSize={14}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
+19
-8
@@ -1,5 +1,6 @@
|
||||
import { createColumnHelper } from "@tanstack/react-table"
|
||||
import { useCallback, useMemo } from "react"
|
||||
import CopyToClipboard from "../../../../components/atoms/copy-to-clipboard"
|
||||
import Thumbnail from "../../../../components/atoms/thumbnail"
|
||||
import Tooltip from "../../../../components/atoms/tooltip"
|
||||
import Button from "../../../../components/fundamentals/button"
|
||||
@@ -45,14 +46,24 @@ export const useAdditionalItemsColumns = ({
|
||||
},
|
||||
}) => {
|
||||
return (
|
||||
<div className="flex items-center gap-base">
|
||||
<div className="gap-base flex items-center">
|
||||
<Thumbnail src={thumbnail} />
|
||||
<div>
|
||||
<p>
|
||||
{product_title}{" "}
|
||||
<span className="text-grey-50">({variant_title})</span>
|
||||
</p>
|
||||
{sku && <p className="text-grey-50">{sku}</p>}
|
||||
<div className="inter-small-regular">
|
||||
<div className="gap-x-2xsmall flex items-center">
|
||||
<p>{product_title}</p>
|
||||
{variant_title && (
|
||||
<p className="text-grey-50">({variant_title})</p>
|
||||
)}
|
||||
</div>
|
||||
{sku && (
|
||||
<span>
|
||||
<CopyToClipboard
|
||||
value={sku}
|
||||
displayValue={sku}
|
||||
iconSize={14}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -101,7 +112,7 @@ export const useAdditionalItemsColumns = ({
|
||||
content="The price has been overridden in a price list, that is applicable to this order."
|
||||
side="top"
|
||||
>
|
||||
<p className="cursor-default text-grey-40 line-through">
|
||||
<p className="text-grey-40 cursor-default line-through">
|
||||
{formatAmountWithSymbol({
|
||||
amount: original_price,
|
||||
currency: orderCurrency,
|
||||
|
||||
@@ -15,11 +15,12 @@ type Props = {
|
||||
}
|
||||
|
||||
export const ClaimSummary = ({ form, order }: Props) => {
|
||||
const { control, getValues } = form
|
||||
const { control } = form
|
||||
|
||||
const claimItems = useWatch({
|
||||
control: control,
|
||||
name: "return_items.items",
|
||||
defaultValue: [],
|
||||
})
|
||||
|
||||
const selectedClaimItems = useMemo(() => {
|
||||
@@ -34,6 +35,7 @@ export const ClaimSummary = ({ form, order }: Props) => {
|
||||
const replacementItems = useWatch({
|
||||
control: control,
|
||||
name: "additional_items.items",
|
||||
defaultValue: [],
|
||||
})
|
||||
|
||||
const replacementItemShipping = useWatch({
|
||||
@@ -84,6 +86,7 @@ export const ClaimSummary = ({ form, order }: Props) => {
|
||||
currencyCode={order.currency_code}
|
||||
productTitle={item.product_title}
|
||||
quantity={item.quantity}
|
||||
sku={item.sku}
|
||||
price={item.total / item.original_quantity}
|
||||
total={
|
||||
(item.total / item.original_quantity) * item.quantity
|
||||
@@ -123,6 +126,7 @@ export const ClaimSummary = ({ form, order }: Props) => {
|
||||
currencyCode={order.currency_code}
|
||||
productTitle={item.product_title}
|
||||
quantity={item.quantity}
|
||||
sku={item.sku}
|
||||
price={item.price}
|
||||
total={item.price * item.quantity}
|
||||
variantTitle={item.variant_title}
|
||||
|
||||
+14
-4
@@ -1,4 +1,5 @@
|
||||
import clsx from "clsx"
|
||||
import CopyToClipboard from "../../../../components/atoms/copy-to-clipboard"
|
||||
import Thumbnail from "../../../../components/atoms/thumbnail"
|
||||
import { formatAmountWithSymbol } from "../../../../utils/prices"
|
||||
|
||||
@@ -9,6 +10,7 @@ type SummaryLineProps = {
|
||||
quantity: number
|
||||
price: number
|
||||
total: number
|
||||
sku?: string | null
|
||||
currencyCode: string
|
||||
isFree?: boolean
|
||||
}
|
||||
@@ -17,6 +19,7 @@ export const SummaryLineItem = ({
|
||||
thumbnail,
|
||||
productTitle,
|
||||
variantTitle,
|
||||
sku,
|
||||
quantity,
|
||||
price,
|
||||
total,
|
||||
@@ -25,16 +28,23 @@ export const SummaryLineItem = ({
|
||||
}: SummaryLineProps) => {
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-x-base">
|
||||
<div className="gap-x-base flex items-center">
|
||||
<div>
|
||||
<Thumbnail src={thumbnail} />
|
||||
</div>
|
||||
<div className="inter-small-regular">
|
||||
<p>{productTitle}</p>
|
||||
<p className="text-grey-50">{variantTitle}</p>
|
||||
<div className="gap-x-2xsmall flex items-center">
|
||||
<p>{productTitle}</p>
|
||||
{variantTitle && <p className="text-grey-50">({variantTitle})</p>}
|
||||
</div>
|
||||
{sku && (
|
||||
<span>
|
||||
<CopyToClipboard value={sku} displayValue={sku} iconSize={14} />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="inter-small-regular flex items-center gap-x-base">
|
||||
<div className="inter-small-regular gap-x-base flex items-center">
|
||||
<p className="text-grey-40">
|
||||
{formatAmountWithSymbol({
|
||||
amount: price,
|
||||
|
||||
@@ -156,6 +156,7 @@ const getReturnableItemsValues = (order: Order) => {
|
||||
thumbnail: item.thumbnail,
|
||||
refundable: item.refundable || 0,
|
||||
product_title: item.variant.product.title,
|
||||
sku: item.variant.sku,
|
||||
variant_title: item.variant.title,
|
||||
quantity: returnableQuantity,
|
||||
original_quantity: item.quantity,
|
||||
|
||||
Reference in New Issue
Block a user