فهرست منبع

feat(dashboard): Implement breadcrumbs generation

Michael Bromley 10 ماه پیش
والد
کامیت
f7cf880edd

+ 2 - 1
packages/dashboard/src/framework/internal/extension-api/extension-api-types.ts

@@ -1,11 +1,12 @@
 import { NavMenuItem } from '@/framework/internal/nav-menu/nav-menu.js';
 import { ListPageProps, ListQueryOptionsShape, ListQueryShape } from '@/framework/internal/page/list-page.js';
 import { TypedDocumentNode } from '@graphql-typed-document-node/core';
+import React from 'react';
 
 export interface DashboardBaseRouteDefinition {
     id: string;
     navMenuItem?: Partial<NavMenuItem> & { sectionId: string };
-    title: string;
+    title: string | React.ReactElement;
 }
 
 export interface DashboardListRouteDefinition<

+ 2 - 1
packages/dashboard/src/framework/internal/page/page-types.ts

@@ -1,6 +1,7 @@
 import { AnyRoute } from '@tanstack/react-router';
+import React from 'react';
 
 export interface PageProps {
-    title: string;
+    title: string | React.ReactElement;
     route: AnyRoute | (() => AnyRoute);
 }

+ 3 - 0
packages/dashboard/src/framework/internal/page/use-extended-router.tsx

@@ -42,6 +42,9 @@ const UseExtendedRouter = (router: Router<AnyRoute, any, any>) => {
             const newRoute = createRoute({
                 path: `/${pathWithoutLeadingSlash}`,
                 getParentRoute: () => authenticatedRoute,
+                loader: () => ({
+                    breadcrumb: config.title,
+                }),
                 component: () => (
                     <ListPage
                         title={config.title}

+ 25 - 8
packages/dashboard/src/routes/_authenticated.tsx

@@ -9,7 +9,7 @@ import {
 } from '@/components/ui/breadcrumb.js';
 import { Separator } from '@/components/ui/separator.js';
 import { SidebarInset, SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar.js';
-import { createFileRoute, Outlet, redirect } from '@tanstack/react-router';
+import { createFileRoute, Link, Outlet, redirect, useRouterState } from '@tanstack/react-router';
 import * as React from 'react';
 
 export const AUTHENTICATED_ROUTE_PREFIX = '/_authenticated';
@@ -25,10 +25,22 @@ export const Route = createFileRoute(AUTHENTICATED_ROUTE_PREFIX)({
             });
         }
     },
+    loader: () => ({
+        breadcrumb: 'Dashboard',
+    }),
     component: AuthLayout,
 });
 
 function AuthLayout() {
+    const matches = useRouterState({ select: s => s.matches });
+    const breadcrumbs = matches
+        .filter(match => match.loaderData?.breadcrumb)
+        .map(({ pathname, loaderData }) => {
+            return {
+                title: loaderData.breadcrumb,
+                path: pathname,
+            };
+        });
     return (
         <SidebarProvider>
             <AppSidebar />
@@ -39,13 +51,18 @@ function AuthLayout() {
                         <Separator orientation="vertical" className="mr-2 h-4" />
                         <Breadcrumb>
                             <BreadcrumbList>
-                                <BreadcrumbItem className="hidden md:block">
-                                    <BreadcrumbLink href="#">Building Your Application</BreadcrumbLink>
-                                </BreadcrumbItem>
-                                <BreadcrumbSeparator className="hidden md:block" />
-                                <BreadcrumbItem>
-                                    <BreadcrumbPage>Data Fetching</BreadcrumbPage>
-                                </BreadcrumbItem>
+                                {breadcrumbs.map(({ title, path }, index, arr) => (
+                                    <>
+                                        <BreadcrumbItem key={index} className="hidden md:block">
+                                            <BreadcrumbLink asChild>
+                                                <Link to={path}>{title}</Link>
+                                            </BreadcrumbLink>
+                                        </BreadcrumbItem>
+                                        {index < arr.length - 1 && (
+                                            <BreadcrumbSeparator className="hidden md:block" />
+                                        )}
+                                    </>
+                                ))}
                             </BreadcrumbList>
                         </Breadcrumb>
                     </div>

+ 3 - 0
packages/dashboard/src/routes/_authenticated/products.tsx

@@ -5,6 +5,9 @@ import React from 'react';
 
 export const Route = createFileRoute('/_authenticated/products')({
     component: ProductListPage,
+    loader: () => ({
+        breadcrumb: 'Products',
+    }),
 });
 
 const productListDocument = graphql(`