Skip to content

Commit

Permalink
feat(dashboard): Migrate to new hooks and API client (#6963)
Browse files Browse the repository at this point in the history
  • Loading branch information
kasperkristensen authored Apr 5, 2024
1 parent 5ba74ec commit 8a5c692
Show file tree
Hide file tree
Showing 195 changed files with 3,932 additions and 6,041 deletions.
3 changes: 2 additions & 1 deletion packages/admin-next/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@medusajs/ui": "workspace:^",
"@radix-ui/react-collapsible": "1.0.3",
"@radix-ui/react-hover-card": "^1.0.7",
"@tanstack/react-query": "4.22.0",
"@tanstack/react-query": "^5.28.14",
"@tanstack/react-table": "8.10.7",
"@tanstack/react-virtual": "^3.0.4",
"@uiw/react-json-view": "^2.0.0-alpha.17",
Expand All @@ -35,6 +35,7 @@
"i18next-http-backend": "2.4.2",
"match-sorter": "^6.3.4",
"medusa-react": "workspace:^",
"qs": "^6.12.0",
"react": "18.2.0",
"react-country-flag": "^3.1.0",
"react-dom": "18.2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@
"inviteUserHint": "Invite a new user to your store.",
"sendInvite": "Send invite",
"pendingInvites": "Pending Invites",
"revokeInviteWarning": "You are about to revoke the invite for {{email}}. This action cannot be undone.",
"deleteInviteWarning": "You are about to delete the invite for {{email}}. This action cannot be undone.",
"resendInvite": "Resend invite",
"copyInviteLink": "Copy invite link",
"expiredOnDate": "Expired on {{date}}",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { SalesChannel } from "@medusajs/medusa"
import {
Product,
ProductCollection,
ProductVariant,
SalesChannel,
} from "@medusajs/medusa"
ProductCollectionDTO,
ProductDTO,
ProductVariantDTO,
} from "@medusajs/types"
import { StatusBadge, Text } from "@medusajs/ui"
import { useTranslation } from "react-i18next"
import { Thumbnail } from "../thumbnail"

export const ProductVariantCell = ({
variants,
}: {
variants: ProductVariant[] | null
variants: ProductVariantDTO[] | null
}) => {
const { t } = useTranslation()

Expand All @@ -35,7 +35,7 @@ export const ProductVariantCell = ({
export const ProductStatusCell = ({
status,
}: {
status: Product["status"]
status: ProductDTO["status"]
}) => {
const { t } = useTranslation()

Expand Down Expand Up @@ -95,7 +95,7 @@ export const ProductAvailabilityCell = ({
)
}

export const ProductTitleCell = ({ product }: { product: Product }) => {
export const ProductTitleCell = ({ product }: { product: ProductDTO }) => {
const thumbnail = product.thumbnail
const title = product.title

Expand All @@ -112,7 +112,7 @@ export const ProductTitleCell = ({ product }: { product: Product }) => {
export const ProductCollectionCell = ({
collection,
}: {
collection: ProductCollection | null
collection: ProductCollectionDTO | null
}) => {
if (!collection) {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import {
import { Avatar, Text } from "@medusajs/ui"
import * as Collapsible from "@radix-ui/react-collapsible"
import { useTranslation } from "react-i18next"
import { useV2Store } from "../../../lib/api-v2"

import { Skeleton } from "../../common/skeleton"
import { NavItem, NavItemProps } from "../../layout/nav-item"
import { Shell } from "../../layout/shell"

import extensions from "medusa-admin:routes/links"
import { useStore } from "../../../hooks/api/store"

export const MainLayout = () => {
return (
Expand Down Expand Up @@ -46,7 +46,7 @@ const MainSidebar = () => {
}

const Header = () => {
const { store, isError, error } = useV2Store({})
const { store, isError, error } = useStore()

const name = store?.name
const fallback = store?.name?.slice(0, 1).toUpperCase()
Expand Down
51 changes: 16 additions & 35 deletions packages/admin-next/dashboard/src/components/layout/shell/shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,21 @@ import {
User as UserIcon,
} from "@medusajs/icons"
import { Avatar, DropdownMenu, IconButton, Kbd, Text, clx } from "@medusajs/ui"
import { PropsWithChildren } from "react"
import {
Link,
Outlet,
UIMatch,
useLocation,
useMatches,
useNavigate,
} from "react-router-dom"
import { useAdminDeleteSession, useAdminGetSession } from "medusa-react"

import { PropsWithChildren } from "react"
import { Skeleton } from "../../common/skeleton"
import { queryClient } from "../../../lib/medusa"

import { useMe } from "../../../hooks/api/users"
import { useSearch } from "../../../providers/search-provider"
import { useSidebar } from "../../../providers/sidebar-provider"
import { useTheme } from "../../../providers/theme-provider"
import { useV2Session } from "../../../lib/api-v2"

const V2_ENABLED = import.meta.env.VITE_MEDUSA_V2 || "false"

export const Shell = ({ children }: PropsWithChildren) => {
return (
Expand Down Expand Up @@ -119,22 +115,7 @@ const Breadcrumbs = () => {
}

const UserBadge = () => {
const isV2Enabled = V2_ENABLED === "true"

console.warn(isV2Enabled)
// Medusa V2 disabled
const v1 = useAdminGetSession({
enabled: !isV2Enabled,
})

// Medusa V2 enabled
const v2 = useV2Session({
enabled: isV2Enabled,
})

// Comment: Only place where we switch between the two modes inline.
// This is to avoid having to rebuild the shell for the app.
const { user, isLoading, isError, error } = !isV2Enabled ? v1 : v2
const { user, isLoading, isError, error } = useMe()

const name = [user?.first_name, user?.last_name].filter(Boolean).join(" ")
const displayName = name || user?.email
Expand Down Expand Up @@ -220,20 +201,20 @@ const ThemeToggle = () => {
}

const Logout = () => {
const navigate = useNavigate()
const { mutateAsync: logoutMutation } = useAdminDeleteSession()
// const navigate = useNavigate()
// const { mutateAsync: logoutMutation } = useAdminDeleteSession()

const handleLayout = async () => {
await logoutMutation(undefined, {
onSuccess: () => {
/**
* When the user logs out, we want to clear the query cache
*/
queryClient.clear()

navigate("/login")
},
})
// await logoutMutation(undefined, {
// onSuccess: () => {
// /**
// * When the user logs out, we want to clear the query cache
// */
// queryClient.clear()
// navigate("/login")
// },
// })
// noop
}

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { ProductCollection } from "@medusajs/medusa"
import { useTranslation } from "react-i18next"

import { ProductCollectionDTO } from "@medusajs/types"
import { PlaceholderCell } from "../../common/placeholder-cell"

type CollectionCellProps = {
collection?: ProductCollection | null
collection?: ProductCollectionDTO | null
}

export const CollectionCell = ({ collection }: CollectionCellProps) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import type { Product } from "@medusajs/medusa"
import type { PricedProduct } from "@medusajs/medusa/dist/types/pricing"
import { useTranslation } from "react-i18next"

import { ProductDTO } from "@medusajs/types"
import { Thumbnail } from "../../../../common/thumbnail"

type ProductCellProps = {
product: Product | PricedProduct
product: ProductDTO
}

export const ProductCell = ({ product }: ProductCellProps) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { SalesChannel } from "@medusajs/medusa"
import { Tooltip } from "@medusajs/ui"
import { useTranslation } from "react-i18next"

import { SalesChannelDTO } from "@medusajs/types"
import { PlaceholderCell } from "../../common/placeholder-cell"

type SalesChannelsCellProps = {
salesChannels?: SalesChannel[] | null
salesChannels?: SalesChannelDTO[] | null
}

export const SalesChannelsCell = ({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ProductVariant } from "@medusajs/medusa"
import { useTranslation } from "react-i18next"

import { ProductVariantDTO } from "@medusajs/types"
import { PlaceholderCell } from "../../common/placeholder-cell"

type VariantCellProps = {
variants?: ProductVariant[] | null
variants?: ProductVariantDTO[] | null
}

export const VariantCell = ({ variants }: VariantCellProps) => {
Expand Down
113 changes: 113 additions & 0 deletions packages/admin-next/dashboard/src/hooks/api/api-keys.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import {
MutationOptions,
QueryKey,
UseMutationOptions,
UseQueryOptions,
useMutation,
useQuery,
} from "@tanstack/react-query"
import { client } from "../../lib/client"
import { queryClient } from "../../lib/medusa"
import { queryKeysFactory } from "../../lib/query-key-factory"
import { CreateApiKeyReq, UpdateApiKeyReq } from "../../types/api-payloads"
import {
ApiKeyDeleteRes,
ApiKeyListRes,
ApiKeyRes,
} from "../../types/api-responses"

const API_KEYS_QUERY_KEY = "api_keys" as const
export const apiKeysQueryKeys = queryKeysFactory(API_KEYS_QUERY_KEY)

export const useApiKey = (
id: string,
query?: Record<string, any>,
options?: Omit<
UseQueryOptions<ApiKeyRes, Error, ApiKeyRes, QueryKey>,
"queryKey" | "queryFn"
>
) => {
const { data, ...rest } = useQuery({
queryFn: () => client.apiKeys.retrieve(id, query),
queryKey: apiKeysQueryKeys.detail(id),
...options,
})

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

export const useApiKeys = (
query?: Record<string, any>,
options?: Omit<
UseQueryOptions<ApiKeyListRes, Error, ApiKeyListRes, QueryKey>,
"queryKey" | "queryFn"
>
) => {
const { data, ...rest } = useQuery({
queryFn: () => client.apiKeys.list(query),
queryKey: apiKeysQueryKeys.list(query),
...options,
})

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

export const useCreateApiKey = (
options?: UseMutationOptions<ApiKeyRes, Error, CreateApiKeyReq>
) => {
return useMutation({
mutationFn: (payload) => client.apiKeys.create(payload),
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries({ queryKey: apiKeysQueryKeys.lists() })

options?.onSuccess?.(data, variables, context)
},
...options,
})
}

export const useUpdateApiKey = (
id: string,
options?: UseMutationOptions<ApiKeyRes, Error, UpdateApiKeyReq>
) => {
return useMutation({
mutationFn: (payload) => client.apiKeys.update(id, payload),
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries({ queryKey: apiKeysQueryKeys.lists() })
queryClient.invalidateQueries({ queryKey: apiKeysQueryKeys.detail(id) })

options?.onSuccess?.(data, variables, context)
},
...options,
})
}

export const useRevokeApiKey = (
id: string,
options?: UseMutationOptions<ApiKeyRes, Error, void>
) => {
return useMutation({
mutationFn: () => client.apiKeys.revoke(id),
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries({ queryKey: apiKeysQueryKeys.lists() })
queryClient.invalidateQueries({ queryKey: apiKeysQueryKeys.detail(id) })

options?.onSuccess?.(data, variables, context)
},
})
}

export const useDeleteApiKey = (
id: string,
options?: MutationOptions<ApiKeyDeleteRes, Error, void>
) => {
return useMutation({
mutationFn: () => client.apiKeys.delete(id),
onSuccess: (data, variables, context) => {
queryClient.invalidateQueries({ queryKey: apiKeysQueryKeys.lists() })
queryClient.invalidateQueries({ queryKey: apiKeysQueryKeys.detail(id) })

options?.onSuccess?.(data, variables, context)
},
})
}
22 changes: 22 additions & 0 deletions packages/admin-next/dashboard/src/hooks/api/auth.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { UseMutationOptions, useMutation } from "@tanstack/react-query"

import { client } from "../../lib/client"
import { EmailPassReq } from "../../types/api-payloads"
import { EmailPassRes } from "../../types/api-responses"

export const useEmailPassLogin = (
options?: UseMutationOptions<EmailPassRes, Error, EmailPassReq>
) => {
return useMutation({
mutationFn: (payload) => client.auth.authenticate.emailPass(payload),
onSuccess: async (data: { token: string }, variables, context) => {
const { token } = data

// Create a new session with the token
await client.auth.login(token)

options?.onSuccess?.(data, variables, context)
},
...options,
})
}
Loading

0 comments on commit 8a5c692

Please sign in to comment.