feat: show active product name in navbar, links to product page
Sub-layout sets product in Zustand store; NavBar reads it. getAccessibleProduct wrapped with React cache to avoid double DB call. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
bc91e3c169
commit
29ed4f2773
5 changed files with 69 additions and 2 deletions
|
|
@ -7,6 +7,7 @@ import { Button } from '@/components/ui/button'
|
|||
import { Badge } from '@/components/ui/badge'
|
||||
import { AppIcon } from '@/components/shared/app-icon'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { useProductStore } from '@/stores/product-store'
|
||||
|
||||
const ROLE_LABELS: Record<string, string> = {
|
||||
PRODUCT_OWNER: 'PO',
|
||||
|
|
@ -21,6 +22,7 @@ interface NavBarProps {
|
|||
|
||||
export function NavBar({ isDemo, roles }: NavBarProps) {
|
||||
const pathname = usePathname()
|
||||
const currentProduct = useProductStore(s => s.currentProduct)
|
||||
|
||||
const productMatch = pathname.match(/^\/products\/([^/]+)/)
|
||||
const productId = productMatch ? productMatch[1] : null
|
||||
|
|
@ -81,6 +83,17 @@ export function NavBar({ isDemo, roles }: NavBarProps) {
|
|||
{roles.map(r => ROLE_LABELS[r]).filter(Boolean).join(' · ')}
|
||||
</span>
|
||||
)}
|
||||
{currentProduct && (
|
||||
<Link
|
||||
href={`/products/${currentProduct.id}`}
|
||||
className="text-xs text-muted-foreground hover:text-foreground transition-colors px-2 truncate max-w-[160px]"
|
||||
title={currentProduct.name}
|
||||
>
|
||||
{currentProduct.name.length > 20
|
||||
? currentProduct.name.slice(0, 20) + '…'
|
||||
: currentProduct.name}
|
||||
</Link>
|
||||
)}
|
||||
<Link
|
||||
href="/settings"
|
||||
className={cn(
|
||||
|
|
|
|||
15
components/shared/set-current-product.tsx
Normal file
15
components/shared/set-current-product.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
'use client'
|
||||
|
||||
import { useEffect } from 'react'
|
||||
import { useProductStore } from '@/stores/product-store'
|
||||
|
||||
export function SetCurrentProduct({ id, name }: { id: string; name: string }) {
|
||||
const { setCurrentProduct, clearCurrentProduct } = useProductStore()
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentProduct(id, name)
|
||||
return () => clearCurrentProduct()
|
||||
}, [id, name, setCurrentProduct, clearCurrentProduct])
|
||||
|
||||
return null
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue