Add settings layout and page structure for authenticated routes
Introduce tabbed navigation for the settings page, including Profile, Password, Sessions, and Preferences sections. Add placeholders for each section with metadata and routes. Redirect `/settings` to `/settings/profile`. Integrate `AuthGuard` for settings and authenticated layouts while incorporating reusable `Header` and `Footer` components.
This commit is contained in:
34
frontend/src/app/(authenticated)/layout.tsx
Normal file
34
frontend/src/app/(authenticated)/layout.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Authenticated Route Group Layout
|
||||||
|
* Wraps all authenticated routes with AuthGuard and provides common layout structure
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
import { AuthGuard } from '@/components/auth';
|
||||||
|
import { Header } from '@/components/layout/Header';
|
||||||
|
import { Footer } from '@/components/layout/Footer';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: {
|
||||||
|
template: '%s | FastNext Template',
|
||||||
|
default: 'Dashboard',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AuthenticatedLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<AuthGuard>
|
||||||
|
<div className="flex min-h-screen flex-col">
|
||||||
|
<Header />
|
||||||
|
<main className="flex-1">
|
||||||
|
{children}
|
||||||
|
</main>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
</AuthGuard>
|
||||||
|
);
|
||||||
|
}
|
||||||
88
frontend/src/app/(authenticated)/settings/layout.tsx
Normal file
88
frontend/src/app/(authenticated)/settings/layout.tsx
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* Settings Layout
|
||||||
|
* Provides tabbed navigation for settings pages
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { usePathname } from 'next/navigation';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||||
|
import { User, Lock, Monitor, Settings as SettingsIcon } from 'lucide-react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings tabs configuration
|
||||||
|
*/
|
||||||
|
const settingsTabs = [
|
||||||
|
{
|
||||||
|
value: 'profile',
|
||||||
|
label: 'Profile',
|
||||||
|
href: '/settings/profile',
|
||||||
|
icon: User,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'password',
|
||||||
|
label: 'Password',
|
||||||
|
href: '/settings/password',
|
||||||
|
icon: Lock,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'sessions',
|
||||||
|
label: 'Sessions',
|
||||||
|
href: '/settings/sessions',
|
||||||
|
icon: Monitor,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'preferences',
|
||||||
|
label: 'Preferences',
|
||||||
|
href: '/settings/preferences',
|
||||||
|
icon: SettingsIcon,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function SettingsLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
const pathname = usePathname();
|
||||||
|
|
||||||
|
// Determine active tab based on pathname
|
||||||
|
const activeTab = settingsTabs.find((tab) => pathname.startsWith(tab.href))?.value || 'profile';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="container mx-auto px-4 py-8">
|
||||||
|
{/* Page Header */}
|
||||||
|
<div className="mb-8">
|
||||||
|
<h1 className="text-3xl font-bold text-gray-900 dark:text-white">
|
||||||
|
Settings
|
||||||
|
</h1>
|
||||||
|
<p className="mt-2 text-gray-600 dark:text-gray-400">
|
||||||
|
Manage your account settings and preferences
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Tabs Navigation */}
|
||||||
|
<Tabs value={activeTab} className="space-y-6">
|
||||||
|
<TabsList className="grid w-full grid-cols-2 md:grid-cols-4 lg:w-[600px]">
|
||||||
|
{settingsTabs.map((tab) => {
|
||||||
|
const Icon = tab.icon;
|
||||||
|
return (
|
||||||
|
<TabsTrigger key={tab.value} value={tab.value} asChild>
|
||||||
|
<Link href={tab.href} className="flex items-center space-x-2">
|
||||||
|
<Icon className="h-4 w-4" />
|
||||||
|
<span>{tab.label}</span>
|
||||||
|
</Link>
|
||||||
|
</TabsTrigger>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
{/* Tab Content */}
|
||||||
|
<div className="rounded-lg border bg-white dark:bg-gray-900 p-6">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
10
frontend/src/app/(authenticated)/settings/page.tsx
Normal file
10
frontend/src/app/(authenticated)/settings/page.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Settings Index Page
|
||||||
|
* Redirects to /settings/profile
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { redirect } from 'next/navigation';
|
||||||
|
|
||||||
|
export default function SettingsPage() {
|
||||||
|
redirect('/settings/profile');
|
||||||
|
}
|
||||||
23
frontend/src/app/(authenticated)/settings/password/page.tsx
Normal file
23
frontend/src/app/(authenticated)/settings/password/page.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Password Settings Page
|
||||||
|
* Change password functionality
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Password Settings',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function PasswordSettingsPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">
|
||||||
|
Password Settings
|
||||||
|
</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-400">
|
||||||
|
Change your password (Coming in Task 3.3)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* User Preferences Page
|
||||||
|
* Theme, notifications, and other preferences
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Preferences',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function PreferencesPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">
|
||||||
|
Preferences
|
||||||
|
</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-400">
|
||||||
|
Configure your preferences (Coming in Task 3.5)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
23
frontend/src/app/(authenticated)/settings/profile/page.tsx
Normal file
23
frontend/src/app/(authenticated)/settings/profile/page.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Profile Settings Page
|
||||||
|
* User profile management - edit name, email, phone, preferences
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Profile Settings',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ProfileSettingsPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">
|
||||||
|
Profile Settings
|
||||||
|
</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-400">
|
||||||
|
Manage your profile information (Coming in Task 3.2)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
23
frontend/src/app/(authenticated)/settings/sessions/page.tsx
Normal file
23
frontend/src/app/(authenticated)/settings/sessions/page.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Session Management Page
|
||||||
|
* View and manage active sessions across devices
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Active Sessions',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function SessionsPage() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">
|
||||||
|
Active Sessions
|
||||||
|
</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-400">
|
||||||
|
Manage your active sessions (Coming in Task 3.4)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user