From 60b9e9a8c65e490340da4b3e5757d71beb6e989b Mon Sep 17 00:00:00 2001 From: OhChangEun <131477920+OhChangEun@users.noreply.github.com> Date: Fri, 18 Sep 2026 13:16:40 +0900 Subject: [PATCH] =?UTF-8?q?fix(wholesale):=20=EB=8C=80=EC=8B=9C=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=20=ED=83=AD=20=EC=A0=9C=EB=AA=A9=20=EB=B0=B0=EC=A7=80?= =?UTF-8?q?=EB=A5=BC=20polling=EB=A7=88=EB=8B=A4=20=EB=8B=A4=EC=8B=9C=20?= =?UTF-8?q?=EC=8D=A8=EC=84=9C=20=EC=9C=A0=EC=A7=80=20#245?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/components/DashboardView.tsx | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/apps/wholesale/src/features/dashboard/components/DashboardView.tsx b/apps/wholesale/src/features/dashboard/components/DashboardView.tsx index 669ec8a..c08d6ca 100644 --- a/apps/wholesale/src/features/dashboard/components/DashboardView.tsx +++ b/apps/wholesale/src/features/dashboard/components/DashboardView.tsx @@ -16,6 +16,8 @@ import { TAB_HREF, } from "../constants"; import { documentTitle } from "../derive"; +/** Next의 늦은 제목 덮어쓰기는 스트리밍 직후 한 프레임 안에 온다 — 1초면 넉넉히 뒤다 */ +const TITLE_REASSERT_MS = 1_000; import { QueryBoundary, QueryBoundaryGroup, @@ -43,7 +45,7 @@ export function DashboardView() { const peek = useDashboardSummaryPeek(); /* 경과 기준 시각. 서버 시각이 없을 때(첫 로딩·summary 실패)만 브라우저 시계 — 큐가 summary 때문에 멈추면 안 된다 */ const now = peek?.now ?? new Date().toISOString(); - useDocumentTitleBadge(peek?.newOrderCount ?? 0); + useDocumentTitleBadge(peek?.newOrderCount ?? 0, peek?.now); return ( @@ -119,15 +121,26 @@ export function DashboardView() { /** * 탭 제목에 신규 주문 건수 배지 — `(4) 대시보드 · 온도 ERP`. 다른 창을 보고 있어도 탭 글자로 보인다. * + * 한 번 쓰고 끝내면 안 된다. 첫 응답 직후 Next가 라우트 `metadata.title`을 뒤늦게 한 번 더 써서 배지를 지우는데, + * 건수가 그대로면 effect가 다시 안 돌아 지워진 채로 남았다(#245). 그래서 쓰고 잠시 뒤 한 번 더 쓰고, + * polling마다 바뀌는 서버 시각(`now`)을 의존성에 넣어 30초마다 다시 쓴다. + * * 되돌릴 땐 **우리가 붙인 제목일 때만** 되돌린다. 라우트를 옮기면 Next가 새 제목을 먼저 쓰고 그 뒤에 * 이 cleanup이 돌아서, 무조건 되돌리면 주문 탭 제목이 `대시보드`로 남는다. */ -function useDocumentTitleBadge(newOrderCount: number) { +function useDocumentTitleBadge( + newOrderCount: number, + tick: string | undefined, +) { useEffect(() => { const badged = documentTitle(newOrderCount); document.title = badged; + const reassert = window.setTimeout(() => { + document.title = badged; + }, TITLE_REASSERT_MS); return () => { + window.clearTimeout(reassert); if (document.title === badged) document.title = DASHBOARD_TITLE; }; - }, [newOrderCount]); + }, [newOrderCount, tick]); }