fixers 10/22

This commit is contained in:
2026-10-22 11:42:20 +05:30
parent a27bdaea64
commit b6b5a142a0
76 changed files with 3773 additions and 1988 deletions
@@ -1,15 +1,17 @@
"use client"
import { Fragment } from "react"
import Link from "next/link"
import { usePathname } from "next/navigation"
import { Breadcrumb, BreadcrumbItem, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb"
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
// Per-segment display labels. Deliberately separate from Header.tsx's
// titleFromPath (which resolves one *full* path to a page title) — a
// breadcrumb needs a label per *segment*, including grouping segments that
// have no page of their own (e.g. "receiving", "grn").
const SEGMENT_LABELS: Record<string, string> = {
dashboard: "Dashboard",
products: "Items",
@@ -48,55 +50,81 @@ const SEGMENT_LABELS: Record<string, string> = {
"owner-report": "Day-End Owner Report",
}
function labelFor(segment: string): string {
if (SEGMENT_LABELS[segment]) return SEGMENT_LABELS[segment]
if (/^[0-9]+$/.test(segment)) return `#${segment}`
return segment.charAt(0).toUpperCase() + segment.slice(1)
}
/**
* Grouping paths with no page of their own (no page.tsx), mapped to where their menu lands — the
* same `landingHref`s as the sidebar. Linking the raw path would 404. (HRM has its own hub page now.)
*/
const GROUP_LANDING: Record<string, string> = {
"/dashboard/production": "/dashboard/production/runs",
"/dashboard/receiving": "/dashboard/receiving/grn",
"/dashboard/sales/bundles": "/dashboard/sales/bundles/templates",
"/dashboard/sales/bundles":
"/dashboard/sales/bundles/templates",
"/dashboard/help/tickets": "/dashboard/help",
}
const linkClass =
"truncate transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring rounded-sm"
function labelFor(segment: string): string {
if (SEGMENT_LABELS[segment]) {
return SEGMENT_LABELS[segment]
}
if (/^[0-9]+$/.test(segment)) {
return `#${segment}`
}
return segment
.split("-")
.map(
(word) =>
word.charAt(0).toUpperCase() + word.slice(1)
)
.join(" ")
}
export function Breadcrumbs() {
const pathname = usePathname() || "/dashboard"
const segments = pathname.split("/").filter(Boolean)
// Nothing to show above the dashboard root itself.
if (segments.length <= 1) return null
if (segments.length <= 1) {
return null
}
const crumbs = segments.map((segment, i) => {
const path = "/" + segments.slice(0, i + 1).join("/")
return { key: path, href: GROUP_LANDING[path] ?? path, label: labelFor(segment) }
const crumbs = segments.map((segment, index) => {
const path = `/${segments
.slice(0, index + 1)
.join("/")}`
return {
key: path,
href: GROUP_LANDING[path] ?? path,
label: labelFor(segment),
}
})
// Remove consecutive duplicate labels, e.g. Sales > Sales.
const uniqueCrumbs = crumbs.filter(
(crumb, index, array) =>
index === 0 ||
crumb.label.toLowerCase() !==
array[index - 1].label.toLowerCase()
)
return (
<Breadcrumb className="mb-4 print:hidden">
<BreadcrumbList>
{crumbs.map((crumb, i) => {
const isLast = i === crumbs.length - 1
{uniqueCrumbs.map((crumb, index) => {
const isLast = index === uniqueCrumbs.length - 1
return (
<Fragment key={crumb.key}>
{index > 0 && <BreadcrumbSeparator />}
<BreadcrumbItem>
{isLast ? (
<BreadcrumbPage>{crumb.label}</BreadcrumbPage>
) : (
<Link href={crumb.href} className={linkClass}>
<BreadcrumbPage>
{crumb.label}
</Link>
</BreadcrumbPage>
) : (
<span className="truncate text-muted-foreground">
{crumb.label}
</span>
)}
</BreadcrumbItem>
{!isLast && <BreadcrumbSeparator />}
</Fragment>
)
})}