chore(layout): remove v2 nav-folding orphans surfaced by P4 refactor

P4 (Plan 2.5, AD-2.5-W1 + AD-2.5-B1) refactored SidebarNav to read
APP_NAVIGATION directly, retiring the OrganizerLayoutV2 → useV2Nav →
AppSidebar :groups → SidebarNav :groups props chain. Five artifacts
were deliberately left in place to keep the P4 diff focused — this
commit removes them.

Deleted:
- src/composables/useV2Nav.ts (+ spec) — v1→v2 nav fold adapter, no
  production consumer post-P4
- src/types/v2/nav.ts — V2NavGroup / V2NavItem types, only consumed
  by the deleted composables above. types/v2/ directory removed (empty)
- src/components-v2/layout/sidebarNavActive.ts (+ spec) — pure helper,
  SidebarNav now uses inlined active check against NavItem.routeName
- navFixture export + V2NavGroup import from stories/v2/_helpers.ts

Also: stale "useV2Nav(orgNavItems)" reference scrubbed from
OrganizerLayoutV2.vue docstring (the function no longer exists; the
comment now describes the retired plumbing generically).

Suite delta: 575 → 557 (−18 specs). The drop is correct — the removed
specs tested deleted dead code (sidebarNavActive: 8 specs, useV2Nav:
10 specs), not contract behaviour.

vue-tsc clean. Scoped ESLint clean (0 errors). Final re-grep on all
deleted symbols (useV2Nav, V2NavGroup, V2NavItem, sidebarNavActive,
navFixture) returns zero hits across apps/app/src/.

Per zero-compromise gap 5 (delete > adapt): orphans don't stay.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-20 19:32:46 +02:00
parent 864cc558e2
commit 967f1a93bb
7 changed files with 1 additions and 313 deletions

View File

@@ -1,46 +0,0 @@
import { describe, expect, it } from 'vitest'
import { isNavItemActive } from '@/components-v2/layout/sidebarNavActive'
import type { V2NavItem } from '@/types/v2/nav'
function makeItem(name: string): V2NavItem {
return { id: name, label: name, icon: 'tabler-home', to: { name } }
}
describe('isNavItemActive', () => {
it('returns true when the current route name exactly matches', () => {
expect(isNavItemActive(makeItem('dashboard'), 'dashboard')).toBe(true)
})
it('returns false when the current route name differs', () => {
expect(isNavItemActive(makeItem('dashboard'), 'events')).toBe(false)
})
it('returns false when currentRouteName is null', () => {
expect(isNavItemActive(makeItem('dashboard'), null)).toBe(false)
})
it('returns false when currentRouteName is undefined', () => {
expect(isNavItemActive(makeItem('dashboard'), undefined)).toBe(false)
})
it('returns true for nested routes: item name is a prefix of current route (dash-separated)', () => {
// e.g. item "organisation" should be active on route "organisation-settings"
expect(isNavItemActive(makeItem('organisation'), 'organisation-settings')).toBe(true)
})
it('does not match partial-word prefixes: "org" should NOT match "organisation-settings"', () => {
expect(isNavItemActive(makeItem('org'), 'organisation-settings')).toBe(false)
})
it('handles symbol route names: returns false (not string — no match)', () => {
const sym = Symbol('dashboard')
expect(isNavItemActive(makeItem('dashboard'), sym)).toBe(false)
})
it('item with to as { name: string } matches correctly', () => {
const item: V2NavItem = { id: 'events', label: 'Events', icon: 'tabler-calendar', to: { name: 'events' } }
expect(isNavItemActive(item, 'events')).toBe(true)
})
})

View File

@@ -1,37 +0,0 @@
import type { V2NavItem } from '@/types/v2/nav'
/**
* Pure helper — determines whether a V2NavItem is "active" given the current
* route name.
*
* Active rules (simplest correct definition):
* 1. Exact match: currentRouteName === item.to.name
* 2. Prefix match for nested routes: currentRouteName starts with
* item.to.name + '-' (e.g. item "organisation" is active on
* "organisation-settings"). The dash boundary prevents "org" from
* spuriously matching "organisation-settings".
*
* Only `to` values that are a plain object with a string `name` property are
* compared — string/array `to` values always return false (router-push
* style not used in v1 nav).
*/
export function isNavItemActive(
item: V2NavItem,
currentRouteName: string | symbol | null | undefined,
): boolean {
if (typeof currentRouteName !== 'string')
return false
const to = item.to
if (typeof to !== 'object' || to === null || Array.isArray(to))
return false
const itemName = (to as { name?: unknown }).name
if (typeof itemName !== 'string')
return false
return currentRouteName === itemName
|| currentRouteName.startsWith(`${itemName}-`)
}