fix(ui): resolve tab slug against the last base-segment match

createTabRoutes.slugFromPathname matched the first occurrence of the
route base segment. When SERVER_ROOT_PATH repeats that segment (e.g.
/logs mounts the UI at /logs/ui, so the audit tab is /logs/ui/logs/audit/),
it read the server-root copy and returned the wrong segment, which the
layout treats as an unknown tab and hard-redirects to a path that
misparses the same way, causing a reload loop. Match the last occurrence
instead: the route base always follows any server-root prefix, and no tab
slug equals the base, so the last match is always the real route base.
This commit is contained in:
ryan-crabbe-berri 2026-07-25 09:18:20 -07:00
parent b9b27c2beb
commit 51cce99399
2 changed files with 6 additions and 1 deletions

View file

@ -25,6 +25,11 @@ describe("createTabRoutes.slugFromPathname", () => {
it("returns empty string when the base segment is not in the path", () => {
expect(routes.slugFromPathname("/teams")).toBe("");
});
it("reads the route base after a server-root prefix that repeats the segment name", () => {
expect(routes.slugFromPathname("/logs/ui/logs/audit/")).toBe("audit");
expect(routes.slugFromPathname("/logs/ui/logs/")).toBe("");
});
});
describe("createTabRoutes.tabHref", () => {

View file

@ -15,7 +15,7 @@ export function createTabRoutes<Slug extends string>(baseSegment: string, slugs:
const slugFromPathname = (pathname: string): string => {
const parts = pathname.split("/").filter(Boolean);
const idx = parts.indexOf(baseSegment);
const idx = parts.lastIndexOf(baseSegment);
if (idx === -1) {
return "";
}