feat(dashboard): Pickup option changes (#11306)

**What**
- update the create and edit shipping option flows to support pickup (shipping) option
- modify "mark as delivered" for pickup case

---

CLOSES CMRC-906 CMRC-907
This commit is contained in:
Frane Polić
2025-02-14 15:14:58 +01:00
committed by GitHub
parent 271337eb23
commit 5dc8a403ef
13 changed files with 310 additions and 126 deletions

View File

@@ -4806,6 +4806,9 @@
"markAsShipped": {
"type": "string"
},
"markAsPickedUp": {
"type": "string"
},
"markAsDelivered": {
"type": "string"
},
@@ -4915,13 +4918,17 @@
},
"fulfillmentDelivered": {
"type": "string"
},
"fulfillmentPickedUp": {
"type": "string"
}
},
"required": [
"created",
"canceled",
"fulfillmentShipped",
"fulfillmentDelivered"
"fulfillmentDelivered",
"fulfillmentPickedUp"
],
"additionalProperties": false
},
@@ -4952,6 +4959,7 @@
"available",
"inStock",
"markAsShipped",
"markAsPickedUp",
"markAsDelivered",
"itemsToFulfillDesc",
"locationDescription",
@@ -5754,6 +5762,23 @@
],
"additionalProperties": false
},
"pickupOptions": {
"type": "object",
"properties": {
"edit": {
"type": "object",
"properties": {
"header": {
"type": "string"
}
},
"required": ["header"],
"additionalProperties": false
}
},
"required": ["edit"],
"additionalProperties": false
},
"shippingOptions": {
"type": "object",
"properties": {
@@ -5779,6 +5804,25 @@
"required": ["header", "hint", "label", "successToast"],
"additionalProperties": false
},
"pickup": {
"type": "object",
"properties": {
"header": {
"type": "string"
},
"hint": {
"type": "string"
},
"label": {
"type": "string"
},
"successToast": {
"type": "string"
}
},
"required": ["header", "hint", "label", "successToast"],
"additionalProperties": false
},
"returns": {
"type": "object",
"properties": {
@@ -5815,7 +5859,7 @@
"type": "string"
}
},
"required": ["shipping", "returns", "tabs", "action"],
"required": ["shipping", "pickup", "returns", "tabs", "action"],
"additionalProperties": false
},
"delete": {
@@ -5996,6 +6040,12 @@
"shipping_other": {
"type": "string"
},
"pickup_one": {
"type": "string"
},
"pickup_other": {
"type": "string"
},
"returns_one": {
"type": "string"
},
@@ -6006,6 +6056,8 @@
"required": [
"shipping_one",
"shipping_other",
"pickup_one",
"pickup_other",
"returns_one",
"returns_other"
],
@@ -6201,6 +6253,7 @@
"fulfillmentSets",
"sidebar",
"salesChannels",
"pickupOptions",
"shippingOptions",
"serviceZones"
],

View File

