Skip to content

Commit

Permalink
feat: update/create SO wil FO
Browse files Browse the repository at this point in the history
  • Loading branch information
fPolic committed Dec 16, 2024
1 parent ab7fa8c commit 225a526
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 17 deletions.
28 changes: 28 additions & 0 deletions packages/admin/dashboard/src/hooks/api/fulfillment-providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ export const fulfillmentProvidersQueryKeys = queryKeysFactory(
FULFILLMENT_PROVIDERS_QUERY_KEY
)

const FULFILLMENT_PROVIDER_OPTIONS_QUERY_KEY =
"fulfillment_provider_options" as const
export const fulfillmentProviderOptionsQueryKeys = queryKeysFactory(
FULFILLMENT_PROVIDER_OPTIONS_QUERY_KEY
)

export const useFulfillmentProviders = (
query?: HttpTypes.AdminFulfillmentProviderListParams,
options?: Omit<
Expand All @@ -29,3 +35,25 @@ export const useFulfillmentProviders = (

return { ...data, ...rest }
}

export const useFulfillmentProviderOptions = (
providerId: string,
options?: Omit<
UseQueryOptions<
HttpTypes.AdminFulfillmentProviderOptionsListResponse,
FetchError,
HttpTypes.AdminFulfillmentProviderOptionsListResponse,
QueryKey
>,
"queryFn" | "queryKey"
>
) => {
const { data, ...rest } = useQuery({
queryFn: () =>
sdk.admin.fulfillmentProvider.listFulfillmentOptions(providerId),
queryKey: fulfillmentProviderOptionsQueryKeys.list(providerId),
...options,
})

return { ...data, ...rest }
}
3 changes: 2 additions & 1 deletion packages/admin/dashboard/src/i18n/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1523,7 +1523,8 @@
"hint": "Whether customers can use this option during checkout."
},
"provider": "Fulfillment provider",
"profile": "Shipping profile"
"profile": "Shipping profile",
"fulfillmentOption": "Fulfillment option"
}
},
"serviceZones": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Heading, Input, RadioGroup, Text } from "@medusajs/ui"
import { UseFormReturn } from "react-hook-form"
import { Heading, Input, RadioGroup, Select, Text } from "@medusajs/ui"
import { UseFormReturn, useWatch } from "react-hook-form"
import { useTranslation } from "react-i18next"

import { HttpTypes } from "@medusajs/types"
Expand All @@ -12,6 +12,8 @@ import { sdk } from "../../../../../lib/client"
import { formatProvider } from "../../../../../lib/format-provider"
import { ShippingOptionPriceType } from "../../../common/constants"
import { CreateShippingOptionSchema } from "./schema"
import { useFulfillmentProviderOptions } from "../../../../../hooks/api/fulfillment-providers"
import { useEffect } from "react"

type CreateShippingOptionDetailsFormProps = {
form: UseFormReturn<CreateShippingOptionSchema>
Expand All @@ -28,6 +30,16 @@ export const CreateShippingOptionDetailsForm = ({
}: CreateShippingOptionDetailsFormProps) => {
const { t } = useTranslation()

const selectedProviderId = useWatch({
control: form.control,
name: "provider_id",
})

const { fulfillment_options: fulfillmentProviderOptions } =
useFulfillmentProviderOptions(selectedProviderId, {
enabled: !!selectedProviderId,
})

const shippingProfiles = useComboboxData({
queryFn: (params) => sdk.admin.shippingProfile.list(params),
queryKey: ["shipping_profiles"],
Expand All @@ -52,6 +64,10 @@ export const CreateShippingOptionDetailsForm = ({
})),
})

useEffect(() => {
form.setValue("fulfillment_option_id", undefined)
}, [selectedProviderId])

return (
<div className="flex flex-1 flex-col items-center overflow-y-auto">
<div className="flex w-full max-w-[720px] flex-col gap-y-8 px-6 py-16">
Expand Down Expand Up @@ -134,9 +150,6 @@ export const CreateShippingOptionDetailsForm = ({
)
}}
/>
</div>

<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
<Form.Field
control={form.control}
name="shipping_profile_id"
Expand All @@ -160,7 +173,9 @@ export const CreateShippingOptionDetailsForm = ({
)
}}
/>
</div>

