Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions apps/monitor-web/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { useRef } from "react";
import { Routes, Route } from "react-router-dom";
import { Dashboard, Login, ErrorLog, ApiDetail, ApiEdit, ErrorDetail, NotFound } from "./pages";
import { Sidebar, ToastContainer } from "./layouts";
import { AuthRoute } from "./components";
import { AuthRoute, ScrollToTop } from "./components";

export default function App() {
const mainRef = useRef<HTMLElement>(null);

return (
<div className="flex h-screen">
<Sidebar />

<main className="relative flex flex-1 flex-col overflow-x-auto overflow-y-auto bg-[#F7F7F7] p-8">
<main
ref={mainRef}
className="relative flex flex-1 flex-col overflow-x-auto overflow-y-auto bg-[#F7F7F7] p-8"
>
<ScrollToTop targetRef={mainRef} />
<div className="flex min-w-[1520px] flex-1 flex-col">
<Routes>
<Route element={<Dashboard />} path="/" />
Expand Down
29 changes: 29 additions & 0 deletions apps/monitor-web/src/components/routes/ScrollToTop.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useEffect, type RefObject } from "react";
import { useLocation } from "react-router-dom";

/**
* 라우트 변경 시 지정한 스크롤 컨테이너의 위치를 최상단으로 초기화하는 컴포넌트입니다.
*
* @remarks
* - `window`가 아니라 `targetRef`로 전달된 스크롤 컨테이너를 직접 제어합니다.
* - `pathname` 변경 시 `top`, `left` 위치를 0으로 되돌립니다.
* - 화면에 렌더링되는 UI 없이 라우팅 사이드 이펙트만 처리합니다.
*
* @author junyeol
*/

interface ScrollToTopProps {
targetRef: RefObject<HTMLElement | null>;
}

const ScrollToTop = ({ targetRef }: ScrollToTopProps) => {
const { pathname } = useLocation();

useEffect(() => {
targetRef.current?.scrollTo({ top: 0, left: 0 });
}, [pathname, targetRef]);

return null;
};

export default ScrollToTop;
1 change: 1 addition & 0 deletions apps/monitor-web/src/components/routes/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as AuthRoute } from "./AuthRoute";
export { default as ScrollToTop } from "./ScrollToTop";
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Badge } from "@/components";
import { MOCK_DASHBOARD_API_LIST } from "@/mock";
import type { ApiStatus } from "@/types";
import type { ApiListItem } from "../_types";
import { useNavigate } from "react-router-dom";

const API_STATUS_LABEL: Record<ApiStatus, string> = {
healthy: "정상",
Expand Down Expand Up @@ -60,6 +61,12 @@ const API_TABLE_COLUMNS: {
];

const DashboardApiList = () => {
const navigate = useNavigate();

const handleGoApiDetail = (apiId: string) => {
navigate(`/api/${apiId}`);
};

return (
<section className="rounded-xl border border-border-divider-default bg-bg-layout-1depth px-12 py-8">
<h2 className="typo-header4-bold text-layout-header">전체 API 목록</h2>
Expand All @@ -78,7 +85,12 @@ const DashboardApiList = () => {

<tbody>
{MOCK_DASHBOARD_API_LIST.map((api) => (
<tr key={api.id}>
<tr
key={api.id}
role="link"
className="cursor-pointer hover:bg-bg-layout-2depth"
onClick={() => handleGoApiDetail(api.id)}
>
Comment thread
junye0l marked this conversation as resolved.
{API_TABLE_COLUMNS.map((column) => (
<td
key={column.id}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const DashboardResponseStatusChart = () => {
innerRadius={80}
outerRadius={120}
paddingAngle={4}
pointerEvents="none"
>
{CHART_DATA.map((entry) => (
<Cell key={entry.name} fill={entry.color} />
Expand Down