Skip to content

feat: header 알림 패널 목업 페이지 추가 - #21

Merged
youngmis merged 10 commits into
devfrom
feature/estimate-request
Jul 28, 2026
Merged

feat: header 알림 패널 목업 페이지 추가#21
youngmis merged 10 commits into
devfrom
feature/estimate-request

Conversation

@youngmis

@youngmis youngmis commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

📋 작업 내용

헤더 알림 아이콘에 알림 패널 추가(목업데이터 조회 및 페이지네이션), 안읽은 알림 갯수 라벨 및 읽은 알림은 디자인 변경


🔥 변경 사항

  1. src/types/notification.ts: 알림 DB 스키마(type, content, isRead 등)에 맞춘 공통 타입을 추가했습니다.
  2. src/components/common/Header/notificationMessages.ts: 알림 타입별 고정 문구(prefix/suffix)를 정의하고, 가변 content를 주황 강조 구간으로 넣는 buildNotificationMessageParts 함수를 추가했습니다.
  3. src/lib/mocks/notifications.mock.ts: GNB 알림 패널용 mock 데이터를 스키마에 맞춰 정리하하였습니다.
  4. src/components/common/Header/NotificationPanel.tsx: 알림 패널 UI를 추가하고, 타입별 문구 조합·읽음/미읽음 스타일·5건 단위 페이지네이션을 구현했습니다.
  5. src/components/common/Header/Header.tsx: 알림 버튼에 패널 토글(바깥 클릭·Esc 닫기)을 연결하고, 미확인 알림 수 빨간 배지와 접근성 속성을 추가했습니다.
  6. src/app/layout.tsx: 알림 패널 확인용으로 Header에 임시 isLogin prop 추가했습니다.

+) src/components/estimate/EstimateRequestForm.tsx: 견적 요청 완료 후 이동 경로를 /estimates에서 /estimates/pending으로 수정했습니다.


✅ 체크리스트

  • 로컬에서 정상 동작을 확인했습니다.
  • 기존 기능에 영향을 주지 않는지 확인했습니다.
  • 불필요한 console.log를 제거했습니다.
  • lint를 통과했습니다.
  • README 또는 문서를 수정했습니다. (필요 시)
  • API 명세와 일치하는지 확인했습니다.

📷 스크린샷 (선택)

image

🔗 관련 이슈

Closes #


💬 To Reviewer

Summary by CodeRabbit

  • 새로운 기능
    • 헤더 알림 패널을 추가했습니다. 읽지 않은 알림 배지, 유형별 강조 문구와 생성 시간, 페이지네이션, 알림별 이동 링크를 제공합니다.
  • 접근성/상호작용 개선
    • 알림 토글에 상태 정보를 반영하고, 바깥 클릭 또는 Escape 키로 패널을 닫을 수 있습니다.
  • 버그 수정
    • 받은 견적 확인 링크가 대기 중 견적 목록으로 정확히 연결되도록 수정했습니다.
  • 기타 개선
    • 리뷰 카드/모달의 접근성 라벨과 ‘기사님’ 표시 이름 기본값을 개선했으며, 알림 패널 그림자 스타일을 추가했습니다.

신영미 and others added 2 commits July 27, 2026 16:47
알림 아이콘에 패널·mock을 연동하고, 견적 요청 완료 후 이동 경로를 /estimates/pending으로 맞춘다.

Co-authored-by: Cursor <cursoragent@cursor.com>
미읽음 수 배지를 표시하고, 타입별 고정 문구에 content를 삽입해 강조하며 읽은 알림은 연한 회색으로 구분한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

헤더에 목데이터 기반 알림 패널, 읽지 않은 알림 배지, 페이지네이션 및 닫기 동작을 추가했습니다. 견적 CTA 경로와 리뷰 접근성·표시 이름 fallback도 변경했습니다.

Changes

헤더 알림 패널

