feat(dashboard, js-sdk): shipping option type mngmt dashboard (#13208)
* chore(types, api): support shipping option type api endpoints * core flows * api * typos * compiler errors * integration tests * remove metadata * changeset * modify test * upsert * change remote query * minor to patch * description optional * chore(dashboard, js-sdk): shipping option type management on admin dashboard * description optional * woops my bad * my bad again * create and edit * prettier * build code from label * remove metadata route * remove some translation text that is not used * remove unsued files * changeset * adapt test * fix test * suggestion --------- Co-authored-by: william bouchard <williambouchard@williams-MacBook-Pro.local>
This commit is contained in:
8
.changeset/tame-grapes-jump.md
Normal file
8
.changeset/tame-grapes-jump.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
"@medusajs/fulfillment": patch
|
||||
"@medusajs/admin-shared": patch
|
||||
"@medusajs/dashboard": patch
|
||||
"@medusajs/js-sdk": patch
|
||||
---
|
||||
|
||||
feat(dashboard, js-sdk): shipping option type mngmt dashboard
|
||||
@@ -66,6 +66,23 @@ medusaIntegrationTestRunner({
|
||||
})
|
||||
|
||||
it("returns a list of shipping option types matching free text search param", async () => {
|
||||
const res = await api.get("/admin/shipping-option-types?q=st1", adminHeaders)
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
|
||||
expect(res.data.shipping_option_types).toEqual([
|
||||
{
|
||||
id: expect.stringMatching(/sotype_.{24}/),
|
||||
label: "Test1",
|
||||
code: "test1",
|
||||
description: "Test1 description",
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it("returns a list of shipping option types matching code search param", async () => {
|
||||
const res = await api.get("/admin/shipping-option-types?code=test1", adminHeaders)
|
||||
|
||||
expect(res.status).toEqual(200)
|
||||
|
||||
@@ -55,6 +55,13 @@ const PRODUCT_CATEGORY_INJECTION_ZONES = [
|
||||
"product_category.list.after",
|
||||
] as const
|
||||
|
||||
const SHIPPING_OPTION_TYPE_INJECTION_ZONES = [
|
||||
"shipping_option_type.details.before",
|
||||
"shipping_option_type.details.after",
|
||||
"shipping_option_type.list.before",
|
||||
"shipping_option_type.list.after",
|
||||
] as const
|
||||
|
||||
const PRODUCT_TYPE_INJECTION_ZONES = [
|
||||
"product_type.details.before",
|
||||
"product_type.details.after",
|
||||
@@ -204,6 +211,7 @@ export const INJECTION_ZONES = [
|
||||
...PRODUCT_COLLECTION_INJECTION_ZONES,
|
||||
...PRODUCT_CATEGORY_INJECTION_ZONES,
|
||||
...PRODUCT_TYPE_INJECTION_ZONES,
|
||||
...SHIPPING_OPTION_TYPE_INJECTION_ZONES,
|
||||
...PRODUCT_TAG_INJECTION_ZONES,
|
||||
...PRICE_LIST_INJECTION_ZONES,
|
||||
...PROMOTION_INJECTION_ZONES,
|
||||
|
||||
@@ -47,6 +47,10 @@ const useSettingRoutes = (): INavItem[] => {
|
||||
label: t("salesChannels.domain"),
|
||||
to: "/settings/sales-channels",
|
||||
},
|
||||
{
|
||||
label: t("shippingOptionTypes.domain"),
|
||||
to: "/settings/shipping-option-types",
|
||||
},
|
||||
{
|
||||
label: t("productTypes.domain"),
|
||||
to: "/settings/product-types",
|
||||
|
||||
@@ -1369,6 +1369,59 @@ export function getRouteMap({
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "shipping-option-types",
|
||||
errorElement: <ErrorBoundary />,
|
||||
element: <Outlet />,
|
||||
handle: {
|
||||
breadcrumb: () => t("shippingOptionTypes.domain"),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
lazy: () =>
|
||||
import(
|
||||
"../../routes/shipping-option-types/shipping-option-type-list"
|
||||
),
|
||||
children: [
|
||||
{
|
||||
path: "create",
|
||||
lazy: () =>
|
||||
import(
|
||||
"../../routes/shipping-option-types/shipping-option-type-create"
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: ":id",
|
||||
lazy: async () => {
|
||||
const { Component, Breadcrumb, loader } = await import(
|
||||
"../../routes/shipping-option-types/shipping-option-type-detail"
|
||||
)
|
||||
|
||||
return {
|
||||
Component,
|
||||
loader,
|
||||
handle: {
|
||||
breadcrumb: (
|
||||
match: UIMatch<HttpTypes.AdminShippingOptionTypeResponse>
|
||||
) => <Breadcrumb {...match} />,
|
||||
},
|
||||
}
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "edit",
|
||||
lazy: () =>
|
||||
import(
|
||||
"../../routes/shipping-option-types/shipping-option-type-edit"
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "product-types",
|
||||
errorElement: <ErrorBoundary />,
|
||||
|
||||
@@ -26,6 +26,7 @@ export * from "./regions"
|
||||
export * from "./reservations"
|
||||
export * from "./sales-channels"
|
||||
export * from "./shipping-options"
|
||||
export * from "./shipping-option-types"
|
||||
export * from "./shipping-profiles"
|
||||
export * from "./stock-locations"
|
||||
export * from "./store"
|
||||
|
||||
128
packages/admin/dashboard/src/hooks/api/shipping-option-types.tsx
Normal file
128
packages/admin/dashboard/src/hooks/api/shipping-option-types.tsx
Normal file
@@ -0,0 +1,128 @@
|
||||
import { FetchError } from "@medusajs/js-sdk"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import {
|
||||
QueryKey,
|
||||
useMutation,
|
||||
UseMutationOptions,
|
||||
useQuery,
|
||||
UseQueryOptions,
|
||||
} from "@tanstack/react-query"
|
||||
import { sdk } from "../../lib/client"
|
||||
import { queryClient } from "../../lib/query-client"
|
||||
import { queryKeysFactory } from "../../lib/query-key-factory"
|
||||
|
||||
const SHIPPING_OPTION_TYPES_QUERY_KEY = "shipping_option_types" as const
|
||||
export const shippingOptionTypesQueryKeys = queryKeysFactory(
|
||||
SHIPPING_OPTION_TYPES_QUERY_KEY
|
||||
)
|
||||
|
||||
export const useShippingOptionType = (
|
||||
id: string,
|
||||
query?: HttpTypes.SelectParams,
|
||||
options?: Omit<
|
||||
UseQueryOptions<
|
||||
HttpTypes.AdminShippingOptionTypeResponse,
|
||||
FetchError,
|
||||
HttpTypes.AdminShippingOptionTypeResponse,
|
||||
QueryKey
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
>
|
||||
) => {
|
||||
const { data, ...rest } = useQuery({
|
||||
queryFn: () => sdk.admin.shippingOptionType.retrieve(id, query),
|
||||
queryKey: shippingOptionTypesQueryKeys.detail(id),
|
||||
...options,
|
||||
})
|
||||
|
||||
return { ...data, ...rest }
|
||||
}
|
||||
|
||||
export const useShippingOptionTypes = (
|
||||
query?: HttpTypes.AdminShippingOptionTypeListParams,
|
||||
options?: Omit<
|
||||
UseQueryOptions<
|
||||
HttpTypes.AdminShippingOptionTypeListResponse,
|
||||
FetchError,
|
||||
HttpTypes.AdminShippingOptionTypeListResponse,
|
||||
QueryKey
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
>
|
||||
) => {
|
||||
const { data, ...rest } = useQuery({
|
||||
queryFn: () => sdk.admin.shippingOptionType.list(query),
|
||||
queryKey: shippingOptionTypesQueryKeys.list(query),
|
||||
...options,
|
||||
})
|
||||
|
||||
return { ...data, ...rest }
|
||||
}
|
||||
|
||||
export const useCreateShippingOptionType = (
|
||||
options?: UseMutationOptions<
|
||||
HttpTypes.AdminShippingOptionTypeResponse,
|
||||
FetchError,
|
||||
HttpTypes.AdminCreateShippingOptionType
|
||||
>
|
||||
) => {
|
||||
return useMutation({
|
||||
mutationFn: (payload) => sdk.admin.shippingOptionType.create(payload),
|
||||
onSuccess: (data, variables, context) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: shippingOptionTypesQueryKeys.lists(),
|
||||
})
|
||||
|
||||
options?.onSuccess?.(data, variables, context)
|
||||
},
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
export const useUpdateShippingOptionType = (
|
||||
id: string,
|
||||
options?: UseMutationOptions<
|
||||
HttpTypes.AdminShippingOptionTypeResponse,
|
||||
FetchError,
|
||||
HttpTypes.AdminUpdateShippingOptionType
|
||||
>
|
||||
) => {
|
||||
return useMutation({
|
||||
mutationFn: (payload) => sdk.admin.shippingOptionType.update(id, payload),
|
||||
onSuccess: (data, variables, context) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: shippingOptionTypesQueryKeys.detail(id),
|
||||
})
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: shippingOptionTypesQueryKeys.lists(),
|
||||
})
|
||||
|
||||
options?.onSuccess?.(data, variables, context)
|
||||
},
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
export const useDeleteShippingOptionType = (
|
||||
id: string,
|
||||
options?: UseMutationOptions<
|
||||
HttpTypes.AdminShippingOptionTypeDeleteResponse,
|
||||
FetchError,
|
||||
void
|
||||
>
|
||||
) => {
|
||||
return useMutation({
|
||||
mutationFn: () => sdk.admin.shippingOptionType.delete(id),
|
||||
onSuccess: (data, variables, context) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: shippingOptionTypesQueryKeys.detail(id),
|
||||
})
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: shippingOptionTypesQueryKeys.lists(),
|
||||
})
|
||||
|
||||
options?.onSuccess?.(data, variables, context)
|
||||
},
|
||||
...options,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { createColumnHelper } from "@tanstack/react-table"
|
||||
import { useMemo } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
import { DateCell } from "../../../components/table/table-cells/common/date-cell"
|
||||
import { TextCell } from "../../../components/table/table-cells/common/text-cell"
|
||||
|
||||
const columnHelper = createColumnHelper<HttpTypes.AdminShippingOptionType>()
|
||||
|
||||
export const useShippingOptionTypeTableColumns = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return useMemo(
|
||||
() => [
|
||||
columnHelper.accessor("label", {
|
||||
header: () => t("fields.label"),
|
||||
cell: ({ getValue }) => <TextCell text={getValue()} />,
|
||||
}),
|
||||
columnHelper.accessor("code", {
|
||||
header: () => t("fields.code"),
|
||||
cell: ({ getValue }) => <TextCell text={getValue()} />,
|
||||
}),
|
||||
columnHelper.accessor("description", {
|
||||
header: () => t("fields.description"),
|
||||
cell: ({ getValue }) => <TextCell text={getValue()} />,
|
||||
}),
|
||||
columnHelper.accessor("created_at", {
|
||||
header: () => t("fields.createdAt"),
|
||||
|
||||
cell: ({ getValue }) => {
|
||||
return <DateCell date={getValue()} />
|
||||
},
|
||||
}),
|
||||
columnHelper.accessor("updated_at", {
|
||||
header: () => t("fields.updatedAt"),
|
||||
cell: ({ getValue }) => {
|
||||
return <DateCell date={getValue()} />
|
||||
},
|
||||
}),
|
||||
],
|
||||
[t]
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { useDateTableFilters } from "./use-date-table-filters"
|
||||
|
||||
export const useShippingOptionTypeTableFilters = () => {
|
||||
return useDateTableFilters()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { useQueryParams } from "../../use-query-params"
|
||||
|
||||
type UseShippingOptionTypeTableQueryProps = {
|
||||
prefix?: string
|
||||
pageSize?: number
|
||||
}
|
||||
|
||||
export const useShippingOptionTypeTableQuery = ({
|
||||
prefix,
|
||||
pageSize = 20,
|
||||
}: UseShippingOptionTypeTableQueryProps) => {
|
||||
const queryObject = useQueryParams(
|
||||
["offset", "q", "order", "created_at", "updated_at"],
|
||||
prefix
|
||||
)
|
||||
|
||||
const { offset, q, order, created_at, updated_at } = queryObject
|
||||
const searchParams: HttpTypes.AdminShippingOptionTypeListParams = {
|
||||
limit: pageSize,
|
||||
offset: offset ? Number(offset) : 0,
|
||||
order,
|
||||
created_at: created_at ? JSON.parse(created_at) : undefined,
|
||||
updated_at: updated_at ? JSON.parse(updated_at) : undefined,
|
||||
q,
|
||||
}
|
||||
|
||||
return {
|
||||
searchParams,
|
||||
raw: queryObject,
|
||||
}
|
||||
}
|
||||
@@ -10411,6 +10411,77 @@
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"shippingOptionTypes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"domain": {
|
||||
"type": "string"
|
||||
},
|
||||
"subtitle": {
|
||||
"type": "string"
|
||||
},
|
||||
"create": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"header": {
|
||||
"type": "string"
|
||||
},
|
||||
"hint": {
|
||||
"type": "string"
|
||||
},
|
||||
"successToast": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["header", "hint", "successToast"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"edit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"header": {
|
||||
"type": "string"
|
||||
},
|
||||
"successToast": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["header", "successToast"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"delete": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"confirmation": {
|
||||
"type": "string"
|
||||
},
|
||||
"successToast": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["confirmation", "successToast"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"code": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["label", "code", "description"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"required": ["domain", "subtitle", "create", "edit", "delete", "fields"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"productTypes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -2799,6 +2799,28 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"shippingOptionTypes": {
|
||||
"domain": "Shipping Option Types",
|
||||
"subtitle": "Organize your shipping options into types.",
|
||||
"create": {
|
||||
"header": "Create Shipping Option Type",
|
||||
"hint": "Create a new shipping option type to categorize your shipping options.",
|
||||
"successToast": "Shipping option type {{label}} was successfully created."
|
||||
},
|
||||
"edit": {
|
||||
"header": "Edit Shipping Option Type",
|
||||
"successToast": "Shipping option type {{label}} was successfully updated."
|
||||
},
|
||||
"delete": {
|
||||
"confirmation": "You are about to delete the shipping option type \"{{label}}\". This action cannot be undone.",
|
||||
"successToast": "Shipping option type \"{{label}}\" was successfully deleted."
|
||||
},
|
||||
"fields": {
|
||||
"label": "Label",
|
||||
"code": "Code",
|
||||
"description": "Description"
|
||||
}
|
||||
},
|
||||
"productTypes": {
|
||||
"domain": "Product Types",
|
||||
"subtitle": "Organize your products into types.",
|
||||
@@ -3051,4 +3073,4 @@
|
||||
"seconds_one": "Second",
|
||||
"seconds_other": "Seconds"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { useNavigate } from "react-router-dom"
|
||||
import { toast, usePrompt } from "@medusajs/ui"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
import { useDeleteShippingOptionType } from "../../../../hooks/api/shipping-option-types"
|
||||
|
||||
export const useDeleteShippingOptionTypeAction = (
|
||||
id: string,
|
||||
label: string
|
||||
) => {
|
||||
const { t } = useTranslation()
|
||||
const prompt = usePrompt()
|
||||
const navigate = useNavigate()
|
||||
|
||||
const { mutateAsync } = useDeleteShippingOptionType(id)
|
||||
|
||||
const handleDelete = async () => {
|
||||
const result = await prompt({
|
||||
title: t("general.areYouSure"),
|
||||
description: t("shippingOptionTypes.delete.confirmation", { label }),
|
||||
confirmText: t("actions.delete"),
|
||||
cancelText: t("actions.cancel"),
|
||||
})
|
||||
|
||||
if (!result) {
|
||||
return
|
||||
}
|
||||
|
||||
await mutateAsync(undefined, {
|
||||
onSuccess: () => {
|
||||
navigate("/settings/shipping-option-types", { replace: true })
|
||||
toast.success(t("shippingOptionTypes.delete.successToast", { label }))
|
||||
},
|
||||
onError: (e) => {
|
||||
toast.error(e.message)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return handleDelete
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { Button, Heading, Input, Text, toast } from "@medusajs/ui"
|
||||
import { useForm } from "react-hook-form"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { z } from "zod"
|
||||
import { Form } from "../../../../../components/common/form"
|
||||
import { RouteFocusModal, useRouteModal, } from "../../../../../components/modals"
|
||||
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||
import { useCreateShippingOptionType } from "../../../../../hooks/api"
|
||||
|
||||
const CreateShippingOptionTypeSchema = z.object({
|
||||
label: z.string().min(1),
|
||||
code: z.string().min(1),
|
||||
description: z.string().optional(),
|
||||
})
|
||||
|
||||
export const CreateShippingOptionTypeForm = () => {
|
||||
const { t } = useTranslation()
|
||||
const { handleSuccess } = useRouteModal()
|
||||
|
||||
const form = useForm<z.infer<typeof CreateShippingOptionTypeSchema>>({
|
||||
defaultValues: {
|
||||
label: "",
|
||||
code: "",
|
||||
description: undefined,
|
||||
},
|
||||
resolver: zodResolver(CreateShippingOptionTypeSchema),
|
||||
})
|
||||
|
||||
const generateCodeFromLabel = (label: string) => {
|
||||
return label
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]/g, "_")
|
||||
.replace(/_+/g, "_")
|
||||
.replace(/^_|_$/g, "")
|
||||
}
|
||||
|
||||
const { mutateAsync, isPending } = useCreateShippingOptionType()
|
||||
|
||||
const handleSubmit = form.handleSubmit(
|
||||
async (values: z.infer<typeof CreateShippingOptionTypeSchema>) => {
|
||||
await mutateAsync(values, {
|
||||
onSuccess: ({ shipping_option_type }) => {
|
||||
toast.success(
|
||||
t("shippingOptionTypes.create.successToast", {
|
||||
label: shipping_option_type.label.trim(),
|
||||
})
|
||||
)
|
||||
|
||||
handleSuccess(
|
||||
`/settings/shipping-option-types/${shipping_option_type.id}`
|
||||
)
|
||||
},
|
||||
onError: (e) => {
|
||||
toast.error(e.message)
|
||||
},
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
<RouteFocusModal.Form form={form}>
|
||||
<KeyboundForm onSubmit={handleSubmit} className="flex h-full flex-col">
|
||||
<RouteFocusModal.Body className="flex flex-col items-center overflow-auto p-16">
|
||||
<div className="flex w-full max-w-[720px] flex-col gap-y-8">
|
||||
<div>
|
||||
<Heading>{t("shippingOptionTypes.create.header")}</Heading>
|
||||
<Text size="small" className="text-ui-fg-subtle">
|
||||
{t("shippingOptionTypes.create.hint")}
|
||||
</Text>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-4">
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="label"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>
|
||||
{t("shippingOptionTypes.fields.label")}
|
||||
</Form.Label>
|
||||
<Form.Control>
|
||||
<Input
|
||||
{...field}
|
||||
onChange={(e) => {
|
||||
if (
|
||||
!form.getFieldState("code").isTouched ||
|
||||
!form.getValues("code")
|
||||
) {
|
||||
form.setValue(
|
||||
"code",
|
||||
generateCodeFromLabel(e.target.value)
|
||||
)
|
||||
}
|
||||
field.onChange(e)
|
||||
}}
|
||||
/>
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="code"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>
|
||||
{t("shippingOptionTypes.fields.code")}
|
||||
</Form.Label>
|
||||
<Form.Control>
|
||||
<Input {...field} />
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="description"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>
|
||||
{t("shippingOptionTypes.fields.description")}
|
||||
<Text
|
||||
size="small"
|
||||
leading="compact"
|
||||
className="text-ui-fg-muted ml-1 inline"
|
||||
>
|
||||
({t("fields.optional")})
|
||||
</Text>
|
||||
</Form.Label>
|
||||
<Form.Control>
|
||||
<Input {...field} />
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</RouteFocusModal.Body>
|
||||
<RouteFocusModal.Footer>
|
||||
<div className="flex items-center justify-end gap-x-2">
|
||||
<RouteFocusModal.Close asChild>
|
||||
<Button size="small" variant="secondary">
|
||||
{t("actions.cancel")}
|
||||
</Button>
|
||||
</RouteFocusModal.Close>
|
||||
<Button
|
||||
size="small"
|
||||
variant="primary"
|
||||
type="submit"
|
||||
isLoading={isPending}
|
||||
>
|
||||
{t("actions.create")}
|
||||
</Button>
|
||||
</div>
|
||||
</RouteFocusModal.Footer>
|
||||
</KeyboundForm>
|
||||
</RouteFocusModal.Form>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./create-shipping-option-type-form"
|
||||
@@ -0,0 +1 @@
|
||||
export { ShippingOptionTypeCreate as Component } from "./shipping-option-type-create"
|
||||
@@ -0,0 +1,10 @@
|
||||
import { RouteFocusModal } from "../../../components/modals"
|
||||
import { CreateShippingOptionTypeForm } from "./components/create-shipping-option-type-form"
|
||||
|
||||
export const ShippingOptionTypeCreate = () => {
|
||||
return (
|
||||
<RouteFocusModal>
|
||||
<CreateShippingOptionTypeForm />
|
||||
</RouteFocusModal>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { UIMatch } from "react-router-dom"
|
||||
|
||||
import { useShippingOptionType } from "../../../hooks/api"
|
||||
|
||||
type ShippingOptionTypeDetailBreadcrumbProps =
|
||||
UIMatch<HttpTypes.AdminShippingOptionTypeResponse>
|
||||
|
||||
export const ShippingOptionTypeDetailBreadcrumb = (
|
||||
props: ShippingOptionTypeDetailBreadcrumbProps
|
||||
) => {
|
||||
const { id } = props.params || {}
|
||||
|
||||
const { shipping_option_type } = useShippingOptionType(id!, undefined, {
|
||||
initialData: props.data,
|
||||
enabled: Boolean(id),
|
||||
})
|
||||
|
||||
if (!shipping_option_type) {
|
||||
return null
|
||||
}
|
||||
|
||||
return <span>{shipping_option_type.label}</span>
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./shipping-option-type-general-section"
|
||||
@@ -0,0 +1,66 @@
|
||||
import { PencilSquare, Trash } from "@medusajs/icons"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { Container, Heading, Text } from "@medusajs/ui"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||
import { useDeleteShippingOptionTypeAction } from "../../../common/hooks/use-delete-shipping-option-type-action"
|
||||
|
||||
type ShippingOptionTypeGeneralSectionProps = {
|
||||
shippingOptionType: HttpTypes.AdminShippingOptionType
|
||||
}
|
||||
|
||||
export const ShippingOptionTypeGeneralSection = ({
|
||||
shippingOptionType,
|
||||
}: ShippingOptionTypeGeneralSectionProps) => {
|
||||
const { t } = useTranslation()
|
||||
const handleDelete = useDeleteShippingOptionTypeAction(
|
||||
shippingOptionType.id,
|
||||
shippingOptionType.label
|
||||
)
|
||||
|
||||
return (
|
||||
<Container className="divide-y p-0">
|
||||
<div className="flex items-center justify-between px-6 py-4">
|
||||
<Heading>{shippingOptionType.label}</Heading>
|
||||
<ActionMenu
|
||||
groups={[
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
label: t("actions.edit"),
|
||||
icon: <PencilSquare />,
|
||||
to: "edit",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
label: t("actions.delete"),
|
||||
icon: <Trash />,
|
||||
onClick: handleDelete,
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div className="text-ui-fg-subtle grid grid-cols-2 items-start px-6 py-4">
|
||||
<Text size="small" leading="compact" weight="plus">
|
||||
{t("fields.code")}
|
||||
</Text>
|
||||
<Text size="small" leading="compact">
|
||||
{shippingOptionType.code}
|
||||
</Text>
|
||||
</div>
|
||||
<div className="text-ui-fg-subtle grid grid-cols-2 items-start px-6 py-4">
|
||||
<Text size="small" leading="compact" weight="plus">
|
||||
{t("fields.description")}
|
||||
</Text>
|
||||
<Text size="small" leading="compact">
|
||||
{shippingOptionType.description || "-"}
|
||||
</Text>
|
||||
</div>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export { ShippingOptionTypeDetailBreadcrumb as Breadcrumb } from "./breadcrumb"
|
||||
export { shippingOptionTypeLoader as loader } from "./loader"
|
||||
export { ShippingOptionTypeDetail as Component } from "./shipping-option-type-detail"
|
||||
@@ -0,0 +1,19 @@
|
||||
import { LoaderFunctionArgs } from "react-router-dom"
|
||||
|
||||
import { shippingOptionTypesQueryKeys } from "../../../hooks/api/shipping-option-types"
|
||||
import { sdk } from "../../../lib/client"
|
||||
import { queryClient } from "../../../lib/query-client"
|
||||
|
||||
const shippingOptionTypeDetailQuery = (id: string) => ({
|
||||
queryKey: shippingOptionTypesQueryKeys.detail(id),
|
||||
queryFn: async () => sdk.admin.shippingOptionType.retrieve(id),
|
||||
})
|
||||
|
||||
export const shippingOptionTypeLoader = async ({
|
||||
params,
|
||||
}: LoaderFunctionArgs) => {
|
||||
const id = params.id
|
||||
const query = shippingOptionTypeDetailQuery(id!)
|
||||
|
||||
return queryClient.ensureQueryData(query)
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { useLoaderData, useParams } from "react-router-dom"
|
||||
|
||||
import { SingleColumnPageSkeleton } from "../../../components/common/skeleton"
|
||||
import { SingleColumnPage } from "../../../components/layout/pages"
|
||||
import { useShippingOptionType } from "../../../hooks/api"
|
||||
import { useExtension } from "../../../providers/extension-provider"
|
||||
import { ShippingOptionTypeGeneralSection } from "./components/shipping-option-type-general-section"
|
||||
import { shippingOptionTypeLoader } from "./loader"
|
||||
|
||||
export const ShippingOptionTypeDetail = () => {
|
||||
const { id } = useParams()
|
||||
const initialData = useLoaderData() as Awaited<
|
||||
ReturnType<typeof shippingOptionTypeLoader>
|
||||
>
|
||||
|
||||
const { shipping_option_type, isPending, isError, error } =
|
||||
useShippingOptionType(id!, undefined, {
|
||||
initialData,
|
||||
})
|
||||
|
||||
const { getWidgets } = useExtension()
|
||||
|
||||
if (isPending || !shipping_option_type) {
|
||||
return <SingleColumnPageSkeleton sections={2} showJSON showMetadata />
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
throw error
|
||||
}
|
||||
|
||||
return (
|
||||
<SingleColumnPage
|
||||
widgets={{
|
||||
after: getWidgets("shipping_option_type.details.after"),
|
||||
before: getWidgets("shipping_option_type.details.before"),
|
||||
}}
|
||||
showJSON
|
||||
showMetadata
|
||||
data={shipping_option_type}
|
||||
>
|
||||
<ShippingOptionTypeGeneralSection
|
||||
shippingOptionType={shipping_option_type}
|
||||
/>
|
||||
</SingleColumnPage>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { Button, Input, Text, toast } from "@medusajs/ui"
|
||||
import { useForm } from "react-hook-form"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { z } from "zod"
|
||||
import { Form } from "../../../../../components/common/form"
|
||||
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
|
||||
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
|
||||
import { useUpdateShippingOptionType } from "../../../../../hooks/api/shipping-option-types"
|
||||
|
||||
const EditShippingOptionTypeSchema = z.object({
|
||||
label: z.string().min(1),
|
||||
code: z.string().min(1),
|
||||
description: z.string().optional(),
|
||||
})
|
||||
|
||||
type EditShippingOptionTypeFormProps = {
|
||||
shippingOptionType: HttpTypes.AdminShippingOptionType
|
||||
}
|
||||
|
||||
export const EditShippingOptionTypeForm = ({
|
||||
shippingOptionType,
|
||||
}: EditShippingOptionTypeFormProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { handleSuccess } = useRouteModal()
|
||||
|
||||
const form = useForm<z.infer<typeof EditShippingOptionTypeSchema>>({
|
||||
defaultValues: {
|
||||
label: shippingOptionType.label,
|
||||
code: shippingOptionType.code,
|
||||
description: shippingOptionType.description,
|
||||
},
|
||||
resolver: zodResolver(EditShippingOptionTypeSchema),
|
||||
})
|
||||
|
||||
const { mutateAsync, isPending } = useUpdateShippingOptionType(
|
||||
shippingOptionType.id
|
||||
)
|
||||
|
||||
const handleSubmit = form.handleSubmit(async (data) => {
|
||||
await mutateAsync(
|
||||
{
|
||||
label: data.label,
|
||||
code: data.code,
|
||||
description: data.description,
|
||||
},
|
||||
{
|
||||
onSuccess: ({ shipping_option_type }) => {
|
||||
toast.success(
|
||||
t("shippingOptionTypes.edit.successToast", {
|
||||
value: shipping_option_type.label,
|
||||
})
|
||||
)
|
||||
handleSuccess()
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(error.message)
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
return (
|
||||
<RouteDrawer.Form form={form}>
|
||||
<KeyboundForm
|
||||
onSubmit={handleSubmit}
|
||||
className="flex flex-1 flex-col overflow-hidden"
|
||||
>
|
||||
<RouteDrawer.Body className="flex flex-1 flex-col gap-y-8 overflow-y-auto">
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="label"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>
|
||||
{t("shippingOptionTypes.fields.label")}
|
||||
</Form.Label>
|
||||
<Form.Control>
|
||||
<Input {...field} />
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="code"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>
|
||||
{t("shippingOptionTypes.fields.code")}
|
||||
</Form.Label>
|
||||
<Form.Control>
|
||||
<Input {...field} />
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name="description"
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>
|
||||
{t("shippingOptionTypes.fields.description")}
|
||||
<Text
|
||||
size="small"
|
||||
leading="compact"
|
||||
className="text-ui-fg-muted ml-1 inline"
|
||||
>
|
||||
({t("fields.optional")})
|
||||
</Text>
|
||||
</Form.Label>
|
||||
<Form.Control>
|
||||
<Input {...field} />
|
||||
</Form.Control>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</RouteDrawer.Body>
|
||||
<RouteDrawer.Footer>
|
||||
<div className="flex items-center justify-end gap-x-2">
|
||||
<RouteDrawer.Close asChild>
|
||||
<Button size="small" variant="secondary">
|
||||
{t("actions.cancel")}
|
||||
</Button>
|
||||
</RouteDrawer.Close>
|
||||
<Button size="small" type="submit" isLoading={isPending}>
|
||||
{t("actions.save")}
|
||||
</Button>
|
||||
</div>
|
||||
</RouteDrawer.Footer>
|
||||
</KeyboundForm>
|
||||
</RouteDrawer.Form>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./edit-shipping-option-type-form"
|
||||
@@ -0,0 +1 @@
|
||||
export { ShippingOptionTypeEdit as Component } from "./shipping-option-type-edit"
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Heading } from "@medusajs/ui"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { useParams } from "react-router-dom"
|
||||
import { RouteDrawer } from "../../../components/modals"
|
||||
import { useShippingOptionType } from "../../../hooks/api"
|
||||
import { EditShippingOptionTypeForm } from "./components/edit-shipping-option-type-form"
|
||||
|
||||
export const ShippingOptionTypeEdit = () => {
|
||||
const { id } = useParams()
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { shipping_option_type, isPending, isError, error } =
|
||||
useShippingOptionType(id!)
|
||||
|
||||
const ready = !isPending && !!shipping_option_type
|
||||
|
||||
if (isError) {
|
||||
throw error
|
||||
}
|
||||
|
||||
return (
|
||||
<RouteDrawer>
|
||||
<RouteDrawer.Header>
|
||||
<Heading>{t("shippingOptionTypes.edit.header")}</Heading>
|
||||
</RouteDrawer.Header>
|
||||
{ready && (
|
||||
<EditShippingOptionTypeForm shippingOptionType={shipping_option_type} />
|
||||
)}
|
||||
</RouteDrawer>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./shipping-option-type-list-table"
|
||||
@@ -0,0 +1,99 @@
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { Button, Container, Heading, Text } from "@medusajs/ui"
|
||||
import { keepPreviousData } from "@tanstack/react-query"
|
||||
import { createColumnHelper } from "@tanstack/react-table"
|
||||
import { useMemo } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { Link } from "react-router-dom"
|
||||
import { _DataTable } from "../../../../../components/table/data-table"
|
||||
import { useShippingOptionTypes } from "../../../../../hooks/api"
|
||||
import { useShippingOptionTypeTableColumns } from "../../../../../hooks/table/columns/use-shipping-option-type-table-columns"
|
||||
import { useShippingOptionTypeTableFilters } from "../../../../../hooks/table/filters/use-shipping-option-type-table-filters"
|
||||
import { useShippingOptionTypeTableQuery } from "../../../../../hooks/table/query/use-shipping-option-type-table-query"
|
||||
import { useDataTable } from "../../../../../hooks/use-data-table"
|
||||
import { ShippingOptionTypeRowActions } from "./shipping-option-type-table-row-actions"
|
||||
|
||||
const PAGE_SIZE = 20
|
||||
|
||||
export const ShippingOptionTypeListTable = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { searchParams, raw } = useShippingOptionTypeTableQuery({
|
||||
pageSize: PAGE_SIZE,
|
||||
})
|
||||
const { shipping_option_types, count, isLoading, isError, error } =
|
||||
useShippingOptionTypes(searchParams, {
|
||||
placeholderData: keepPreviousData,
|
||||
})
|
||||
|
||||
const filters = useShippingOptionTypeTableFilters()
|
||||
const columns = useColumns()
|
||||
|
||||
const { table } = useDataTable({
|
||||
columns,
|
||||
data: shipping_option_types,
|
||||
count,
|
||||
getRowId: (row) => row.id,
|
||||
pageSize: PAGE_SIZE,
|
||||
})
|
||||
|
||||
if (isError) {
|
||||
throw error
|
||||
}
|
||||
|
||||
return (
|
||||
<Container className="divide-y p-0">
|
||||
<div className="flex items-center justify-between px-6 py-4">
|
||||
<div>
|
||||
<Heading>{t("shippingOptionTypes.domain")}</Heading>
|
||||
<Text className="text-ui-fg-subtle" size="small">
|
||||
{t("shippingOptionTypes.subtitle")}
|
||||
</Text>
|
||||
</div>
|
||||
<Button size="small" variant="secondary" asChild>
|
||||
<Link to="create">{t("actions.create")}</Link>
|
||||
</Button>
|
||||
</div>
|
||||
<_DataTable
|
||||
table={table}
|
||||
filters={filters}
|
||||
isLoading={isLoading}
|
||||
columns={columns}
|
||||
pageSize={PAGE_SIZE}
|
||||
count={count}
|
||||
orderBy={[
|
||||
{ key: "label", label: t("fields.label") },
|
||||
{ key: "code", label: t("fields.code") },
|
||||
{ key: "description", label: t("fields.description") },
|
||||
{ key: "created_at", label: t("fields.createdAt") },
|
||||
{ key: "updated_at", label: t("fields.updatedAt") },
|
||||
]}
|
||||
navigateTo={({ original }) => original.id}
|
||||
queryObject={raw}
|
||||
pagination
|
||||
search
|
||||
/>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const columnHelper = createColumnHelper<HttpTypes.AdminShippingOptionType>()
|
||||
|
||||
const useColumns = () => {
|
||||
const base = useShippingOptionTypeTableColumns()
|
||||
|
||||
return useMemo(
|
||||
() => [
|
||||
...base,
|
||||
columnHelper.display({
|
||||
id: "actions",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<ShippingOptionTypeRowActions shippingOptionType={row.original} />
|
||||
)
|
||||
},
|
||||
}),
|
||||
],
|
||||
[base]
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { PencilSquare, Trash } from "@medusajs/icons"
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { ActionMenu } from "../../../../../components/common/action-menu"
|
||||
import { useDeleteShippingOptionTypeAction } from "../../../common/hooks/use-delete-shipping-option-type-action"
|
||||
|
||||
type ShippingOptionTypeRowActionsProps = {
|
||||
shippingOptionType: HttpTypes.AdminShippingOptionType
|
||||
}
|
||||
|
||||
export const ShippingOptionTypeRowActions = ({
|
||||
shippingOptionType,
|
||||
}: ShippingOptionTypeRowActionsProps) => {
|
||||
const { t } = useTranslation()
|
||||
const handleDelete = useDeleteShippingOptionTypeAction(
|
||||
shippingOptionType.id,
|
||||
shippingOptionType.label
|
||||
)
|
||||
|
||||
return (
|
||||
<ActionMenu
|
||||
groups={[
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
label: t("actions.edit"),
|
||||
icon: <PencilSquare />,
|
||||
to: `/settings/shipping-option-types/${shippingOptionType.id}/edit`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
label: t("actions.delete"),
|
||||
icon: <Trash />,
|
||||
onClick: handleDelete,
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { ShippingOptionTypeList as Component } from "./shipping-option-type-list"
|
||||
@@ -0,0 +1,18 @@
|
||||
import { SingleColumnPage } from "../../../components/layout/pages"
|
||||
import { useExtension } from "../../../providers/extension-provider"
|
||||
import { ShippingOptionTypeListTable } from "./components/shipping-option-type-list-table"
|
||||
|
||||
export const ShippingOptionTypeList = () => {
|
||||
const { getWidgets } = useExtension()
|
||||
|
||||
return (
|
||||
<SingleColumnPage
|
||||
widgets={{
|
||||
after: getWidgets("shipping_option_type.list.after"),
|
||||
before: getWidgets("shipping_option_type.list.before"),
|
||||
}}
|
||||
>
|
||||
<ShippingOptionTypeListTable />
|
||||
</SingleColumnPage>
|
||||
)
|
||||
}
|
||||
@@ -43,6 +43,7 @@ import { TaxRegion } from "./tax-region"
|
||||
import { Upload } from "./upload"
|
||||
import { User } from "./user"
|
||||
import { WorkflowExecution } from "./workflow-execution"
|
||||
import { ShippingOptionType } from "./shipping-option-type"
|
||||
|
||||
export class Admin {
|
||||
/**
|
||||
@@ -113,6 +114,10 @@ export class Admin {
|
||||
* @tags fulfillment
|
||||
*/
|
||||
public shippingOption: ShippingOption
|
||||
/**
|
||||
* @tags fulfillment
|
||||
*/
|
||||
public shippingOptionType: ShippingOptionType
|
||||
/**
|
||||
* @tags fulfillment
|
||||
*/
|
||||
@@ -240,6 +245,7 @@ export class Admin {
|
||||
this.fulfillment = new Fulfillment(client)
|
||||
this.fulfillmentProvider = new FulfillmentProvider(client)
|
||||
this.shippingOption = new ShippingOption(client)
|
||||
this.shippingOptionType = new ShippingOptionType(client)
|
||||
this.shippingProfile = new ShippingProfile(client)
|
||||
this.inventoryItem = new InventoryItem(client)
|
||||
this.notification = new Notification(client)
|
||||
|
||||
219
packages/core/js-sdk/src/admin/shipping-option-type.ts
Normal file
219
packages/core/js-sdk/src/admin/shipping-option-type.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
import { HttpTypes } from "@medusajs/types"
|
||||
import { Client } from "../client"
|
||||
import { ClientHeaders } from "../types"
|
||||
|
||||
export class ShippingOptionType {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
private client: Client
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
constructor(client: Client) {
|
||||
this.client = client
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a shipping option type. It sends a request to the
|
||||
* [Create Shipping Option Type](TODO HERE)
|
||||
* API route.
|
||||
*
|
||||
* @param body - The shipping option type's details.
|
||||
* @param query - Configure the fields to retrieve in the shipping option type.
|
||||
* @param headers - Headers to pass in the request
|
||||
* @returns The shipping option type's details.
|
||||
*
|
||||
* @example
|
||||
* sdk.admin.shippingOptionType.create({
|
||||
* label: "Standard",
|
||||
* code: "standard",
|
||||
* description: "Ship in 2-3 days."
|
||||
* })
|
||||
* .then(({ shipping_option_type }) => {
|
||||
* console.log(shipping_option_type)
|
||||
* })
|
||||
*/
|
||||
async create(
|
||||
body: HttpTypes.AdminCreateShippingOptionType,
|
||||
query?: HttpTypes.SelectParams,
|
||||
headers?: ClientHeaders
|
||||
) {
|
||||
return this.client.fetch<HttpTypes.AdminShippingOptionTypeResponse>(
|
||||
`/admin/shipping-option-types`,
|
||||
{
|
||||
method: "POST",
|
||||
headers,
|
||||
body,
|
||||
query,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This method updates a shipping option type. It sends a request to the
|
||||
* [Update Shipping Option Type](TODO HERE)
|
||||
* API route.
|
||||
*
|
||||
* @param id - The shipping option type's ID.
|
||||
* @param body - The data to update in the shipping option type.
|
||||
* @param query - Configure the fields to retrieve in the shipping option type.
|
||||
* @param headers - Headers to pass in the request
|
||||
* @returns The shipping option type's details.
|
||||
*
|
||||
* @example
|
||||
* sdk.admin.shippingOptionType.update("sotype_123", {
|
||||
* code: "express"
|
||||
* })
|
||||
* .then(({ shipping_option_type }) => {
|
||||
* console.log(shipping_option_type)
|
||||
* })
|
||||
*/
|
||||
async update(
|
||||
id: string,
|
||||
body: HttpTypes.AdminUpdateShippingOptionType,
|
||||
query?: HttpTypes.SelectParams,
|
||||
headers?: ClientHeaders
|
||||
) {
|
||||
return this.client.fetch<HttpTypes.AdminShippingOptionTypeResponse>(
|
||||
`/admin/shipping-option-types/${id}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers,
|
||||
body,
|
||||
query,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This method retrieves a paginated list of shipping option types. It sends a request to the
|
||||
* [List Shipping Option Types](TODO HERE) API route.
|
||||
*
|
||||
* @param query - Filters and pagination configurations.
|
||||
* @param headers - Headers to pass in the request.
|
||||
* @returns The paginated list of shipping option types.
|
||||
*
|
||||
* @example
|
||||
* To retrieve the list of shipping option types:
|
||||
*
|
||||
* ```ts
|
||||
* sdk.admin.shippingOptionType.list()
|
||||
* .then(({ shipping_option_types, count, limit, offset }) => {
|
||||
* console.log(shipping_option_types)
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* 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.shippingOptionType.list({
|
||||
* limit: 10,
|
||||
* offset: 10
|
||||
* })
|
||||
* .then(({ shipping_option_types, count, limit, offset }) => {
|
||||
* console.log(shipping_option_types)
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* Using the `fields` query parameter, you can specify the fields and relations to retrieve
|
||||
* in each shipping option type:
|
||||
*
|
||||
* ```ts
|
||||
* sdk.admin.shippingOptionType.list({
|
||||
* fields: "id,*shippingOptions"
|
||||
* })
|
||||
* .then(({ shipping_option_types, count, limit, offset }) => {
|
||||
* console.log(shipping_option_types)
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations).
|
||||
*/
|
||||
async list(
|
||||
query?: HttpTypes.AdminShippingOptionTypeListParams,
|
||||
headers?: ClientHeaders
|
||||
) {
|
||||
return this.client.fetch<HttpTypes.AdminShippingOptionTypeListResponse>(
|
||||
`/admin/shipping-option-types`,
|
||||
{
|
||||
headers,
|
||||
query: query,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This method retrieves a shipping option type by its ID. It sends a request to the
|
||||
* [Get Shipping Option Type](TODO HERE)
|
||||
* API route.
|
||||
*
|
||||
* @param id - The shipping option type's ID.
|
||||
* @param query - Configure the fields to retrieve in the shipping option type.
|
||||
* @param headers - Headers to pass in the request
|
||||
* @returns The shipping option type's details.
|
||||
*
|
||||
* @example
|
||||
* To retrieve a shipping option type by its ID:
|
||||
*
|
||||
* ```ts
|
||||
* sdk.admin.shippingOptionType.retrieve("sotype_123")
|
||||
* .then(({ shipping_option_type }) => {
|
||||
* console.log(shipping_option_type)
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* To specify the fields and relations to retrieve:
|
||||
*
|
||||
* ```ts
|
||||
* sdk.admin.shippingOptionType.retrieve("sotype_123", {
|
||||
* fields: "id,*shippingOptions"
|
||||
* })
|
||||
* .then(({ shipping_option_type }) => {
|
||||
* console.log(shipping_option_type)
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations).
|
||||
*/
|
||||
async retrieve(
|
||||
id: string,
|
||||
query?: HttpTypes.SelectParams,
|
||||
headers?: ClientHeaders
|
||||
) {
|
||||
return this.client.fetch<HttpTypes.AdminShippingOptionTypeResponse>(
|
||||
`/admin/shipping-option-types/${id}`,
|
||||
{
|
||||
query,
|
||||
headers,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deletes a shipping option type. It sends a request to the
|
||||
* [Delete Shipping Option Type](TODO HERE)
|
||||
* API route.
|
||||
*
|
||||
* @param id - The shipping option type's ID.
|
||||
* @param headers - Headers to pass in the request
|
||||
* @returns The shipping option type's details.
|
||||
*
|
||||
* @example
|
||||
* sdk.admin.shippingOptionType.delete("sotype_123")
|
||||
* .then(({ deleted }) => {
|
||||
* console.log(deleted)
|
||||
* })
|
||||
*/
|
||||
async delete(id: string, headers?: ClientHeaders) {
|
||||
return this.client.fetch<HttpTypes.AdminShippingOptionTypeDeleteResponse>(
|
||||
`/admin/shipping-option-types/${id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@ import { ShippingOption } from "./shipping-option"
|
||||
|
||||
export const ShippingOptionType = model.define("shipping_option_type", {
|
||||
id: model.id({ prefix: "sotype" }).primaryKey(),
|
||||
label: model.text(),
|
||||
description: model.text().nullable(),
|
||||
code: model.text(),
|
||||
label: model.text().searchable(),
|
||||
description: model.text().searchable().nullable(),
|
||||
code: model.text().searchable(),
|
||||
shipping_option: model.hasOne(() => ShippingOption, {
|
||||
mappedBy: "type",
|
||||
}),
|
||||
|
||||
@@ -10,7 +10,7 @@ import { ShippingProfile } from "./shipping-profile"
|
||||
export const ShippingOption = model
|
||||
.define("shipping_option", {
|
||||
id: model.id({ prefix: "so" }).primaryKey(),
|
||||
name: model.text(),
|
||||
name: model.text().searchable(),
|
||||
price_type: model
|
||||
.enum(ShippingOptionPriceType)
|
||||
.default(ShippingOptionPriceType.FLAT),
|
||||
|
||||
Reference in New Issue
Block a user