diff --git a/packages/admin-next/dashboard/public/locales/en-US/translation.json b/packages/admin-next/dashboard/public/locales/en-US/translation.json index a1c9eab9135f..a7414466cfd0 100644 --- a/packages/admin-next/dashboard/public/locales/en-US/translation.json +++ b/packages/admin-next/dashboard/public/locales/en-US/translation.json @@ -84,7 +84,9 @@ "lastThirtyDays": "Last 30 days", "lastNinetyDays": "Last 90 days", "lastTwelveMonths": "Last 12 months", - "custom": "Custom" + "custom": "Custom", + "from": "From", + "to": "To" }, "compare": { "lessThan": "Less than", @@ -673,10 +675,19 @@ }, "shippingProfile": { "domain": "Shipping Profiles", - "title": "Create a shipping profile", - "detailsHint": "Specify the details of the shipping profile", - "deleteWaring": "You are about to delete the profile: {{name}}. This action cannot be undone.", - "typeHint": "Enter shipping profile type, for example: Express, Freight, etc." + "create": { + "header": "Create Shipping Profile", + "hint": "Create a new shipping profile to group products with similar shipping requirements.", + "successToast": "Shipping profile {{name}} was successfully created." + }, + "delete": { + "title": "Delete Shipping Profile", + "description": "You are about to delete the shipping profile {{name}}. This action cannot be undone.", + "successToast": "Shipping profile {{name}} was successfully deleted." + }, + "tooltip": { + "type": "Enter shipping profile type, for example: Express, Freight, etc." + } }, "discounts": { "domain": "Discounts", diff --git a/packages/admin-next/dashboard/src/components/common/section/section-row.tsx b/packages/admin-next/dashboard/src/components/common/section/section-row.tsx index aefc164b9a4a..3b4e4ed973db 100644 --- a/packages/admin-next/dashboard/src/components/common/section/section-row.tsx +++ b/packages/admin-next/dashboard/src/components/common/section/section-row.tsx @@ -1,9 +1,10 @@ -import { Text } from "@medusajs/ui" +import { Text, clx } from "@medusajs/ui" +import { ReactNode } from "react" export type SectionRowProps = { title: string - value?: React.ReactNode | string | null - actions?: React.ReactNode + value?: ReactNode | string | null + actions?: ReactNode } export const SectionRow = ({ title, value, actions }: SectionRowProps) => { @@ -11,9 +12,12 @@ export const SectionRow = ({ title, value, actions }: SectionRowProps) => { return (
{title} diff --git a/packages/admin-next/dashboard/src/components/common/skeleton/skeleton.tsx b/packages/admin-next/dashboard/src/components/common/skeleton/skeleton.tsx index 0aa1807bdba4..0b2b2c8c17e5 100644 --- a/packages/admin-next/dashboard/src/components/common/skeleton/skeleton.tsx +++ b/packages/admin-next/dashboard/src/components/common/skeleton/skeleton.tsx @@ -1,16 +1,151 @@ -import { clx } from "@medusajs/ui" +import { Container, Heading, Text, clx } from "@medusajs/ui" +import { CSSProperties, ComponentPropsWithoutRef } from "react" type SkeletonProps = { className?: string + style?: CSSProperties } -export const Skeleton = ({ className }: SkeletonProps) => { +export const Skeleton = ({ className, style }: SkeletonProps) => { return (
) } + +type TextSkeletonProps = { + size?: ComponentPropsWithoutRef["size"] + leading?: ComponentPropsWithoutRef["leading"] + characters?: number +} + +type HeadingSkeletonProps = { + level?: ComponentPropsWithoutRef["level"] + characters?: number +} + +export const HeadingSkeleton = ({ + level = "h1", + characters = 10, +}: HeadingSkeletonProps) => { + let charWidth = 9 + + switch (level) { + case "h1": + charWidth = 11 + break + case "h2": + charWidth = 10 + break + case "h3": + charWidth = 9 + break + } + + return ( + + ) +} + +export const TextSkeleton = ({ + size = "small", + leading = "compact", + characters = 10, +}: TextSkeletonProps) => { + let charWidth = 9 + + switch (size) { + case "xlarge": + charWidth = 13 + break + case "large": + charWidth = 11 + break + case "base": + charWidth = 10 + break + case "small": + charWidth = 9 + break + case "xsmall": + charWidth = 8 + break + } + + return ( + + ) +} + +export const IconButtonSkeleton = () => { + return +} + +type GeneralSectionSkeletonProps = { + rowCount?: number +} + +export const GeneralSectionSkeleton = ({ + rowCount, +}: GeneralSectionSkeletonProps) => { + const rows = Array.from({ length: rowCount ?? 0 }, (_, i) => i) + + return ( + +
+ + +
+ {rows.map((row) => ( +
+ + +
+ ))} +
+ ) +} + +export const JsonViewSectionSkeleton = () => { + return ( + +
+
+ + +
+ +
+
+ ) +} diff --git a/packages/admin-next/dashboard/src/components/layout/main-layout/main-layout.tsx b/packages/admin-next/dashboard/src/components/layout/main-layout/main-layout.tsx index d15e9e8b0270..6f52f7528328 100644 --- a/packages/admin-next/dashboard/src/components/layout/main-layout/main-layout.tsx +++ b/packages/admin-next/dashboard/src/components/layout/main-layout/main-layout.tsx @@ -148,12 +148,6 @@ const useCoreRoutes = (): Omit[] => { icon: , label: t("shipping.domain"), to: "/shipping", - items: [ - { - label: t("shippingProfile.domain"), - to: "/shipping-profiles", - }, - ], }, ] } diff --git a/packages/admin-next/dashboard/src/components/layout/settings-layout/settings-layout.tsx b/packages/admin-next/dashboard/src/components/layout/settings-layout/settings-layout.tsx index 3f375a3f7db8..65ff53808531 100644 --- a/packages/admin-next/dashboard/src/components/layout/settings-layout/settings-layout.tsx +++ b/packages/admin-next/dashboard/src/components/layout/settings-layout/settings-layout.tsx @@ -53,6 +53,10 @@ const useSettingRoutes = (): NavItemProps[] => { label: t("salesChannels.domain"), to: "/settings/sales-channels", }, + { + label: t("shippingProfile.domain"), + to: "/settings/shipping-profiles", + }, ], [t] ) diff --git a/packages/admin-next/dashboard/src/components/table/data-table/data-table-filter/date-filter.tsx b/packages/admin-next/dashboard/src/components/table/data-table/data-table-filter/date-filter.tsx index ce8e14fce517..255285ddffed 100644 --- a/packages/admin-next/dashboard/src/components/table/data-table/data-table-filter/date-filter.tsx +++ b/packages/admin-next/dashboard/src/components/table/data-table/data-table-filter/date-filter.tsx @@ -1,12 +1,12 @@ import { EllipseMiniSolid, XMarkMini } from "@medusajs/icons" import { DatePicker, Text, clx } from "@medusajs/ui" import * as Popover from "@radix-ui/react-popover" -import { format } from "date-fns" import isEqual from "lodash/isEqual" import { MouseEvent, useMemo, useState } from "react" import { t } from "i18next" import { useTranslation } from "react-i18next" +import { useDate } from "../../../../hooks/use-date" import { useSelectedParams } from "../hooks" import { useDataTableFilterContext } from "./context" import { IFilter } from "./types" @@ -17,19 +17,19 @@ type DateComparisonOperator = { /** * The filtered date must be greater than or equal to this value. */ - gte?: string + $gte?: string /** * The filtered date must be less than or equal to this value. */ - lte?: string + $lte?: string /** * The filtered date must be less than this value. */ - lt?: string + $lt?: string /** * The filtered date must be greater than this value. */ - gt?: string + $gt?: string } export const DateFilter = ({ @@ -40,6 +40,8 @@ export const DateFilter = ({ const [open, setOpen] = useState(openOnMount) const [showCustom, setShowCustom] = useState(false) + const { getFullDate } = useDate() + const { key, label } = filter const { removeFilter } = useDataTableFilterContext() @@ -60,14 +62,14 @@ export const DateFilter = ({ const currentValue = selectedParams.get() const currentDateComparison = parseDateComparison(currentValue) - const customStartValue = getDateFromComparison(currentDateComparison, "gte") - const customEndValue = getDateFromComparison(currentDateComparison, "lte") + const customStartValue = getDateFromComparison(currentDateComparison, "$gte") + const customEndValue = getDateFromComparison(currentDateComparison, "$lte") const handleCustomDateChange = ( value: Date | undefined, pos: "start" | "end" ) => { - const key = pos === "start" ? "gte" : "lte" + const key = pos === "start" ? "$gte" : "$lte" const dateValue = value ? value.toISOString() : undefined selectedParams.add( @@ -84,7 +86,7 @@ export const DateFilter = ({ } const formatCustomDate = (date: Date | undefined) => { - return date ? format(date, "dd MMM, yyyy") : undefined + return date ? getFullDate({ date: date }) : undefined } const getCustomDisplayValue = () => { @@ -194,12 +196,12 @@ export const DateFilter = ({
- Starting + {t("filters.date.from")}
handleCustomDateChange(d, "start")} @@ -209,12 +211,12 @@ export const DateFilter = ({
- Ending + {t("filters.date.to")}
{ @@ -301,13 +303,13 @@ const usePresets = () => { { label: t("filters.date.today"), value: { - gte: today.toISOString(), + $gte: today.toISOString(), }, }, { label: t("filters.date.lastSevenDays"), value: { - gte: new Date( + $gte: new Date( today.getTime() - 7 * 24 * 60 * 60 * 1000 ).toISOString(), // 7 days ago }, @@ -315,7 +317,7 @@ const usePresets = () => { { label: t("filters.date.lastThirtyDays"), value: { - gte: new Date( + $gte: new Date( today.getTime() - 30 * 24 * 60 * 60 * 1000 ).toISOString(), // 30 days ago }, @@ -323,7 +325,7 @@ const usePresets = () => { { label: t("filters.date.lastNinetyDays"), value: { - gte: new Date( + $gte: new Date( today.getTime() - 90 * 24 * 60 * 60 * 1000 ).toISOString(), // 90 days ago }, @@ -331,7 +333,7 @@ const usePresets = () => { { label: t("filters.date.lastTwelveMonths"), value: { - gte: new Date( + $gte: new Date( today.getTime() - 365 * 24 * 60 * 60 * 1000 ).toISOString(), // 365 days ago }, @@ -349,7 +351,7 @@ const parseDateComparison = (value: string[]) => { const getDateFromComparison = ( comparison: DateComparisonOperator | null, - key: "gte" | "lte" + key: "$gte" | "$lte" ) => { return comparison?.[key] ? new Date(comparison[key] as string) : undefined } diff --git a/packages/admin-next/dashboard/src/hooks/api/shipping-profiles.tsx b/packages/admin-next/dashboard/src/hooks/api/shipping-profiles.tsx index a356384106cb..09e902cd2be0 100644 --- a/packages/admin-next/dashboard/src/hooks/api/shipping-profiles.tsx +++ b/packages/admin-next/dashboard/src/hooks/api/shipping-profiles.tsx @@ -7,11 +7,11 @@ import { } from "@tanstack/react-query" import { CreateShippingProfileReq } from "../../types/api-payloads" import { - ShippingProfileDeleteRes, ShippingProfileListRes, ShippingProfileRes, } from "../../types/api-responses" +import { DeleteResponse } from "@medusajs/types" import { client } from "../../lib/client" import { queryClient } from "../../lib/medusa" import { queryKeysFactory } from "../../lib/query-key-factory" @@ -41,6 +41,25 @@ export const useCreateShippingProfile = ( }) } +export const useShippingProfile = ( + id: string, + query?: Record, + options?: UseQueryOptions< + ShippingProfileRes, + Error, + ShippingProfileRes, + QueryKey + > +) => { + const { data, ...rest } = useQuery({ + queryFn: () => client.shippingProfiles.retrieve(id, query), + queryKey: shippingProfileQueryKeys.detail(id, query), + ...options, + }) + + return { ...data, ...rest } +} + export const useShippingProfiles = ( query?: Record, options?: Omit< @@ -64,11 +83,11 @@ export const useShippingProfiles = ( export const useDeleteShippingProfile = ( profileId: string, - options?: UseMutationOptions + options?: UseMutationOptions ) => { return useMutation({ mutationFn: () => client.shippingProfiles.delete(profileId), - onSuccess: (data: any, variables: any, context: any) => { + onSuccess: (data, variables, context) => { queryClient.invalidateQueries({ queryKey: shippingProfileQueryKeys.lists(), }) diff --git a/packages/admin-next/dashboard/src/lib/client/shipping-profiles.ts b/packages/admin-next/dashboard/src/lib/client/shipping-profiles.ts index 9dbbcce73ba8..f716db1e301d 100644 --- a/packages/admin-next/dashboard/src/lib/client/shipping-profiles.ts +++ b/packages/admin-next/dashboard/src/lib/client/shipping-profiles.ts @@ -1,27 +1,35 @@ -import { deleteRequest, getRequest, postRequest } from "./common" import { CreateShippingProfileReq } from "../../types/api-payloads" import { ShippingProfileDeleteRes, ShippingProfileListRes, ShippingProfileRes, } from "../../types/api-responses" +import { deleteRequest, getRequest, postRequest } from "./common" async function createShippingProfile(payload: CreateShippingProfileReq) { return postRequest(`/admin/shipping-profiles`, payload) } +async function retrieveShippingProfile( + id: string, + query?: Record +) { + return getRequest(`/admin/shipping-profiles/${id}`, query) +} + async function listShippingProfiles(query?: Record) { return getRequest(`/admin/shipping-profiles`, query) } -async function deleteShippingProfile(profileId: string) { +async function deleteShippingProfile(id: string) { return deleteRequest( - `/admin/shipping-profiles/${profileId}` + `/admin/shipping-profiles/${id}` ) } export const shippingProfiles = { - create: createShippingProfile, + retrieve: retrieveShippingProfile, list: listShippingProfiles, + create: createShippingProfile, delete: deleteShippingProfile, } diff --git a/packages/admin-next/dashboard/src/providers/router-provider/v1.tsx b/packages/admin-next/dashboard/src/providers/router-provider/v1.tsx index 8154065b2987..16ac2d62554f 100644 --- a/packages/admin-next/dashboard/src/providers/router-provider/v1.tsx +++ b/packages/admin-next/dashboard/src/providers/router-provider/v1.tsx @@ -1,6 +1,4 @@ import type { - AdminCustomerGroupsRes, - AdminCustomersRes, AdminDiscountsRes, AdminDraftOrdersRes, AdminGiftCardsRes, diff --git a/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx b/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx index 990769947b2b..b7f8dece69db 100644 --- a/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx +++ b/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx @@ -329,21 +329,6 @@ export const v2Routes: RouteObject[] = [ }, ], }, - { - path: "shipping-profiles", - lazy: () => - import("../../v2-routes/shipping/shipping-profiles-list"), - handle: { - crumb: () => "Shipping Profiles", - }, - children: [ - { - path: "create", - lazy: () => - import("../../v2-routes/shipping/shipping-profile-create"), - }, - ], - }, { path: "/customers", handle: { @@ -727,6 +712,38 @@ export const v2Routes: RouteObject[] = [ }, ], }, + { + path: "shipping-profiles", + element: , + handle: { + crumb: () => "Shipping Profiles", + }, + children: [ + { + path: "", + lazy: () => + import( + "../../v2-routes/shipping-profiles/shipping-profiles-list" + ), + children: [ + { + path: "create", + lazy: () => + import( + "../../v2-routes/shipping-profiles/shipping-profile-create" + ), + }, + ], + }, + { + path: ":id", + lazy: () => + import( + "../../v2-routes/shipping-profiles/shipping-profile-detail" + ), + }, + ], + }, { path: "api-key-management", element: , diff --git a/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-general-section/region-general-section.tsx b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-general-section/region-general-section.tsx index 0666df106220..0812463af9db 100644 --- a/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-general-section/region-general-section.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/regions/region-detail/components/region-general-section/region-general-section.tsx @@ -3,12 +3,12 @@ import { RegionDTO } from "@medusajs/types" import { Badge, Container, Heading, Text, usePrompt } from "@medusajs/ui" import { useTranslation } from "react-i18next" +import { useNavigate } from "react-router-dom" import { ActionMenu } from "../../../../../components/common/action-menu" -import { formatProvider } from "../../../../../lib/format-provider" -import { currencies } from "../../../../../lib/currencies" -import { useDeleteRegion } from "../../../../../hooks/api/regions.tsx" import { ListSummary } from "../../../../../components/common/list-summary" -import { useNavigate } from "react-router-dom" +import { useDeleteRegion } from "../../../../../hooks/api/regions.tsx" +import { currencies } from "../../../../../lib/currencies" +import { formatProvider } from "../../../../../lib/format-provider" type RegionGeneralSectionProps = { region: RegionDTO @@ -23,7 +23,7 @@ export const RegionGeneralSection = ({ region }: RegionGeneralSectionProps) => { {region.name}
-
+
{t("fields.currency")} @@ -36,7 +36,7 @@ export const RegionGeneralSection = ({ region }: RegionGeneralSectionProps) => {
-
+
{t("fields.paymentProviders")} diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profile-create/components/create-shipping-profile-form/create-shipping-profile-form.tsx b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-create/components/create-shipping-profile-form/create-shipping-profile-form.tsx similarity index 79% rename from packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profile-create/components/create-shipping-profile-form/create-shipping-profile-form.tsx rename to packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-create/components/create-shipping-profile-form/create-shipping-profile-form.tsx index fad098b480e7..e7bab2c383eb 100644 --- a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profile-create/components/create-shipping-profile-form/create-shipping-profile-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-create/components/create-shipping-profile-form/create-shipping-profile-form.tsx @@ -1,14 +1,14 @@ -import { Button, Heading, Input, Text } from "@medusajs/ui" -import { useForm } from "react-hook-form" -import * as zod from "zod" 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 * as zod from "zod" +import { Form } from "../../../../../components/common/form" import { RouteFocusModal, useRouteModal, } from "../../../../../components/route-modal" -import { Form } from "../../../../../components/common/form" import { useCreateShippingProfile } from "../../../../../hooks/api/shipping-profiles" const CreateShippingOptionsSchema = zod.object({ @@ -31,11 +31,30 @@ export function CreateShippingProfileForm() { const { mutateAsync, isPending } = useCreateShippingProfile() const handleSubmit = form.handleSubmit(async (values) => { - await mutateAsync({ - name: values.name, - type: values.type, - }) - handleSuccess("/shipping-profiles") + await mutateAsync( + { + name: values.name, + type: values.type, + }, + { + onSuccess: ({ shipping_profile }) => { + toast.success(t("general.success"), { + description: t("shippingProfile.create.successToast", { + name: shipping_profile.name, + }), + dismissLabel: t("actions.close"), + }) + + handleSuccess(`/settings/shipping-profiles/${shipping_profile.id}`) + }, + onError: (error) => { + toast.error(t("general.error"), { + description: error.message, + dismissLabel: t("actions.close"), + }) + }, + } + ) }) return ( @@ -61,10 +80,10 @@ export function CreateShippingProfileForm() {
- {t("shippingProfile.title")} + {t("shippingProfile.create.header")} - {t("shippingProfile.detailsHint")} + {t("shippingProfile.create.hint")}
@@ -89,7 +108,7 @@ export function CreateShippingProfileForm() { render={({ field }) => { return ( - + {t("fields.type")} diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profile-create/components/create-shipping-profile-form/index.ts b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-create/components/create-shipping-profile-form/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profile-create/components/create-shipping-profile-form/index.ts rename to packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-create/components/create-shipping-profile-form/index.ts diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profile-create/index.ts b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-create/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profile-create/index.ts rename to packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-create/index.ts diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profile-create/shipping-profile-create.tsx b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-create/shipping-profile-create.tsx similarity index 100% rename from packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profile-create/shipping-profile-create.tsx rename to packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-create/shipping-profile-create.tsx diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-detail/components/shipping-profile-general-section/index.ts b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-detail/components/shipping-profile-general-section/index.ts new file mode 100644 index 000000000000..e345ebc5f2ef --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-detail/components/shipping-profile-general-section/index.ts @@ -0,0 +1 @@ +export * from "./shipping-profile-general-section" diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-detail/components/shipping-profile-general-section/shipping-profile-general-section.tsx b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-detail/components/shipping-profile-general-section/shipping-profile-general-section.tsx new file mode 100644 index 000000000000..9eac64407e34 --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-detail/components/shipping-profile-general-section/shipping-profile-general-section.tsx @@ -0,0 +1,80 @@ +import { Trash } from "@medusajs/icons" +import { AdminShippingProfileResponse } from "@medusajs/types" +import { Container, Heading, toast, usePrompt } from "@medusajs/ui" +import { useTranslation } from "react-i18next" +import { useNavigate } from "react-router-dom" +import { ActionMenu } from "../../../../../components/common/action-menu" +import { SectionRow } from "../../../../../components/common/section" +import { useDeleteShippingProfile } from "../../../../../hooks/api/shipping-profiles" + +type ShippingProfileGeneralSectionProps = { + profile: AdminShippingProfileResponse["shipping_profile"] +} + +export const ShippingProfileGeneralSection = ({ + profile, +}: ShippingProfileGeneralSectionProps) => { + const { t } = useTranslation() + const prompt = usePrompt() + const navigate = useNavigate() + + const { mutateAsync } = useDeleteShippingProfile(profile.id) + + const handleDelete = async () => { + const res = await prompt({ + title: t("shippingProfile.delete.title"), + description: t("shippingProfile.delete.description", { + name: profile.name, + }), + verificationText: profile.name, + verificationInstruction: t("general.typeToConfirm"), + confirmText: t("actions.delete"), + cancelText: t("actions.cancel"), + }) + + if (!res) { + return + } + + await mutateAsync(undefined, { + onSuccess: () => { + toast.success(t("general.success"), { + description: t("shippingProfile.delete.successToast", { + name: profile.name, + }), + dismissLabel: t("actions.close"), + }) + + navigate("/settings/shipping-profiles", { replace: true }) + }, + onError: (error) => { + toast.error(t("general.error"), { + description: error.message, + dismissLabel: t("actions.close"), + }) + }, + }) + } + + return ( + +
+ {profile.name} + , + label: t("actions.delete"), + onClick: handleDelete, + }, + ], + }, + ]} + /> +
+ +
+ ) +} diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-detail/index.ts b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-detail/index.ts new file mode 100644 index 000000000000..2d352f3b8e52 --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-detail/index.ts @@ -0,0 +1 @@ +export { ShippingProfileDetail as Component } from "./shipping-profile-detail" diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-detail/shipping-profile-detail.tsx b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-detail/shipping-profile-detail.tsx new file mode 100644 index 000000000000..02c16c967a64 --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profile-detail/shipping-profile-detail.tsx @@ -0,0 +1,36 @@ +import { useParams } from "react-router-dom" +import { JsonViewSection } from "../../../components/common/json-view-section" +import { + GeneralSectionSkeleton, + JsonViewSectionSkeleton, +} from "../../../components/common/skeleton" +import { useShippingProfile } from "../../../hooks/api/shipping-profiles" +import { ShippingProfileGeneralSection } from "./components/shipping-profile-general-section" + +export const ShippingProfileDetail = () => { + const { id } = useParams() + + const { shipping_profile, isLoading, isError, error } = useShippingProfile( + id! + ) + + if (isLoading || !shipping_profile) { + return ( +
+ + +
+ ) + } + + if (isError) { + throw error + } + + return ( +
+ + +
+ ) +} diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/index.ts b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/index.ts rename to packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/index.ts diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/shipping-options-row-actions.tsx b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/shipping-options-row-actions.tsx similarity index 58% rename from packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/shipping-options-row-actions.tsx rename to packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/shipping-options-row-actions.tsx index 4f79e67a318b..00ca93bd2b51 100644 --- a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/shipping-options-row-actions.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/shipping-options-row-actions.tsx @@ -1,7 +1,7 @@ import { Trash } from "@medusajs/icons" -import { usePrompt } from "@medusajs/ui" +import { AdminShippingProfileResponse } from "@medusajs/types" +import { toast, usePrompt } from "@medusajs/ui" import { useTranslation } from "react-i18next" -import { ShippingProfileDTO } from "@medusajs/types" import { ActionMenu } from "../../../../../components/common/action-menu" import { useDeleteShippingProfile } from "../../../../../hooks/api/shipping-profiles" @@ -9,17 +9,17 @@ import { useDeleteShippingProfile } from "../../../../../hooks/api/shipping-prof export const ShippingOptionsRowActions = ({ profile, }: { - profile: ShippingProfileDTO + profile: AdminShippingProfileResponse["shipping_profile"] }) => { const { t } = useTranslation() const prompt = usePrompt() - // TODO: MISSING ENDPOINT + const { mutateAsync } = useDeleteShippingProfile(profile.id) const handleDelete = async () => { const res = await prompt({ - title: t("general.areYouSure"), - description: t("shippingProfile.deleteWaring", { + title: t("shippingProfile.delete.title"), + description: t("shippingProfile.delete.description", { name: profile.name, }), verificationText: profile.name, @@ -32,7 +32,22 @@ export const ShippingOptionsRowActions = ({ return } - await mutateAsync() + await mutateAsync(undefined, { + onSuccess: () => { + toast.success(t("general.success"), { + description: t("shippingProfile.delete.successToast", { + name: profile.name, + }), + dismissLabel: t("actions.close"), + }) + }, + onError: (error) => { + toast.error(t("general.error"), { + description: error.message, + dismissLabel: t("actions.close"), + }) + }, + }) } return ( diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/shipping-profile-list-table.tsx b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/shipping-profile-list-table.tsx similarity index 56% rename from packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/shipping-profile-list-table.tsx rename to packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/shipping-profile-list-table.tsx index 86568cfdc788..1b695ad6db8f 100644 --- a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/shipping-profile-list-table.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/shipping-profile-list-table.tsx @@ -1,29 +1,31 @@ import { Button, Container, Heading } from "@medusajs/ui" import { Link } from "react-router-dom" +import { keepPreviousData } from "@tanstack/react-query" import { useTranslation } from "react-i18next" import { DataTable } from "../../../../../components/table/data-table" -import { useDataTable } from "../../../../../hooks/use-data-table" -import { useShippingProfilesTableColumns } from "./use-shipping-profiles-table-columns" -import { useShippingProfilesTableQuery } from "./use-shipping-profiles-table-query" -import { NoRecords } from "../../../../../components/common/empty-table-content" import { useShippingProfiles } from "../../../../../hooks/api/shipping-profiles" +import { useDataTable } from "../../../../../hooks/use-data-table" +import { useShippingProfileTableColumns } from "./use-shipping-profile-table-columns" +import { useShippingProfileTableFilters } from "./use-shipping-profile-table-filters" +import { useShippingProfileTableQuery } from "./use-shipping-profile-table-query" const PAGE_SIZE = 20 export const ShippingProfileListTable = () => { const { t } = useTranslation() - const { raw, searchParams } = useShippingProfilesTableQuery({ + const { raw, searchParams } = useShippingProfileTableQuery({ pageSize: PAGE_SIZE, }) const { shipping_profiles, count, isLoading, isError, error } = - useShippingProfiles({ - ...searchParams, + useShippingProfiles(searchParams, { + placeholderData: keepPreviousData, }) - const columns = useShippingProfilesTableColumns() + const columns = useShippingProfileTableColumns() + const filters = useShippingProfileTableFilters() const { table } = useDataTable({ data: shipping_profiles, @@ -38,8 +40,6 @@ export const ShippingProfileListTable = () => { throw error } - const noData = !isLoading && !shipping_profiles.length - return (
@@ -50,19 +50,19 @@ export const ShippingProfileListTable = () => {
- {noData ? ( - - ) : ( - - )} + row.id} + queryObject={raw} + search + pagination + /> ) } diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profiles-table-columns.tsx b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profile-table-columns.tsx similarity index 76% rename from packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profiles-table-columns.tsx rename to packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profile-table-columns.tsx index a7ae29183d53..caeeab161944 100644 --- a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profiles-table-columns.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profile-table-columns.tsx @@ -1,13 +1,14 @@ +import { AdminShippingProfileResponse } from "@medusajs/types" import { createColumnHelper } from "@tanstack/react-table" import { useMemo } from "react" import { useTranslation } from "react-i18next" -import { ShippingProfileDTO } from "@medusajs/types" import { ShippingOptionsRowActions } from "./shipping-options-row-actions" -const columnHelper = createColumnHelper() +const columnHelper = + createColumnHelper() -export const useShippingProfilesTableColumns = () => { +export const useShippingProfileTableColumns = () => { const { t } = useTranslation() return useMemo( diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profile-table-filters.tsx b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profile-table-filters.tsx new file mode 100644 index 000000000000..1bf3892a4833 --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profile-table-filters.tsx @@ -0,0 +1,33 @@ +import { useTranslation } from "react-i18next" +import { Filter } from "../../../../../components/table/data-table" + +export const useShippingProfileTableFilters = () => { + const { t } = useTranslation() + + let filters: Filter[] = [] + + filters.push({ + key: "name", + label: t("fields.name"), + type: "string", + }) + + filters.push({ + key: "type", + label: t("fields.type"), + type: "string", + }) + + const dateFilters: Filter[] = [ + { label: t("fields.createdAt"), key: "created_at" }, + { label: t("fields.updatedAt"), key: "updated_at" }, + ].map((f) => ({ + key: f.key, + label: f.label, + type: "date", + })) + + filters = [...filters, ...dateFilters] + + return filters +} diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profile-table-query.tsx b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profile-table-query.tsx new file mode 100644 index 000000000000..27e32214c445 --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profile-table-query.tsx @@ -0,0 +1,30 @@ +import { useQueryParams } from "../../../../../hooks/use-query-params" + +export const useShippingProfileTableQuery = ({ + pageSize = 20, + prefix, +}: { + pageSize?: number + prefix?: string +}) => { + const raw = useQueryParams( + ["offset", "q", "order", "created_at", "updated_at", "name", "type"], + prefix + ) + + const searchParams = { + limit: pageSize, + offset: raw.offset ? parseInt(raw.offset) : 0, + q: raw.q, + order: raw.order, + created_at: raw.created_at ? JSON.parse(raw.created_at) : undefined, + updated_at: raw.updated_at ? JSON.parse(raw.updated_at) : undefined, + name: raw.name, + type: raw.type, + } + + return { + searchParams, + raw, + } +} diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/index.ts b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/index.ts similarity index 100% rename from packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/index.ts rename to packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/index.ts diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/shipping-profile-list.tsx b/packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/shipping-profile-list.tsx similarity index 100% rename from packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/shipping-profile-list.tsx rename to packages/admin-next/dashboard/src/v2-routes/shipping-profiles/shipping-profiles-list/shipping-profile-list.tsx diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping/const.ts b/packages/admin-next/dashboard/src/v2-routes/shipping/const.ts deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profiles-table-query.tsx b/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profiles-table-query.tsx deleted file mode 100644 index 51ba906e7ec2..000000000000 --- a/packages/admin-next/dashboard/src/v2-routes/shipping/shipping-profiles-list/components/shipping-profile-list-table/use-shipping-profiles-table-query.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { useQueryParams } from "../../../../../hooks/use-query-params" - -export const useShippingProfilesTableQuery = ({ - pageSize = 20, - prefix, -}: { - pageSize?: number - prefix?: string -}) => { - const raw = useQueryParams(["offset"], prefix) - - const searchParams = { - limit: pageSize, - offset: raw.offset, - } - - return { - searchParams, - raw, - } -} diff --git a/packages/fulfillment/src/models/shipping-profile.ts b/packages/fulfillment/src/models/shipping-profile.ts index 87db7f40b68d..96c332716c0c 100644 --- a/packages/fulfillment/src/models/shipping-profile.ts +++ b/packages/fulfillment/src/models/shipping-profile.ts @@ -2,6 +2,7 @@ import { createPsqlIndexStatementHelper, DALUtils, generateEntityId, + Searchable, } from "@medusajs/utils" import { DAL } from "@medusajs/types" @@ -41,10 +42,12 @@ export default class ShippingProfile { @PrimaryKey({ columnType: "text" }) id: string + @Searchable() @Property({ columnType: "text" }) @ShippingProfileTypeIndex.MikroORMIndex() name: string + @Searchable() @Property({ columnType: "text" }) type: string diff --git a/packages/medusa/src/api-v2/admin/shipping-profiles/validators.ts b/packages/medusa/src/api-v2/admin/shipping-profiles/validators.ts index 4da3e2a36af1..20418a729d05 100644 --- a/packages/medusa/src/api-v2/admin/shipping-profiles/validators.ts +++ b/packages/medusa/src/api-v2/admin/shipping-profiles/validators.ts @@ -1,5 +1,9 @@ import { z } from "zod" -import { createFindParams, createSelectParams } from "../../utils/validators" +import { + createFindParams, + createOperatorMap, + createSelectParams, +} from "../../utils/validators" export type AdminGetShippingProfileParamsType = z.infer< typeof AdminGetShippingProfileParams @@ -14,8 +18,14 @@ export const AdminGetShippingProfilesParams = createFindParams({ offset: 0, }).merge( z.object({ + q: z.string().optional(), type: z.string().optional(), name: z.string().optional(), + created_at: createOperatorMap().optional(), + updated_at: createOperatorMap().optional(), + deleted_at: createOperatorMap().optional(), + $and: z.lazy(() => AdminGetShippingProfilesParams.array()).optional(), + $or: z.lazy(() => AdminGetShippingProfilesParams.array()).optional(), }) )