@@ -1281,6 +1281,7 @@
"available": "Available",
"inStock": "In stock",
"markAsShipped": "Mark as shipped",
"markAsPickedUp": "Mark as picked up",
"markAsDelivered": "Mark as delivered",
"itemsToFulfillDesc": "Choose items and quantities to fulfill",
"locationDescription": "Choose which location you want to fulfill items from.",
@@ -1310,7 +1311,8 @@
"created": "Fulfillment created successfully",
"canceled": "Fulfillment successfully canceled",
"fulfillmentShipped": "Cannot cancel an already shipped fulfillment",
"fulfillmentDelivered": "Fulfillment marked as delivered successfully"
"fulfillmentDelivered": "Fulfillment marked as delivered successfully",
"fulfillmentPickedUp": "Fulfillment marked as picked up successfully"
},
"trackingLabel": "Tracking",
"shippingFromLabel": "Shipping from",
@@ -1520,6 +1522,11 @@
"action": "Connect sales channels",
"successToast": "Sales channels were successfully updated."
},
"pickupOptions": {
"edit": {
"header": "Edit Pickup Option"
}
},
"shippingOptions": {
"create": {
"shipping": {
@@ -1528,6 +1535,12 @@
"label": "Shipping options",
"successToast": "Shipping option {{name}} was successfully created."
},
"pickup": {
"header": "Create Pickup Option for {{zone}}",
"hint": "Create a new pickup option to define how products are picked up from this location.",
"label": "Pickup options",
"successToast": "Pickup option {{name}} was successfully created."
},
"returns": {
"header": "Create a Return Option for {{zone}}",
"hint": "Create a new return option to define how products are returned to this location.",
@@ -1591,6 +1604,8 @@
"count": {
"shipping_one": "{{count}} shipping option",
"shipping_other": "{{count}} shipping options",
"pickup_one": "{{count}} pickup option",
"pickup_other": "{{count}} pickup options",
"returns_one": "{{count}} return option",
"returns_other": "{{count}} return options"
},

View File

@@ -195,12 +195,14 @@ type ServiceZoneOptionsProps = {
zone: HttpTypes.AdminServiceZone
locationId: string
fulfillmentSetId: string
type: FulfillmentSetType
}
function ServiceZoneOptions({
zone,
locationId,
fulfillmentSetId,
type,
}: ServiceZoneOptionsProps) {
const { t } = useTranslation()
@@ -216,7 +218,7 @@ function ServiceZoneOptions({
<div className="flex flex-col gap-y-4 px-6 py-4">
<div className="item-center flex justify-between">
<span className="text-ui-fg-subtle txt-small self-center font-medium">
{t("stockLocations.shippingOptions.create.shipping.label")}
{t(`stockLocations.shippingOptions.create.${type}.label`)}
</span>
<LinkButton
to={`/settings/locations/${locationId}/fulfillment-set/${fulfillmentSetId}/service-zone/${zone.id}/shipping-option/create`}
@@ -274,9 +276,15 @@ type ServiceZoneProps = {
zone: HttpTypes.AdminServiceZone
locationId: string
fulfillmentSetId: string
type: FulfillmentSetType
}
function ServiceZone({ zone, locationId, fulfillmentSetId }: ServiceZoneProps) {
function ServiceZone({
zone,
locationId,
fulfillmentSetId,
type,
}: ServiceZoneProps) {
const { t } = useTranslation()
const prompt = usePrompt()
const [open, setOpen] = useState(true)
@@ -368,7 +376,7 @@ function ServiceZone({ zone, locationId, fulfillmentSetId }: ServiceZoneProps) {
/>
<span>·</span>
<Text className="text-ui-fg-subtle txt-small">
{t("stockLocations.shippingOptions.fields.count.shipping", {
{t(`stockLocations.shippingOptions.fields.count.${type}`, {
count: shippingOptionsCount,
})}
</Text>
@@ -427,6 +435,7 @@ function ServiceZone({ zone, locationId, fulfillmentSetId }: ServiceZoneProps) {
<ServiceZoneOptions
fulfillmentSetId={fulfillmentSetId}
locationId={locationId}
type={type}
zone={zone}
/>
)}
@@ -570,6 +579,7 @@ function FulfillmentSet(props: FulfillmentSetProps) {
{fulfillmentSet?.service_zones.map((zone) => (
<ServiceZone
zone={zone}
type={type}
key={zone.id}
locationId={locationId}
fulfillmentSetId={fulfillmentSet.id}

View File

@@ -10,7 +10,10 @@ import { Combobox } from "../../../../../components/inputs/combobox"
import { useComboboxData } from "../../../../../hooks/use-combobox-data"
import { sdk } from "../../../../../lib/client"
import { formatProvider } from "../../../../../lib/format-provider"
import { ShippingOptionPriceType } from "../../../common/constants"
import {
FulfillmentSetType,
ShippingOptionPriceType,
} from "../../../common/constants"
import { CreateShippingOptionSchema } from "./schema"
type CreateShippingOptionDetailsFormProps = {
@@ -20,6 +23,7 @@ type CreateShippingOptionDetailsFormProps = {
locationId: string
fulfillmentProviderOptions: HttpTypes.AdminFulfillmentProviderOption[]
selectedProviderId?: string
type: FulfillmentSetType
}
export const CreateShippingOptionDetailsForm = ({
@@ -29,9 +33,12 @@ export const CreateShippingOptionDetailsForm = ({
locationId,
fulfillmentProviderOptions,
selectedProviderId,
type,
}: CreateShippingOptionDetailsFormProps) => {
const { t } = useTranslation()
const isPickup = type === FulfillmentSetType.Pickup
const shippingProfiles = useComboboxData({
queryFn: (params) => sdk.admin.shippingProfile.list(params),
queryKey: ["shipping_profiles"],
@@ -63,7 +70,7 @@ export const CreateShippingOptionDetailsForm = ({
<Heading>
{t(
`stockLocations.shippingOptions.create.${
isReturn ? "returns" : "shipping"
isPickup ? "pickup" : isReturn ? "returns" : "shipping"
}.header`,
{
zone: zone.name,
@@ -73,54 +80,56 @@ export const CreateShippingOptionDetailsForm = ({
<Text size="small" className="text-ui-fg-subtle">
{t(
`stockLocations.shippingOptions.create.${
isReturn ? "returns" : "shipping"
isReturn ? "returns" : isPickup ? "pickup" : "shipping"
}.hint`
)}
</Text>
</div>
<Form.Field
control={form.control}
name="price_type"
render={({ field }) => {
return (
<Form.Item>
<Form.Label>
{t("stockLocations.shippingOptions.fields.priceType.label")}
</Form.Label>
<Form.Control>
<RadioGroup
className="grid grid-cols-1 gap-4 md:grid-cols-2"
{...field}
onValueChange={field.onChange}
>
<RadioGroup.ChoiceBox
className="flex-1"
value={ShippingOptionPriceType.FlatRate}
label={t(
"stockLocations.shippingOptions.fields.priceType.options.fixed.label"
)}
description={t(
"stockLocations.shippingOptions.fields.priceType.options.fixed.hint"
)}
/>
<RadioGroup.ChoiceBox
className="flex-1"
value={ShippingOptionPriceType.Calculated}
label={t(
"stockLocations.shippingOptions.fields.priceType.options.calculated.label"
)}
description={t(
"stockLocations.shippingOptions.fields.priceType.options.calculated.hint"
)}
/>
</RadioGroup>
</Form.Control>
<Form.ErrorMessage />
</Form.Item>
)
}}
/>
{!isPickup && (
<Form.Field
control={form.control}
name="price_type"
render={({ field }) => {
return (
<Form.Item>
<Form.Label>
{t("stockLocations.shippingOptions.fields.priceType.label")}
</Form.Label>
<Form.Control>
<RadioGroup
className="grid grid-cols-1 gap-4 md:grid-cols-2"
{...field}
onValueChange={field.onChange}
>
<RadioGroup.ChoiceBox
className="flex-1"
value={ShippingOptionPriceType.FlatRate}
label={t(
"stockLocations.shippingOptions.fields.priceType.options.fixed.label"
)}
description={t(
"stockLocations.shippingOptions.fields.priceType.options.fixed.hint"
)}
/>
<RadioGroup.ChoiceBox
className="flex-1"
value={ShippingOptionPriceType.Calculated}
label={t(
"stockLocations.shippingOptions.fields.priceType.options.calculated.label"
)}
description={t(
"stockLocations.shippingOptions.fields.priceType.options.calculated.hint"
)}
/>
</RadioGroup>
</Form.Control>
<Form.ErrorMessage />
</Form.Item>
)
}}
/>
)}
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
<Form.Field
@@ -238,16 +247,21 @@ export const CreateShippingOptionDetailsForm = ({
/>
</div>
<Divider />
<SwitchBox
control={form.control}
name="enabled_in_store"
label={t("stockLocations.shippingOptions.fields.enableInStore.label")}
description={t(
"stockLocations.shippingOptions.fields.enableInStore.hint"
)}
/>
{!isPickup && (
<>
<Divider />
<SwitchBox
control={form.control}
name="enabled_in_store"
label={t(
"stockLocations.shippingOptions.fields.enableInStore.label"
)}
description={t(
"stockLocations.shippingOptions.fields.enableInStore.hint"
)}
/>
</>
)}
</div>
</div>
)

View File

@@ -12,7 +12,10 @@ import {
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
import { useCreateShippingOptions } from "../../../../../hooks/api/shipping-options"
import { castNumber } from "../../../../../lib/cast-number"
import { ShippingOptionPriceType } from "../../../common/constants"
import {
FulfillmentSetType,
ShippingOptionPriceType,
} from "../../../common/constants"
import { buildShippingOptionPriceRules } from "../../../common/utils/price-rule-helpers"
import { CreateShippingOptionDetailsForm } from "./create-shipping-option-details-form"
import { CreateShippingOptionsPricesForm } from "./create-shipping-options-prices-form"
@@ -31,12 +34,14 @@ type CreateShippingOptionFormProps = {
zone: HttpTypes.AdminServiceZone
locationId: string
isReturn?: boolean
type: FulfillmentSetType
}
export function CreateShippingOptionsForm({
zone,
isReturn,
locationId,
type,
}: CreateShippingOptionFormProps) {
const [activeTab, setActiveTab] = useState<Tab>(Tab.DETAILS)
const [validDetails, setValidDetails] = useState(false)
@@ -309,13 +314,14 @@ export function CreateShippingOptionsForm({
form={form}
zone={zone}
isReturn={isReturn}
type={type}
locationId={locationId}
fulfillmentProviderOptions={fulfillmentProviderOptions || []}
selectedProviderId={selectedProviderId}
/>
</ProgressTabs.Content>
<ProgressTabs.Content value={Tab.PRICING} className="size-full">
<CreateShippingOptionsPricesForm form={form} />
<CreateShippingOptionsPricesForm form={form} type={type} />
</ProgressTabs.Content>
</RouteFocusModal.Body>
<RouteFocusModal.Footer>

View File

@@ -1,4 +1,4 @@
import { useMemo, useState } from "react"
import { useEffect, useMemo, useState } from "react"
import { UseFormReturn, useWatch } from "react-hook-form"
import { DataGrid } from "../../../../../components/data-grid"
@@ -12,18 +12,24 @@ import { useRegions } from "../../../../../hooks/api/regions"
import { useStore } from "../../../../../hooks/api/store"
import { ConditionalPriceForm } from "../../../common/components/conditional-price-form"
import { ShippingOptionPriceProvider } from "../../../common/components/shipping-option-price-provider"
import { CONDITIONAL_PRICES_STACKED_MODAL_ID } from "../../../common/constants"
import {
FulfillmentSetType,
CONDITIONAL_PRICES_STACKED_MODAL_ID,
} from "../../../common/constants"
import { useShippingOptionPriceColumns } from "../../../common/hooks/use-shipping-option-price-columns"
import { ConditionalPriceInfo } from "../../../common/types"
import { CreateShippingOptionSchema } from "./schema"
type PricingPricesFormProps = {
form: UseFormReturn<CreateShippingOptionSchema>
type: FulfillmentSetType
}
export const CreateShippingOptionsPricesForm = ({
form,
type,
}: PricingPricesFormProps) => {
const isPickup = type === FulfillmentSetType.Pickup
const { getIsOpen, setIsOpen } = useStackedModal()
const [selectedPrice, setSelectedPrice] =
useState<ConditionalPriceInfo | null>(null)
@@ -80,6 +86,25 @@ export const CreateShippingOptionsPricesForm = ({
[currencies, regions]
)
/**
* Prefill prices with 0 if createing a pickup (shipping) option
*/
useEffect(() => {
if (!isLoading && isPickup) {
if (currencies.length > 0) {
currencies.forEach((currency) => {
form.setValue(`currency_prices.${currency}`, "0")
})
}
if (regions.length > 0) {
regions.forEach((region) => {
form.setValue(`region_prices.${region.id}`, "0")
})
}
}
}, [isLoading, isPickup])
if (isStoreError) {
throw storeError
}

View File

@@ -4,6 +4,7 @@ import { RouteFocusModal } from "../../../components/modals"
import { useStockLocation } from "../../../hooks/api/stock-locations"
import { CreateShippingOptionsForm } from "./components/create-shipping-options-form"
import { LOC_CREATE_SHIPPING_OPTION_FIELDS } from "./constants"
import { FulfillmentSetType } from "../common/constants"
export function LocationServiceZoneShippingOptionCreate() {
const { location_id, fset_id, zone_id } = useParams()
@@ -15,9 +16,18 @@ export function LocationServiceZoneShippingOptionCreate() {
fields: LOC_CREATE_SHIPPING_OPTION_FIELDS,
})
const zone = stock_location?.fulfillment_sets
?.find((f) => f.id === fset_id)
?.service_zones?.find((z) => z.id === zone_id)
const fulfillmentSet = stock_location?.fulfillment_sets?.find(
(f) => f.id === fset_id
)
if (!isPending && !isFetching && !fulfillmentSet) {
throw json(
{ message: `Fulfillment set with ID ${fset_id} was not found` },
404
)
}
const zone = fulfillmentSet?.service_zones?.find((z) => z.id === zone_id)
if (!isPending && !isFetching && !zone) {
throw json(
@@ -37,6 +47,7 @@ export function LocationServiceZoneShippingOptionCreate() {
zone={zone}
isReturn={isReturn}
locationId={location_id!}
type={fulfillmentSet!.type as FulfillmentSetType}
/>
)}
</RouteFocusModal>

View File

@@ -15,11 +15,15 @@ import { useComboboxData } from "../../../../../hooks/use-combobox-data"
import { sdk } from "../../../../../lib/client"
import { pick } from "../../../../../lib/common"
import { isOptionEnabledInStore } from "../../../../../lib/shipping-options"
import { ShippingOptionPriceType } from "../../../common/constants"
import {
FulfillmentSetType,
ShippingOptionPriceType,
} from "../../../common/constants"
type EditShippingOptionFormProps = {
locationId: string
shippingOption: HttpTypes.AdminShippingOption
type: FulfillmentSetType
}
const EditShippingOptionSchema = zod.object({
@@ -32,10 +36,13 @@ const EditShippingOptionSchema = zod.object({
export const EditShippingOptionForm = ({
locationId,
shippingOption,
type,
}: EditShippingOptionFormProps) => {
const { t } = useTranslation()
const { handleSuccess } = useRouteModal()
const isPickup = type === FulfillmentSetType.Pickup
const shippingProfiles = useComboboxData({
queryFn: (params) => sdk.admin.shippingProfile.list(params),
queryKey: ["shipping_profiles"],
@@ -108,46 +115,48 @@ export const EditShippingOptionForm = ({
<RouteDrawer.Body>
<div className="flex flex-col gap-y-8">
<div className="flex flex-col gap-y-8">
<Form.Field
control={form.control}
name="price_type"
render={({ field }) => {
return (
<Form.Item>
<Form.Label>
{t(
"stockLocations.shippingOptions.fields.priceType.label"
)}
</Form.Label>
<Form.Control>
<RadioGroup {...field} onValueChange={field.onChange}>
<RadioGroup.ChoiceBox
className="flex-1"
value={ShippingOptionPriceType.FlatRate}
label={t(
"stockLocations.shippingOptions.fields.priceType.options.fixed.label"
)}
description={t(
"stockLocations.shippingOptions.fields.priceType.options.fixed.hint"
)}
/>
<RadioGroup.ChoiceBox
className="flex-1"
value={ShippingOptionPriceType.Calculated}
label={t(
"stockLocations.shippingOptions.fields.priceType.options.calculated.label"
)}
description={t(
"stockLocations.shippingOptions.fields.priceType.options.calculated.hint"
)}
/>
</RadioGroup>
</Form.Control>
<Form.ErrorMessage />
</Form.Item>
)
}}
/>
{!isPickup && (
<Form.Field
control={form.control}
name="price_type"
render={({ field }) => {
return (
<Form.Item>
<Form.Label>
{t(
"stockLocations.shippingOptions.fields.priceType.label"
)}
</Form.Label>
<Form.Control>
<RadioGroup {...field} onValueChange={field.onChange}>
<RadioGroup.ChoiceBox
className="flex-1"
value={ShippingOptionPriceType.FlatRate}
label={t(
"stockLocations.shippingOptions.fields.priceType.options.fixed.label"
)}
description={t(
"stockLocations.shippingOptions.fields.priceType.options.fixed.hint"
)}
/>
<RadioGroup.ChoiceBox
className="flex-1"
value={ShippingOptionPriceType.Calculated}
label={t(
"stockLocations.shippingOptions.fields.priceType.options.calculated.label"
)}
description={t(
"stockLocations.shippingOptions.fields.priceType.options.calculated.hint"
)}
/>
</RadioGroup>
</Form.Control>
<Form.ErrorMessage />
</Form.Item>
)
}}
/>
)}
<div className="grid gap-y-4">
<Form.Field
@@ -193,18 +202,21 @@ export const EditShippingOptionForm = ({
/>
</div>
<Divider />
<SwitchBox
control={form.control}
name="enabled_in_store"
label={t(
"stockLocations.shippingOptions.fields.enableInStore.label"
)}
description={t(
"stockLocations.shippingOptions.fields.enableInStore.hint"
)}
/>
{!isPickup && (
<>
<Divider />
<SwitchBox
control={form.control}
name="enabled_in_store"
label={t(
"stockLocations.shippingOptions.fields.enableInStore.label"
)}
description={t(
"stockLocations.shippingOptions.fields.enableInStore.hint"
)}
/>
</>
)}
</div>
</div>
</RouteDrawer.Body>

View File

@@ -5,6 +5,7 @@ import { json, useParams } from "react-router-dom"
import { RouteDrawer } from "../../../components/modals"
import { useShippingOptions } from "../../../hooks/api/shipping-options"
import { EditShippingOptionForm } from "./components/edit-region-form"
import { FulfillmentSetType } from "../common/constants"
export const LocationServiceZoneShippingOptionEdit = () => {
const { t } = useTranslation()
@@ -14,6 +15,7 @@ export const LocationServiceZoneShippingOptionEdit = () => {
const { shipping_options, isPending, isFetching, isError, error } =
useShippingOptions({
id: so_id,
fields: "+service_zone.fulfillment_set.type",
})
const shippingOption = shipping_options?.find((so) => so.id === so_id)
@@ -29,15 +31,27 @@ export const LocationServiceZoneShippingOptionEdit = () => {
throw error
}
const isPickup =
shippingOption?.service_zone.fulfillment_set.type ===
FulfillmentSetType.Pickup
return (
<RouteDrawer>
<RouteDrawer.Header>
<Heading>{t("stockLocations.shippingOptions.edit.header")}</Heading>
<Heading>
{t(
`stockLocations.${isPickup ? "pickupOptions" : "shippingOptions"}.edit.header`
)}
</Heading>
</RouteDrawer.Header>
{shippingOption && (
<EditShippingOptionForm
shippingOption={shippingOption}
locationId={location_id!}
type={
shippingOption.service_zone.fulfillment_set
.type as FulfillmentSetType
}
/>
)}
</RouteDrawer>

View File

@@ -30,6 +30,7 @@ import {
import { useStockLocation } from "../../../../../hooks/api/stock-locations"
import { formatProvider } from "../../../../../lib/format-provider"
import { getLocaleAmount } from "../../../../../lib/money-amount-helpers"
import { FulfillmentSetType } from "../../../../locations/common/constants"
type OrderFulfillmentSectionProps = {
order: AdminOrder
@@ -213,6 +214,10 @@ const Fulfillment = ({
const showLocation = !!fulfillment.location_id
const isPickUpFulfillment =
fulfillment.shipping_option?.service_zone.fulfillment_set.type ===
FulfillmentSetType.Pickup
const { stock_location, isError, error } = useStockLocation(
fulfillment.location_id!,
undefined,
@@ -222,7 +227,9 @@ const Fulfillment = ({
)
let statusText = fulfillment.requires_shipping
? "Awaiting shipping"
? isPickUpFulfillment
? "Awaiting pickup"
: "Awaiting shipping"
: "Awaiting delivery"
let statusColor: "blue" | "green" | "red" = "blue"
let statusTimestamp = fulfillment.created_at
@@ -251,7 +258,9 @@ const Fulfillment = ({
!fulfillment.canceled_at &&
!fulfillment.shipped_at &&
!fulfillment.delivered_at &&
fulfillment.requires_shipping
fulfillment.requires_shipping &&
!isPickUpFulfillment
const showDeliveryButton =
!fulfillment.canceled_at && !fulfillment.delivered_at
@@ -267,7 +276,13 @@ const Fulfillment = ({
if (res) {
await markAsDelivered(undefined, {
onSuccess: () => {
toast.success(t("orders.fulfillment.toast.fulfillmentDelivered"))
toast.success(
t(
isPickUpFulfillment
? "orders.fulfillment.toast.fulfillmentPickedUp"
: "orders.fulfillment.toast.fulfillmentDelivered"
)
)
},
onError: (e) => {
toast.error(e.message)
@@ -431,7 +446,11 @@ const Fulfillment = ({
<div className="bg-ui-bg-subtle flex items-center justify-end gap-x-2 rounded-b-xl px-4 py-4">
{showDeliveryButton && (
<Button onClick={handleMarkAsDelivered} variant="secondary">
{t("orders.fulfillment.markAsDelivered")}
{t(
isPickUpFulfillment
? "orders.fulfillment.markAsPickedUp"
: "orders.fulfillment.markAsDelivered"
)}
</Button>
)}

View File

@@ -37,6 +37,7 @@ const DEFAULT_RELATIONS = [
"*promotion",
"*shipping_methods",
"*fulfillments",
"+fulfillments.shipping_option.service_zone.fulfillment_set.type",
"*fulfillments.items",
"*fulfillments.labels",
"*fulfillments.labels",