관리자 화면 스크롤 복원

This commit is contained in:
Yun Chan 2026-07-03 20:27:54 +09:00
parent d939253b3f
commit a5a2e2ea78
4 changed files with 47 additions and 1 deletions

View file

@ -629,6 +629,36 @@ test.describe("admin route guards", () => {
.poll(() => Array.from(seenAdminEndpoints).sort())
.toEqual(["health", "tickets", "uptime", "usage", "users"]);
});
test("resets scroll when moving from long admin pages to access policy", async ({ page }) => {
await mockAdminSession(page, {
user_id: "scroll-admin",
email: "scroll-admin@twentyoz.kr",
display_name: "Scroll Admin",
role: "admin",
admin_access: true,
super_admin: true,
onboarding_completed_at: 1_782_900_000,
});
await page.goto("/admin/users");
await expect(page.getByRole("heading", { name: "가입 승인과 권한 관리" })).toBeVisible();
const scrolled = await page.evaluate(() => {
document.documentElement.style.minHeight = "2200px";
document.body.style.minHeight = "2200px";
window.scrollTo(0, 900);
return window.scrollY;
});
expect(scrolled).toBeGreaterThan(0);
await page.locator(".vg-nav").getByRole("link", { name: "권한" }).click();
await expect(page).toHaveURL(/\/admin\/access$/);
await expect
.poll(() => page.evaluate(() => window.scrollY))
.toBe(0);
await expect(page.getByRole("heading", { name: "역할, 그룹, 접근 범위" })).toBeInViewport();
});
});
test.describe("admin route", () => {

View file

@ -15,7 +15,7 @@
AuthContext . .
===================================================================== */
import type { ReactNode } from "react";
import { useEffect, type ReactNode } from "react";
import { BrowserRouter, Navigate, Route, Routes, useLocation } from "react-router-dom";
import { AuthProvider, canAccessRole, initialPathForUser, useAuth, roleHomePath, type AuthUser, type Role } from "./lib/auth";
@ -129,6 +129,18 @@ function RootRedirect() {
return <Navigate to={user ? initialPathForUser(user) : "/login"} replace />;
}
function ScrollToTopOnPathChange() {
const { pathname } = useLocation();
useEffect(() => {
window.scrollTo({ top: 0, left: 0, behavior: "auto" });
document.documentElement.scrollTop = 0;
document.body.scrollTop = 0;
}, [pathname]);
return null;
}
function AppRoutes() {
return (
<PendingApprovalGate>
@ -298,6 +310,7 @@ export default function App() {
return (
<BrowserRouter>
<AuthProvider>
<ScrollToTopOnPathChange />
<AppRoutes />
</AuthProvider>
</BrowserRouter>