From ba73ffca79caf412c81a37c242573d47c1c4a32b Mon Sep 17 00:00:00 2001 From: gearnode Date: Tue, 18 Feb 2025 09:49:00 +0100 Subject: [PATCH] Use name for breadcrump Signed-off-by: gearnode --- .../src/contexts/BreadcrumbContext.tsx | 33 +++++ apps/console/src/layouts/ConsoleLayout.tsx | 119 +++++++++++------- apps/console/src/pages/VendorOverviewPage.tsx | 9 ++ 3 files changed, 114 insertions(+), 47 deletions(-) create mode 100644 apps/console/src/contexts/BreadcrumbContext.tsx diff --git a/apps/console/src/contexts/BreadcrumbContext.tsx b/apps/console/src/contexts/BreadcrumbContext.tsx new file mode 100644 index 000000000..ef9b339d9 --- /dev/null +++ b/apps/console/src/contexts/BreadcrumbContext.tsx @@ -0,0 +1,33 @@ +import React, { createContext, useContext, useState, useCallback } from 'react'; + +type BreadcrumbContextType = { + segments: Record; + setBreadcrumbSegment: (path: string, display: string) => void; +}; + +const BreadcrumbContext = createContext(undefined); + +export function BreadcrumbProvider({ children }: { children: React.ReactNode }) { + const [segments, setSegments] = useState>({}); + + const setBreadcrumbSegment = useCallback((path: string, display: string) => { + setSegments(prev => ({ + ...prev, + [path]: display + })); + }, []); + + return ( + + {children} + + ); +} + +export function useBreadcrumb() { + const context = useContext(BreadcrumbContext); + if (context === undefined) { + throw new Error('useBreadcrumb must be used within a BreadcrumbProvider'); + } + return context; +} \ No newline at end of file diff --git a/apps/console/src/layouts/ConsoleLayout.tsx b/apps/console/src/layouts/ConsoleLayout.tsx index 45796b358..bec20cca3 100644 --- a/apps/console/src/layouts/ConsoleLayout.tsx +++ b/apps/console/src/layouts/ConsoleLayout.tsx @@ -15,58 +15,83 @@ import { SidebarProvider, SidebarTrigger, } from "@/components/ui/sidebar"; +import { BreadcrumbProvider, useBreadcrumb } from "@/contexts/BreadcrumbContext"; -export default function ConsoleLayout() { +function BreadcrumbNavigation() { const location = useLocation(); const pathSegments = location.pathname.split("/").filter(Boolean); + const { segments } = useBreadcrumb(); + + const getBreadcrumbText = (segment: string, path: string) => { + // Check if we have a custom segment name + const fullPath = pathSegments + .slice(0, pathSegments.indexOf(segment) + 1) + .join('/'); + + // Look for patterns like 'vendors/:id' in our segments + const patternPath = fullPath.replace(/\/[^/]+$/, '/:id'); + if (segments[patternPath]) { + return segments[patternPath]; + } + + // Default to capitalized segment + return segment.charAt(0).toUpperCase() + segment.slice(1); + }; return ( - - - -
-
- - - - - - - Home - - - {pathSegments.map((segment, index) => { - const path = `/${pathSegments.slice(0, index + 1).join("/")}`; - const isLast = index === pathSegments.length - 1; + + + + + Home + + + {pathSegments.map((segment, index) => { + const path = `/${pathSegments.slice(0, index + 1).join("/")}`; + const isLast = index === pathSegments.length - 1; - return ( - - - - {isLast ? ( - - {segment.charAt(0).toUpperCase() + segment.slice(1)} - - ) : ( - - - {segment.charAt(0).toUpperCase() + - segment.slice(1)} - - - )} - - - ); - })} - - -
-
-
- -
-
-
+ return ( + + + + {isLast ? ( + + {getBreadcrumbText(segment, path)} + + ) : ( + + + {getBreadcrumbText(segment, path)} + + + )} + + + ); + })} + + + ); +} + +export default function ConsoleLayout() { + return ( + + + + +
+
+ + + +
+
+
+ +
+
+
+
); } diff --git a/apps/console/src/pages/VendorOverviewPage.tsx b/apps/console/src/pages/VendorOverviewPage.tsx index b41bafd8d..7404bac28 100644 --- a/apps/console/src/pages/VendorOverviewPage.tsx +++ b/apps/console/src/pages/VendorOverviewPage.tsx @@ -16,6 +16,8 @@ import { Suspense, useEffect } from "react"; import type { VendorOverviewPageQuery as VendorOverviewPageQueryType } from "./__generated__/VendorOverviewPageQuery.graphql"; import { useParams } from "react-router"; import { Helmet } from "react-helmet-async"; +import { useBreadcrumb } from "@/contexts/BreadcrumbContext"; + const VendorOverviewPageQuery = graphql` query VendorOverviewPageQuery($vendorId: ID!) { node(id: $vendorId) { @@ -36,6 +38,13 @@ function VendorOverviewPageContent({ }) { const data = usePreloadedQuery(VendorOverviewPageQuery, queryRef); const [riskLevel, setRiskLevel] = useState("medium"); + const { setBreadcrumbSegment } = useBreadcrumb(); + + useEffect(() => { + if (data.node?.name) { + setBreadcrumbSegment('vendors/:id', data.node.name); + } + }, [data.node?.name, setBreadcrumbSegment]); return (