Skip to content

Commit 4cabc14

Browse files
Add layout components for authentication and main application structure
- Implement AuthLayout for authentication-related pages - Create Header and Footer components for consistent layout - Establish MainLayout to wrap Header, Footer, and Outlet - Define authRoutes and mainRoutes for routing structure
1 parent 2e0c8ad commit 4cabc14

File tree

8 files changed

+236
-33
lines changed

8 files changed

+236
-33
lines changed

src/components/layout/auth-layout.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Outlet } from "react-router";
2+
3+
// This layout is used for authentication-related pages like login and register
4+
const AuthLayout = () => {
5+
return (
6+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
7+
<section className="flex flex-col items-center justify-center ">
8+
<h1>Auth Layout</h1>
9+
<p>
10+
Modify this layout to include your authentication-related components
11+
You can also add a logo or any other branding elements here.
12+
</p>
13+
</section>
14+
<Outlet />
15+
</div>
16+
);
17+
};
18+
19+
export default AuthLayout;

src/components/layout/footer.tsx

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
const Footer = () => {
2+
const currentYear = new Date().getFullYear();
3+
4+
return (
5+
<footer className="bg-gray-50 border-t">
6+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
7+
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
8+
<div className="col-span-1 md:col-span-2">
9+
<h3 className="text-lg font-semibold text-gray-900 mb-4">
10+
App Name
11+
</h3>
12+
<p className="text-gray-600 text-sm">
13+
A modern React application built with TypeScript, React Router,
14+
and Tailwind CSS.
15+
</p>
16+
</div>
17+
18+
<div>
19+
<h4 className="text-md font-medium text-gray-900 mb-3">
20+
Quick Links
21+
</h4>
22+
<ul className="space-y-2">
23+
<li>
24+
<a
25+
href="/"
26+
className="text-gray-600 hover:text-gray-900 text-sm"
27+
>
28+
Home
29+
</a>
30+
</li>
31+
<li>
32+
<a
33+
href="/create-post"
34+
className="text-gray-600 hover:text-gray-900 text-sm"
35+
>
36+
Create Post
37+
</a>
38+
</li>
39+
<li>
40+
<a
41+
href="/admin"
42+
className="text-gray-600 hover:text-gray-900 text-sm"
43+
>
44+
Admin
45+
</a>
46+
</li>
47+
</ul>
48+
</div>
49+
50+
<div>
51+
<h4 className="text-md font-medium text-gray-900 mb-3">Support</h4>
52+
<ul className="space-y-2">
53+
<li>
54+
<a
55+
href="#"
56+
className="text-gray-600 hover:text-gray-900 text-sm"
57+
>
58+
Documentation
59+
</a>
60+
</li>
61+
<li>
62+
<a
63+
href="#"
64+
className="text-gray-600 hover:text-gray-900 text-sm"
65+
>
66+
Contact Us
67+
</a>
68+
</li>
69+
<li>
70+
<a
71+
href="#"
72+
className="text-gray-600 hover:text-gray-900 text-sm"
73+
>
74+
Privacy Policy
75+
</a>
76+
</li>
77+
</ul>
78+
</div>
79+
</div>
80+
81+
<div className="mt-8 pt-8 border-t border-gray-200">
82+
<p className="text-center text-gray-500 text-sm">
83+
© {currentYear} App Name. All rights reserved.
84+
</p>
85+
</div>
86+
</div>
87+
</footer>
88+
);
89+
};
90+
91+
export default Footer;

src/components/layout/header.tsx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { Link } from "react-router";
2+
3+
const Header = () => {
4+
return (
5+
<header className="bg-white shadow-sm border-b">
6+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
7+
<div className="flex justify-between items-center h-16">
8+
<div className="flex items-center">
9+
<Link to="/" className="text-xl font-bold text-gray-900">
10+
App Name
11+
</Link>
12+
</div>
13+
14+
<nav className="hidden md:flex space-x-8">
15+
<Link
16+
to="/"
17+
className="text-gray-500 hover:text-gray-900 px-3 py-2 rounded-md text-sm font-medium"
18+
>
19+
Home
20+
</Link>
21+
<Link
22+
to="/create-post"
23+
className="text-gray-500 hover:text-gray-900 px-3 py-2 rounded-md text-sm font-medium"
24+
>
25+
Create Post
26+
</Link>
27+
<Link
28+
to="/admin"
29+
className="text-gray-500 hover:text-gray-900 px-3 py-2 rounded-md text-sm font-medium"
30+
>
31+
Admin
32+
</Link>
33+
</nav>
34+
35+
<div className="flex items-center space-x-4">
36+
<Link
37+
to="/login"
38+
className="text-gray-500 hover:text-gray-900 px-3 py-2 rounded-md text-sm font-medium"
39+
>
40+
Login
41+
</Link>
42+
</div>
43+
</div>
44+
</div>
45+
</header>
46+
);
47+
};
48+
49+
export default Header;

src/components/layout/main-layout.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Outlet } from "react-router";
2+
import Header from "./header";
3+
import Footer from "./footer";
4+
5+
const MainLayout = () => {
6+
return (
7+
<div className="min-h-screen flex flex-col">
8+
<Header />
9+
<main className="flex-1">
10+
<Outlet />
11+
</main>
12+
<Footer />
13+
</div>
14+
);
15+
};
16+
17+
export default MainLayout;

src/layout.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@ import { Outlet } from "react-router";
44
const Layout = () => {
55
return (
66
<Providers>
7-
<header>Header</header>
8-
<main>
9-
<Outlet />
10-
</main>
11-
<footer>Footer</footer>
7+
<Outlet />
128
</Providers>
139
);
1410
};

src/routes/auth-routes.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import AuthLayout from "@/components/layout/auth-layout";
2+
import { ROUTE_CONSTANTS } from "@/lib/constants";
3+
import withGuards from "@/lib/utils/with-guards";
4+
import { LoginPage } from "@/pages/login";
5+
import type { RouteObject } from "react-router";
6+
7+
const authRoutes: RouteObject = {
8+
// For Layout Routes, the path is not required.
9+
Component: AuthLayout,
10+
children: [
11+
{
12+
path: ROUTE_CONSTANTS.LOGIN,
13+
index: true,
14+
Component: withGuards(LoginPage, { mode: "auth" }),
15+
},
16+
],
17+
};
18+
19+
export default authRoutes;

src/routes/index.tsx

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,28 @@
11
import { ROUTE_CONSTANTS } from "@/lib/constants";
22
import Layout from "../layout";
33

4-
import { HomePage } from "../pages/home";
5-
import { LoginPage } from "../pages/login";
64
import ErrorElement from "@/components/error-element";
75
import NotFound from "@/components/not-found";
8-
import { AdminPage } from "@/pages/admin";
96
import { ForbiddenPage } from "@/pages/forbidden";
10-
import { CreatePostPage } from "@/pages/create-post";
117
import blogRoutes from "./blog-routes";
128
import type { RouteObject } from "react-router";
13-
import withGuards from "@/lib/utils/with-guards";
9+
import authRoutes from "./auth-routes";
10+
11+
import mainRoutes from "./main-routes";
1412

1513
const routes: RouteObject[] = [
1614
{
1715
path: "/",
1816
Component: Layout,
1917
errorElement: <ErrorElement />,
2018
children: [
21-
{
22-
index: true,
23-
Component: withGuards(HomePage, {
24-
guard: { roles: ["admin", "user", "guest"] },
25-
}),
26-
},
27-
{
28-
path: ROUTE_CONSTANTS.ADMIN,
29-
Component: withGuards(AdminPage, {
30-
guard: { roles: ["admin"] },
31-
}),
32-
},
33-
{
34-
path: ROUTE_CONSTANTS.CREATE_POST,
35-
Component: withGuards(CreatePostPage, {
36-
guard: { roles: ["user", "admin"], scopes: ["write"] },
37-
}),
38-
},
19+
authRoutes,
20+
mainRoutes,
21+
blogRoutes,
3922
{
4023
path: ROUTE_CONSTANTS.FORBIDDEN,
4124
Component: ForbiddenPage,
4225
},
43-
{
44-
path: ROUTE_CONSTANTS.LOGIN,
45-
Component: withGuards(LoginPage, { mode: "auth" }),
46-
},
47-
blogRoutes,
4826
],
4927
},
5028
{

src/routes/main-routes.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import MainLayout from "@/components/layout/main-layout";
2+
import { ROUTE_CONSTANTS } from "@/lib/constants";
3+
import withGuards from "@/lib/utils/with-guards";
4+
import { AdminPage } from "@/pages/admin";
5+
import { CreatePostPage } from "@/pages/create-post";
6+
import { HomePage } from "@/pages/home";
7+
import type { RouteObject } from "react-router";
8+
9+
const mainRoutes: RouteObject = {
10+
// For Layout Routes, the path is not required.
11+
Component: MainLayout,
12+
children: [
13+
{
14+
index: true, // This will be the default route when the path is "/"
15+
Component: withGuards(HomePage, {
16+
guard: { roles: ["admin", "user", "guest"] },
17+
}),
18+
},
19+
{
20+
path: ROUTE_CONSTANTS.ADMIN,
21+
Component: withGuards(AdminPage, {
22+
guard: { roles: ["admin"] },
23+
}),
24+
},
25+
{
26+
path: ROUTE_CONSTANTS.CREATE_POST,
27+
Component: withGuards(CreatePostPage, {
28+
guard: { roles: ["user", "admin"], scopes: ["write"] },
29+
}),
30+
},
31+
],
32+
};
33+
34+
export default mainRoutes;

0 commit comments

Comments
 (0)