Skip to content

Commit d433038

Browse files
committed
feat(admin): hide public footer and help banner on /admin routes (#3240, #3262)
1 parent 97d644f commit d433038

5 files changed

Lines changed: 81 additions & 4 deletions

File tree

packages/app/src/app/layout.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ import Script from "next/script";
44
import { MatomoAnalytics } from "~/modules/analytics";
55
import { SessionProviderWrapper } from "~/modules/auth";
66
import {
7-
Footer,
87
Header,
98
ImpersonateBanner,
10-
ResourceBanner,
9+
PublicChrome,
1110
SkipLinks,
1211
} from "~/modules/layout";
1312
import { ProfileModal } from "~/modules/profile";
@@ -59,8 +58,7 @@ export default function RootLayout({
5958
<ImpersonateBanner />
6059
<Header />
6160
{children}
62-
<ResourceBanner />
63-
<Footer />
61+
<PublicChrome />
6462
<ProfileModal />
6563
</TRPCReactProvider>
6664
</SessionProviderWrapper>

packages/app/src/e2e/admin.e2e.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ test("admin user can access /admin and sees backoffice page", async ({
1010
await expect(page.getByText("administrateur")).toBeVisible();
1111
});
1212

13+
test("admin routes hide the public footer and help banner", async ({
14+
page,
15+
}) => {
16+
await page.goto("/admin");
17+
await expect(page.locator("footer#footer")).toHaveCount(0);
18+
await expect(
19+
page.getByRole("region", { name: "Ressources et aide" }),
20+
).toHaveCount(0);
21+
});
22+
1323
test("admin user can access /admin/impersonate and sees impersonate page", async ({
1424
page,
1525
}) => {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"use client";
2+
3+
import { usePathname } from "next/navigation";
4+
5+
import { Footer } from "./Footer";
6+
import { ResourceBanner } from "./ResourceBanner";
7+
8+
/**
9+
* Renders the public help banner + footer on every route except the backoffice.
10+
* Admin pages (`/admin/**`) get a stripped-down chrome so the sidebar + admin
11+
* content fill the viewport without competing with public navigation.
12+
*/
13+
export function PublicChrome() {
14+
const pathname = usePathname();
15+
if (pathname?.startsWith("/admin")) {
16+
return null;
17+
}
18+
return (
19+
<>
20+
<ResourceBanner />
21+
<Footer />
22+
</>
23+
);
24+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { render, screen } from "@testing-library/react";
2+
import { usePathname } from "next/navigation";
3+
import { beforeEach, describe, expect, it, type Mock, vi } from "vitest";
4+
5+
import { PublicChrome } from "../PublicChrome";
6+
7+
vi.mock("../Footer", () => ({
8+
Footer: () => <footer data-testid="public-footer">footer</footer>,
9+
}));
10+
vi.mock("../ResourceBanner", () => ({
11+
ResourceBanner: () => (
12+
<section data-testid="public-resource-banner">banner</section>
13+
),
14+
}));
15+
16+
describe("PublicChrome", () => {
17+
beforeEach(() => {
18+
(usePathname as Mock).mockReturnValue("/");
19+
});
20+
21+
it("renders ResourceBanner + Footer on public routes", () => {
22+
render(<PublicChrome />);
23+
expect(screen.getByTestId("public-resource-banner")).toBeInTheDocument();
24+
expect(screen.getByTestId("public-footer")).toBeInTheDocument();
25+
});
26+
27+
it("renders nothing on /admin", () => {
28+
(usePathname as Mock).mockReturnValue("/admin");
29+
const { container } = render(<PublicChrome />);
30+
expect(container).toBeEmptyDOMElement();
31+
});
32+
33+
it("renders nothing on nested /admin/* routes", () => {
34+
(usePathname as Mock).mockReturnValue("/admin/declarations");
35+
const { container } = render(<PublicChrome />);
36+
expect(container).toBeEmptyDOMElement();
37+
});
38+
39+
it("renders chrome on non-admin nested routes", () => {
40+
(usePathname as Mock).mockReturnValue("/mon-espace/declarations");
41+
render(<PublicChrome />);
42+
expect(screen.getByTestId("public-footer")).toBeInTheDocument();
43+
});
44+
});

packages/app/src/modules/layout/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export { Breadcrumb } from "./Breadcrumb";
22
export { Footer } from "./Footer";
33
export { Header } from "./Header";
44
export { ImpersonateBanner } from "./ImpersonateBanner";
5+
export { PublicChrome } from "./PublicChrome";
56
export { ResourceBanner } from "./ResourceBanner";
67
export { DsfrPictogram } from "./shared/DsfrPictogram";
78
export { NewTabNotice } from "./shared/NewTabNotice";

0 commit comments

Comments
 (0)