forked from cardosofelipe/fast-next-template
fix(frontend): move dashboard to /dashboard route
The dashboard page was created at (authenticated)/page.tsx which would serve the same route as [locale]/page.tsx (the public landing page). Next.js doesn't allow route groups to override parent pages. Changes: - Move dashboard page to (authenticated)/dashboard/page.tsx - Update Header nav links to point to /dashboard - Update AppBreadcrumbs home link to /dashboard - Update E2E tests to navigate to /dashboard Now authenticated users should navigate to /dashboard for their homepage, while /en serves the public landing page for unauthenticated users. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,7 @@ test.describe('Main Dashboard Page', () => {
|
|||||||
|
|
||||||
test('should display welcome header with user name', async ({ page }) => {
|
test('should display welcome header with user name', async ({ page }) => {
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Check for welcome message
|
// Check for welcome message
|
||||||
@@ -32,6 +33,7 @@ test.describe('Main Dashboard Page', () => {
|
|||||||
|
|
||||||
test('should display quick stats cards', async ({ page }) => {
|
test('should display quick stats cards', async ({ page }) => {
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Check for stats cards
|
// Check for stats cards
|
||||||
@@ -43,6 +45,7 @@ test.describe('Main Dashboard Page', () => {
|
|||||||
|
|
||||||
test('should display recent projects section', async ({ page }) => {
|
test('should display recent projects section', async ({ page }) => {
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Check recent projects heading
|
// Check recent projects heading
|
||||||
@@ -56,6 +59,7 @@ test.describe('Main Dashboard Page', () => {
|
|||||||
|
|
||||||
test('should navigate to projects page when clicking View all', async ({ page }) => {
|
test('should navigate to projects page when clicking View all', async ({ page }) => {
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Click view all link
|
// Click view all link
|
||||||
@@ -68,6 +72,7 @@ test.describe('Main Dashboard Page', () => {
|
|||||||
|
|
||||||
test('should have Create Project button', async ({ page }) => {
|
test('should have Create Project button', async ({ page }) => {
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Check for create project button
|
// Check for create project button
|
||||||
@@ -77,6 +82,7 @@ test.describe('Main Dashboard Page', () => {
|
|||||||
|
|
||||||
test('should display pending approvals when they exist', async ({ page }) => {
|
test('should display pending approvals when they exist', async ({ page }) => {
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Check for pending approvals section
|
// Check for pending approvals section
|
||||||
@@ -87,6 +93,7 @@ test.describe('Main Dashboard Page', () => {
|
|||||||
|
|
||||||
test('should have accessible heading hierarchy', async ({ page }) => {
|
test('should have accessible heading hierarchy', async ({ page }) => {
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Check for h1 (welcome message)
|
// Check for h1 (welcome message)
|
||||||
@@ -100,6 +107,7 @@ test.describe('Main Dashboard Page', () => {
|
|||||||
|
|
||||||
test('should be keyboard navigable', async ({ page }) => {
|
test('should be keyboard navigable', async ({ page }) => {
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Tab through the page elements
|
// Tab through the page elements
|
||||||
@@ -115,6 +123,7 @@ test.describe('Main Dashboard Page', () => {
|
|||||||
await page.setViewportSize({ width: 375, height: 667 });
|
await page.setViewportSize({ width: 375, height: 667 });
|
||||||
|
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Page should still be functional on mobile
|
// Page should still be functional on mobile
|
||||||
@@ -127,6 +136,7 @@ test.describe('Main Dashboard Page', () => {
|
|||||||
|
|
||||||
// Measure navigation timing
|
// Measure navigation timing
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
const duration = Date.now() - start;
|
const duration = Date.now() - start;
|
||||||
|
|
||||||
@@ -144,6 +154,7 @@ test.describe('Main Dashboard Empty State', () => {
|
|||||||
// This tests the empty state path - in demo mode we have mock data
|
// This tests the empty state path - in demo mode we have mock data
|
||||||
// so we check for the empty state component being available
|
// so we check for the empty state component being available
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// In demo mode we always have projects, but the empty state exists
|
// In demo mode we always have projects, but the empty state exists
|
||||||
@@ -160,6 +171,7 @@ test.describe('Main Dashboard Stats Interaction', () => {
|
|||||||
|
|
||||||
test('should display stats with numeric values', async ({ page }) => {
|
test('should display stats with numeric values', async ({ page }) => {
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Stats should show numbers
|
// Stats should show numbers
|
||||||
@@ -169,6 +181,7 @@ test.describe('Main Dashboard Stats Interaction', () => {
|
|||||||
|
|
||||||
test('should make stats cards clickable where appropriate', async ({ page }) => {
|
test('should make stats cards clickable where appropriate', async ({ page }) => {
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Active Projects stat should link to projects
|
// Active Projects stat should link to projects
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ test.describe('Projects List Page', () => {
|
|||||||
|
|
||||||
test('should be accessible from dashboard', async ({ page }) => {
|
test('should be accessible from dashboard', async ({ page }) => {
|
||||||
await loginViaUI(page);
|
await loginViaUI(page);
|
||||||
|
await page.goto('/en/dashboard');
|
||||||
await page.waitForLoadState('networkidle');
|
await page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
// Click "View all" link from dashboard
|
// Click "View all" link from dashboard
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ export function AppBreadcrumbs({ items, showHome = true, className }: AppBreadcr
|
|||||||
{showHome && (
|
{showHome && (
|
||||||
<li className="flex items-center">
|
<li className="flex items-center">
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href="/dashboard"
|
||||||
className="flex items-center text-muted-foreground hover:text-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-sm"
|
className="flex items-center text-muted-foreground hover:text-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-sm"
|
||||||
aria-label="Home"
|
aria-label="Home"
|
||||||
data-testid="breadcrumb-home"
|
data-testid="breadcrumb-home"
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export function Header() {
|
|||||||
<div className="container mx-auto flex h-16 items-center px-4">
|
<div className="container mx-auto flex h-16 items-center px-4">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<div className="flex items-center space-x-8">
|
<div className="flex items-center space-x-8">
|
||||||
<Link href="/" className="flex items-center space-x-2">
|
<Link href="/dashboard" className="flex items-center space-x-2">
|
||||||
<Image
|
<Image
|
||||||
src="/logo-icon.svg"
|
src="/logo-icon.svg"
|
||||||
alt="Syndarix Logo"
|
alt="Syndarix Logo"
|
||||||
@@ -96,7 +96,7 @@ export function Header() {
|
|||||||
|
|
||||||
{/* Navigation Links */}
|
{/* Navigation Links */}
|
||||||
<nav className="hidden md:flex items-center space-x-1">
|
<nav className="hidden md:flex items-center space-x-1">
|
||||||
<NavLink href="/" exact>
|
<NavLink href="/dashboard" exact>
|
||||||
{t('home')}
|
{t('home')}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
{user?.is_superuser && <NavLink href="/admin">{t('admin')}</NavLink>}
|
{user?.is_superuser && <NavLink href="/admin">{t('admin')}</NavLink>}
|
||||||
|
|||||||
Reference in New Issue
Block a user