Layer / File(s) Summary
알림 계약과 표시 데이터
src/types/notification.ts, src/components/common/Header/notificationMessages.ts, src/lib/mocks/notifications.mock.ts
알림 모델, 타입별 메시지 템플릿, 페이지 크기, 목 알림 목록과 읽지 않은 개수 집계를 추가했습니다.
알림 패널 표시와 페이지네이션
src/components/common/Header/NotificationPanel.tsx, src/styles/tokens.theme.css
알림을 페이지 단위로 렌더링하고 메시지 강조·읽음 상태·링크·빈 상태·페이지 이동 및 패널 shadow를 처리합니다.
헤더 토글과 닫기 동작
src/components/common/Header/Header.tsx
알림 배지·ARIA 속성·바깥 클릭·Escape·패널 내부 닫기를 연결했습니다.

견적·리뷰·인증 보완

Layer / File(s) Summary
견적 CTA와 리뷰 표시 수정
src/components/estimate/EstimateRequestForm.tsx, src/components/review/*
진행 중 견적 링크를 /estimates/pending으로 변경하고, 리뷰 링크의 제목 참조 접근성과 닉네임 fallback 표시를 수정했습니다.
인증 세션 브리지 문서 보강
src/lib/auth/session.ts
인증 세션 변경 이벤트 브리지의 규칙 예외 사유를 주석에 추가했습니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  actor 사용자
  participant Header
  participant NotificationPanel
  사용자->>Header: 알림 토글 클릭
  Header->>NotificationPanel: 패널 표시 및 onClose 전달
  사용자->>NotificationPanel: 닫기 또는 알림 링크 클릭
  NotificationPanel->>Header: onClose 호출
  Header->>NotificationPanel: 패널 닫기
Loading

Possibly related PRs

Suggested labels: 🏢코드리뷰

Suggested reviewers: wkdalswn11, 9g-g9, yooseohyeon

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 69.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 헤더 알림 패널과 관련 목업 데이터·페이지네이션 추가를 잘 요약하고 있어 변경의 핵심과 관련이 있습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/estimate-request

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/components/common/Header/notificationMessages.ts (1)

68-71: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

객체 타입은 interface로 선언하세요.

NotificationMessagePart는 확장 가능한 객체 구조이므로 프로젝트 규칙에 맞게 interface NotificationMessagePart로 바꾸는 편이 일관적입니다.

수정 예시
-export type NotificationMessagePart = {
+export interface NotificationMessagePart {
   text: string;
   highlight?: boolean;
-};
+}

As per coding guidelines, 객체 형태 타입은 interface를 우선 사용해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/common/Header/notificationMessages.ts` around lines 68 - 71,
Change NotificationMessagePart from an object type alias to an interface while
preserving its text property and optional highlight property.

Source: Coding guidelines

src/components/common/Header/NotificationPanel.tsx (1)

46-46: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

패널 그림자는 디자인 토큰으로 교체하세요.

shadow-[2px_2px_8px_0_rgba(0,0,0,0.06)]는 알림 패널의 shadow를 하드코딩합니다. 기존 semantic shadow utility를 사용하거나, 없다면 토큰에 추가한 뒤 사용하세요.

As per path instructions, 알림 패널의 shadow는 하드코딩하지 않고 디자인 토큰 기반으로 사용해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/common/Header/NotificationPanel.tsx` at line 46, Replace the
hardcoded shadow utility in the NotificationPanel class string with the existing
semantic shadow utility for panels. If no suitable utility exists, add the
corresponding design token first, then reference that token instead of using an
arbitrary shadow value; keep the remaining styling unchanged.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/layout.tsx`:
- Around line 36-37: Update the root layout’s Header usage so isLogin is derived
from the actual authentication state rather than being hardcoded true. Remove
the temporary notification-panel fixture comment/state from the global layout,
and isolate it in a development-only fixture or Storybook while preserving
unauthenticated and login-page headers.

In `@src/components/common/Header/NotificationPanel.tsx`:
- Around line 79-107: Update the notification item rendering in
NotificationPanel so notifications with a linkUrl wrap their content in
next/link’s Link and navigate to that URL. Keep notifications without linkUrl
non-clickable and preserve the existing styling and message/timestamp content.

---

Nitpick comments:
In `@src/components/common/Header/notificationMessages.ts`:
- Around line 68-71: Change NotificationMessagePart from an object type alias to
an interface while preserving its text property and optional highlight property.

In `@src/components/common/Header/NotificationPanel.tsx`:
- Line 46: Replace the hardcoded shadow utility in the NotificationPanel class
string with the existing semantic shadow utility for panels. If no suitable
utility exists, add the corresponding design token first, then reference that
token instead of using an arbitrary shadow value; keep the remaining styling
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 316c2032-ebe7-4321-92e1-60714d7be331

📥 Commits

Reviewing files that changed from the base of the PR and between dd5c38b and 7c529ec.

📒 Files selected for processing (7)
  • src/app/layout.tsx
  • src/components/common/Header/Header.tsx
  • src/components/common/Header/NotificationPanel.tsx
  • src/components/common/Header/notificationMessages.ts
  • src/components/estimate/EstimateRequestForm.tsx
  • src/lib/mocks/notifications.mock.ts
  • src/types/notification.ts

Comment thread src/app/layout.tsx Outdated
Comment thread src/components/common/Header/NotificationPanel.tsx Outdated

@juengseulki juengseulki left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 PR 리뷰

👍 좋았던 점

  • 알림 타입과 메시지 조합 로직을 별도 파일로 분리해 NotificationPanel이 UI 렌더링에 집중하도록 구성한 점이 좋았습니다.
  • 알림 패널의 바깥 클릭과 Escape 닫기를 모두 지원해 기본적인 사용성을 잘 챙겼습니다.
  • 알림 버튼에 aria-expanded, aria-controls, 읽지 않은 알림 수가 포함된 aria-label을 적용한 점도 좋았습니다.
  • 읽음 여부에 따라 메시지와 시간의 색상을 함께 변경해 상태가 명확하게 구분됩니다.
  • 페이지네이션 버튼의 disabled 상태와 aria-current를 적용해 현재 페이지를 구분한 점도 좋았습니다.
  • 견적 요청 완료 후 이동 경로를 /estimates/pending으로 수정한 것도 현재 라우팅 구조에 맞습니다.

🚨 수정이 필요한 부분

  • 루트 레이아웃에서 isLogin을 고정하면 모든 페이지가 로그인 Header로 표시됩니다.
  • linkUrl이 있는 알림도 현재 이동 기능이 없어 관련 화면에 접근할 수 없습니다.

🔍 확인 및 제안

인라인 코멘트로 아래 내용을 남기면 좋을 것 같습니다.

  • 알림이 없는 경우 빈 상태 UI를 제공할 계획인지 궁금합니다.
  • 알림 content가 가변 강조 문구인지 완성된 메시지인지 백엔드 API와 합의된 구조인지 확인이 필요합니다.

전체적으로 알림 패널의 UI 구성과 접근성 처리는 꼼꼼하게 되어 있습니다. 다만 전역 로그인 상태 고정과 알림 이동 기능은 실제 서비스 동작에 영향을 주기 때문에 수정 후 머지하는 것이 좋겠습니다. 😊

Comment thread src/app/layout.tsx Outdated
Comment thread src/components/common/Header/NotificationPanel.tsx Outdated
Comment thread src/components/common/Header/NotificationPanel.tsx
Comment thread src/components/common/Header/notificationMessages.ts
신영미 and others added 2 commits July 27, 2026 18:57
알림 아이콘에 패널·mock을 연동하고, 견적 요청 완료 후 이동 경로를 /estimates/pending으로 맞춘다.

Co-authored-by: Cursor <cursoragent@cursor.com>
미읽음 수 배지를 표시하고, 타입별 고정 문구에 content를 삽입해 강조하며 읽은 알림은 연한 회색으로 구분한다.

Co-authored-by: Cursor <cursoragent@cursor.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/components/common/Header/Header.tsx (2)

168-186: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

알림 배지에 Text 컴포넌트 미사용 + aria-controls 패턴 불일치.

  • 배지 <span>text-[length:var(--font-size-12)] 같은 임의 텍스트 크기 클래스를 직접 사용합니다. 프로필 메뉴 등 다른 텍스트는 모두 Text variant를 쓰는데 이 배지만 예외입니다.
  • aria-controls={notificationPanelId}는 패널이 닫혀 DOM에 없을 때도 항상 설정되는 반면, 바로 아래 프로필 트리거(Line 204)는 isProfileMenuOpen ? ... : undefined로 조건부 처리합니다. 같은 파일 안에서 패턴이 갈립니다.

As per path instructions, "텍스트는 Text 컴포넌트의 variant 를 사용합니다... 직접 text-[16px] 같은 클래스를 쓰면 지적해 주세요."

🎨 Text 컴포넌트 및 aria-controls 일관화
-                aria-controls={notificationPanelId}
+                aria-controls={isNotificationOpen ? notificationPanelId : undefined}
                 {unreadCount > 0 ? (
-                  <span
+                  <Text
+                    as="span"
                     aria-hidden="true"
-                    className="bg-status-error text-text-inverse absolute -top-4 -right-6 flex h-16 min-w-16 items-center justify-center rounded-full px-4 text-[length:var(--font-size-12)] leading-none font-semibold"
+                    variant="sm-semibold" // 프로젝트에 정의된 배지/캡션용 variant로 교체
+                    className="bg-status-error text-text-inverse absolute -top-4 -right-6 flex h-16 min-w-16 items-center justify-center rounded-full px-4 leading-none"
                   >
                     {unreadCount}
-                  </span>
+                  </Text>
                 ) : null}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/common/Header/Header.tsx` around lines 168 - 186, Update the
notification badge in the header to use the existing Text component with the
appropriate variant instead of the direct text-[length:var(--font-size-12)]
class, preserving its current visual styling. Make aria-controls conditional
like the profile trigger: provide notificationPanelId only when
isNotificationOpen is true, otherwise pass undefined.

Source: Path instructions


52-69: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

알림 패널 닫힐 때 포커스 복원 누락.

closeNotification이 상태만 끄고 트리거 버튼으로 포커스를 되돌리지 않습니다. 반면 아래 프로필 메뉴의 closeMenu(Line 71-74)는 triggerRef.current?.focus()로 복원합니다. 사용자가 패널 안(페이지네이션 버튼 등)으로 Tab 이동 후 Escape를 누르면 포커스가 사라진 DOM을 따라가 유실됩니다.

As per coding guidelines, "키보드 접근성, focus·disabled·hover·active 상태, aria 속성, 모달 focus 관리... 확인한다".

♿ 프로필 메뉴 패턴과 일관되게 포커스 복원
+  const notificationTriggerRef = useRef<HTMLButtonElement>(null);
+
   const closeNotification = useCallback(() => {
     setIsNotificationOpen(false);
+    notificationTriggerRef.current?.focus();
   }, []);

그리고 버튼에 ref 연결:

               <button
+                ref={notificationTriggerRef}
                 type="button"
                 aria-label={unreadCount > 0 ? `알림, 읽지 않은 알림 ${unreadCount}개` : "알림"}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/common/Header/Header.tsx` around lines 52 - 69, Update
closeNotification in Header to restore focus to the notification trigger via its
ref after closing, matching the profile menu’s closeMenu behavior. Ensure the
trigger button is connected to the corresponding ref so Escape or outside-click
closure returns focus correctly.

Source: Coding guidelines

svgr.options.ts (1)

35-43: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

다색 아이콘 규칙에도 svgoConfig를 넣어 convertColors를 끄세요. svgrColorOptions는 현재 SVGO 기본값을 그대로 타서 색 값이 정규화될 수 있습니다. **/icons/color/*.svg는 원색 유지가 목적이니 preset-default에서 convertColors: false를 명시하는 게 안전합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@svgr.options.ts` around lines 35 - 43, Update the svgrColorOptions
configuration to include an svgoConfig using the preset-default plugin with
convertColors disabled, preserving original colors for icons under the color
path while leaving the existing runtimeConfig, icon, and svgProps settings
unchanged.
🧹 Nitpick comments (3)
src/components/review/ReviewStarRating.tsx (1)

62-82: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

radiogroup 패턴의 키보드 상호작용이 빠져 있습니다.

WAI-ARIA radio group은 그룹이 하나의 탭 정지점을 갖고 화살표 키로 선택을 이동합니다. 현재는 별 5개가 모두 탭 정지점이며 화살표 키 처리가 없어 스크린 리더 사용자가 예상과 다르게 동작합니다. roving tabindex + onKeyDown 을 추가하거나, 더 간단하게는 sr-only <input type="radio"> + <label> 조합으로 브라우저 기본 동작에 위임하는 방법을 권합니다.

♿ roving tabindex 최소 적용 예
           <button
             key={starValue}
             type="button"
             role="radio"
             aria-checked={starValue === clamped}
             aria-label={`${label} ${starValue}점`}
+            tabIndex={starValue === (clamped || 1) ? 0 : -1}
             disabled={disabled}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/review/ReviewStarRating.tsx` around lines 62 - 82, Update the
radio-group implementation around the star button mapping so only the currently
selected star is tabbable via roving tabindex, while unselected stars use
tabindex -1. Add keyboard handling for ArrowLeft/ArrowUp and
ArrowRight/ArrowDown to move selection appropriately and call onChange, while
preserving disabled behavior and the existing aria-checked state.

Source: Coding guidelines

src/components/review/ReviewsShell.tsx (1)

1-19: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

"use client" 는 제거해도 됩니다.
이 컴포넌트는 상태나 훅이 없고, ReviewTabs만 클라이언트 컴포넌트로 두면 됩니다. 셸은 서버 컴포넌트로 유지해서 클라이언트 경계를 더 좁히세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/review/ReviewsShell.tsx` around lines 1 - 19, Remove the "use
client" directive from ReviewsShell so it remains a server component, while
keeping ReviewTabs as the client component that provides the interactive
behavior. Preserve the existing ReviewsShellProps interface and children
rendering unchanged.

Source: Coding guidelines

src/components/common/Header/Header.tsx (1)

58-69: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Escape 처리를 공용 훅으로 분리해도 좋습니다.
알림 패널과 프로필 메뉴가 각각 Escape 리스너를 직접 등록합니다. useEscapeKey(isOpen, onEscape) 같은 훅으로 묶고, 프로필 메뉴의 화살표/Home/End 처리만 남기면 중복이 줄어듭니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/common/Header/Header.tsx` around lines 58 - 69, Extract the
Escape-key listener logic from Header’s notification effect into a shared
useEscapeKey(isOpen, onEscape) hook, then use that hook for the notification
panel and profile menu. Remove their duplicated Escape listener setup while
preserving the profile menu’s existing Arrow/Home/End keyboard handling.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/review/MyReviewCard.tsx`:
- Around line 29-30: Remove the redundant aria-label from the element using
aria-labelledby in MyReviewCard, leaving aria-labelledby as the single
accessible-name source so the existing heading-based link name remains
authoritative.

In `@src/components/review/ReviewTabs.tsx`:
- Around line 20-23: Review the nav element in ReviewTabs and replace the
hardcoded shadow-[0_2px_5px_0_rgba(...)] utility with the appropriate semantic
shadow-* utility defined by the project’s design tokens in tokens.theme.css,
preserving the existing border and layout classes.

In `@src/components/review/WritableReviewCard.tsx`:
- Line 21: Update the displayName fallback in
src/components/review/WritableReviewCard.tsx:21-21 and
src/components/review/ReviewWriteModal.tsx:51-51 from the literal "기사님" to
mover.name, preserving the existing trimmed nickname behavior. This keeps the
rendered title and aria-label references in WritableReviewCard and
ReviewWriteModal from duplicating the suffix.

In `@src/lib/auth/session.ts`:
- Around line 23-55: 분리된 브라우저 이벤트 계층으로 notifyAuthSessionChange와
subscribeAuthSession의 window.dispatchEvent 및 전역 리스너 등록·해제 로직을 이동하고,
src/lib/auth/session.ts에는 순수한 인증 세션 로직만 남기세요. 인증 모듈에서 해당 부수효과를 유지해야 한다면 이 파일을
규칙의 명시적 예외로 문서화하세요.

In `@src/lib/mocks/reviews.mock.ts`:
- Around line 231-245: Update getMockMyReviews to normalize query.limit to a
positive integer before calculating totalPages, pagination, and slicing; ensure
zero, negative, and non-integer limits cannot produce Infinity or broken
pagination, while preserving the existing default behavior for omitted limits.

---

Outside diff comments:
In `@src/components/common/Header/Header.tsx`:
- Around line 168-186: Update the notification badge in the header to use the
existing Text component with the appropriate variant instead of the direct
text-[length:var(--font-size-12)] class, preserving its current visual styling.
Make aria-controls conditional like the profile trigger: provide
notificationPanelId only when isNotificationOpen is true, otherwise pass
undefined.
- Around line 52-69: Update closeNotification in Header to restore focus to the
notification trigger via its ref after closing, matching the profile menu’s
closeMenu behavior. Ensure the trigger button is connected to the corresponding
ref so Escape or outside-click closure returns focus correctly.

In `@svgr.options.ts`:
- Around line 35-43: Update the svgrColorOptions configuration to include an
svgoConfig using the preset-default plugin with convertColors disabled,
preserving original colors for icons under the color path while leaving the
existing runtimeConfig, icon, and svgProps settings unchanged.

---

Nitpick comments:
In `@src/components/common/Header/Header.tsx`:
- Around line 58-69: Extract the Escape-key listener logic from Header’s
notification effect into a shared useEscapeKey(isOpen, onEscape) hook, then use
that hook for the notification panel and profile menu. Remove their duplicated
Escape listener setup while preserving the profile menu’s existing
Arrow/Home/End keyboard handling.

In `@src/components/review/ReviewsShell.tsx`:
- Around line 1-19: Remove the "use client" directive from ReviewsShell so it
remains a server component, while keeping ReviewTabs as the client component
that provides the interactive behavior. Preserve the existing ReviewsShellProps
interface and children rendering unchanged.

In `@src/components/review/ReviewStarRating.tsx`:
- Around line 62-82: Update the radio-group implementation around the star
button mapping so only the currently selected star is tabbable via roving
tabindex, while unselected stars use tabindex -1. Add keyboard handling for
ArrowLeft/ArrowUp and ArrowRight/ArrowDown to move selection appropriately and
call onChange, while preserving disabled behavior and the existing aria-checked
state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e1bc0fce-f82c-44c9-9371-aeff0035088c

📥 Commits

Reviewing files that changed from the base of the PR and between 7c529ec and 7ba4d53.

📒 Files selected for processing (31)
  • next.config.ts
  • src/app/reviews/layout.tsx
  • src/app/reviews/me/page.tsx
  • src/app/reviews/page.tsx
  • src/app/reviews/writable/page.tsx
  • src/components/common/Header/Header.tsx
  • src/components/estimate/EstimateRequestForm.tsx
  • src/components/estimate/pending/PendingEstimateCard.tsx
  • src/components/review/MyReviewCard.tsx
  • src/components/review/MyReviewsPageClient.tsx
  • src/components/review/ReviewEmptyState.tsx
  • src/components/review/ReviewPageFrame.tsx
  • src/components/review/ReviewStarRating.tsx
  • src/components/review/ReviewTabs.tsx
  • src/components/review/ReviewWriteModal.tsx
  • src/components/review/ReviewsShell.tsx
  • src/components/review/WritableReviewCard.tsx
  • src/components/review/WritableReviewsPageClient.tsx
  • src/hooks/useCreateReview.ts
  • src/hooks/useMyReviews.ts
  • src/hooks/useReviewableEstimates.ts
  • src/lib/api/reviews.ts
  • src/lib/auth/session.ts
  • src/lib/constants/apiRoutes.ts
  • src/lib/constants/appRoutes.ts
  • src/lib/constants/queryKeys.ts
  • src/lib/dev-auth.ts
  • src/lib/mocks/reviews.mock.ts
  • src/types/estimate.ts
  • src/types/review.ts
  • svgr.options.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/estimate/EstimateRequestForm.tsx

Comment thread src/components/review/MyReviewCard.tsx Outdated
Comment thread src/components/review/ReviewTabs.tsx
Comment thread src/components/review/WritableReviewCard.tsx Outdated
Comment thread src/lib/auth/session.ts
Comment thread src/lib/mocks/reviews.mock.ts
@9g-g9

9g-g9 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

작업 고생 많으셨습니다! 👍
header 내 알람 추가 하신 것으로 이해했습니다.

크게 문제는 없어보이는데, Text component 이용과 shadow token 에 대해 인라인 코멘트 남겨두겠습니다!

신영미 and others added 3 commits July 28, 2026 16:32
알림 linkUrl이 있는 항목은 클릭 이동 시 패널이 닫히도록 하고, 알림이 없을 때는 빈 상태 문구를 표시하며 페이지네이션을 숨긴다.

Co-authored-by: Cursor <cursoragent@cursor.com>
feature/estimate-request 브랜치에 최신 dev 변경사항을 병합하고 Header 충돌을 해소한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
Header 병합 충돌을 해결해 feature/estimate-request와 원격 브랜치 상태를 동기화한다.

Co-authored-by: Cursor <cursoragent@cursor.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/common/Header/Header.tsx`:
- Around line 174-194: Update the notification button in Header so aria-controls
references notificationPanelId only when isNotificationOpen is true; omit the
attribute while the conditionally rendered NotificationPanel is closed, matching
the profile menu’s conditional ARIA behavior.

In `@src/components/estimate/EstimateRequestForm.tsx`:
- Line 321: Update the CTA text associated with the /estimates/pending link in
EstimateRequestForm so it refers to pending or in-progress estimates rather than
received estimates, matching the destination’s established naming.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ad3d0f77-f67a-4f85-9eb3-3534b447a655

📥 Commits

Reviewing files that changed from the base of the PR and between 7ba4d53 and bde8990.

📒 Files selected for processing (6)
  • src/components/common/Header/Header.tsx
  • src/components/common/Header/NotificationPanel.tsx
  • src/components/common/Header/notificationMessages.ts
  • src/components/estimate/EstimateRequestForm.tsx
  • src/lib/mocks/notifications.mock.ts
  • src/types/notification.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/types/notification.ts
  • src/lib/mocks/notifications.mock.ts
  • src/components/common/Header/notificationMessages.ts
  • src/components/common/Header/NotificationPanel.tsx

Comment thread src/components/common/Header/Header.tsx
Comment thread src/components/estimate/EstimateRequestForm.tsx
리뷰 카드와 작성 모달의 표시명 fallback을 mover.name으로 통일하고, 알림 버튼 aria-controls 조건부 처리 및 인증 세션 이벤트 예외 문서를 보강한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread src/components/common/Header/Header.tsx Outdated
Comment thread src/components/common/Header/NotificationPanel.tsx Outdated
신영미 and others added 2 commits July 28, 2026 17:47
배지 숫자에 Text 컴포넌트를 적용하고, 알림 패널 그림자를 디자인 토큰(shadow-notification)으로 치환해 스타일 일관성을 맞춘다.

Co-authored-by: Cursor <cursoragent@cursor.com>
styles 토큰 충돌을 해결하고 notification/toast shadow 토큰을 모두 반영한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
@youngmis
youngmis merged commit 32e4eef into dev Jul 28, 2026
1 check was pending

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/common/Header/Header.tsx (1)

47-68: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

알림 패널을 닫을 때 트리거 버튼으로 포커스를 복귀시켜 주세요.

현재 closeNotification은 패널만 제거하므로 닫기 버튼이나 Escape로 닫은 뒤 포커스가 제거될 요소에 남습니다. 알림 버튼에 ref를 연결하고 키보드 닫기 경로에서는 해당 버튼으로 포커스를 복귀하세요. 바깥 클릭 닫기에서는 사용자의 클릭 위치를 빼앗지 않도록 별도 경로로 처리하는 것이 좋습니다.

Also applies to: 174-198

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/common/Header/Header.tsx` around lines 47 - 68, Update
closeNotification and the notification trigger flow to restore focus to the
notification button when the panel closes via its close button or Escape. Add
and attach a ref to the trigger button, and use a keyboard/programmatic close
path that focuses it after closing; keep outside-click dismissal separate so it
does not steal focus from the user’s click target.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/components/common/Header/Header.tsx`:
- Around line 47-68: Update closeNotification and the notification trigger flow
to restore focus to the notification button when the panel closes via its close
button or Escape. Add and attach a ref to the trigger button, and use a
keyboard/programmatic close path that focuses it after closing; keep
outside-click dismissal separate so it does not steal focus from the user’s
click target.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 57faab64-c1aa-4c5f-8053-b051423e6d39

📥 Commits

Reviewing files that changed from the base of the PR and between f7687ee and 57a22e8.

📒 Files selected for processing (3)
  • src/components/common/Header/Header.tsx
  • src/components/common/Header/NotificationPanel.tsx
  • src/styles/tokens.theme.css

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants