chore(dashboard): render main layout as home page for v2 (#6823)
* chore(dashboard): render main layout as home page for v2 * chore: throw an error on store not existing
This commit is contained in:
1 parent
a843b121cd
commit
448a30d030
7 files changed
+246
-6
No files matched your search
@@ -0,0 +1 @@
|
|||||||
|
export * from "./main-layout"
|
||||||
@@ -0,0 +1,205 @@
|
|||||||
|
import {
|
||||||
|
Buildings,
|
||||||
|
ChevronDownMini,
|
||||||
|
CurrencyDollar,
|
||||||
|
MinusMini,
|
||||||
|
ReceiptPercent,
|
||||||
|
ShoppingCart,
|
||||||
|
SquaresPlus,
|
||||||
|
Tag,
|
||||||
|
Users,
|
||||||
|
} from "@medusajs/icons"
|
||||||
|
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"
|
||||||
|
|
||||||
|
export const MainLayout = () => {
|
||||||
|
return (
|
||||||
|
<Shell>
|
||||||
|
<MainSidebar />
|
||||||
|
</Shell>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const MainSidebar = () => {
|
||||||
|
return (
|
||||||
|
<aside className="flex flex-1 flex-col justify-between overflow-y-auto">
|
||||||
|
<div className="flex flex-1 flex-col">
|
||||||
|
<div className="bg-ui-bg-subtle sticky top-0">
|
||||||
|
<Header />
|
||||||
|
<div className="px-3">
|
||||||
|
<div className="border-ui-border-strong h-px w-full border-b border-dashed" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<CoreRouteSection />
|
||||||
|
<ExtensionRouteSection />
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const Header = () => {
|
||||||
|
const { store, isError, error } = useV2Store({})
|
||||||
|
|
||||||
|
const name = store?.name
|
||||||
|
const fallback = store?.name?.slice(0, 1).toUpperCase()
|
||||||
|
|
||||||
|
if (isError) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full px-3 py-2">
|
||||||
|
<div className="flex items-center p-1 md:pr-2">
|
||||||
|
<div className="flex items-center gap-x-3">
|
||||||
|
{fallback ? (
|
||||||
|
<Avatar variant="squared" fallback={fallback} />
|
||||||
|
) : (
|
||||||
|
<Skeleton className="h-8 w-8 rounded-md" />
|
||||||
|
)}
|
||||||
|
{name ? (
|
||||||
|
<Text size="small" weight="plus" leading="compact">
|
||||||
|
{store.name}
|
||||||
|
</Text>
|
||||||
|
) : (
|
||||||
|
<Skeleton className="h-[9px] w-[120px]" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const useCoreRoutes = (): Omit<NavItemProps, "pathname">[] => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
icon: <ShoppingCart />,
|
||||||
|
label: t("orders.domain"),
|
||||||
|
to: "/orders",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: t("draftOrders.domain"),
|
||||||
|
to: "/draft-orders",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <Tag />,
|
||||||
|
label: t("products.domain"),
|
||||||
|
to: "/products",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: t("collections.domain"),
|
||||||
|
to: "/collections",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("categories.domain"),
|
||||||
|
to: "/categories",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("giftCards.domain"),
|
||||||
|
to: "/gift-cards",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <Buildings />,
|
||||||
|
label: t("inventory.domain"),
|
||||||
|
to: "/inventory",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: t("reservations.domain"),
|
||||||
|
to: "/reservations",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <Users />,
|
||||||
|
label: t("customers.domain"),
|
||||||
|
to: "/customers",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: t("customerGroups.domain"),
|
||||||
|
to: "/customer-groups",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <ReceiptPercent />,
|
||||||
|
label: t("discounts.domain"),
|
||||||
|
to: "/discounts",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <CurrencyDollar />,
|
||||||
|
label: t("pricing.domain"),
|
||||||
|
to: "/pricing",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const CoreRouteSection = () => {
|
||||||
|
const coreRoutes = useCoreRoutes()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="flex flex-col gap-y-1 py-2">
|
||||||
|
{coreRoutes.map((route) => {
|
||||||
|
return <NavItem key={route.to} {...route} />
|
||||||
|
})}
|
||||||
|
</nav>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const ExtensionRouteSection = () => {
|
||||||
|
if (!extensions.links || extensions.links.length === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="px-3">
|
||||||
|
<div className="border-ui-border-strong h-px w-full border-b border-dashed" />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-y-1 py-2">
|
||||||
|
<Collapsible.Root defaultOpen>
|
||||||
|
<div className="px-4">
|
||||||
|
<Collapsible.Trigger asChild className="group/trigger">
|
||||||
|
<button className="text-ui-fg-subtle flex w-full items-center justify-between px-2">
|
||||||
|
<Text size="xsmall" weight="plus" leading="compact">
|
||||||
|
Extensions
|
||||||
|
</Text>
|
||||||
|
<div className="text-ui-fg-muted">
|
||||||
|
<ChevronDownMini className="group-data-[state=open]/trigger:hidden" />
|
||||||
|
<MinusMini className="group-data-[state=closed]/trigger:hidden" />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</Collapsible.Trigger>
|
||||||
|
</div>
|
||||||
|
<Collapsible.Content>
|
||||||
|
<div className="flex flex-col gap-y-1 py-1 pb-4">
|
||||||
|
{extensions.links.map((link) => {
|
||||||
|
return (
|
||||||
|
<NavItem
|
||||||
|
key={link.path}
|
||||||
|
to={link.path}
|
||||||
|
label={link.label}
|
||||||
|
icon={link.icon ? <link.icon /> : <SquaresPlus />}
|
||||||
|
type="extension"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Collapsible.Content>
|
||||||
|
</Collapsible.Root>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -8,7 +8,11 @@ export const useV2Store = ({ initialData }: { initialData?: any }) => {
|
|||||||
{ initialData }
|
{ initialData }
|
||||||
)
|
)
|
||||||
|
|
||||||
const store = data.stores[0]
|
const store = data?.stores[0]
|
||||||
|
|
||||||
|
if (!isLoading && !isError && typeof store === "undefined") {
|
||||||
|
throw new Error("Store does not exist")
|
||||||
|
}
|
||||||
|
|
||||||
return { store, isLoading, isError, error }
|
return { store, isLoading, isError, error }
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
import { Navigate, RouteObject, useLocation } from "react-router-dom"
|
import { Navigate, RouteObject, useLocation } from "react-router-dom"
|
||||||
|
import { MainLayout } from "../../components/layout-v2/main-layout"
|
||||||
import { SettingsLayout } from "../../components/layout/settings-layout"
|
import { SettingsLayout } from "../../components/layout/settings-layout"
|
||||||
|
|
||||||
import { Outlet } from "react-router-dom"
|
import { Outlet } from "react-router-dom"
|
||||||
|
|
||||||
import { SidebarProvider } from "../sidebar-provider"
|
|
||||||
import { SearchProvider } from "../search-provider"
|
|
||||||
import { ErrorBoundary } from "../../components/error/error-boundary"
|
|
||||||
import { Spinner } from "@medusajs/icons"
|
import { Spinner } from "@medusajs/icons"
|
||||||
|
import { ErrorBoundary } from "../../components/error/error-boundary"
|
||||||
import { useV2Session } from "../../lib/api-v2"
|
import { useV2Session } from "../../lib/api-v2"
|
||||||
|
import { SearchProvider } from "../search-provider"
|
||||||
|
import { SidebarProvider } from "../sidebar-provider"
|
||||||
|
|
||||||
export const ProtectedRoute = () => {
|
export const ProtectedRoute = () => {
|
||||||
const { user, isLoading } = useV2Session()
|
const { user, isLoading } = useV2Session()
|
||||||
@@ -52,6 +53,30 @@ export const v2Routes: RouteObject[] = [
|
|||||||
path: "*",
|
path: "*",
|
||||||
lazy: () => import("../../routes/no-match"),
|
lazy: () => import("../../routes/no-match"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
element: <ProtectedRoute />,
|
||||||
|
errorElement: <ErrorBoundary />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
element: <MainLayout />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/orders",
|
||||||
|
handle: {
|
||||||
|
crumb: () => "Orders",
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
lazy: () => import("../../v2-routes/orders/order-list"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
element: <ProtectedRoute />,
|
element: <ProtectedRoute />,
|
||||||
errorElement: <ErrorBoundary />,
|
errorElement: <ErrorBoundary />,
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ import { useNavigate } from "react-router-dom"
|
|||||||
export const Home = () => {
|
export const Home = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
// Currently, the home page simply redirects to the settings page
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
navigate("/settings", { replace: true })
|
navigate("/orders", { replace: true })
|
||||||
}, [navigate])
|
}, [navigate])
|
||||||
|
|
||||||
return <div />
|
return <div />
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export { OrderList as Component } from "./order-list"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// TODO: This is just a placeholder to render the actual "home" page
|
||||||
|
// after logging in. Replace this with the actual order components when ready
|
||||||
|
export const OrderList = () => {
|
||||||
|
return <div className="flex w-full flex-col gap-y-2"></div>
|
||||||
|
}
|
||||||
Reference in new issue
Block a user