From f9f3ee13113c470804d3e48830f79439ef38b9a5 Mon Sep 17 00:00:00 2001 From: njrini99-code Date: Tue, 30 Jun 2026 09:25:11 -0400 Subject: [PATCH 1/2] feat(routes): canonicalize create and recovery paths --- CLAUDE.md | 4 +- docs/operations/ROUTE_OWNERSHIP_MATRIX.md | 2 +- e2e/accessibility/critical-routes.spec.ts | 4 +- e2e/baseball-box-score.spec.ts | 10 ++--- e2e/course-library.spec.ts | 4 +- e2e/golf-dashboard.spec.ts | 4 +- e2e/golf-round.spec.ts | 8 ++-- e2e/route-crawler/route-crawler.spec.ts | 8 +++- memory/context/golfhelm-features.md | 10 ++--- memory/features/golf-round-lifecycle.md | 4 +- memory/features/qualifiers.md | 4 +- memory/features/shot-tracking.md | 6 +-- memory/projects/golfhelm.md | 14 +++---- memory/registry.yml | 4 +- next.config.mjs | 38 ++++++++++++++++++- scripts/__tests__/cmd-k-coverage.test.mjs | 8 ++-- scripts/__tests__/coachhelm-hub.test.mjs | 2 +- scripts/__tests__/emptystate-vocab.test.mjs | 4 +- scripts/__tests__/genome-fluid.test.mjs | 2 +- .../route-hygiene/check-route-coverage.mjs | 2 +- .../ui-intelligence/normalize-devin-routes.ts | 8 ++-- .../games/{new => create}/NewGameClient.tsx | 0 .../stats/games/{new => create}/error.tsx | 2 +- .../stats/games/{new => create}/loading.tsx | 0 .../stats/games/{new => create}/page.tsx | 0 src/app/golf/(auth)/signup/page.tsx | 2 +- .../(dashboard)/FairwayDashboardShell.tsx | 2 +- .../components/PlayerCoachHelmDashboard.tsx | 2 +- .../coachhelm/genome/[playerId]/page.tsx | 2 +- .../{compare => compare-players}/error.tsx | 2 +- .../{compare => compare-players}/loading.tsx | 0 .../{compare => compare-players}/page.tsx | 2 +- .../dashboard/components/PlayerDashboard.tsx | 4 +- .../my-qualifiers/my-qualifiers-client.tsx | 2 +- .../dashboard/qualifiers/[id]/page.tsx | 2 +- .../qualifiers/{new => create}/error.tsx | 2 +- .../qualifiers/{new => create}/loading.tsx | 0 .../{new => create}/new-qualifier-client.tsx | 0 .../qualifiers/{new => create}/page.tsx | 0 .../continue/[id]/continue-round-client.tsx | 2 +- .../rounds/{new => create}/error.tsx | 2 +- .../rounds/{new => create}/layout.tsx | 0 .../rounds/{new => create}/loading.tsx | 0 .../{new => create}/new-round-client.tsx | 2 +- .../dashboard/rounds/{new => create}/page.tsx | 0 .../(dashboard)/dashboard/rounds/page.tsx | 4 +- .../{recover => recover-draft}/error.tsx | 2 +- .../{recover => recover-draft}/loading.tsx | 0 .../{recover => recover-draft}/page.tsx | 0 .../recover-round-client.tsx | 0 .../dashboard/stats/stats-client.tsx | 2 +- src/app/golf/README.md | 3 +- src/components/auth/golf-sign-up-form.tsx | 6 +-- src/components/baseball/games/GamesList.tsx | 4 +- src/components/errors/RouteErrorBoundary.tsx | 4 +- .../coachhelm/FairwayPlayerCoachHelm.tsx | 2 +- .../pages/coachhelm/FairwayStatsCockpit.tsx | 2 +- .../pages/coachhelm/GenomeCompareView.tsx | 4 +- .../pages/coachhelm/GenomeDetailView.tsx | 2 +- .../dashboard/FairwayPlayerDashboard.tsx | 6 +-- .../my-qualifiers/FairwayMyQualifiers.tsx | 4 +- .../player-game/FairwayMyGameProfile.tsx | 2 +- .../pages/qualifiers/FairwayNewQualifier.tsx | 2 +- .../qualifiers/FairwayQualifierDetail.tsx | 2 +- .../pages/qualifiers/FairwayQualifiers.tsx | 2 +- .../rounds-recover/FairwayRecoverRound.tsx | 2 +- .../pages/rounds/FairwayRoundsLibrary.tsx | 4 +- .../rounds/FairwayUnsyncedRoundBanner.tsx | 2 +- src/components/golf/CommandPalette.tsx | 4 +- .../v2/IntelligenceCommandCenter.tsx | 2 +- .../v3/Genome/GenomeComparePicker.tsx | 2 +- .../golf/dashboard/todays-mission-card.tsx | 2 +- .../golf/qualifiers/CreateQualifierButton.tsx | 2 +- src/components/landing/Hero.tsx | 4 +- src/components/layout/mobile-bottom-nav.tsx | 6 +-- src/components/ui/button.tsx | 6 +-- src/components/ui/empty-state.tsx | 4 +- src/lib/error-logging.ts | 2 +- 78 files changed, 158 insertions(+), 117 deletions(-) rename src/app/baseball/(dashboard)/dashboard/stats/games/{new => create}/NewGameClient.tsx (100%) rename src/app/baseball/(dashboard)/dashboard/stats/games/{new => create}/error.tsx (90%) rename src/app/baseball/(dashboard)/dashboard/stats/games/{new => create}/loading.tsx (100%) rename src/app/baseball/(dashboard)/dashboard/stats/games/{new => create}/page.tsx (100%) rename src/app/golf/(dashboard)/dashboard/coachhelm/genome/{compare => compare-players}/error.tsx (88%) rename src/app/golf/(dashboard)/dashboard/coachhelm/genome/{compare => compare-players}/loading.tsx (100%) rename src/app/golf/(dashboard)/dashboard/coachhelm/genome/{compare => compare-players}/page.tsx (99%) rename src/app/golf/(dashboard)/dashboard/qualifiers/{new => create}/error.tsx (90%) rename src/app/golf/(dashboard)/dashboard/qualifiers/{new => create}/loading.tsx (100%) rename src/app/golf/(dashboard)/dashboard/qualifiers/{new => create}/new-qualifier-client.tsx (100%) rename src/app/golf/(dashboard)/dashboard/qualifiers/{new => create}/page.tsx (100%) rename src/app/golf/(dashboard)/dashboard/rounds/{new => create}/error.tsx (91%) rename src/app/golf/(dashboard)/dashboard/rounds/{new => create}/layout.tsx (100%) rename src/app/golf/(dashboard)/dashboard/rounds/{new => create}/loading.tsx (100%) rename src/app/golf/(dashboard)/dashboard/rounds/{new => create}/new-round-client.tsx (99%) rename src/app/golf/(dashboard)/dashboard/rounds/{new => create}/page.tsx (100%) rename src/app/golf/(dashboard)/dashboard/rounds/{recover => recover-draft}/error.tsx (90%) rename src/app/golf/(dashboard)/dashboard/rounds/{recover => recover-draft}/loading.tsx (100%) rename src/app/golf/(dashboard)/dashboard/rounds/{recover => recover-draft}/page.tsx (100%) rename src/app/golf/(dashboard)/dashboard/rounds/{recover => recover-draft}/recover-round-client.tsx (100%) diff --git a/CLAUDE.md b/CLAUDE.md index 9bbe3e3c9..c6b494b61 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -100,7 +100,7 @@ import type { Player, Coach, Organization } from '@/lib/types'; | CoachHelm Analytics | `/dashboard/analytics/coachhelm` | golf_insight_effectiveness | coachhelm-analytics.ts | | Coaching Settings | `/dashboard/settings/coaching-intelligence` | golf_coach_philosophy | (in settings page) | | Development Plans | `/dashboard/development` | golf_player_focus_areas | development.ts | -| Create Qualifier | `/dashboard/qualifiers/new` | golf_qualifiers | golf.ts | +| Create Qualifier | `/dashboard/qualifiers/create` | golf_qualifiers | golf.ts | | Team Stats | `/dashboard/stats/team` | golf_player_stats_cache | stats.ts, stats-v2.ts | ### Player-Only Features @@ -110,7 +110,7 @@ import type { Player, Coach, Organization } from '@/lib/types'; | Player CoachHelm | `/dashboard/coachhelm` | golf_predictions | shot-analytics.ts | | My Development | `/dashboard/my-development` | golf_player_focus_areas | development.ts | | My Qualifiers | `/dashboard/my-qualifiers` | golf_qualifier_entries | golf.ts | -| Round Entry | `/dashboard/rounds/new` | golf_rounds | golf.ts | +| Round Entry | `/dashboard/rounds/create` | golf_rounds | golf.ts | | Continue Round | `/dashboard/rounds/continue/[id]` | golf_shots | golf.ts | | Round Review | `/dashboard/rounds/[id]/review` | golf_round_reviews | round-reviews.ts, round-review-system.ts | | Classes | `/dashboard/classes` | golf_player_classes | (inline) | diff --git a/docs/operations/ROUTE_OWNERSHIP_MATRIX.md b/docs/operations/ROUTE_OWNERSHIP_MATRIX.md index 441376959..4081fb0f2 100644 --- a/docs/operations/ROUTE_OWNERSHIP_MATRIX.md +++ b/docs/operations/ROUTE_OWNERSHIP_MATRIX.md @@ -30,7 +30,7 @@ Helm Sports Labs route ownership for GolfHelm and BaseballHelm. Canonical URLs n | --- | --- | --- | --- | | `/golf/dashboard/coachhelm` | CoachHelm | player | Player CoachHelm entry | | `/golf/dashboard/my-qualifiers` | Qualifiers | player | | -| `/golf/dashboard/rounds/new` | Rounds | player | Round entry | +| `/golf/dashboard/rounds/create` | Rounds | player | Round entry | ## CoachHelm surface classification diff --git a/e2e/accessibility/critical-routes.spec.ts b/e2e/accessibility/critical-routes.spec.ts index 3fadfa3b9..eb24ca0c2 100644 --- a/e2e/accessibility/critical-routes.spec.ts +++ b/e2e/accessibility/critical-routes.spec.ts @@ -5,7 +5,9 @@ const routes = ['/', '/golf', '/baseball']; for (const route of routes) { test(`critical route has no severe accessibility violations: ${route}`, async ({ page }) => { - await page.goto(route); + await page.goto(route, { waitUntil: 'networkidle', timeout: 30_000 }).catch(() => {}); + // Sport landings server-redirect to login/onboarding — scan the settled page. + await page.waitForLoadState('domcontentloaded'); const results = await new AxeBuilder({ page }) .withTags(['wcag2a', 'wcag2aa']) .analyze(); diff --git a/e2e/baseball-box-score.spec.ts b/e2e/baseball-box-score.spec.ts index 4ec415e47..1f5063c5b 100644 --- a/e2e/baseball-box-score.spec.ts +++ b/e2e/baseball-box-score.spec.ts @@ -36,7 +36,7 @@ test.describe('Coach - Create New Game', () => { test('should display the new game form', async ({ page }) => { // TODO: requires test data setup (coach must belong to college/juco team) - await page.goto('/baseball/dashboard/stats/games/new'); + await page.goto('/baseball/dashboard/stats/games/create'); await waitForPageLoad(page); await expect( @@ -55,7 +55,7 @@ test.describe('Coach - Create New Game', () => { test('should require a game date before submitting', async ({ page }) => { // TODO: requires test data setup - await page.goto('/baseball/dashboard/stats/games/new'); + await page.goto('/baseball/dashboard/stats/games/create'); await waitForPageLoad(page); // Clear the date field and attempt to submit @@ -79,7 +79,7 @@ test.describe('Coach - Create New Game', () => { test('should fill game details and submit the create-game form', async ({ page }) => { // TODO: requires test data setup (coach must belong to college/juco team with a roster) - await page.goto('/baseball/dashboard/stats/games/new'); + await page.goto('/baseball/dashboard/stats/games/create'); await waitForPageLoad(page); // Set game type to "game" @@ -123,7 +123,7 @@ test.describe('Coach - Create New Game', () => { await page.waitForTimeout(1500); const currentUrl = page.url(); const wentToGamePage = currentUrl.includes('/stats/games/'); - const stayedOnForm = currentUrl.includes('/stats/games/new') || currentUrl.includes('/dashboard'); + const stayedOnForm = currentUrl.includes('/stats/games/create') || currentUrl.includes('/dashboard'); expect(wentToGamePage || stayedOnForm).toBeTruthy(); } }); @@ -411,7 +411,7 @@ test.describe('Coach - Games List and Box Score View', () => { await waitForPageLoad(page); const addButton = page.locator( - 'a[href*="/stats/games/new"], button:has-text("Add Game"), a:has-text("Add Game")' + 'a[href*="/stats/games/create"], button:has-text("Add Game"), a:has-text("Add Game")' ).first(); if (await addButton.count() > 0 && await addButton.isVisible({ timeout: 5000 })) { diff --git a/e2e/course-library.spec.ts b/e2e/course-library.spec.ts index 8145ad2c9..c973bb658 100644 --- a/e2e/course-library.spec.ts +++ b/e2e/course-library.spec.ts @@ -111,7 +111,7 @@ test.describe('Cloud Course Library — authenticated flow', () => { test('"Browse course library" on new round opens the tee picker', async ({ page, }) => { - await page.goto('/golf/dashboard/rounds/new'); + await page.goto('/golf/dashboard/rounds/create'); const browse = page.getByRole('button', { name: /Browse course library/i }); // Only present when not resuming an in-progress round; guard so the test @@ -136,7 +136,7 @@ test.describe('Cloud Course Library — authenticated flow', () => { test('capture: premium course picker screenshots', async ({ page }) => { const dir = 'e2e-screenshots'; - await page.goto('/golf/dashboard/rounds/new'); + await page.goto('/golf/dashboard/rounds/create'); const browse = page.getByRole('button', { name: /Browse course library/i }); await browse.waitFor({ state: 'visible', timeout: 10000 }).catch(() => {}); if (!(await browse.isVisible().catch(() => false))) { diff --git a/e2e/golf-dashboard.spec.ts b/e2e/golf-dashboard.spec.ts index 9bb32c601..aa31231a2 100644 --- a/e2e/golf-dashboard.spec.ts +++ b/e2e/golf-dashboard.spec.ts @@ -45,7 +45,7 @@ test.describe('Golf Dashboard - Player Flow', () => { test('should access new round page and see all steps', async ({ page }) => { // Navigate to new round page - await page.goto('http://localhost:3000/golf/dashboard/rounds/new'); + await page.goto('http://localhost:3000/golf/dashboard/rounds/create'); // Step 1: Setup - Should see course setup form await expect(page.locator('h1')).toContainText('New Round'); @@ -114,7 +114,7 @@ test.describe('Golf Dashboard - Player Flow', () => { test('should verify emerald color scheme throughout', async ({ page }) => { // Go to new round page - await page.goto('http://localhost:3000/golf/dashboard/rounds/new'); + await page.goto('http://localhost:3000/golf/dashboard/rounds/create'); // Check for emerald focus rings on inputs const courseNameInput = page.locator('#courseName'); diff --git a/e2e/golf-round.spec.ts b/e2e/golf-round.spec.ts index d3b148ed7..1b722b11e 100644 --- a/e2e/golf-round.spec.ts +++ b/e2e/golf-round.spec.ts @@ -26,7 +26,7 @@ test.describe('Golf Round - Complete Flow', () => { test('should complete a full round entry', async ({ page }) => { // Navigate to new round page - await page.goto('http://localhost:3000/golf/dashboard/rounds/new'); + await page.goto('http://localhost:3000/golf/dashboard/rounds/create'); // Step 1: Course Setup await page.fill('#courseName', 'E2E Test Course'); @@ -57,7 +57,7 @@ test.describe('Golf Round - Complete Flow', () => { test('should show validation errors for invalid input', async ({ page }) => { // Navigate to new round page - await page.goto('http://localhost:3000/golf/dashboard/rounds/new'); + await page.goto('http://localhost:3000/golf/dashboard/rounds/create'); // Try to proceed without filling course name const nextButton = page.locator('button:has-text("Next: Configure Holes")'); @@ -72,7 +72,7 @@ test.describe('Golf Round - Complete Flow', () => { test('should save round in progress', async ({ page }) => { // Navigate to new round page - await page.goto('http://localhost:3000/golf/dashboard/rounds/new'); + await page.goto('http://localhost:3000/golf/dashboard/rounds/create'); // Setup course await page.fill('#courseName', 'Progress Test Course'); @@ -113,7 +113,7 @@ test.describe('Golf Round - Complete Flow', () => { test('should handle network errors gracefully', async ({ page }) => { // Navigate to new round page - await page.goto('http://localhost:3000/golf/dashboard/rounds/new'); + await page.goto('http://localhost:3000/golf/dashboard/rounds/create'); // Setup course await page.fill('#courseName', 'Network Error Test'); diff --git a/e2e/route-crawler/route-crawler.spec.ts b/e2e/route-crawler/route-crawler.spec.ts index 309f8d9b1..a167c98ad 100644 --- a/e2e/route-crawler/route-crawler.spec.ts +++ b/e2e/route-crawler/route-crawler.spec.ts @@ -56,9 +56,13 @@ async function crawlPage( page.on('pageerror', (err) => consoleErrors.push(err.message)); page.on('requestfailed', (req) => { const url = req.url(); - if (!url.includes('_next') && !url.includes('favicon')) { - failedRequests.push(`${req.failure()?.errorText ?? 'failed'} ${url}`); + if (url.includes('_next') || url.includes('favicon') || url.includes('sentry.io')) { + return; } + const errText = req.failure()?.errorText ?? 'failed'; + // Benign during client/server redirects — the navigation aborts in-flight beacons. + if (errText.includes('ERR_ABORTED')) return; + failedRequests.push(`${errText} ${url}`); }); const response = await page.goto(targetPath, { waitUntil: 'domcontentloaded', timeout: 30_000 }); diff --git a/memory/context/golfhelm-features.md b/memory/context/golfhelm-features.md index 9ae7feff3..d28dc78b7 100644 --- a/memory/context/golfhelm-features.md +++ b/memory/context/golfhelm-features.md @@ -65,7 +65,7 @@ Players create rounds with shot-by-shot tracking. Rounds populate stats, trigger ### Data Flow ``` -/golf/dashboard/rounds/new → NewRoundClient (4-step wizard) +/golf/dashboard/rounds/create → NewRoundClient (4-step wizard) Step 1: Setup (course, type, qualifier selection, saved courses) Step 2: Hole config (par/yardage per hole, or skip if saved course) Step 3: Shot tracking (ShotTrackingComprehensive component) @@ -91,12 +91,12 @@ Players create rounds with shot-by-shot tracking. Rounds populate stats, trigger ### Key Files | Type | Path | |------|------| -| Route (new) | `src/app/golf/(dashboard)/dashboard/rounds/new/page.tsx` | +| Route (new) | `src/app/golf/(dashboard)/dashboard/rounds/create/page.tsx` | | Route (list) | `src/app/golf/(dashboard)/dashboard/rounds/page.tsx` | | Route (detail) | `src/app/golf/(dashboard)/dashboard/rounds/[id]/page.tsx` | | Route (review) | `src/app/golf/(dashboard)/dashboard/rounds/[id]/review/page.tsx` | | Route (continue) | `src/app/golf/(dashboard)/dashboard/rounds/continue/[id]/page.tsx` | -| Client wizard | `src/app/golf/(dashboard)/dashboard/rounds/new/new-round-client.tsx` | +| Client wizard | `src/app/golf/(dashboard)/dashboard/rounds/create/new-round-client.tsx` | | Shot tracking | `src/components/golf/ShotTrackingComprehensive.tsx` | | Actions | `src/app/golf/actions/golf.ts` (submit, save, delete) | | Drafts | `src/app/golf/actions/round-drafts.ts` | @@ -206,7 +206,7 @@ Display: getQualifierLeaderboard() → positions, ties, totals |------|------| | Route (list) | `src/app/golf/(dashboard)/dashboard/qualifiers/page.tsx` | | Route (detail) | `src/app/golf/(dashboard)/dashboard/qualifiers/[id]/page.tsx` | -| Route (new) | `src/app/golf/(dashboard)/dashboard/qualifiers/new/page.tsx` | +| Route (new) | `src/app/golf/(dashboard)/dashboard/qualifiers/create/page.tsx` | | Actions | `src/app/golf/actions/golf.ts` (qualifier functions) | | Components | `src/components/golf/qualifiers/` | | Hook | `src/hooks/golf/use-qualifier-realtime.ts` | @@ -915,7 +915,7 @@ Player view of qualifying tournaments they're entered in. Shows progress, scores → Progress: rounds completed / total rounds → Score and to-par display → Status badges: Upcoming (slate), In Progress (amber), Complete (green), Ended (slate) - → Action: "Enter Round" button for in-progress qualifiers → rounds/new + → Action: "Enter Round" button for in-progress qualifiers → rounds/create → Link to full leaderboard → qualifiers/[id] ``` diff --git a/memory/features/golf-round-lifecycle.md b/memory/features/golf-round-lifecycle.md index e45d8c90e..2efd22961 100644 --- a/memory/features/golf-round-lifecycle.md +++ b/memory/features/golf-round-lifecycle.md @@ -15,11 +15,11 @@ This is one of the highest-risk product areas because a broken write path can lo ### Routes - `src/app/golf/(dashboard)/dashboard/rounds/page.tsx` -- `src/app/golf/(dashboard)/dashboard/rounds/new/**` +- `src/app/golf/(dashboard)/dashboard/rounds/create/**` - `src/app/golf/(dashboard)/dashboard/rounds/continue/[id]/**` - `src/app/golf/(dashboard)/dashboard/rounds/[id]/**` - `src/app/golf/(dashboard)/dashboard/rounds/[id]/review/**` -- `src/app/golf/(dashboard)/dashboard/rounds/recover/**` +- `src/app/golf/(dashboard)/dashboard/rounds/recover-draft-draft/**` ### Actions diff --git a/memory/features/qualifiers.md b/memory/features/qualifiers.md index 8447b9b19..5936689f6 100644 --- a/memory/features/qualifiers.md +++ b/memory/features/qualifiers.md @@ -19,7 +19,7 @@ There are three user surfaces: ### Routes - `src/app/golf/(dashboard)/dashboard/qualifiers/page.tsx` -- `src/app/golf/(dashboard)/dashboard/qualifiers/new/page.tsx` +- `src/app/golf/(dashboard)/dashboard/qualifiers/create/page.tsx` - `src/app/golf/(dashboard)/dashboard/qualifiers/[id]/page.tsx` - `src/app/golf/(dashboard)/dashboard/my-qualifiers/page.tsx` - `src/app/golf/(dashboard)/dashboard/coachhelm/qualifying/**` @@ -56,7 +56,7 @@ Coach creates qualifier -> INSERT golf_qualifier_entries Player enters a qualifier round - -> rounds/new with qualifier context + -> rounds/create with qualifier context -> submitGolfRoundComprehensive() -> WRITE golf_rounds.qualifier_id -> WRITE golf_holes and golf_shots diff --git a/memory/features/shot-tracking.md b/memory/features/shot-tracking.md index 928bc3d84..c62007c08 100644 --- a/memory/features/shot-tracking.md +++ b/memory/features/shot-tracking.md @@ -14,14 +14,14 @@ The current round flow uses a wizard for setup, hole configuration, shot capture ### Routes -- `src/app/golf/(dashboard)/dashboard/rounds/new/**` +- `src/app/golf/(dashboard)/dashboard/rounds/create/**` - `src/app/golf/(dashboard)/dashboard/rounds/continue/[id]/**` -- `src/app/golf/(dashboard)/dashboard/rounds/recover/**` +- `src/app/golf/(dashboard)/dashboard/rounds/recover-draft-draft/**` ### Components - `src/components/golf/ShotTrackingComprehensive.tsx` -- `src/app/golf/(dashboard)/dashboard/rounds/new/new-round-client.tsx` +- `src/app/golf/(dashboard)/dashboard/rounds/create/new-round-client.tsx` - `src/app/golf/(dashboard)/dashboard/rounds/continue/[id]/continue-round-client.tsx` - `src/components/golf/rounds/**` diff --git a/memory/projects/golfhelm.md b/memory/projects/golfhelm.md index 79f2d7046..260477a56 100644 --- a/memory/projects/golfhelm.md +++ b/memory/projects/golfhelm.md @@ -59,7 +59,7 @@ | `/golf/dashboard/analytics/coachhelm` | CoachHelm analytics | | `/golf/dashboard/settings/coaching-intelligence` | AI philosophy config | | `/golf/dashboard/development` | Player development plans (focus areas) | -| `/golf/dashboard/qualifiers/new` | Create qualifier | +| `/golf/dashboard/qualifiers/create` | Create qualifier | | `/golf/dashboard/stats/team` | Team-level analytics | ### Player-Only Routes @@ -70,7 +70,7 @@ | `/golf/dashboard/my-development` | My development focus areas | | `/golf/dashboard/my-qualifiers` | My qualifier progress | | `/golf/dashboard/my-insights` | → Redirects to `/dashboard/coachhelm` | -| `/golf/dashboard/rounds/new` | Create new round | +| `/golf/dashboard/rounds/create` | Create new round | | `/golf/dashboard/rounds/continue/[id]` | Resume in-progress round | | `/golf/dashboard/rounds/[id]/review` | AI round review | | `/golf/dashboard/classes` | Class schedule management | @@ -314,7 +314,7 @@ src/lib/coachhelm/ - `/baseball/dashboard/stats` - `/baseball/dashboard/stats/games` - `/baseball/dashboard/stats/games/[gameId]` -- `/baseball/dashboard/stats/games/new` +- `/baseball/dashboard/stats/games/create` - `/baseball/dashboard/stats/season` - `/baseball/dashboard/stats/upload` - `/baseball/dashboard/tasks` @@ -358,7 +358,7 @@ src/lib/coachhelm/ - `/golf/dashboard/coachhelm` - `/golf/dashboard/coachhelm/chat` - `/golf/dashboard/coachhelm/genome/[playerId]` -- `/golf/dashboard/coachhelm/genome/compare` +- `/golf/dashboard/coachhelm/genome/compare-players-players-players` - `/golf/dashboard/coachhelm/qualifying/[id]` - `/golf/dashboard/courses` - `/golf/dashboard/development` @@ -378,7 +378,7 @@ src/lib/coachhelm/ - `/golf/dashboard/players/[playerId]/game/print` - `/golf/dashboard/qualifiers` - `/golf/dashboard/qualifiers/[id]` -- `/golf/dashboard/qualifiers/new` +- `/golf/dashboard/qualifiers/create` - `/golf/dashboard/recruiting` - `/golf/dashboard/roster` - `/golf/dashboard/roster/[id]` @@ -386,8 +386,8 @@ src/lib/coachhelm/ - `/golf/dashboard/rounds/[id]` - `/golf/dashboard/rounds/[id]/review` - `/golf/dashboard/rounds/continue/[id]` -- `/golf/dashboard/rounds/new` -- `/golf/dashboard/rounds/recover` +- `/golf/dashboard/rounds/create` +- `/golf/dashboard/rounds/recover-draft-draft` - `/golf/dashboard/settings` - `/golf/dashboard/settings/coaching-intelligence` - `/golf/dashboard/settings/notifications` diff --git a/memory/registry.yml b/memory/registry.yml index ff1d1b4bc..2c2db62ad 100644 --- a/memory/registry.yml +++ b/memory/registry.yml @@ -259,9 +259,9 @@ features: - docs/ROUND_REVIEW_ACCURACY_REPORT.md code: routes: - - src/app/golf/(dashboard)/dashboard/rounds/new/** + - src/app/golf/(dashboard)/dashboard/rounds/create/** - src/app/golf/(dashboard)/dashboard/rounds/continue/** - - src/app/golf/(dashboard)/dashboard/rounds/recover/** + - src/app/golf/(dashboard)/dashboard/rounds/recover-draft-draft/** components: - src/components/golf/ShotTrackingComprehensive.tsx - src/components/golf/rounds/** diff --git a/next.config.mjs b/next.config.mjs index f8ac1a67a..6fd525b7f 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -113,9 +113,43 @@ const nextConfig = { // The previous custom config forced ALL node_modules into a single ~3MB // "vendor" chunk, causing render-blocking on mobile devices. - // Redirects (if needed) + // Permanent redirects for renamed routes (bookmarks, external links, SEO) async redirects() { - return []; + return [ + { + source: '/golf/dashboard/rounds/new', + destination: '/golf/dashboard/rounds/create', + permanent: true, + }, + { + source: '/golf/dashboard/rounds/recover', + destination: '/golf/dashboard/rounds/recover-draft', + permanent: true, + }, + { + source: '/golf/dashboard/qualifiers/new', + destination: '/golf/dashboard/qualifiers/create', + permanent: true, + }, + { + source: '/baseball/dashboard/stats/games/new', + destination: '/baseball/dashboard/stats/games/create', + permanent: true, + }, + { + source: '/golf/dashboard/coachhelm/genome/compare', + destination: '/golf/dashboard/coachhelm/genome/compare-players', + permanent: true, + }, + // Public player profile moved from /player/[id] → /profile/[id] + // UUID constraint avoids catching /baseball/player/today, /passport, etc. + { + source: + '/baseball/player/:id([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})', + destination: '/baseball/profile/:id', + permanent: true, + }, + ]; }, // Headers for caching and security diff --git a/scripts/__tests__/cmd-k-coverage.test.mjs b/scripts/__tests__/cmd-k-coverage.test.mjs index 66f4577fb..a68ef4708 100644 --- a/scripts/__tests__/cmd-k-coverage.test.mjs +++ b/scripts/__tests__/cmd-k-coverage.test.mjs @@ -81,11 +81,11 @@ const ALLOWLIST = new Map([ // Sub-action / utility pages reached from a parent that IS in the manifest. [ - '/golf/dashboard/qualifiers/new', + '/golf/dashboard/qualifiers/create', 'create-qualifier sub-action; reached from the Qualifiers list', ], [ - '/golf/dashboard/rounds/recover', + '/golf/dashboard/rounds/recover-draft-draft', 'round-recovery utility; reached from My Rounds', ], @@ -95,7 +95,7 @@ const ALLOWLIST = new Map([ // from the Qualifiers list and Genome Compare static entries respectively.) [ '/golf/dashboard/coachhelm/genome/[playerId]', - 'dynamic — needs playerId; static landing is genome/compare (in manifest)', + 'dynamic — needs playerId; static landing is genome/compare-players-players (in manifest)', ], [ '/golf/dashboard/coachhelm/qualifying/[id]', @@ -258,7 +258,7 @@ test('every W4B route the audit called out is in the Cmd+K manifest', async () = '/golf/dashboard/intelligence', '/golf/dashboard/analytics/coachhelm', '/golf/dashboard/coachhelm/chat', - '/golf/dashboard/coachhelm/genome/compare', + '/golf/dashboard/coachhelm/genome/compare-players-players-players', '/golf/dashboard/settings/notifications', '/golf/dashboard/settings/coaching-intelligence', '/golf/dashboard/stats/team', diff --git a/scripts/__tests__/coachhelm-hub.test.mjs b/scripts/__tests__/coachhelm-hub.test.mjs index 9080f17b8..7ca802ffd 100644 --- a/scripts/__tests__/coachhelm-hub.test.mjs +++ b/scripts/__tests__/coachhelm-hub.test.mjs @@ -47,7 +47,7 @@ const SURFACES = [ { name: 'insights', href: '/golf/dashboard/insights' }, { name: 'analytics/coachhelm', href: '/golf/dashboard/analytics/coachhelm' }, { name: 'chat', href: '/golf/dashboard/coachhelm/chat' }, - { name: 'genome', href: '/golf/dashboard/coachhelm/genome/compare' }, + { name: 'genome', href: '/golf/dashboard/coachhelm/genome/compare-players-players-players' }, { name: 'qualifying', href: '/golf/dashboard/qualifiers' }, { name: 'coaching-intelligence', href: '/golf/dashboard/settings/coaching-intelligence' }, ]; diff --git a/scripts/__tests__/emptystate-vocab.test.mjs b/scripts/__tests__/emptystate-vocab.test.mjs index 45ce0202c..36142a574 100644 --- a/scripts/__tests__/emptystate-vocab.test.mjs +++ b/scripts/__tests__/emptystate-vocab.test.mjs @@ -120,8 +120,8 @@ test('intentionally action-less configs (search, camps) stay action-less', () => // Lock the exact hrefs that drive navigation CTAs so a copy edit can never // silently re-point or drop them. const REQUIRED_HREFS = { - rounds: '/golf/dashboard/rounds/new', - stats: '/golf/dashboard/rounds/new', + rounds: '/golf/dashboard/rounds/create', + stats: '/golf/dashboard/rounds/create', watchlist: '/baseball/dashboard/discover', pipeline: '/baseball/dashboard/discover', }; diff --git a/scripts/__tests__/genome-fluid.test.mjs b/scripts/__tests__/genome-fluid.test.mjs index 138462dce..512e745de 100644 --- a/scripts/__tests__/genome-fluid.test.mjs +++ b/scripts/__tests__/genome-fluid.test.mjs @@ -42,7 +42,7 @@ const CONSUMER_FILES = [ ), join( REPO_ROOT, - 'src/app/golf/(dashboard)/dashboard/coachhelm/genome/compare/page.tsx', + 'src/app/golf/(dashboard)/dashboard/coachhelm/genome/compare-players-players-players/page.tsx', ), join( REPO_ROOT, diff --git a/scripts/route-hygiene/check-route-coverage.mjs b/scripts/route-hygiene/check-route-coverage.mjs index c12e14c5e..82beee4da 100644 --- a/scripts/route-hygiene/check-route-coverage.mjs +++ b/scripts/route-hygiene/check-route-coverage.mjs @@ -13,7 +13,7 @@ const CRITICAL_ROUTES = [ '/golf/dashboard', '/golf/dashboard/stats', '/golf/dashboard/rounds', - '/golf/dashboard/rounds/new', + '/golf/dashboard/rounds/create', '/golf/dashboard/coachhelm', '/golf/dashboard/coachhelm/chat', '/golf/dashboard/roster', diff --git a/scripts/ui-intelligence/normalize-devin-routes.ts b/scripts/ui-intelligence/normalize-devin-routes.ts index 1ac9c871c..1c81fd0af 100644 --- a/scripts/ui-intelligence/normalize-devin-routes.ts +++ b/scripts/ui-intelligence/normalize-devin-routes.ts @@ -202,9 +202,9 @@ const TABLE: TableRow[] = [ { route: '/golf/dashboard/analytics/coachhelm', role: 'coach', category: 'analytics', criticality: 'medium' }, { route: '/golf/dashboard/settings/coaching-intelligence', role: 'coach', category: 'settings', criticality: 'medium' }, { route: '/golf/dashboard/development', role: 'coach', category: 'coachhelm', criticality: 'high' }, - { route: '/golf/dashboard/qualifiers/new', role: 'coach', category: 'qualifiers', criticality: 'medium' }, + { route: '/golf/dashboard/qualifiers/create', role: 'coach', category: 'qualifiers', criticality: 'medium' }, { route: '/golf/dashboard/stats/team', role: 'coach', category: 'stats', criticality: 'high' }, - { route: '/golf/dashboard/coachhelm/genome/compare', role: 'coach', category: 'coachhelm', criticality: 'medium' }, + { route: '/golf/dashboard/coachhelm/genome/compare-players-players-players', role: 'coach', category: 'coachhelm', criticality: 'medium' }, { route: '/golf/dashboard/recruiting', role: 'coach', @@ -231,8 +231,8 @@ const TABLE: TableRow[] = [ { route: '/golf/dashboard/my-game-profile', role: 'player', category: 'player', criticality: 'medium' }, { route: '/golf/dashboard/my-standing', role: 'player', category: 'player', criticality: 'medium' }, { route: '/golf/dashboard/classes', role: 'player', category: 'player', criticality: 'low' }, - { route: '/golf/dashboard/rounds/new', role: 'player', category: 'rounds', criticality: 'high' }, - { route: '/golf/dashboard/rounds/recover', role: 'player', category: 'rounds', criticality: 'low' }, + { route: '/golf/dashboard/rounds/create', role: 'player', category: 'rounds', criticality: 'high' }, + { route: '/golf/dashboard/rounds/recover-draft-draft', role: 'player', category: 'rounds', criticality: 'low' }, // --- SHARED — emit BOTH coach + player. auth true, enabled true --- { route: '/golf/dashboard', label: 'Dashboard', role: 'shared', category: 'core', criticality: 'high' }, diff --git a/src/app/baseball/(dashboard)/dashboard/stats/games/new/NewGameClient.tsx b/src/app/baseball/(dashboard)/dashboard/stats/games/create/NewGameClient.tsx similarity index 100% rename from src/app/baseball/(dashboard)/dashboard/stats/games/new/NewGameClient.tsx rename to src/app/baseball/(dashboard)/dashboard/stats/games/create/NewGameClient.tsx diff --git a/src/app/baseball/(dashboard)/dashboard/stats/games/new/error.tsx b/src/app/baseball/(dashboard)/dashboard/stats/games/create/error.tsx similarity index 90% rename from src/app/baseball/(dashboard)/dashboard/stats/games/new/error.tsx rename to src/app/baseball/(dashboard)/dashboard/stats/games/create/error.tsx index bf34a76dc..13b2a528f 100644 --- a/src/app/baseball/(dashboard)/dashboard/stats/games/new/error.tsx +++ b/src/app/baseball/(dashboard)/dashboard/stats/games/create/error.tsx @@ -13,7 +13,7 @@ export default function NewGameError({ diff --git a/src/app/golf/(dashboard)/FairwayDashboardShell.tsx b/src/app/golf/(dashboard)/FairwayDashboardShell.tsx index f8fca07a2..c75c6f8db 100644 --- a/src/app/golf/(dashboard)/FairwayDashboardShell.tsx +++ b/src/app/golf/(dashboard)/FairwayDashboardShell.tsx @@ -649,7 +649,7 @@ function FairwayDashboardContent({ // top bar must not compete with the round controls. The page brings its own // `.fairway-ds` scope + bg; we only stick its control header below the notch. const isImmersive = - pathname === '/golf/dashboard/rounds/new' || pathname.startsWith('/golf/dashboard/rounds/continue'); + pathname === '/golf/dashboard/rounds/create' || pathname.startsWith('/golf/dashboard/rounds/continue'); // Immersive routes render no drawer; if the bridged drawer state is somehow // open, force it closed so SidebarProvider's body-scroll-lock can't soft-lock diff --git a/src/app/golf/(dashboard)/dashboard/coachhelm/components/PlayerCoachHelmDashboard.tsx b/src/app/golf/(dashboard)/dashboard/coachhelm/components/PlayerCoachHelmDashboard.tsx index 3de7c1ffb..4adb2e286 100644 --- a/src/app/golf/(dashboard)/dashboard/coachhelm/components/PlayerCoachHelmDashboard.tsx +++ b/src/app/golf/(dashboard)/dashboard/coachhelm/components/PlayerCoachHelmDashboard.tsx @@ -105,7 +105,7 @@ function EmptyState() { description="Complete a few rounds to unlock AI-powered insights about your game. CoachHelm analyzes your performance patterns to provide personalized recommendations." action={{ label: 'Log Your First Round', - href: '/golf/dashboard/rounds/new', + href: '/golf/dashboard/rounds/create', }} /> ); diff --git a/src/app/golf/(dashboard)/dashboard/coachhelm/genome/[playerId]/page.tsx b/src/app/golf/(dashboard)/dashboard/coachhelm/genome/[playerId]/page.tsx index de0552066..56ed007f5 100644 --- a/src/app/golf/(dashboard)/dashboard/coachhelm/genome/[playerId]/page.tsx +++ b/src/app/golf/(dashboard)/dashboard/coachhelm/genome/[playerId]/page.tsx @@ -163,7 +163,7 @@ export default async function CoachGenomePage({ params }: PageProps) {
Compare diff --git a/src/app/golf/(dashboard)/dashboard/coachhelm/genome/compare/error.tsx b/src/app/golf/(dashboard)/dashboard/coachhelm/genome/compare-players/error.tsx similarity index 88% rename from src/app/golf/(dashboard)/dashboard/coachhelm/genome/compare/error.tsx rename to src/app/golf/(dashboard)/dashboard/coachhelm/genome/compare-players/error.tsx index ceb29f4ee..a02b739de 100644 --- a/src/app/golf/(dashboard)/dashboard/coachhelm/genome/compare/error.tsx +++ b/src/app/golf/(dashboard)/dashboard/coachhelm/genome/compare-players/error.tsx @@ -13,7 +13,7 @@ export default function Error({ { e.preventDefault(); e.stopPropagation(); - router.push(`/golf/dashboard/rounds/new?qualifier=${qualifier.id}`); + router.push(`/golf/dashboard/rounds/create?qualifier=${qualifier.id}`); }} className="px-3 py-1.5 text-sm font-medium rounded-lg bg-primary-600 text-white hover:bg-primary-700 transition-colors" > diff --git a/src/app/golf/(dashboard)/dashboard/qualifiers/[id]/page.tsx b/src/app/golf/(dashboard)/dashboard/qualifiers/[id]/page.tsx index 5ddc5db04..8aaf2d99f 100644 --- a/src/app/golf/(dashboard)/dashboard/qualifiers/[id]/page.tsx +++ b/src/app/golf/(dashboard)/dashboard/qualifiers/[id]/page.tsx @@ -323,7 +323,7 @@ export default async function QualifierDetailPage({ params }: PageProps) { {canPlayRound && (
diff --git a/src/app/golf/(dashboard)/dashboard/qualifiers/new/error.tsx b/src/app/golf/(dashboard)/dashboard/qualifiers/create/error.tsx similarity index 90% rename from src/app/golf/(dashboard)/dashboard/qualifiers/new/error.tsx rename to src/app/golf/(dashboard)/dashboard/qualifiers/create/error.tsx index 1b3a75cfc..3329dbe5a 100644 --- a/src/app/golf/(dashboard)/dashboard/qualifiers/new/error.tsx +++ b/src/app/golf/(dashboard)/dashboard/qualifiers/create/error.tsx @@ -13,7 +13,7 @@ export default function Error({ { - router.push('/golf/dashboard/rounds/recover?from=submit'); + router.push('/golf/dashboard/rounds/recover-draft?from=submit'); }); return; } diff --git a/src/app/golf/(dashboard)/dashboard/rounds/new/error.tsx b/src/app/golf/(dashboard)/dashboard/rounds/create/error.tsx similarity index 91% rename from src/app/golf/(dashboard)/dashboard/rounds/new/error.tsx rename to src/app/golf/(dashboard)/dashboard/rounds/create/error.tsx index 95634a3d7..9d7906782 100644 --- a/src/app/golf/(dashboard)/dashboard/rounds/new/error.tsx +++ b/src/app/golf/(dashboard)/dashboard/rounds/create/error.tsx @@ -13,7 +13,7 @@ export default function Error({ { - router.push('/golf/dashboard/rounds/recover?from=submit'); + router.push('/golf/dashboard/rounds/recover-draft?from=submit'); }); return; } diff --git a/src/app/golf/(dashboard)/dashboard/rounds/new/page.tsx b/src/app/golf/(dashboard)/dashboard/rounds/create/page.tsx similarity index 100% rename from src/app/golf/(dashboard)/dashboard/rounds/new/page.tsx rename to src/app/golf/(dashboard)/dashboard/rounds/create/page.tsx diff --git a/src/app/golf/(dashboard)/dashboard/rounds/page.tsx b/src/app/golf/(dashboard)/dashboard/rounds/page.tsx index 120283b6f..a48f7303f 100644 --- a/src/app/golf/(dashboard)/dashboard/rounds/page.tsx +++ b/src/app/golf/(dashboard)/dashboard/rounds/page.tsx @@ -233,7 +233,7 @@ export default async function RoundsPage() { subtitle={`${rounds.length} round${rounds.length !== 1 ? 's' : ''} recorded`} > {userRole === 'player' && ( - + } /> diff --git a/src/components/fairway/pages/coachhelm/FairwayStatsCockpit.tsx b/src/components/fairway/pages/coachhelm/FairwayStatsCockpit.tsx index 06728c61f..6f74f1d38 100644 --- a/src/components/fairway/pages/coachhelm/FairwayStatsCockpit.tsx +++ b/src/components/fairway/pages/coachhelm/FairwayStatsCockpit.tsx @@ -726,7 +726,7 @@ export function FairwayStatsCockpit({ playerId, className, isOwnStats = false }: action={ isOwnStats ? ( ) : undefined } diff --git a/src/components/fairway/pages/coachhelm/GenomeCompareView.tsx b/src/components/fairway/pages/coachhelm/GenomeCompareView.tsx index 0a7ec2762..237234173 100644 --- a/src/components/fairway/pages/coachhelm/GenomeCompareView.tsx +++ b/src/components/fairway/pages/coachhelm/GenomeCompareView.tsx @@ -56,7 +56,7 @@ import { IconCheck } from '@/components/icons'; import { Users as LucideUsers } from 'lucide-react'; /* --------------------------------------------------------------------------- - * Props — mirror the genome/compare route's reads (serializable) + * Props — mirror the genome/compare-players route's reads (serializable) * ------------------------------------------------------------------------- */ export interface ComparePlayerOption { @@ -388,7 +388,7 @@ function ComparePicker({ const params = new URLSearchParams(); params.set(paramName, id); if (otherParamValue) params.set(otherParam, otherParamValue); - return `/golf/dashboard/coachhelm/genome/compare?${params.toString()}`; + return `/golf/dashboard/coachhelm/genome/compare-players?${params.toString()}`; } return ( diff --git a/src/components/fairway/pages/coachhelm/GenomeDetailView.tsx b/src/components/fairway/pages/coachhelm/GenomeDetailView.tsx index fcbdda1bb..d49263943 100644 --- a/src/components/fairway/pages/coachhelm/GenomeDetailView.tsx +++ b/src/components/fairway/pages/coachhelm/GenomeDetailView.tsx @@ -297,7 +297,7 @@ export function GenomeDetailView({ leftIcon={} asChild > - Compare + Compare ) : null}
diff --git a/src/components/fairway/pages/dashboard/FairwayPlayerDashboard.tsx b/src/components/fairway/pages/dashboard/FairwayPlayerDashboard.tsx index eed4b6613..48f1b22b2 100644 --- a/src/components/fairway/pages/dashboard/FairwayPlayerDashboard.tsx +++ b/src/components/fairway/pages/dashboard/FairwayPlayerDashboard.tsx @@ -251,7 +251,7 @@ export function FairwayPlayerDashboard({ data, enhancedData }: FairwayPlayerDash const newRoundCta = ( ); @@ -299,7 +299,7 @@ export function FairwayPlayerDashboard({ data, enhancedData }: FairwayPlayerDash icon={} actions={ } > @@ -503,7 +503,7 @@ export function FairwayPlayerDashboard({ data, enhancedData }: FairwayPlayerDash description="Your logged rounds will show up here." action={ } /> diff --git a/src/components/fairway/pages/my-qualifiers/FairwayMyQualifiers.tsx b/src/components/fairway/pages/my-qualifiers/FairwayMyQualifiers.tsx index cc5580549..88e2ea65c 100644 --- a/src/components/fairway/pages/my-qualifiers/FairwayMyQualifiers.tsx +++ b/src/components/fairway/pages/my-qualifiers/FairwayMyQualifiers.tsx @@ -23,7 +23,7 @@ * • Concluded section shows an honest subtle EmptyState; never a fabricated * past qualifier. * - * The "Start qualifying round" CTA deep-links to rounds/new?qualifier= — the + * The "Start qualifying round" CTA deep-links to rounds/create?qualifier= — the * already-wired entry path that auto-selects the qualifier + sets round_type. * * Tokens ONLY: bg-canvas, text-text-*, font-fw-display/sans/mono, rounded-card, @@ -47,7 +47,7 @@ import { IconCalendar, IconMapPin, IconArrowRight, IconGolf } from '@/components import type { PlayerQualifierInfo } from '@/app/golf/actions/golf'; const detailHref = (id: string) => `/golf/dashboard/qualifiers/${id}`; -const startRoundHref = (id: string) => `/golf/dashboard/rounds/new?qualifier=${id}`; +const startRoundHref = (id: string) => `/golf/dashboard/rounds/create?qualifier=${id}`; export interface FairwayMyQualifiersProps { qualifiers: PlayerQualifierInfo[]; diff --git a/src/components/fairway/pages/player-game/FairwayMyGameProfile.tsx b/src/components/fairway/pages/player-game/FairwayMyGameProfile.tsx index 3d35b181d..b52b21d68 100644 --- a/src/components/fairway/pages/player-game/FairwayMyGameProfile.tsx +++ b/src/components/fairway/pages/player-game/FairwayMyGameProfile.tsx @@ -250,7 +250,7 @@ export function FairwayMyGameProfile({ shape automatically.

diff --git a/src/components/fairway/pages/qualifiers/FairwayNewQualifier.tsx b/src/components/fairway/pages/qualifiers/FairwayNewQualifier.tsx index bf833ea82..05259b6d8 100644 --- a/src/components/fairway/pages/qualifiers/FairwayNewQualifier.tsx +++ b/src/components/fairway/pages/qualifiers/FairwayNewQualifier.tsx @@ -4,7 +4,7 @@ * ============================================================================ * Fairway · Qualifiers · FairwayNewQualifier (ADDITIVE · FLAG-GATED) * ---------------------------------------------------------------------------- - * The flag-on redesign of the COACH /golf/dashboard/qualifiers/new route — the + * The flag-on redesign of the COACH /golf/dashboard/qualifiers/create route — the * create-qualifier form. A presentation rebuild on the Fairway form primitives; * the create logic is reused VERBATIM via `createGolfQualifier` (same import * path, same input contract). diff --git a/src/components/fairway/pages/qualifiers/FairwayQualifierDetail.tsx b/src/components/fairway/pages/qualifiers/FairwayQualifierDetail.tsx index 7804ed6f8..659150b0a 100644 --- a/src/components/fairway/pages/qualifiers/FairwayQualifierDetail.tsx +++ b/src/components/fairway/pages/qualifiers/FairwayQualifierDetail.tsx @@ -196,7 +196,7 @@ export function FairwayQualifierDetail(props: FairwayQualifierDetailProps) { if (isPlayer && canPlayRound) { primaryAction = ( diff --git a/src/components/fairway/pages/qualifiers/FairwayQualifiers.tsx b/src/components/fairway/pages/qualifiers/FairwayQualifiers.tsx index dd6b13c51..af29e4a00 100644 --- a/src/components/fairway/pages/qualifiers/FairwayQualifiers.tsx +++ b/src/components/fairway/pages/qualifiers/FairwayQualifiers.tsx @@ -53,7 +53,7 @@ import { import { IconCalendar, IconMapPin, IconGolf, IconArrowRight, IconPlus } from '@/components/icons'; import type { GolfQualifier } from '@/lib/types/golf'; -const CREATE_HREF = '/golf/dashboard/qualifiers/new'; +const CREATE_HREF = '/golf/dashboard/qualifiers/create'; const detailHref = (id: string) => `/golf/dashboard/qualifiers/${id}`; /** Status segments for the filter row. */ diff --git a/src/components/fairway/pages/rounds-recover/FairwayRecoverRound.tsx b/src/components/fairway/pages/rounds-recover/FairwayRecoverRound.tsx index 69f878205..4e7840577 100644 --- a/src/components/fairway/pages/rounds-recover/FairwayRecoverRound.tsx +++ b/src/components/fairway/pages/rounds-recover/FairwayRecoverRound.tsx @@ -4,7 +4,7 @@ * ============================================================================ * Fairway · pages/rounds-recover · FairwayRecoverRound (ADDITIVE · FLAG-GATED) * ---------------------------------------------------------------------------- - * The flag-on redesign of the PLAYER /golf/dashboard/rounds/recover route — the + * The flag-on redesign of the PLAYER /golf/dashboard/rounds/recover-draft route — the * incomplete-round recovery flow. A self-contained client (mirroring the legacy * RecoverRoundClient shape) that scans the SAME offline storage — modern + legacy * IndexedDB plus localStorage emergency saves — and re-submits a recoverable diff --git a/src/components/fairway/pages/rounds/FairwayRoundsLibrary.tsx b/src/components/fairway/pages/rounds/FairwayRoundsLibrary.tsx index a61491d72..0d4033502 100644 --- a/src/components/fairway/pages/rounds/FairwayRoundsLibrary.tsx +++ b/src/components/fairway/pages/rounds/FairwayRoundsLibrary.tsx @@ -344,7 +344,7 @@ export function FairwayRoundsLibrary({ const primaryAction = !isCoach ? ( ) : undefined; @@ -479,7 +479,7 @@ export function FairwayRoundsLibrary({ action={ !isCoach ? ( ) : undefined } diff --git a/src/components/fairway/pages/rounds/FairwayUnsyncedRoundBanner.tsx b/src/components/fairway/pages/rounds/FairwayUnsyncedRoundBanner.tsx index c03ddfbcb..23b884cec 100644 --- a/src/components/fairway/pages/rounds/FairwayUnsyncedRoundBanner.tsx +++ b/src/components/fairway/pages/rounds/FairwayUnsyncedRoundBanner.tsx @@ -139,7 +139,7 @@ export function FairwayUnsyncedRoundBanner({ hasServerInProgress }: FairwayUnsyn