<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
<Form.Field
control={form.control}
name="provider_id"
Expand Down Expand Up @@ -190,6 +205,43 @@ export const CreateShippingOptionDetailsForm = ({
)
}}
/>

<Form.Field
control={form.control}
name="fulfillment_option_id"
render={({ field }) => {
return (
<Form.Item>
<Form.Label>
{t(
"stockLocations.shippingOptions.fields.fulfillmentOption"
)}
</Form.Label>
<Form.Control>
<Select
{...field}
onValueChange={field.onChange}
disabled={!selectedProviderId}
key={selectedProviderId}
>
<Select.Trigger ref={field.ref}>
<Select.Value />
</Select.Trigger>

<Select.Content>
{fulfillmentProviderOptions?.map((option) => (
<Select.Item value={option.id} key={option.id}>
{option.name || option.id}
</Select.Item>
))}
</Select.Content>
</Select>
</Form.Control>
<Form.ErrorMessage />
</Form.Item>
)
}}
/>
</div>

<Divider />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export function CreateShippingOptionsForm({
enabled_in_store: true,
shipping_profile_id: "",
provider_id: "",
fulfillment_option_id: "",
region_prices: {},
currency_prices: {},
conditional_region_prices: {},
Expand Down Expand Up @@ -130,6 +131,7 @@ export function CreateShippingOptionsForm({
service_zone_id: zone.id,
shipping_profile_id: data.shipping_profile_id,
provider_id: data.provider_id,
fulfillment_option_id: data.fulfillment_option_id,
prices: allPrices,
rules: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const CreateShippingOptionDetailsSchema = z.object({
enabled_in_store: z.boolean(),
shipping_profile_id: z.string().min(1),
provider_id: z.string().min(1),
fulfillment_option_id: z.string().min(1),
})

export const ShippingOptionConditionalPriceSchema = z.object({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HttpTypes } from "@medusajs/types"
import { Button, Input, RadioGroup, toast } from "@medusajs/ui"
import { useForm } from "react-hook-form"
import { Button, Input, RadioGroup, Select, toast } from "@medusajs/ui"
import { useForm, useWatch } from "react-hook-form"
import { useTranslation } from "react-i18next"
import * as zod from "zod"

Expand All @@ -17,6 +17,7 @@ import { pick } from "../../../../../lib/common"
import { formatProvider } from "../../../../../lib/format-provider"
import { isOptionEnabledInStore } from "../../../../../lib/shipping-options"
import { ShippingOptionPriceType } from "../../../common/constants"
import { useFulfillmentProviderOptions } from "../../../../../hooks/api/fulfillment-providers"

type EditShippingOptionFormProps = {
locationId: string
Expand All @@ -29,6 +30,7 @@ const EditShippingOptionSchema = zod.object({
enabled_in_store: zod.boolean().optional(),
shipping_profile_id: zod.string(),
provider_id: zod.string(),
fulfillment_option_id: zod.string(),
})

export const EditShippingOptionForm = ({
Expand Down Expand Up @@ -71,9 +73,21 @@ export const EditShippingOptionForm = ({
enabled_in_store: isOptionEnabledInStore(shippingOption),
shipping_profile_id: shippingOption.shipping_profile_id,
provider_id: shippingOption.provider_id,
fulfillment_option_id: shippingOption.data
?.fulfillment_option_id as string,
},
})

const selectedProviderId = useWatch({
control: form.control,
name: "provider_id",
})

const { fulfillment_options: fulfillmentProviderOptions } =
useFulfillmentProviderOptions(selectedProviderId, {
enabled: !!selectedProviderId,
})

const { mutateAsync, isPending: isLoading } = useUpdateShippingOptions(
shippingOption.id
)
Expand All @@ -96,12 +110,18 @@ export const EditShippingOptionForm = ({
storeRule.value = values.enabled_in_store ? "true" : "false"
}

console.log(shippingOption)

await mutateAsync(
{
name: values.name,
price_type: values.price_type,
shipping_profile_id: values.shipping_profile_id,
provider_id: values.provider_id,
data: {
...(shippingOption.data ?? {}),
fulfillment_option_id: values.fulfillment_option_id,
},
rules,
},
{
Expand Down Expand Up @@ -238,6 +258,42 @@ export const EditShippingOptionForm = ({
)
}}
/>
<Form.Field
control={form.control}
name="fulfillment_option_id"
render={({ field }) => {
return (
<Form.Item>
<Form.Label>
{t(
"stockLocations.shippingOptions.fields.fulfillmentOption"
)}
</Form.Label>
<Form.Control>
<Select
{...field}
onValueChange={field.onChange}
disabled={!selectedProviderId}
key={selectedProviderId}
>
<Select.Trigger ref={field.ref}>
<Select.Value />
</Select.Trigger>

<Select.Content>
{fulfillmentProviderOptions?.map((option) => (
<Select.Item value={option.id} key={option.id}>
{option.name || option.id}
</Select.Item>
))}
</Select.Content>
</Select>
</Form.Control>
<Form.ErrorMessage />
</Form.Item>
)
}}
/>
</div>

<Divider />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ export const createShippingOptionsWorkflow = createWorkflow(
* so we can have simpler update flow for both cases and allow updating price_type.
*/
const prices = (option as any).prices ?? []

option.data = {
fulfillment_option_id: option.fulfillment_option_id,
...(option.data ?? {}),
}

delete (option as any).fulfillment_option_id

return {
shipping_option_index: index,
prices,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ export const updateShippingOptionsWorkflow = createWorkflow(
delete (option as FulfillmentWorkflow.UpdateFlatRateShippingOptionInput)
.prices

if (option.fulfillment_option_id) {
option.data = {
fulfillment_option_id: option.fulfillment_option_id,
...(option.data ?? {}),
}

delete (option as any).fulfillment_option_id
}

/**
* When we are updating an option to be calculated, remove the prices.
*/
Expand Down
37 changes: 28 additions & 9 deletions packages/core/js-sdk/src/admin/fulfillment-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,25 @@ export class FulfillmentProvider {
* This method retrieves a paginated list of fulfillment providers. It sends a request to the
* [List Fulfillment Providers](https://docs.medusajs.com/api/admin#fulfillment-providers_getfulfillmentproviders)
* API route.
*
*
* @param query - Filters and pagination configurations.
* @param headers - Headers to pass in the request.
* @returns The paginated list of providers.
*
*
* @example
* To retrieve the list of fulfillment providers:
*
*
* ```ts
* sdk.admin.fulfillmentProvider.list()
* .then(({ fulfillment_providers, count, limit, offset }) => {
* console.log(fulfillment_providers)
* })
* ```
*
*
* To configure the pagination, pass the `limit` and `offset` query parameters.
*
*
* For example, to retrieve only 10 items and skip 10 items:
*
*
* ```ts
* sdk.admin.fulfillmentProvider.list({
* limit: 10,
Expand All @@ -46,10 +46,10 @@ export class FulfillmentProvider {
* console.log(fulfillment_providers)
* })
* ```
*
*
* Using the `fields` query parameter, you can specify the fields and relations to retrieve
* in each fulfillment provider:
*
*
* ```ts
* sdk.admin.fulfillmentProvider.list({
* fields: "id"
Expand All @@ -58,7 +58,7 @@ export class FulfillmentProvider {
* console.log(fulfillment_providers)
* })
* ```
*
*
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations).
*/
async list(
Expand All @@ -74,4 +74,23 @@ export class FulfillmentProvider {
}
)
}

/**
* This method retrieves a list of fulfillment options for a given fulfillment provider. It sends a request to the
* [List Fulfillment Options](https://docs.medusajs.com/api/admin#fulfillment-providers_getfulfillmentprovideroptions)
* API route.
*
* @param id - The ID of the fulfillment provider.
* @param headers - Headers to pass in the request.
* @returns The list of fulfillment options.
*/
async listFulfillmentOptions(id: string, headers?: ClientHeaders) {
return await this.client.fetch<HttpTypes.AdminFulfillmentProviderOptionsListResponse>(
`/admin/fulfillment-providers/${id}/options`,
{
method: "GET",
headers,
}
)
}
}
Loading

0 comments on commit 225a526

Please sign in to comment.