feat(dashboard): Setup parallel V2 routes (#6691)

**What**
- Moves all current route definitions to `v1.tsx`
- Creates a new `v2.tsx` file for future V2 routes.
- Updates RouteProvider to serve V1 or V2 routes based on if `MEDUSA_V2` is set.

**How to use it**
When working on V2 domains you should set `MEDUSA_V2=true` in `/packages/admin-next/dashboard/.env`. We can't use the Feature Flag in the Medusa project since there are breaking changes in the `/admin/store` endpoint between the two versions, so it needs to be managed manually.

**For people implementing V2 domains**
To add a new route you should:

- Add the route component in `/v2-routes`
- Define which path will render it in `v2.tsx`.

I would prefer that we don't try to implement a lot of conditional code that will make the codebase unnecessarily complex. So if I was to implement the V2 login page, I would copy/past the v1 login route into `v2-routes`, make the required changes, eg. replace `useAdminLogin` with `useAdminCustomPost(...)`, instead of trying to force the current V1 Login page to work with both APIs.

There will hopefully be a lot of components/sections from each domain that is re-usable between versions. As an example if you are working on the Product details page for V2 you might want to reuse the `product-general-section.tsx` file, as it works without having to make any modifications. In that case I propose that we create a `modules/product` folder and move the component in there which we can them import into both the v1 and v2 version of the route.
This commit is contained in:
Kasper Fabricius Kristensen
2024-03-14 19:05:44 +01:00
committed by GitHub
parent cc1b66842c
commit c384ede3b1
6 changed files with 822 additions and 789 deletions

View File

@@ -1,798 +1,14 @@
import type {
AdminCollectionsRes,
AdminCustomerGroupsRes,
AdminCustomersRes,
AdminGiftCardsRes,
AdminOrdersRes,
AdminProductsRes,
AdminPublishableApiKeysRes,
AdminRegionsRes,
AdminSalesChannelsRes,
AdminUserRes,
} from "@medusajs/medusa"
import { import {
Outlet,
RouterProvider as Provider, RouterProvider as Provider,
RouteObject,
createBrowserRouter, createBrowserRouter,
} from "react-router-dom" } from "react-router-dom"
import { ProtectedRoute } from "../../components/authentication/require-auth" import { v1Routes } from "./v1"
import { ErrorBoundary } from "../../components/error/error-boundary" import { v2Routes } from "./v2"
import { MainLayout } from "../../components/layout/main-layout"
import { SettingsLayout } from "../../components/layout/settings-layout"
import routes from "medusa-admin:routes/pages" const V2_ENABLED = import.meta.env.MEDUSA_V2 || false
import settings from "medusa-admin:settings/pages"
const routeExtensions: RouteObject[] = routes.pages.map((ext) => { const router = createBrowserRouter(V2_ENABLED ? v2Routes : v1Routes)
return {
path: ext.path,
async lazy() {
const { default: Component } = await import(/* @vite-ignore */ ext.file)
return { Component }
},
}
})
const settingsExtensions: RouteObject[] = settings.pages.map((ext) => {
return {
path: `/settings${ext.path}`,
async lazy() {
const { default: Component } = await import(/* @vite-ignore */ ext.file)
return { Component }
},
}
})
const router = createBrowserRouter([
{
path: "/login",
lazy: () => import("../../routes/login"),
},
{
path: "/reset-password",
element: <Outlet />,
children: [
{
index: true,
lazy: () =>
import("../../routes/reset-password/reset-password-request"),
},
{
path: ":token",
lazy: () => import("../../routes/reset-password/reset-password-token"),
},
],
},
{
path: "/invite",
lazy: () => import("../../routes/invite"),
},
{
element: <ProtectedRoute />,
errorElement: <ErrorBoundary />,
children: [
{
path: "/",
element: <MainLayout />,
children: [
{
index: true,
lazy: () => import("../../routes/home"),
},
{
path: "/orders",
handle: {
crumb: () => "Orders",
},
children: [
{
path: "",
lazy: () => import("../../routes/orders/order-list"),
},
{
path: ":id",
lazy: () => import("../../routes/orders/order-detail"),
handle: {
crumb: (data: AdminOrdersRes) =>
`Order #${data.order.display_id}`,
},
},
],
},
{
path: "/draft-orders",
handle: {
crumb: () => "Draft Orders",
},
children: [
{
index: true,
lazy: () =>
import("../../routes/draft-orders/draft-order-list"),
},
{
path: ":id",
lazy: () =>
import("../../routes/draft-orders/draft-order-detail"),
},
],
},
{
path: "/products",
handle: {
crumb: () => "Products",
},
children: [
{
path: "",
lazy: () => import("../../routes/products/product-list"),
children: [
{
path: "create",
lazy: () => import("../../routes/products/product-create"),
},
],
},
{
path: ":id",
lazy: () => import("../../routes/products/product-detail"),
handle: {
crumb: (data: AdminProductsRes) => data.product.title,
},
children: [
{
path: "edit",
lazy: () => import("../../routes/products/product-edit"),
},
{
path: "sales-channels",
lazy: () =>
import("../../routes/products/product-sales-channels"),
},
{
path: "attributes",
lazy: () =>
import("../../routes/products/product-attributes"),
},
{
path: "options",
lazy: () => import("../../routes/products/product-options"),
},
{
path: "gallery",
lazy: () => import("../../routes/products/product-gallery"),
},
],
},
],
},
{
path: "/categories",
handle: {
crumb: () => "Categories",
},
children: [
{
index: true,
lazy: () => import("../../routes/categories/list"),
},
{
path: ":id",
lazy: () => import("../../routes/categories/details"),
},
],
},
{
path: "/collections",
handle: {
crumb: () => "Collections",
},
children: [
{
path: "",
lazy: () => import("../../routes/collections/collection-list"),
children: [
{
path: "create",
lazy: () =>
import("../../routes/collections/collection-create"),
},
],
},
{
path: ":id",
handle: {
crumb: (data: AdminCollectionsRes) => data.collection.title,
},
lazy: () =>
import("../../routes/collections/collection-detail"),
children: [
{
path: "edit",
lazy: () =>
import("../../routes/collections/collection-edit"),
},
{
path: "add-products",
lazy: () =>
import(
"../../routes/collections/collection-add-products"
),
},
],
},
],
},
{
path: "/inventory",
handle: {
crumb: () => "Inventory",
},
lazy: () => import("../../routes/inventory/inventory-list"),
},
{
path: "/reservations",
handle: {
crumb: () => "Reservations",
},
children: [
{
path: "",
lazy: () =>
import("../../routes/reservations/reservation-list"),
},
{
path: ":id",
lazy: () =>
import("../../routes/reservations/reservation-detail"),
// children: [
// {
// path: "edit",
// lazy: () =>
// import("../../routes/reservations/reservation-edit"),
// },
// ],
},
],
},
{
path: "/customers",
handle: {
crumb: () => "Customers",
},
children: [
{
path: "",
lazy: () => import("../../routes/customers/customer-list"),
children: [
{
path: "create",
lazy: () =>
import("../../routes/customers/customer-create"),
},
],
},
{
path: ":id",
lazy: () => import("../../routes/customers/customer-detail"),
handle: {
crumb: (data: AdminCustomersRes) => data.customer.email,
},
children: [
{
path: "edit",
lazy: () => import("../../routes/customers/customer-edit"),
},
],
},
],
},
{
path: "/customer-groups",
handle: {
crumb: () => "Customer Groups",
},
children: [
{
path: "",
lazy: () =>
import("../../routes/customer-groups/customer-group-list"),
children: [
{
path: "create",
lazy: () =>
import(
"../../routes/customer-groups/customer-group-create"
),
},
],
},
{
path: ":id",
lazy: () =>
import("../../routes/customer-groups/customer-group-detail"),
handle: {
crumb: (data: AdminCustomerGroupsRes) =>
data.customer_group.name,
},
children: [
{
path: "add-customers",
lazy: () =>
import(
"../../routes/customer-groups/customer-group-add-customers"
),
},
{
path: "edit",
lazy: () =>
import(
"../../routes/customer-groups/customer-group-edit"
),
},
],
},
],
},
{
path: "/gift-cards",
handle: {
crumb: () => "Gift Cards",
},
children: [
{
path: "",
lazy: () => import("../../routes/gift-cards/gift-card-list"),
children: [
{
path: "create",
lazy: () =>
import("../../routes/gift-cards/gift-card-create"),
},
],
},
{
path: ":id",
lazy: () => import("../../routes/gift-cards/gift-card-detail"),
handle: {
crumb: (data: AdminGiftCardsRes) => data.gift_card.code,
},
children: [
{
path: "edit",
lazy: () =>
import("../../routes/gift-cards/gift-card-edit"),
},
],
},
],
},
{
path: "/discounts",
handle: {
crumb: () => "Discounts",
},
children: [
{
index: true,
lazy: () => import("../../routes/discounts/list"),
},
{
path: "create",
lazy: () => import("../../routes/discounts/create"),
},
{
path: ":id",
lazy: () => import("../../routes/discounts/details"),
children: [
{
path: "edit",
lazy: () => import("../../routes/discounts/edit-details"),
},
{
path: "configuration",
lazy: () =>
import("../../routes/discounts/edit-configuration"),
},
],
},
],
},
{
path: "/pricing",
handle: {
crumb: () => "Pricing",
},
children: [
{
path: "",
lazy: () => import("../../routes/pricing/pricing-list"),
children: [
// {
// path: "create",
// lazy: () => import("../../routes/pricing/pricing-create"),
// },
],
},
{
path: ":id",
lazy: () => import("../../routes/pricing/pricing-detail"),
children: [
{
path: "edit",
lazy: () => import("../../routes/pricing/pricing-edit"),
},
{
path: "products/add",
lazy: () =>
import("../../routes/pricing/pricing-products-add"),
},
{
path: "products/edit",
lazy: () =>
import("../../routes/pricing/pricing-products-edit"),
},
],
},
],
},
],
},
{
path: "/settings",
element: <SettingsLayout />,
handle: {
crumb: () => "Settings",
},
children: [
{
index: true,
lazy: () => import("../../routes/settings"),
},
{
path: "profile",
lazy: () => import("../../routes/profile/profile-detail"),
handle: {
crumb: () => "Profile",
},
children: [
{
path: "edit",
lazy: () => import("../../routes/profile/profile-edit"),
},
],
},
{
path: "store",
lazy: () => import("../../routes/store/store-detail"),
handle: {
crumb: () => "Store",
},
children: [
{
path: "edit",
lazy: () => import("../../routes/store/store-edit"),
},
{
path: "add-currencies",
lazy: () => import("../../routes/store/store-add-currencies"),
},
],
},
{
path: "locations",
element: <Outlet />,
handle: {
crumb: () => "Locations",
},
children: [
{
path: "",
lazy: () => import("../../routes/locations/location-list"),
children: [
{
path: "create",
lazy: () =>
import("../../routes/locations/location-create"),
},
],
},
{
path: ":id",
lazy: () => import("../../routes/locations/location-detail"),
children: [
{
path: "edit",
lazy: () => import("../../routes/locations/location-edit"),
},
{
path: "add-sales-channels",
lazy: () =>
import(
"../../routes/locations/location-add-sales-channels"
),
},
],
},
],
},
{
path: "return-reasons",
element: <Outlet />,
handle: {
crumb: () => "Return Reasons",
},
children: [
{
path: "",
lazy: () =>
import("../../routes/return-reasons/return-reason-list"),
children: [
{
path: "create",
lazy: () =>
import(
"../../routes/return-reasons/return-reason-create"
),
},
{
path: ":id/edit",
lazy: () =>
import("../../routes/return-reasons/return-reason-edit"),
},
],
},
],
},
{
path: "regions",
element: <Outlet />,
handle: {
crumb: () => "Regions",
},
children: [
{
path: "",
lazy: () => import("../../routes/regions/region-list"),
children: [
{
path: "create",
lazy: () => import("../../routes/regions/region-create"),
},
],
},
{
path: ":id",
lazy: () => import("../../routes/regions/region-detail"),
handle: {
crumb: (data: AdminRegionsRes) => data.region.name,
},
children: [
{
path: "edit",
lazy: () => import("../../routes/regions/region-edit"),
},
{
path: "countries/add",
lazy: () =>
import("../../routes/regions/region-add-countries"),
},
{
path: "shipping-options/:so_id/edit",
lazy: () =>
import(
"../../routes/regions/region-edit-shipping-option"
),
},
{
path: "shipping-options/create",
lazy: () =>
import(
"../../routes/regions/region-create-shipping-option"
),
},
],
},
],
},
{
path: "users",
element: <Outlet />,
handle: {
crumb: () => "Users",
},
children: [
{
path: "",
lazy: () => import("../../routes/users/user-list"),
children: [
{
path: "invite",
lazy: () => import("../../routes/users/user-invite"),
},
],
},
{
path: ":id",
lazy: () => import("../../routes/users/user-detail"),
handle: {
crumb: (data: AdminUserRes) => data.user.email,
},
children: [
{
path: "edit",
lazy: () => import("../../routes/users/user-edit"),
},
],
},
],
},
{
path: "taxes",
handle: {
crumb: () => "Taxes",
},
children: [
{
path: "",
lazy: () => import("../../routes/taxes/tax-list"),
},
{
path: ":id",
lazy: () => import("../../routes/taxes/tax-detail"),
handle: {
crumb: (data: AdminRegionsRes) => data.region.name,
},
children: [
{
path: "edit",
lazy: () => import("../../routes/taxes/tax-edit"),
},
{
path: "tax-rates/create",
lazy: () => import("../../routes/taxes/tax-rate-create"),
},
{
path: "tax-rates/:rate_id/edit",
lazy: () => import("../../routes/taxes/tax-rate-edit"),
},
{
path: "tax-rates/:rate_id/edit-overrides",
lazy: () =>
import("../../routes/taxes/tax-rate-edit-overrides"),
},
],
},
],
},
{
path: "sales-channels",
element: <Outlet />,
handle: {
crumb: () => "Sales Channels",
},
children: [
{
path: "",
lazy: () =>
import("../../routes/sales-channels/sales-channel-list"),
children: [
{
path: "create",
lazy: () =>
import(
"../../routes/sales-channels/sales-channel-create"
),
},
],
},
{
path: ":id",
lazy: () =>
import("../../routes/sales-channels/sales-channel-detail"),
handle: {
crumb: (data: AdminSalesChannelsRes) =>
data.sales_channel.name,
},
children: [
{
path: "edit",
lazy: () =>
import("../../routes/sales-channels/sales-channel-edit"),
},
{
path: "add-products",
lazy: () =>
import(
"../../routes/sales-channels/sales-channel-add-products"
),
},
],
},
],
},
{
path: "api-key-management",
element: <Outlet />,
handle: {
crumb: () => "API Key Management",
},
children: [
{
path: "",
lazy: () =>
import(
"../../routes/api-key-management/api-key-management-list"
),
children: [
{
path: "create",
lazy: () =>
import(
"../../routes/api-key-management/api-key-management-create"
),
},
],
},
{
path: ":id",
lazy: () =>
import(
"../../routes/api-key-management/api-key-management-detail"
),
handle: {
crumb: (data: AdminPublishableApiKeysRes) =>
data.publishable_api_key.title,
},
children: [
{
path: "edit",
lazy: () =>
import(
"../../routes/api-key-management/api-key-management-edit"
),
},
{
path: "add-sales-channels",
lazy: () =>
import(
"../../routes/api-key-management/api-key-management-add-sales-channels"
),
},
],
},
],
},
{
path: "executions",
element: <Outlet />,
handle: {
crumb: () => "Executions",
},
children: [
{
path: "",
lazy: () => import("../../routes/executions/execution-list"),
},
{
path: ":id",
lazy: () => import("../../routes/executions/execution-detail"),
},
],
},
...settingsExtensions,
],
},
...routeExtensions,
],
},
{
path: "*",
lazy: () => import("../../routes/no-match"),
},
])
export const RouterProvider = () => { export const RouterProvider = () => {
return <Provider router={router} /> return <Provider router={router} />

View File

@@ -0,0 +1,795 @@
import type {
AdminCollectionsRes,
AdminCustomerGroupsRes,
AdminCustomersRes,
AdminGiftCardsRes,
AdminOrdersRes,
AdminProductsRes,
AdminPublishableApiKeysRes,
AdminRegionsRes,
AdminSalesChannelsRes,
AdminUserRes,
} from "@medusajs/medusa"
import { Outlet, RouteObject } from "react-router-dom"
import { ProtectedRoute } from "../../components/authentication/require-auth"
import { ErrorBoundary } from "../../components/error/error-boundary"
import { MainLayout } from "../../components/layout/main-layout"
import { SettingsLayout } from "../../components/layout/settings-layout"
import routes from "medusa-admin:routes/pages"
import settings from "medusa-admin:settings/pages"
const routeExtensions: RouteObject[] = routes.pages.map((ext) => {
return {
path: ext.path,
async lazy() {
const { default: Component } = await import(/* @vite-ignore */ ext.file)
return { Component }
},
}
})
const settingsExtensions: RouteObject[] = settings.pages.map((ext) => {
return {
path: `/settings${ext.path}`,
async lazy() {
const { default: Component } = await import(/* @vite-ignore */ ext.file)
return { Component }
},
}
})
/**
* V1 routes.
*
* These routes are loaded by default.
*/
export const v1Routes: RouteObject[] = [
{
path: "/login",
lazy: () => import("../../routes/login"),
},
{
path: "/reset-password",
element: <Outlet />,
children: [
{
index: true,
lazy: () =>
import("../../routes/reset-password/reset-password-request"),
},
{
path: ":token",
lazy: () => import("../../routes/reset-password/reset-password-token"),
},
],
},
{
path: "/invite",
lazy: () => import("../../routes/invite"),
},
{
element: <ProtectedRoute />,
errorElement: <ErrorBoundary />,
children: [
{
path: "/",
element: <MainLayout />,
children: [
{
index: true,
lazy: () => import("../../routes/home"),
},
{
path: "/orders",
handle: {
crumb: () => "Orders",
},
children: [
{
path: "",
lazy: () => import("../../routes/orders/order-list"),
},
{
path: ":id",
lazy: () => import("../../routes/orders/order-detail"),
handle: {
crumb: (data: AdminOrdersRes) =>
`Order #${data.order.display_id}`,
},
},
],
},
{
path: "/draft-orders",
handle: {
crumb: () => "Draft Orders",
},
children: [
{
index: true,
lazy: () =>
import("../../routes/draft-orders/draft-order-list"),
},
{
path: ":id",
lazy: () =>
import("../../routes/draft-orders/draft-order-detail"),
},
],
},
{
path: "/products",
handle: {
crumb: () => "Products",
},
children: [
{
path: "",
lazy: () => import("../../routes/products/product-list"),
children: [
{
path: "create",
lazy: () => import("../../routes/products/product-create"),
},
],
},
{
path: ":id",
lazy: () => import("../../routes/products/product-detail"),
handle: {
crumb: (data: AdminProductsRes) => data.product.title,
},
children: [
{
path: "edit",
lazy: () => import("../../routes/products/product-edit"),
},
{
path: "sales-channels",
lazy: () =>
import("../../routes/products/product-sales-channels"),
},
{
path: "attributes",
lazy: () =>
import("../../routes/products/product-attributes"),
},
{
path: "options",
lazy: () => import("../../routes/products/product-options"),
},
{
path: "gallery",
lazy: () => import("../../routes/products/product-gallery"),
},
],
},
],
},
{
path: "/categories",
handle: {
crumb: () => "Categories",
},
children: [
{
index: true,
lazy: () => import("../../routes/categories/list"),
},
{
path: ":id",
lazy: () => import("../../routes/categories/details"),
},
],
},
{
path: "/collections",
handle: {
crumb: () => "Collections",
},
children: [
{
path: "",
lazy: () => import("../../routes/collections/collection-list"),
children: [
{
path: "create",
lazy: () =>
import("../../routes/collections/collection-create"),
},
],
},
{
path: ":id",
handle: {
crumb: (data: AdminCollectionsRes) => data.collection.title,
},
lazy: () =>
import("../../routes/collections/collection-detail"),
children: [
{
path: "edit",
lazy: () =>
import("../../routes/collections/collection-edit"),
},
{
path: "add-products",
lazy: () =>
import(
"../../routes/collections/collection-add-products"
),
},
],
},
],
},
{
path: "/inventory",
handle: {
crumb: () => "Inventory",
},
lazy: () => import("../../routes/inventory/inventory-list"),
},
{
path: "/reservations",
handle: {
crumb: () => "Reservations",
},
children: [
{
path: "",
lazy: () =>
import("../../routes/reservations/reservation-list"),
},
{
path: ":id",
lazy: () =>
import("../../routes/reservations/reservation-detail"),
// children: [
// {
// path: "edit",
// lazy: () =>
// import("../../routes/reservations/reservation-edit"),
// },
// ],
},
],
},
{
path: "/customers",
handle: {
crumb: () => "Customers",
},
children: [
{
path: "",
lazy: () => import("../../routes/customers/customer-list"),
children: [
{
path: "create",
lazy: () =>
import("../../routes/customers/customer-create"),
},
],
},
{
path: ":id",
lazy: () => import("../../routes/customers/customer-detail"),
handle: {
crumb: (data: AdminCustomersRes) => data.customer.email,
},
children: [
{
path: "edit",
lazy: () => import("../../routes/customers/customer-edit"),
},
],
},
],
},
{
path: "/customer-groups",
handle: {
crumb: () => "Customer Groups",
},
children: [
{
path: "",
lazy: () =>
import("../../routes/customer-groups/customer-group-list"),
children: [
{
path: "create",
lazy: () =>
import(
"../../routes/customer-groups/customer-group-create"
),
},
],
},
{
path: ":id",
lazy: () =>
import("../../routes/customer-groups/customer-group-detail"),
handle: {
crumb: (data: AdminCustomerGroupsRes) =>
data.customer_group.name,
},
children: [
{
path: "add-customers",
lazy: () =>
import(
"../../routes/customer-groups/customer-group-add-customers"
),
},
{
path: "edit",
lazy: () =>
import(
"../../routes/customer-groups/customer-group-edit"
),
},
],
},
],
},
{
path: "/gift-cards",
handle: {
crumb: () => "Gift Cards",
},
children: [
{
path: "",
lazy: () => import("../../routes/gift-cards/gift-card-list"),
children: [
{
path: "create",
lazy: () =>
import("../../routes/gift-cards/gift-card-create"),
},
],
},
{
path: ":id",
lazy: () => import("../../routes/gift-cards/gift-card-detail"),
handle: {
crumb: (data: AdminGiftCardsRes) => data.gift_card.code,
},
children: [
{
path: "edit",
lazy: () =>
import("../../routes/gift-cards/gift-card-edit"),
},
],
},
],
},
{
path: "/discounts",
handle: {
crumb: () => "Discounts",
},
children: [
{
index: true,
lazy: () => import("../../routes/discounts/list"),
},
{
path: "create",
lazy: () => import("../../routes/discounts/create"),
},
{
path: ":id",
lazy: () => import("../../routes/discounts/details"),
children: [
{
path: "edit",
lazy: () => import("../../routes/discounts/edit-details"),
},
{
path: "configuration",
lazy: () =>
import("../../routes/discounts/edit-configuration"),
},
],
},
],
},
{
path: "/pricing",
handle: {
crumb: () => "Pricing",
},
children: [
{
path: "",
lazy: () => import("../../routes/pricing/pricing-list"),
children: [
// {
// path: "create",
// lazy: () => import("../../routes/pricing/pricing-create"),
// },
],
},
{
path: ":id",
lazy: () => import("../../routes/pricing/pricing-detail"),
children: [
{
path: "edit",
lazy: () => import("../../routes/pricing/pricing-edit"),
},
{
path: "products/add",
lazy: () =>
import("../../routes/pricing/pricing-products-add"),
},
{
path: "products/edit",
lazy: () =>
import("../../routes/pricing/pricing-products-edit"),
},
],
},
],
},
],
},
{
path: "/settings",
element: <SettingsLayout />,
handle: {
crumb: () => "Settings",
},
children: [
{
index: true,
lazy: () => import("../../routes/settings"),
},
{
path: "profile",
lazy: () => import("../../routes/profile/profile-detail"),
handle: {
crumb: () => "Profile",
},
children: [
{
path: "edit",
lazy: () => import("../../routes/profile/profile-edit"),
},
],
},
{
path: "store",
lazy: () => import("../../routes/store/store-detail"),
handle: {
crumb: () => "Store",
},
children: [
{
path: "edit",
lazy: () => import("../../routes/store/store-edit"),
},
{
path: "add-currencies",
lazy: () => import("../../routes/store/store-add-currencies"),
},
],
},
{
path: "locations",
element: <Outlet />,
handle: {
crumb: () => "Locations",
},
children: [
{
path: "",
lazy: () => import("../../routes/locations/location-list"),
children: [
{
path: "create",
lazy: () =>
import("../../routes/locations/location-create"),
},
],
},
{
path: ":id",
lazy: () => import("../../routes/locations/location-detail"),
children: [
{
path: "edit",
lazy: () => import("../../routes/locations/location-edit"),
},
{
path: "add-sales-channels",
lazy: () =>
import(
"../../routes/locations/location-add-sales-channels"
),
},
],
},
],
},
{
path: "return-reasons",
element: <Outlet />,
handle: {
crumb: () => "Return Reasons",
},
children: [
{
path: "",
lazy: () =>
import("../../routes/return-reasons/return-reason-list"),
children: [
{
path: "create",
lazy: () =>
import(
"../../routes/return-reasons/return-reason-create"
),
},
{
path: ":id/edit",
lazy: () =>
import("../../routes/return-reasons/return-reason-edit"),
},
],
},
],
},
{
path: "regions",
element: <Outlet />,
handle: {
crumb: () => "Regions",
},
children: [
{
path: "",
lazy: () => import("../../routes/regions/region-list"),
children: [
{
path: "create",
lazy: () => import("../../routes/regions/region-create"),
},
],
},
{
path: ":id",
lazy: () => import("../../routes/regions/region-detail"),
handle: {
crumb: (data: AdminRegionsRes) => data.region.name,
},
children: [
{
path: "edit",
lazy: () => import("../../routes/regions/region-edit"),
},
{
path: "countries/add",
lazy: () =>
import("../../routes/regions/region-add-countries"),
},
{
path: "shipping-options/:so_id/edit",
lazy: () =>
import(
"../../routes/regions/region-edit-shipping-option"
),
},
{
path: "shipping-options/create",
lazy: () =>
import(
"../../routes/regions/region-create-shipping-option"
),
},
],
},
],
},
{
path: "users",
element: <Outlet />,
handle: {
crumb: () => "Users",
},
children: [
{
path: "",
lazy: () => import("../../routes/users/user-list"),
children: [
{
path: "invite",
lazy: () => import("../../routes/users/user-invite"),
},
],
},
{
path: ":id",
lazy: () => import("../../routes/users/user-detail"),
handle: {
crumb: (data: AdminUserRes) => data.user.email,
},
children: [
{
path: "edit",
lazy: () => import("../../routes/users/user-edit"),
},
],
},
],
},
{
path: "taxes",
handle: {
crumb: () => "Taxes",
},
children: [
{
path: "",
lazy: () => import("../../routes/taxes/tax-list"),
},
{
path: ":id",
lazy: () => import("../../routes/taxes/tax-detail"),
handle: {
crumb: (data: AdminRegionsRes) => data.region.name,
},
children: [
{
path: "edit",
lazy: () => import("../../routes/taxes/tax-edit"),
},
{
path: "tax-rates/create",
lazy: () => import("../../routes/taxes/tax-rate-create"),
},
{
path: "tax-rates/:rate_id/edit",
lazy: () => import("../../routes/taxes/tax-rate-edit"),
},
{
path: "tax-rates/:rate_id/edit-overrides",
lazy: () =>
import("../../routes/taxes/tax-rate-edit-overrides"),
},
],
},
],
},
{
path: "sales-channels",
element: <Outlet />,
handle: {
crumb: () => "Sales Channels",
},
children: [
{
path: "",
lazy: () =>
import("../../routes/sales-channels/sales-channel-list"),
children: [
{
path: "create",
lazy: () =>
import(
"../../routes/sales-channels/sales-channel-create"
),
},
],
},
{
path: ":id",
lazy: () =>
import("../../routes/sales-channels/sales-channel-detail"),
handle: {
crumb: (data: AdminSalesChannelsRes) =>
data.sales_channel.name,
},
children: [
{
path: "edit",
lazy: () =>
import("../../routes/sales-channels/sales-channel-edit"),
},
{
path: "add-products",
lazy: () =>
import(
"../../routes/sales-channels/sales-channel-add-products"
),
},
],
},
],
},
{
path: "api-key-management",
element: <Outlet />,
handle: {
crumb: () => "API Key Management",
},
children: [
{
path: "",
lazy: () =>
import(
"../../routes/api-key-management/api-key-management-list"
),
children: [
{
path: "create",
lazy: () =>
import(
"../../routes/api-key-management/api-key-management-create"
),
},
],
},
{
path: ":id",
lazy: () =>
import(
"../../routes/api-key-management/api-key-management-detail"
),
handle: {
crumb: (data: AdminPublishableApiKeysRes) =>
data.publishable_api_key.title,
},
children: [
{
path: "edit",
lazy: () =>
import(
"../../routes/api-key-management/api-key-management-edit"
),
},
{
path: "add-sales-channels",
lazy: () =>
import(
"../../routes/api-key-management/api-key-management-add-sales-channels"
),
},
],
},
],
},
{
path: "executions",
element: <Outlet />,
handle: {
crumb: () => "Executions",
},
children: [
{
path: "",
lazy: () => import("../../routes/executions/execution-list"),
},
{
path: ":id",
lazy: () => import("../../routes/executions/execution-detail"),
},
],
},
...settingsExtensions,
],
},
...routeExtensions,
],
},
{
path: "*",
lazy: () => import("../../routes/no-match"),
},
]

View File

@@ -0,0 +1,17 @@
import { RouteObject } from "react-router-dom"
/**
* Experimental V2 routes.
*
* These routes are only available if the `MEDUSA_V2` feature flag is enabled.
*/
export const v2Routes: RouteObject[] = [
{
path: "/login",
lazy: () => import("../../v2-routes/login"),
},
{
path: "*",
lazy: () => import("../../routes/no-match"),
},
]

View File

@@ -0,0 +1 @@
export { Login as Component } from "./login"

View File

@@ -0,0 +1,3 @@
export const Login = () => {
return <div>Medusa V2 Login</div>
}

View File

@@ -1,7 +1,8 @@
/// <reference types="vite/client" /> // / <reference types="vite/client" />
interface ImportMetaEnv { interface ImportMetaEnv {
readonly MEDUSA_ADMIN_BACKEND_URL: string readonly MEDUSA_ADMIN_BACKEND_URL: string
readonly MEDUSA_V2: boolean
} }
interface ImportMeta { interface ImportMeta {