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:
Kasper Fabricius Kristensen
2023-03-05 18:17:45 +01:00
committed by GitHub
parent d4e3e119de
commit 67ba8be02b
9 changed files with 91 additions and 35 deletions
@@ -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}
@@ -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} />,
@@ -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>
@@ -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>
)
@@ -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}
@@ -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,