fix(dashboard,types): Fix TS errors (#10457)

**What**
- Fixes TS erros in dashboard project
- Updates incorrect HTTP Invite types
- Fixes incorrectly formatted dates in dashboard
This commit is contained in:
Kasper Fabricius Kristensen
2024-12-08 12:51:13 +01:00
committed by GitHub
parent 55f5ce4690
commit 864f53011b
28 changed files with 120 additions and 252 deletions
+6
View File
@@ -0,0 +1,6 @@
---
"@medusajs/dashboard": patch
"@medusajs/types": patch
---
fix(dashboard,types): Fix TS errors
@@ -1,7 +1,7 @@
import { DropdownMenu, IconButton, clx } from "@medusajs/ui"
import { EllipsisHorizontal } from "@medusajs/icons"
import { ReactNode } from "react"
import { PropsWithChildren, ReactNode } from "react"
import { Link } from "react-router-dom"
import { ConditionalTooltip } from "../conditional-tooltip"
@@ -28,18 +28,20 @@ export type ActionGroup = {
actions: Action[]
}
type ActionMenuProps = {
type ActionMenuProps = PropsWithChildren<{
groups: ActionGroup[]
}
}>
export const ActionMenu = ({ groups, children }: ActionMenuProps) => {
const inner = children ?? (
<IconButton size="small" variant="transparent">
<EllipsisHorizontal />
</IconButton>
)
export const ActionMenu = ({ groups }: ActionMenuProps) => {
return (
<DropdownMenu>
<DropdownMenu.Trigger asChild>
<IconButton size="small" variant="transparent">
<EllipsisHorizontal />
</IconButton>
</DropdownMenu.Trigger>
<DropdownMenu.Trigger asChild>{inner}</DropdownMenu.Trigger>
<DropdownMenu.Content>
{groups.map((group, index) => {
if (!group.actions.length) {
@@ -1,96 +0,0 @@
import { DropdownMenu, clx } from "@medusajs/ui"
import { PropsWithChildren, ReactNode } from "react"
import { Link } from "react-router-dom"
type Action = {
icon: ReactNode
label: string
disabled?: boolean
} & (
| {
to: string
onClick?: never
}
| {
onClick: () => void
to?: never
}
)
type ActionGroup = {
actions: Action[]
}
type ActionMenuProps = {
groups: ActionGroup[]
}
export const ButtonMenu = ({
groups,
children,
}: PropsWithChildren<ActionMenuProps>) => {
return (
<DropdownMenu>
<DropdownMenu.Trigger asChild>{children}</DropdownMenu.Trigger>
<DropdownMenu.Content>
{groups.map((group, index) => {
if (!group.actions.length) {
return null
}
const isLast = index === groups.length - 1
return (
<DropdownMenu.Group key={index}>
{group.actions.map((action, index) => {
if (action.onClick) {
return (
<DropdownMenu.Item
disabled={action.disabled}
key={index}
onClick={(e) => {
e.stopPropagation()
action.onClick()
}}
className={clx(
"[&_svg]:text-ui-fg-subtle flex items-center gap-x-2",
{
"[&_svg]:text-ui-fg-disabled": action.disabled,
}
)}
>
{action.icon}
<span>{action.label}</span>
</DropdownMenu.Item>
)
}
return (
<div key={index}>
<DropdownMenu.Item
className={clx(
"[&_svg]:text-ui-fg-subtle flex items-center gap-x-2",
{
"[&_svg]:text-ui-fg-disabled": action.disabled,
}
)}
asChild
disabled={action.disabled}
>
<Link to={action.to} onClick={(e) => e.stopPropagation()}>
{action.icon}
<span>{action.label}</span>
</Link>
</DropdownMenu.Item>
</div>
)
})}
{!isLast && <DropdownMenu.Separator />}
</DropdownMenu.Group>
)
})}
</DropdownMenu.Content>
</DropdownMenu>
)
}
@@ -1 +0,0 @@
export * from "./action-menu"
@@ -1,11 +0,0 @@
import format from "date-fns/format"
export function formatDate(date: string | Date) {
const value = new Date(date)
value.setMinutes(value.getMinutes() - value.getTimezoneOffset())
const hour12 = Intl.DateTimeFormat().resolvedOptions().hour12
const timestampFormat = hour12 ? "dd MMM yyyy hh:MM a" : "dd MMM yyyy HH:MM"
return format(value, timestampFormat)
}
@@ -2,11 +2,11 @@ import { Heading, Input, Select, clx } from "@medusajs/ui"
import { useTranslation } from "react-i18next"
import { z } from "zod"
import { HttpTypes } from "@medusajs/types"
import { Control } from "react-hook-form"
import { AddressSchema } from "../../../lib/schemas"
import { Form } from "../../common/form"
import { CountrySelect } from "../../inputs/country-select"
import { HttpTypes } from "@medusajs/types"
type AddressFieldValues = z.infer<typeof AddressSchema>
@@ -187,14 +187,24 @@ export const AddressForm = ({
<Select.Value />
</Select.Trigger>
<Select.Content>
{countries.map((country) => (
<Select.Item
key={country.iso_2}
value={country.iso_2}
>
{country.display_name}
</Select.Item>
))}
{countries.map((country) => {
/**
* If a country does not have an ISO 2 code, it is not
* a valid country and should not be selectable.
*/
if (!country.iso_2) {
return null
}
return (
<Select.Item
key={country.iso_2}
value={country.iso_2}
>
{country.display_name}
</Select.Item>
)
})}
</Select.Content>
</Select>
) : (
@@ -18,7 +18,7 @@ import {
Trash,
} from "@medusajs/icons"
import { FetchError } from "@medusajs/js-sdk"
import { ComponentPropsWithoutRef, forwardRef, useRef } from "react"
import { ComponentPropsWithoutRef, forwardRef } from "react"
import { ConditionalTooltip } from "../../common/conditional-tooltip"
import { Form } from "../../common/form"
import { InlineTip } from "../../common/inline-tip"
@@ -78,7 +78,6 @@ const InnerForm = <TRes,>({
const { t } = useTranslation()
const { handleSuccess } = useRouteModal()
const deletedOriginalRows = useRef<string[]>([])
const hasUneditableRows = getHasUneditableRows(metadata)
const form = useForm<z.infer<typeof MetadataSchema>>({
@@ -1,6 +1,6 @@
import { Tooltip } from "@medusajs/ui"
import format from "date-fns/format"
import { useTranslation } from "react-i18next"
import { useDate } from "../../../../../hooks/use-date"
import { PlaceholderCell } from "../placeholder-cell"
type DateCellProps = {
@@ -8,28 +8,26 @@ type DateCellProps = {
}
export const CreatedAtCell = ({ date }: DateCellProps) => {
const { getFullDate } = useDate()
if (!date) {
return <PlaceholderCell />
}
const value = new Date(date)
value.setMinutes(value.getMinutes() - value.getTimezoneOffset())
const hour12 = Intl.DateTimeFormat().resolvedOptions().hour12
const timestampFormat = hour12 ? "dd MMM yyyy hh:MM a" : "dd MMM yyyy HH:MM"
return (
<div className="flex h-full w-full items-center overflow-hidden">
<Tooltip
className="z-10"
content={
<span className="text-pretty">{`${format(
value,
timestampFormat
)}`}</span>
<span className="text-pretty">{`${getFullDate({
date,
includeTime: true,
})}`}</span>
}
>
<span className="truncate">{format(value, "dd MMM yyyy")}</span>
<span className="truncate">
{getFullDate({ date, includeTime: true })}
</span>
</Tooltip>
</div>
)
@@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next"
export const CustomerCell = ({
customer,
}: {
customer: HttpTypes.AdminCustomer | null
customer?: HttpTypes.AdminCustomer | null
}) => {
if (!customer) {
return <span className="text-ui-fg-muted">-</span>
@@ -1,9 +1,10 @@
import { HttpTypes } from "@medusajs/types"
import { useTranslation } from "react-i18next"
import { getOrderPaymentStatus } from "../../../../../lib/order-helpers"
import { StatusCell } from "../../common/status-cell"
type PaymentStatusCellProps = {
status: PaymentStatus
status: HttpTypes.AdminOrder["payment_status"]
}
export const PaymentStatusCell = ({ status }: PaymentStatusCellProps) => {
@@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next"
export const SalesChannelCell = ({
channel,
}: {
channel: HttpTypes.AdminSalesChannel | null
channel?: HttpTypes.AdminSalesChannel | null
}) => {
if (!channel) {
return <span className="text-ui-fg-muted">-</span>
@@ -1,4 +1,4 @@
import { RegionCountryDTO } from "@medusajs/types"
import { HttpTypes } from "@medusajs/types"
import { useTranslation } from "react-i18next"
import { countries as COUNTRIES } from "../../../../../lib/data/countries"
@@ -6,24 +6,24 @@ import { ListSummary } from "../../../../common/list-summary"
import { PlaceholderCell } from "../../common/placeholder-cell"
type CountriesCellProps = {
countries?: RegionCountryDTO[] | null
countries?: HttpTypes.AdminRegionCountry[] | null
}
export const CountriesCell = ({ countries }: CountriesCellProps) => {
const { t } = useTranslation()
if (!countries || countries.length === 0) {
return <PlaceholderCell />
}
const list = countries
.map(
(country) =>
COUNTRIES.find((c) => c.iso_2 === country.iso_2)?.display_name
)
.filter(Boolean) as string[]
return (
<div className="flex size-full items-center overflow-hidden">
<ListSummary
list={countries.map(
(country) =>
COUNTRIES.find((c) => c.iso_2 === country.iso_2)!.display_name
)}
/>
<ListSummary list={list} />
</div>
)
}
@@ -1,32 +0,0 @@
import { InjectionZone } from "@medusajs/admin-shared"
import { ComponentType } from "react"
import { LoaderFunction } from "react-router-dom"
import { CustomFieldConfiguration } from "../../extensions/custom-field-registry/types"
export type RouteExtension = {
Component: ComponentType
loader?: LoaderFunction
path: string
}
export type MenuItemExtension = {
label: string
path: string
icon?: ComponentType
}
export type WidgetExtension = {
Component: ComponentType
zone: InjectionZone[]
}
export type RoutingExtensionConfig = {
routes: RouteExtension[]
menuItems: MenuItemExtension[]
}
export type DashboardExtensionConfig = {
customFields?: CustomFieldConfiguration
menuItems?: MenuItemExtension[]
widgets?: WidgetExtension[]
}
@@ -1,11 +1,14 @@
import { UseMutationOptions, useMutation } from "@tanstack/react-query"
import { FetchError } from "@medusajs/js-sdk"
import { sdk } from "../../lib/client"
import { HttpTypes } from "@medusajs/types"
import { UseMutationOptions, useMutation } from "@tanstack/react-query"
import { sdk } from "../../lib/client"
export const useSignInWithEmailPass = (
options?: UseMutationOptions<
string,
| string
| {
location: string
},
FetchError,
HttpTypes.AdminSignUpWithEmailPassword
>
@@ -208,14 +208,13 @@ export const useAddClaimInboundItems = (
id: string,
orderId: string,
options?: UseMutationOptions<
HttpTypes.AdminClaimResponse,
HttpTypes.AdminClaimReturnPreviewResponse,
FetchError,
HttpTypes.AdminAddClaimInboundItems
>
) => {
return useMutation({
mutationFn: (payload: HttpTypes.AdminAddClaimInboundItems) =>
sdk.admin.claim.addInboundItems(id, payload),
mutationFn: (payload) => sdk.admin.claim.addInboundItems(id, payload),
onSuccess: (data: any, variables: any, context: any) => {
queryClient.invalidateQueries({
queryKey: ordersQueryKeys.details(),
@@ -37,7 +37,7 @@ export const useCollection = (
}
export const useCollections = (
query?: FindParams & HttpTypes.AdminCollectionFilters,
query?: FindParams & HttpTypes.AdminCollectionListParams,
options?: Omit<
UseQueryOptions<
PaginatedResponse<{ collections: HttpTypes.AdminCollection[] }>,
@@ -60,7 +60,7 @@ export const useCollections = (
export const useUpdateCollection = (
id: string,
options?: UseMutationOptions<
{ collection: HttpTypes.AdminCollection },
HttpTypes.AdminCollectionResponse,
FetchError,
HttpTypes.AdminUpdateCollection
>
@@ -82,7 +82,7 @@ export const useUpdateCollection = (
export const useUpdateCollectionProducts = (
id: string,
options?: UseMutationOptions<
{ collection: HttpTypes.AdminCollection },
HttpTypes.AdminCollectionResponse,
FetchError,
HttpTypes.AdminUpdateCollectionProducts
>
@@ -110,7 +110,7 @@ export const useUpdateCollectionProducts = (
export const useCreateCollection = (
options?: UseMutationOptions<
{ collection: HttpTypes.AdminCollection },
HttpTypes.AdminCollectionResponse,
FetchError,
HttpTypes.AdminCreateCollection
>
@@ -1,8 +1,5 @@
import {
AdminInviteResponse,
HttpTypes,
PaginatedResponse,
} from "@medusajs/types"
import { FetchError } from "@medusajs/js-sdk"
import { HttpTypes } from "@medusajs/types"
import {
QueryKey,
UseMutationOptions,
@@ -13,7 +10,6 @@ import {
import { sdk } from "../../lib/client"
import { queryClient } from "../../lib/query-client"
import { queryKeysFactory } from "../../lib/query-key-factory"
import { FetchError } from "@medusajs/js-sdk"
const INVITES_QUERY_KEY = "invites" as const
const invitesQueryKeys = queryKeysFactory(INVITES_QUERY_KEY)
@@ -22,9 +18,9 @@ export const useInvite = (
id: string,
options?: Omit<
UseQueryOptions<
{ invite: HttpTypes.AdminInviteResponse },
HttpTypes.AdminInviteResponse,
FetchError,
{ invite: HttpTypes.AdminInviteResponse },
HttpTypes.AdminInviteResponse,
QueryKey
>,
"queryFn" | "queryKey"
@@ -43,9 +39,9 @@ export const useInvites = (
query?: Record<string, any>,
options?: Omit<
UseQueryOptions<
PaginatedResponse<{ invites: HttpTypes.AdminInviteResponse[] }>,
HttpTypes.AdminInviteListResponse,
FetchError,
PaginatedResponse<{ invites: HttpTypes.AdminInviteResponse[] }>,
HttpTypes.AdminInviteListResponse,
QueryKey
>,
"queryFn" | "queryKey"
@@ -62,7 +58,7 @@ export const useInvites = (
export const useCreateInvite = (
options?: UseMutationOptions<
{ invite: AdminInviteResponse },
HttpTypes.AdminInviteResponse,
FetchError,
HttpTypes.AdminCreateInvite
>
@@ -79,11 +75,7 @@ export const useCreateInvite = (
export const useResendInvite = (
id: string,
options?: UseMutationOptions<
{ invite: AdminInviteResponse },
FetchError,
void
>
options?: UseMutationOptions<HttpTypes.AdminInviteResponse, FetchError, void>
) => {
return useMutation({
mutationFn: () => sdk.admin.invite.resend(id),
@@ -118,7 +110,7 @@ export const useDeleteInvite = (
export const useAcceptInvite = (
inviteToken: string,
options?: UseMutationOptions<
{ user: HttpTypes.AdminUserResponse },
HttpTypes.AdminAcceptInviteResponse,
FetchError,
HttpTypes.AdminAcceptInvite & { auth_token: string }
>
@@ -128,7 +128,7 @@ export const useBatchPriceListPrices = (
id: string,
query?: HttpTypes.AdminPriceListParams,
options?: UseMutationOptions<
HttpTypes.AdminPriceListResponse,
HttpTypes.AdminPriceListBatchResponse,
FetchError,
HttpTypes.AdminBatchPriceListPrice
>
@@ -1,3 +1,4 @@
import { HttpTypes } from "@medusajs/types"
import {
ColumnDef,
ColumnDefBase,
@@ -33,7 +34,6 @@ import {
TotalCell,
TotalHeader,
} from "../../../components/table/table-cells/order/total-cell"
import { HttpTypes } from "@medusajs/types"
// We have to use any here, as the type of Order is so complex that it lags the TS server
const columnHelper = createColumnHelper<HttpTypes.AdminOrder>()
-1
View File
@@ -1 +0,0 @@
export * from "./render"
@@ -1,15 +1,15 @@
import { useMemo, useState } from "react"
import { AdminOrder, AdminOrderPreview } from "@medusajs/types"
import { Button, Heading, Input, toast } from "@medusajs/ui"
import { useMemo, useState } from "react"
import { useTranslation } from "react-i18next"
import {
RouteFocusModal,
StackedFocusModal,
useStackedModal,
} from "../../../../../components/modals"
import { useAddOrderEditItems } from "../../../../../hooks/api/order-edits"
import { AddOrderEditItemsTable } from "../add-order-edit-items-table"
import { OrderEditItem } from "./order-edit-item"
import { useAddOrderEditItems } from "../../../../../hooks/api/order-edits"
type ExchangeInboundSectionProps = {
order: AdminOrder
@@ -39,16 +39,19 @@ export const OrderEditItemsSection = ({
* CALLBACKS
*/
const onItemsSelected = async () => {
try {
await addItems({
await addItems(
{
items: addedVariants.map((i) => ({
variant_id: i,
quantity: 1,
})),
})
} catch (e) {
toast.error(e.message)
}
},
{
onError: (e) => {
toast.error(e.message)
},
}
)
setIsOpen("inbound-items", false)
}
@@ -38,7 +38,6 @@ import {
import { AdminReservation } from "@medusajs/types/src/http"
import { AdminPaymentCollection } from "../../../../../../../../core/types/dist/http/payment/admin/entities"
import { ActionMenu } from "../../../../../components/common/action-menu"
import { ButtonMenu } from "../../../../../components/common/button-menu/button-menu"
import { Thumbnail } from "../../../../../components/common/thumbnail"
import { useClaims } from "../../../../../hooks/api/claims"
import { useExchanges } from "../../../../../hooks/api/exchanges"
@@ -193,7 +192,7 @@ export const OrderSummarySection = ({ order }: OrderSummarySectionProps) => {
{t("orders.returns.receive.action")}
</Button>
) : (
<ButtonMenu
<ActionMenu
groups={[
{
actions: receivableReturns.map((r) => {
@@ -225,7 +224,7 @@ export const OrderSummarySection = ({ order }: OrderSummarySectionProps) => {
<Button variant="secondary" size="small">
{t("orders.returns.receive.action")}
</Button>
</ButtonMenu>
</ActionMenu>
))}
{showAllocateButton && (
@@ -3,7 +3,7 @@ import { AdminReturn } from "@medusajs/types"
import { Badge, Popover, Text } from "@medusajs/ui"
import { useState } from "react"
import { useTranslation } from "react-i18next"
import { formatDate } from "../../../../../components/common/date"
import { useDate } from "../../../../../hooks/use-date"
type ReturnInfoPopoverProps = {
orderReturn: AdminReturn
@@ -13,6 +13,8 @@ function ReturnInfoPopover({ orderReturn }: ReturnInfoPopoverProps) {
const { t } = useTranslation()
const [open, setOpen] = useState(false)
const { getFullDate } = useDate()
const handleMouseEnter = () => {
setOpen(true)
}
@@ -44,7 +46,7 @@ function ReturnInfoPopover({ orderReturn }: ReturnInfoPopoverProps) {
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
autoFocus={false}
className="focus-visible:outline-none align-sub"
className="align-sub focus-visible:outline-none"
>
<InformationCircleSolid />
</Popover.Trigger>
@@ -52,7 +54,7 @@ function ReturnInfoPopover({ orderReturn }: ReturnInfoPopoverProps) {
<Popover.Content
align="center"
side="top"
className="bg-ui-bg-component focus-visible:outline-none p-2"
className="bg-ui-bg-component p-2 focus-visible:outline-none"
>
<div className="">
<Badge size="2xsmall" className="mb-2" rounded="full">
@@ -64,7 +66,7 @@ function ReturnInfoPopover({ orderReturn }: ReturnInfoPopoverProps) {
{t(`orders.returns.returnRequested`)}
</span>
{" · "}
{formatDate(orderReturn.requested_at)}
{getFullDate({ date: orderReturn.requested_at, includeTime: true })}
</Text>
<Text size="xsmall">
@@ -73,7 +75,10 @@ function ReturnInfoPopover({ orderReturn }: ReturnInfoPopoverProps) {
</span>
{" · "}
{orderReturn.received_at
? formatDate(orderReturn.received_at)
? getFullDate({
date: orderReturn.received_at,
includeTime: true,
})
: "-"}
</Text>
</div>
@@ -32,20 +32,12 @@ export const useDeleteTaxRegionAction = ({
await mutateAsync(undefined, {
onSuccess: () => {
toast.success(t("general.success"), {
description: t("taxRegions.delete.successToast"),
dismissable: true,
dismissLabel: t("actions.close"),
})
toast.success(t("taxRegions.delete.successToast"))
navigate(to, { replace: true })
},
onError: (e) => {
toast.error(t("general.error"), {
description: e.message,
dismissable: true,
dismissLabel: t("actions.close"),
})
toast.error(e.message)
},
})
}
@@ -4,14 +4,14 @@ import { useForm } from "react-hook-form"
import { useTranslation } from "react-i18next"
import * as zod from "zod"
import { UserDTO } from "@medusajs/types"
import { HttpTypes } from "@medusajs/types"
import { Form } from "../../../../../components/common/form"
import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
import { useUpdateUser } from "../../../../../hooks/api/users"
type EditUserFormProps = {
user: UserDTO
user: HttpTypes.AdminUser
}
const EditUserFormSchema = zod.object({
@@ -1,6 +1,6 @@
import { zodResolver } from "@hookform/resolvers/zod"
import { ArrowPath, Link, Trash } from "@medusajs/icons"
import { InviteDTO } from "@medusajs/types"
import { HttpTypes } from "@medusajs/types"
import {
Alert,
Button,
@@ -70,7 +70,7 @@ export const InviteUserForm = () => {
const columns = useColumns()
const { table } = useDataTable({
data: (invites ?? []) as InviteDTO[],
data: invites ?? [],
columns,
count,
enablePagination: true,
@@ -185,7 +185,7 @@ export const InviteUserForm = () => {
)
}
const InviteActions = ({ invite }: { invite: InviteDTO }) => {
const InviteActions = ({ invite }: { invite: HttpTypes.AdminInvite }) => {
const { mutateAsync: revokeAsync } = useDeleteInvite(invite.id)
const { mutateAsync: resendAsync } = useResendInvite(invite.id)
@@ -253,7 +253,7 @@ const InviteActions = ({ invite }: { invite: InviteDTO }) => {
)
}
const columnHelper = createColumnHelper<InviteDTO>()
const columnHelper = createColumnHelper<HttpTypes.AdminInvite>()
const useColumns = () => {
const { t } = useTranslation()
@@ -7,8 +7,8 @@ import { useUpdateUser, useUser } from "../../../hooks/api"
export const UserMetadata = () => {
const { id } = useParams()
const { user, isPending, isError, error } = useUser(id)
const { mutateAsync, isPending: isMutating } = useUpdateUser(id)
const { user, isPending, isError, error } = useUser(id!)
const { mutateAsync, isPending: isMutating } = useUpdateUser(id!)
if (isError) {
throw error
@@ -18,7 +18,7 @@ export interface AdminInvite {
/**
* The date the invite expires.
*/
expires_at?: Date
expires_at: string
/**
* Key-value pairs of custom data.
*/
@@ -26,9 +26,9 @@ export interface AdminInvite {
/**
* The date that the invite was created.
*/
created_at?: Date
created_at: string
/**
* The date that the invite was updated.
*/
updated_at?: Date
updated_at: string
}