Files
property-management-network/components/dashboard/breadcrumbs.tsx
T
Leon SerfatyandClaude Opus 4.8 857b9a7811 Initial import: property management SaaS + security hardening + admin dashboard
Property Management Network — Next.js 16 (App Router), Better Auth,
Drizzle ORM over PostgreSQL, Stripe, OpenAI, Resend.

Includes:
- Security hardening: access-control/IDOR fixes, TLS-by-default DB layer,
  constant-time cron auth, strict security headers, atomic AI quota gating,
  HTML/email output encoding, demo-backdoor disabled in production.
- Superadmin dashboard at /admin (overview/MRR, server-paginated users with
  ban/impersonate/plan/delete, billing, platform activity + admin audit log,
  AI usage, system health) via the Better Auth admin plugin.
- Seed/migration utility scripts under scripts/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 20:36:07 -04:00

75 lines
2.1 KiB
TypeScript

"use client"
import Link from "next/link"
import { usePathname } from "next/navigation"
import { ChevronRight, Home } from "lucide-react"
const SEGMENT_LABELS: Record<string, string> = {
dashboard: "Dashboard",
properties: "Properties",
tenants: "Tenants",
rent: "Rent Tracker",
maintenance: "Maintenance",
leases: "Leases",
expenses: "Expenses",
reports: "Reports",
vendors: "Vendors",
inspections: "Inspections",
ai: "AI Assistant",
settings: "Settings",
profile: "Profile",
billing: "Billing",
demo: "Demo Data",
new: "New",
edit: "Edit",
generate: "Generate",
documents: "Documents",
}
function isUUID(s: string) {
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(s)
}
export function Breadcrumbs() {
const pathname = usePathname()
const segments = pathname.split("/").filter(Boolean)
// Don't show on top-level pages (only 1 segment)
if (segments.length <= 1) return null
const crumbs: { label: string; href: string }[] = []
let acc = ""
for (const seg of segments) {
acc += `/${seg}`
if (isUUID(seg)) {
crumbs.push({ label: "Detail", href: acc })
} else {
crumbs.push({ label: SEGMENT_LABELS[seg] ?? seg, href: acc })
}
}
return (
<nav className="mb-4 flex items-center gap-1.5 text-xs text-white/30">
<Link href="/dashboard" className="flex items-center gap-1 transition hover:text-white/60">
<Home className="h-3 w-3" />
</Link>
{crumbs.map((crumb, i) => {
const isLast = i === crumbs.length - 1
return (
<span key={crumb.href} className="flex items-center gap-1.5">
<ChevronRight className="h-3 w-3 text-white/15" />
{isLast ? (
<span className="font-medium text-white/60">{crumb.label}</span>
) : (
<Link href={crumb.href} className="transition hover:text-white/60">
{crumb.label}
</Link>
)}
</span>
)
})}
</nav>
)
}