fix(draft-order, medusa, types): ui polish (#13376)
**What** - ensure unique promotion changes are displayed in the activity section - check linked promotions by id and not code - list promotions - add id param - make address payload fields nullish - Add items view UI tweaks --- CLOSES SUP-2400
This commit is contained in:
1 parent
e67974ffe5
commit
0000ed6998
10 files changed
+114
-77
No files matched your search
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/draft-order": patch
|
||||||
|
"@medusajs/types": patch
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(draft-order,medusa,types): draft order promotion UI polish
|
||||||
@@ -1078,6 +1078,11 @@ export interface BaseOrderChange {
|
|||||||
* The order change action details.
|
* The order change action details.
|
||||||
*/
|
*/
|
||||||
export interface BaseOrderChangeAction {
|
export interface BaseOrderChangeAction {
|
||||||
|
/**
|
||||||
|
* The ordering of the order change action
|
||||||
|
*/
|
||||||
|
ordering: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ID of the order change action
|
* The ID of the order change action
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ export interface AdminGetPromotionsParams
|
|||||||
* Filter by promotion code.
|
* Filter by promotion code.
|
||||||
*/
|
*/
|
||||||
code?: string | string[] | OperatorMap<string>
|
code?: string | string[] | OperatorMap<string>
|
||||||
|
/**
|
||||||
|
* Filter by promotion ID.
|
||||||
|
*/
|
||||||
|
id?: string[] | string | OperatorMap<string>
|
||||||
/**
|
/**
|
||||||
* Filter by campaign ID to retrieve promotions by campaign.
|
* Filter by campaign ID to retrieve promotions by campaign.
|
||||||
*/
|
*/
|
||||||
@@ -51,7 +55,9 @@ export interface AdminGetPromotionsParams
|
|||||||
/**
|
/**
|
||||||
* Filter by the promotion's application method type.
|
* Filter by the promotion's application method type.
|
||||||
*/
|
*/
|
||||||
application_method_type?: ApplicationMethodTypeValues | ApplicationMethodTypeValues[]
|
application_method_type?:
|
||||||
|
| ApplicationMethodTypeValues
|
||||||
|
| ApplicationMethodTypeValues[]
|
||||||
/**
|
/**
|
||||||
* An array of filters to apply on the entity, where each item in the array is joined with an "and" condition.
|
* An array of filters to apply on the entity, where each item in the array is joined with an "and" condition.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -34,52 +34,52 @@ export interface UpsertOrderAddressDTO {
|
|||||||
/**
|
/**
|
||||||
* The company name.
|
* The company name.
|
||||||
*/
|
*/
|
||||||
company?: string
|
company?: string | null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The first name of the customer.
|
* The first name of the customer.
|
||||||
*/
|
*/
|
||||||
first_name?: string
|
first_name?: string | null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The last name of the customer.
|
* The last name of the customer.
|
||||||
*/
|
*/
|
||||||
last_name?: string
|
last_name?: string | null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The address 1 of the address.
|
* The address 1 of the address.
|
||||||
*/
|
*/
|
||||||
address_1?: string
|
address_1?: string | null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The address 2 of the address.
|
* The address 2 of the address.
|
||||||
*/
|
*/
|
||||||
address_2?: string
|
address_2?: string | null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The city of the address.
|
* The city of the address.
|
||||||
*/
|
*/
|
||||||
city?: string
|
city?: string | null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The country code of the address.
|
* The country code of the address.
|
||||||
*/
|
*/
|
||||||
country_code?: string
|
country_code?: string | null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The lower-case [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) province of the address.
|
* The lower-case [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) province of the address.
|
||||||
*/
|
*/
|
||||||
province?: string
|
province?: string | null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The postal code of the address.
|
* The postal code of the address.
|
||||||
*/
|
*/
|
||||||
postal_code?: string
|
postal_code?: string | null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The phone of the address.
|
* The phone of the address.
|
||||||
*/
|
*/
|
||||||
phone?: string
|
phone?: string | null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds custom data in key-value pairs.
|
* Holds custom data in key-value pairs.
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ export const AdminGetPromotionsParamsFields = z.object({
|
|||||||
code: z
|
code: z
|
||||||
.union([z.string(), z.array(z.string()), createOperatorMap()])
|
.union([z.string(), z.array(z.string()), createOperatorMap()])
|
||||||
.optional(),
|
.optional(),
|
||||||
|
id: z
|
||||||
|
.union([z.string(), z.array(z.string()), createOperatorMap()])
|
||||||
|
.optional(),
|
||||||
campaign_id: z.union([z.string(), z.array(z.string())]).optional(),
|
campaign_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
application_method: z
|
application_method: z
|
||||||
.object({
|
.object({
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ import { z } from "zod"
|
|||||||
|
|
||||||
export const AddressPayload = z
|
export const AddressPayload = z
|
||||||
.object({
|
.object({
|
||||||
first_name: z.string().optional(),
|
first_name: z.string().nullish(),
|
||||||
last_name: z.string().optional(),
|
last_name: z.string().nullish(),
|
||||||
phone: z.string().optional(),
|
phone: z.string().nullish(),
|
||||||
company: z.string().optional(),
|
company: z.string().nullish(),
|
||||||
address_1: z.string().optional(),
|
address_1: z.string().nullish(),
|
||||||
address_2: z.string().optional(),
|
address_2: z.string().nullish(),
|
||||||
city: z.string().optional(),
|
city: z.string().nullish(),
|
||||||
country_code: z.string().optional(),
|
country_code: z.string().nullish(),
|
||||||
province: z.string().optional(),
|
province: z.string().nullish(),
|
||||||
postal_code: z.string().optional(),
|
postal_code: z.string().nullish(),
|
||||||
metadata: z.record(z.unknown()).optional(),
|
metadata: z.record(z.unknown()).nullish(),
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
|
|
||||||
|
|||||||
+35
-19
@@ -26,7 +26,7 @@ export const ActivitySection = ({ order, changes }: ActivitySectionProps) => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className="p-0 overflow-hidden">
|
<Container className="overflow-hidden p-0">
|
||||||
<div className="px-6 py-4">
|
<div className="px-6 py-4">
|
||||||
<Heading>Activity</Heading>
|
<Heading>Activity</Heading>
|
||||||
</div>
|
</div>
|
||||||
@@ -83,9 +83,9 @@ const CollapsibleActivityItemList = ({
|
|||||||
{!open && (
|
{!open && (
|
||||||
<div className="grid grid-cols-[20px_1fr] items-start gap-2">
|
<div className="grid grid-cols-[20px_1fr] items-start gap-2">
|
||||||
<div className="flex size-full flex-col items-center">
|
<div className="flex size-full flex-col items-center">
|
||||||
<div className="border-ui-border-strong w-px flex-1 bg-[linear-gradient(var(--border-strong)_33%,rgba(255,255,255,0)_0%)] bg-[length:1px_3px] bg-right bg-repeat-y bg-clip-content" />
|
<div className="border-ui-border-strong w-px flex-1 bg-[linear-gradient(var(--border-strong)_33%,rgba(255,255,255,0)_0%)] bg-[length:1px_3px] bg-clip-content bg-right bg-repeat-y" />
|
||||||
</div>
|
</div>
|
||||||
<Collapsible.Trigger className="text-left p-0 m-0 pb-4 text-ui-fg-muted hover:text-ui-fg-base focus:text-ui-fg-base outline-none transition-colors">
|
<Collapsible.Trigger className="text-ui-fg-muted hover:text-ui-fg-base focus:text-ui-fg-base m-0 p-0 pb-4 text-left outline-none transition-colors">
|
||||||
<Text size="small" leading="compact" weight="plus">
|
<Text size="small" leading="compact" weight="plus">
|
||||||
{`Show ${items.length} more ${
|
{`Show ${items.length} more ${
|
||||||
items.length === 1 ? "activity" : "activities"
|
items.length === 1 ? "activity" : "activities"
|
||||||
@@ -130,22 +130,22 @@ const ActivityItem = ({ item, isFirst = false }: ActivityItemProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clx("grid grid-cols-[20px_1fr] items-start gap-x-2 w-full")}
|
className={clx("grid w-full grid-cols-[20px_1fr] items-start gap-x-2")}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col items-center gap-0.5 h-full">
|
<div className="flex h-full flex-col items-center gap-0.5">
|
||||||
<div className="size-5 flex items-center justify-center">
|
<div className="flex size-5 items-center justify-center">
|
||||||
<div className="size-2.5 rounded-full shadow-borders-base flex items-center justify-center">
|
<div className="shadow-borders-base flex size-2.5 items-center justify-center rounded-full">
|
||||||
<div className="size-1.5 rounded-full bg-ui-tag-neutral-icon" />
|
<div className="bg-ui-tag-neutral-icon size-1.5 rounded-full" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!isFirst && (
|
{!isFirst && (
|
||||||
<div className="flex flex-1 items-center justify-center">
|
<div className="flex flex-1 items-center justify-center">
|
||||||
<div className="h-full w-px bg-ui-border-base" />
|
<div className="bg-ui-border-base h-full w-px" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={clx("flex flex-col", !isFirst && "pb-4")}>
|
<div className={clx("flex flex-col", !isFirst && "pb-4")}>
|
||||||
<div className="flex items-center gap-x-2 justify-between">
|
<div className="flex items-center justify-between gap-x-2">
|
||||||
<Text size="small" weight="plus" leading="compact">
|
<Text size="small" weight="plus" leading="compact">
|
||||||
{item.label}
|
{item.label}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -159,10 +159,10 @@ const ActivityItem = ({ item, isFirst = false }: ActivityItemProps) => {
|
|||||||
</div>
|
</div>
|
||||||
{item.content && renderContent(item.content)}
|
{item.content && renderContent(item.content)}
|
||||||
{item.userId && (
|
{item.userId && (
|
||||||
<div className="pt-2 text-ui-fg-muted">
|
<div className="text-ui-fg-muted pt-2">
|
||||||
{isUserLoaded ? (
|
{isUserLoaded ? (
|
||||||
<Link to={`/settings/users/${user.id}`} className="w-fit">
|
<Link to={`/settings/users/${user.id}`} className="w-fit">
|
||||||
<div className="flex items-center gap-x-1.5 w-fit">
|
<div className="flex w-fit items-center gap-x-1.5">
|
||||||
<Text size="small">By</Text>
|
<Text size="small">By</Text>
|
||||||
<Avatar
|
<Avatar
|
||||||
size="2xsmall"
|
size="2xsmall"
|
||||||
@@ -179,8 +179,8 @@ const ActivityItem = ({ item, isFirst = false }: ActivityItemProps) => {
|
|||||||
) : (
|
) : (
|
||||||
<div className="flex items-center gap-x-1.5">
|
<div className="flex items-center gap-x-1.5">
|
||||||
<Text size="small">By</Text>
|
<Text size="small">By</Text>
|
||||||
<Skeleton className="rounded-full w-5 h-5" />
|
<Skeleton className="h-5 w-5 rounded-full" />
|
||||||
<Skeleton className="w-[75px] h-4" />
|
<Skeleton className="h-4 w-[75px]" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -215,7 +215,14 @@ function getEditActivityItems(
|
|||||||
promotionsRemoved: 0,
|
promotionsRemoved: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const action of change.actions) {
|
const orderedActions = change.actions.sort((a, b) => {
|
||||||
|
return a.ordering - b.ordering
|
||||||
|
})
|
||||||
|
|
||||||
|
const addedPromotionMap = new Map<string, true>()
|
||||||
|
const removedPromotionMap = new Map<string, true>()
|
||||||
|
|
||||||
|
for (const action of orderedActions) {
|
||||||
if (!action.details) {
|
if (!action.details) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -234,13 +241,22 @@ function getEditActivityItems(
|
|||||||
case "SHIPPING_REMOVE":
|
case "SHIPPING_REMOVE":
|
||||||
counts.shippingMethodsRemoved += 1
|
counts.shippingMethodsRemoved += 1
|
||||||
break
|
break
|
||||||
case "PROMOTION_ADD":
|
case "PROMOTION_ADD": {
|
||||||
counts.promotionsAdded += 1
|
addedPromotionMap.set(action.reference_id!, true)
|
||||||
break
|
break
|
||||||
case "PROMOTION_REMOVE":
|
}
|
||||||
counts.promotionsRemoved += 1
|
case "PROMOTION_REMOVE": {
|
||||||
|
if (addedPromotionMap.has(action.reference_id!)) {
|
||||||
|
addedPromotionMap.delete(action.reference_id!)
|
||||||
|
} else {
|
||||||
|
removedPromotionMap.set(action.reference_id!, true)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
counts.promotionsAdded = addedPromotionMap.size
|
||||||
|
counts.promotionsRemoved = removedPromotionMap.size
|
||||||
}
|
}
|
||||||
|
|
||||||
const createActivityItem = (
|
const createActivityItem = (
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ export const addressSchema = z.object({
|
|||||||
first_name: z.string().min(1),
|
first_name: z.string().min(1),
|
||||||
last_name: z.string().min(1),
|
last_name: z.string().min(1),
|
||||||
address_1: z.string().min(1),
|
address_1: z.string().min(1),
|
||||||
address_2: z.string().optional(),
|
address_2: z.string().nullish(),
|
||||||
company: z.string().optional(),
|
company: z.string().nullish(),
|
||||||
city: z.string().min(1),
|
city: z.string().min(1),
|
||||||
province: z.string().optional(),
|
province: z.string().nullish(),
|
||||||
postal_code: z.string().min(1),
|
postal_code: z.string().min(1),
|
||||||
phone: z.string().optional(),
|
phone: z.string().nullish(),
|
||||||
})
|
})
|
||||||
@@ -216,7 +216,7 @@ const ItemsForm = ({ preview, currencyCode }: ItemsFormProps) => {
|
|||||||
</RouteFocusModal.Title>
|
</RouteFocusModal.Title>
|
||||||
<RouteFocusModal.Description asChild>
|
<RouteFocusModal.Description asChild>
|
||||||
<Text size="small" className="text-ui-fg-subtle">
|
<Text size="small" className="text-ui-fg-subtle">
|
||||||
Edit the items in the draft order.
|
Edit the items in the draft order
|
||||||
</Text>
|
</Text>
|
||||||
</RouteFocusModal.Description>
|
</RouteFocusModal.Description>
|
||||||
</div>
|
</div>
|
||||||
@@ -261,7 +261,7 @@ const ItemsForm = ({ preview, currencyCode }: ItemsFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl">
|
<div className="bg-ui-bg-subtle shadow-elevation-card-rest rounded-xl">
|
||||||
<div className="px-[5px]">
|
<div className="px-[5px]">
|
||||||
<div className="grid grid-cols-[1fr_1fr_1fr_28px] gap-3 px-4 py-2 text-ui-fg-muted">
|
<div className="text-ui-fg-muted grid grid-cols-[2fr_1fr_2fr_28px] gap-3 px-4 py-2">
|
||||||
<div>
|
<div>
|
||||||
<Text size="small" weight="plus">
|
<Text size="small" weight="plus">
|
||||||
Item
|
Item
|
||||||
@@ -282,7 +282,7 @@ const ItemsForm = ({ preview, currencyCode }: ItemsFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-y-1.5 px-[5px] pb-[5px]">
|
<div className="flex flex-col gap-y-1.5 px-[5px] pb-[5px]">
|
||||||
{itemCount <= 0 ? (
|
{itemCount <= 0 ? (
|
||||||
<div className="flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1">
|
<div className="bg-ui-bg-base shadow-elevation-card-rest flex flex-col items-center justify-center gap-1 gap-x-3 rounded-lg p-4">
|
||||||
<Text size="small" weight="plus" leading="compact">
|
<Text size="small" weight="plus" leading="compact">
|
||||||
There are no items in this order
|
There are no items in this order
|
||||||
</Text>
|
</Text>
|
||||||
@@ -300,7 +300,7 @@ const ItemsForm = ({ preview, currencyCode }: ItemsFormProps) => {
|
|||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<div className="flex items-center justify-center gap-x-3 bg-ui-bg-base rounded-lg p-4 shadow-elevation-card-rest flex-col gap-1">
|
<div className="bg-ui-bg-base shadow-elevation-card-rest flex flex-col items-center justify-center gap-1 gap-x-3 rounded-lg p-4">
|
||||||
<Text size="small" weight="plus" leading="compact">
|
<Text size="small" weight="plus" leading="compact">
|
||||||
No items found
|
No items found
|
||||||
</Text>
|
</Text>
|
||||||
@@ -348,7 +348,7 @@ const ItemsForm = ({ preview, currencyCode }: ItemsFormProps) => {
|
|||||||
</StackedFocusModal>
|
</StackedFocusModal>
|
||||||
</RouteFocusModal.Body>
|
</RouteFocusModal.Body>
|
||||||
<RouteFocusModal.Footer>
|
<RouteFocusModal.Footer>
|
||||||
<div className="flex items-center gap-x-2 justify-end">
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
<RouteFocusModal.Close asChild>
|
<RouteFocusModal.Close asChild>
|
||||||
<Button size="small" variant="secondary" type="button">
|
<Button size="small" variant="secondary" type="button">
|
||||||
Cancel
|
Cancel
|
||||||
@@ -461,8 +461,8 @@ const VariantItem = ({ item, preview, currencyCode }: ItemProps) => {
|
|||||||
return (
|
return (
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={onSubmit}>
|
<form onSubmit={onSubmit}>
|
||||||
<div className="grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center">
|
<div className="bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,2fr)_28px] items-center gap-3 rounded-lg px-4 py-2">
|
||||||
<div className="flex items-center gap-x-3 w-full">
|
<div className="flex w-full items-center gap-x-3">
|
||||||
<Thumbnail
|
<Thumbnail
|
||||||
thumbnail={item.thumbnail}
|
thumbnail={item.thumbnail}
|
||||||
alt={item.product_title ?? undefined}
|
alt={item.product_title ?? undefined}
|
||||||
@@ -490,7 +490,7 @@ const VariantItem = ({ item, preview, currencyCode }: ItemProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{editing ? (
|
{editing ? (
|
||||||
<div className="flex-1 w-full">
|
<div className="w-full flex-1">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="quantity"
|
name="quantity"
|
||||||
@@ -506,14 +506,14 @@ const VariantItem = ({ item, preview, currencyCode }: ItemProps) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex-1 w-full">
|
<div className="w-full flex-1">
|
||||||
<Text size="small" weight="plus">
|
<Text size="small" weight="plus">
|
||||||
{item.quantity}
|
{item.quantity}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{editing ? (
|
{editing ? (
|
||||||
<div className="flex-1 w-full">
|
<div className="w-full flex-1">
|
||||||
<Form.Field
|
<Form.Field
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="unit_price"
|
name="unit_price"
|
||||||
@@ -536,7 +536,7 @@ const VariantItem = ({ item, preview, currencyCode }: ItemProps) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex-1 flex items-center justify-end w-full">
|
<div className="flex w-full flex-1 items-center justify-end">
|
||||||
<Text size="small" weight="plus">
|
<Text size="small" weight="plus">
|
||||||
{getLocaleAmount(item.unit_price, currencyCode)}
|
{getLocaleAmount(item.unit_price, currencyCode)}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -670,7 +670,7 @@ const CustomItem = ({ item, preview, currencyCode }: ItemProps) => {
|
|||||||
return (
|
return (
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={onSubmit}>
|
<form onSubmit={onSubmit}>
|
||||||
<div className="grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)_28px] gap-3 px-4 py-2 bg-ui-bg-base shadow-elevation-card-rest rounded-lg items-center">
|
<div className="bg-ui-bg-base shadow-elevation-card-rest grid grid-cols-[minmax(0,2fr)_minmax(0,1fr)_minmax(0,2fr)_28px] items-center gap-3 rounded-lg px-4 py-2">
|
||||||
<div className="flex items-center gap-x-3">
|
<div className="flex items-center gap-x-3">
|
||||||
<Thumbnail
|
<Thumbnail
|
||||||
thumbnail={item.thumbnail}
|
thumbnail={item.thumbnail}
|
||||||
@@ -737,7 +737,7 @@ const CustomItem = ({ item, preview, currencyCode }: ItemProps) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex-1 flex items-center justify-end">
|
<div className="flex flex-1 items-center justify-end">
|
||||||
<Text size="small" weight="plus">
|
<Text size="small" weight="plus">
|
||||||
{getLocaleAmount(item.unit_price, currencyCode)}
|
{getLocaleAmount(item.unit_price, currencyCode)}
|
||||||
</Text>
|
</Text>
|
||||||
@@ -917,7 +917,7 @@ const ExistingItemsForm = ({ orderId, items }: ExistingItemsFormProps) => {
|
|||||||
/>
|
/>
|
||||||
</StackedFocusModal.Body>
|
</StackedFocusModal.Body>
|
||||||
<StackedFocusModal.Footer>
|
<StackedFocusModal.Footer>
|
||||||
<div className="flex items-center gap-x-2 justify-end">
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
<StackedFocusModal.Close asChild>
|
<StackedFocusModal.Close asChild>
|
||||||
<Button size="small" variant="secondary" type="button">
|
<Button size="small" variant="secondary" type="button">
|
||||||
Cancel
|
Cancel
|
||||||
@@ -1120,9 +1120,9 @@ const CustomItemForm = ({ orderId, currencyCode }: CustomItemFormProps) => {
|
|||||||
<Form.Label>Quantity</Form.Label>
|
<Form.Label>Quantity</Form.Label>
|
||||||
<Form.Hint>Enter the quantity of the item</Form.Hint>
|
<Form.Hint>Enter the quantity of the item</Form.Hint>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 w-full">
|
<div className="w-full flex-1">
|
||||||
<Form.Control>
|
<Form.Control>
|
||||||
<div className="flex-1 w-full">
|
<div className="w-full flex-1">
|
||||||
<NumberInput {...field} className="w-full" />
|
<NumberInput {...field} className="w-full" />
|
||||||
</div>
|
</div>
|
||||||
</Form.Control>
|
</Form.Control>
|
||||||
@@ -1136,7 +1136,7 @@ const CustomItemForm = ({ orderId, currencyCode }: CustomItemFormProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</StackedFocusModal.Body>
|
</StackedFocusModal.Body>
|
||||||
<StackedFocusModal.Footer>
|
<StackedFocusModal.Footer>
|
||||||
<div className="flex items-center gap-x-2 justify-end">
|
<div className="flex items-center justify-end gap-x-2">
|
||||||
<StackedFocusModal.Close asChild>
|
<StackedFocusModal.Close asChild>
|
||||||
<Button size="small" variant="secondary" type="button">
|
<Button size="small" variant="secondary" type="button">
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
+15
-15
@@ -78,24 +78,24 @@ const PromotionForm = ({ preview }: PromotionFormProps) => {
|
|||||||
const { mutateAsync: addPromotions, isPending: isAddingPromotions } =
|
const { mutateAsync: addPromotions, isPending: isAddingPromotions } =
|
||||||
useDraftOrderAddPromotions(preview.id)
|
useDraftOrderAddPromotions(preview.id)
|
||||||
|
|
||||||
const promoCodes = getPromotionCodes(items, shipping_methods)
|
const promoIds = getPromotionIds(items, shipping_methods)
|
||||||
|
|
||||||
const { promotions, isPending, isError, error } = usePromotions(
|
const { promotions, isPending, isError, error } = usePromotions(
|
||||||
{
|
{
|
||||||
code: promoCodes,
|
id: promoIds,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: !!promoCodes.length,
|
enabled: !!promoIds.length,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const comboboxData = useComboboxData({
|
const comboboxData = useComboboxData({
|
||||||
queryKey: ["promotions", "combobox", promoCodes],
|
queryKey: ["promotions", "combobox", promoIds],
|
||||||
queryFn: async (params) => {
|
queryFn: async (params) => {
|
||||||
return await sdk.admin.promotion.list({
|
return await sdk.admin.promotion.list({
|
||||||
...params,
|
...params,
|
||||||
code: {
|
id: {
|
||||||
$nin: promoCodes,
|
$nin: promoIds,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -261,7 +261,7 @@ const PromotionItem = ({
|
|||||||
<div
|
<div
|
||||||
key={promotion.id}
|
key={promotion.id}
|
||||||
className={clx(
|
className={clx(
|
||||||
"px-3 py-2 rounded-lg bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between",
|
"bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
|
||||||
{
|
{
|
||||||
"animate-pulse": isLoading,
|
"animate-pulse": isLoading,
|
||||||
}
|
}
|
||||||
@@ -271,7 +271,7 @@ const PromotionItem = ({
|
|||||||
<Text size="small" weight="plus" leading="compact">
|
<Text size="small" weight="plus" leading="compact">
|
||||||
{promotion.code}
|
{promotion.code}
|
||||||
</Text>
|
</Text>
|
||||||
<div className="flex items-center gap-1.5 text-ui-fg-subtle">
|
<div className="text-ui-fg-subtle flex items-center gap-1.5">
|
||||||
{displayValue && (
|
{displayValue && (
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<Text size="small" leading="compact">
|
<Text size="small" leading="compact">
|
||||||
@@ -337,17 +337,17 @@ const formatPercentage = (value?: number | null, isPercentageValue = false) => {
|
|||||||
return formatter.format(val)
|
return formatter.format(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPromotionCodes(
|
function getPromotionIds(
|
||||||
items: HttpTypes.AdminOrderPreview["items"],
|
items: HttpTypes.AdminOrderPreview["items"],
|
||||||
shippingMethods: HttpTypes.AdminOrderPreview["shipping_methods"]
|
shippingMethods: HttpTypes.AdminOrderPreview["shipping_methods"]
|
||||||
) {
|
) {
|
||||||
const codes = new Set<string>()
|
const promotionIds = new Set<string>()
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
if (item.adjustments) {
|
if (item.adjustments) {
|
||||||
for (const adjustment of item.adjustments) {
|
for (const adjustment of item.adjustments) {
|
||||||
if (adjustment.code) {
|
if (adjustment.promotion_id) {
|
||||||
codes.add(adjustment.code)
|
promotionIds.add(adjustment.promotion_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -356,14 +356,14 @@ function getPromotionCodes(
|
|||||||
for (const shippingMethod of shippingMethods) {
|
for (const shippingMethod of shippingMethods) {
|
||||||
if (shippingMethod.adjustments) {
|
if (shippingMethod.adjustments) {
|
||||||
for (const adjustment of shippingMethod.adjustments) {
|
for (const adjustment of shippingMethod.adjustments) {
|
||||||
if (adjustment.code) {
|
if (adjustment.promotion_id) {
|
||||||
codes.add(adjustment.code)
|
promotionIds.add(adjustment.promotion_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Array.from(codes)
|
return Array.from(promotionIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Promotions
|
export default Promotions
|
||||||
Reference in new issue
Block a user