Skip to content

feat: 상세 페이지 네비게이션 UX 개선 - #64

Merged
juengseulki merged 9 commits into
devfrom
feat/detail-navigation-ui
Aug 4, 2026
Merged

feat: 상세 페이지 네비게이션 UX 개선#64
juengseulki merged 9 commits into
devfrom
feat/detail-navigation-ui

Conversation

@juengseulki

@juengseulki juengseulki commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

📋 작업 내용

상세 페이지의 이동 편의성을 개선하기 위해 공통 뒤로가기 버튼과 Scroll To Top 버튼을 추가했습니다.


🔥 변경 사항

공통 뒤로가기

  • 기사님 상세
  • 받았던 견적 상세
  • 대기 중인 견적 상세
  • 보낸 견적 요청 상세

에 작은 Ghost 형태의 뒤로가기 버튼을 추가했습니다.

  • 기존 ArrowLeft 아이콘 재사용
  • router.back() 기반 이동
  • 화면별 fallback 경로 적용
  • 모바일 최소 터치 영역 확보
  • focus-visible 및 aria-label 적용

Scroll To Top

로그인·회원가입·프로필 생성 및 수정 화면을 제외한 일반 페이지에 공통 Top 버튼을 적용했습니다.

  • 기존 컬러 캐릭터 에셋 재사용
  • 캐릭터 하단에 TOP 텍스트 표시
  • 일정 거리 이상 스크롤 시 노출
  • 클릭 시 부드럽게 최상단 이동
  • Desktop / Tablet / Mobile 대응
  • 다른 플로팅 UI와 겹치지 않도록 위치 조정

✅ 체크리스트

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

📷 스크린샷 (선택)

localhost_3000_ localhost_3000_(iPad Pro) localhost_3000_(iPhone 12 Pro) localhost_3000_111

🔗 관련 이슈

Closes #


💬 To Reviewer

  • 기사님 상세 및 견적 상세에서 뒤로가기 버튼의 위치와 UX가 자연스러운지 확인 부탁드립니다.
  • router.back()과 fallback 경로가 의도한 대로 동작하는지 확인 부탁드립니다.
  • Scroll To Top 버튼의 노출 시점(스크롤 거리)과 위치가 Desktop / Tablet / Mobile에서 적절한지 확인 부탁드립니다.
  • Top 버튼이 다른 플로팅 UI(Toast 등)와 겹치지 않는지 확인 부탁드립니다.
  • 로그인/회원가입/프로필 관련 화면에서는 Top 버튼이 노출되지 않는지 확인 부탁드립니다.

Summary by CodeRabbit

  • 새 기능

    • 상세 화면에 뒤로가기 버튼을 추가했습니다. 이전 기록이 없으면 해당 목록으로 이동합니다.
    • 페이지를 아래로 스크롤하면 최상단으로 이동하는 버튼이 표시됩니다.
    • 이동 기사 상세 화면에도 일관된 상세 헤더와 뒤로가기를 제공합니다.
  • 개선 사항

    • 견적 상세 화면의 헤더와 반응형 레이아웃을 개선했습니다.
    • 견적 요청 취소 후 관련 목록과 상세 정보가 최신 상태로 갱신됩니다.
    • 로딩 및 오류 화면에서도 동일한 뒤로가기 경험을 제공합니다.
    • 상세 페이지 간 이동 시 뒤로가기 동작이 더욱 안정적으로 처리됩니다.

jeungseulki and others added 3 commits August 4, 2026 11:39
기사·견적 상세 Header에 작은 뒤로가기를 두고, 이력이 없으면 목록 fallback으로 이동한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
AppShell에 컬러 캐릭터 TOP 버튼을 마운트하고, 인증·프로필 화면에서는 숨긴다.

Co-authored-by: Cursor <cursoragent@cursor.com>
SENT_DETAIL_ROOT invalidate를 추가하고, focus ring이 잘리지 않도록 overflow-clip을 제거한다.

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

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f8f94051-89df-4b3b-ada8-7e4f287495c5

📥 Commits

Reviewing files that changed from the base of the PR and between ba7345d and 702dcca.

📒 Files selected for processing (1)
  • src/components/estimate/sent/SentEstimateDetailPage.tsx

📝 Walkthrough

Walkthrough

상세 화면에 내부 진입을 고려한 fallback 뒤로가기를 추가했습니다. 견적·기사 상세 이동을 기록하고, 공통 최상단 이동 버튼을 연결했습니다. 견적 취소 후 보낸 견적 목록과 상세 캐시를 무효화합니다.

Changes

상세 화면 내비게이션과 공통 UI 제어

Layer / File(s) Summary
뒤로가기 계약과 공통 헤더
src/hooks/useDetailBackNavigation.ts, src/lib/utils/detailNavigation.ts, src/components/common/DetailBackButton.tsx, src/components/estimate/detail/*
내부 상세 진입이면 router.back()을 호출합니다. 그 외에는 fallbackHrefrouter.replace()를 호출합니다. 상세 헤더와 로딩·오류 상태에 뒤로가기 버튼을 연결합니다.
견적과 기사 상세 연결
src/components/estimate/.../*DetailView.tsx, src/components/estimate/sent/SentEstimateDetailPage.tsx, src/components/mover/detail/MoverDetailView.tsx
받은 견적, 대기 견적, 견적 요청, 보낸 견적, 기사 상세의 상태별 fallback 경로를 설정합니다. 기사 상세의 로딩·미존재·오류 상태에도 공통 헤더를 표시합니다.
내부 상세 이동 추적
src/lib/utils/detailNavigation.ts, src/components/estimate/..., src/components/mover/MoverCard.tsx, src/components/review/MyReviewCard.tsx, src/hooks/useMoverDesignation.ts
일반 단일 클릭에서 대상 경로를 sessionStorage에 기록합니다. 견적·기사 상세 링크와 확정 견적 이동이 기록 함수를 호출한 뒤 이동합니다.
공통 스크롤과 캐시 갱신
src/components/common/ScrollToTopButton.tsx, src/components/layout/AppShell.tsx, src/lib/constants/queryKeys.ts, src/hooks/useCancelEstimateRequest.ts
제외 경로에서는 최상단 이동 버튼을 숨깁니다. 400px 이상 스크롤하면 버튼을 표시합니다. 견적 취소 성공 후 관련 보낸 견적 캐시를 무효화합니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant EstimateList
  participant DetailNavigation
  participant DetailPage
  participant DetailBackButton
  participant NextRouter
  EstimateList->>DetailNavigation: 내부 상세 경로 기록
  EstimateList->>NextRouter: 상세 페이지로 이동
  DetailPage->>DetailBackButton: fallbackHref 전달
  DetailBackButton->>DetailNavigation: 내부 진입 상태 소비
  DetailNavigation->>NextRouter: router.back() 또는 fallbackHref로 replace()
Loading

Possibly related PRs

Suggested reviewers: 9g-g9, soooob43

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.15% 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 제목은 공통 뒤로가기와 Scroll To Top을 포함한 상세 페이지 네비게이션 UX 개선이라는 주요 변경을 명확하게 요약합니다.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/detail-navigation-ui

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: 1

🧹 Nitpick comments (2)
src/components/estimate/detail/EstimateDetailHeader.tsx (1)

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

불필요한 "use client"를 제거하세요.

EstimateDetailHeader는 hook, 이벤트 처리, 브라우저 API를 사용하지 않습니다. DetailBackButton만 Client Component로 유지하면 됩니다.

"use client"는 이 파일의 import와 하위 컴포넌트를 클라이언트 그래프에 포함합니다. 정적 헤더까지 Client Component로 만들면 전송 JavaScript 범위가 불필요하게 커집니다. (nextjs.org)

수정 예시
-"use client";
-

As per coding guidelines, “불필요한 상태·useEffect·Client Component를 추가하지 않는다” 규칙을 적용했습니다.

🤖 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/estimate/detail/EstimateDetailHeader.tsx` at line 1, Remove
the top-level "use client" directive from EstimateDetailHeader so it remains a
Server Component. Keep DetailBackButton as the only Client Component boundary
and preserve the existing header rendering.

Sources: Coding guidelines, Path instructions

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

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

위치 spacing에 기존 디자인 토큰을 사용하세요.

1rem, 1.5rem, 2rem, 7rem을 직접 지정하면 공통 spacing 및 반응형 위치 값과 분리됩니다. Safe-area 처리가 필요하면 기존 토큰 또는 공통 safe-area 유틸과 조합하세요.

As per path instructions, src/styles/tokens.theme.css는 Scroll To Top 버튼의 spacing 및 반응형 레이아웃에 토큰 alias 사용을 요구합니다.

🤖 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/ScrollToTopButton.tsx` around lines 87 - 90, Update the
position classes in ScrollToTopButton to use the existing spacing-token aliases
for the 1rem, 1.5rem, 2rem, and 7rem values, including the responsive variants.
Preserve the current safe-area handling by combining those tokens with the
established safe-area utility or token.

Sources: Coding guidelines, 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/hooks/useDetailBackNavigation.ts`:
- Around line 13-19: Update the fallback navigation in the
useDetailBackNavigation callback to call router.replace(fallbackHref) instead of
router.push(fallbackHref), while preserving the existing router.back() behavior
when browser history is available.

---

Nitpick comments:
In `@src/components/common/ScrollToTopButton.tsx`:
- Around line 87-90: Update the position classes in ScrollToTopButton to use the
existing spacing-token aliases for the 1rem, 1.5rem, 2rem, and 7rem values,
including the responsive variants. Preserve the current safe-area handling by
combining those tokens with the established safe-area utility or token.

In `@src/components/estimate/detail/EstimateDetailHeader.tsx`:
- Line 1: Remove the top-level "use client" directive from EstimateDetailHeader
so it remains a Server Component. Keep DetailBackButton as the only Client
Component boundary and preserve the existing header rendering.
🪄 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: f6a2b08a-8500-4df5-b1f3-e9c6392efb4f

📥 Commits

Reviewing files that changed from the base of the PR and between fb1b525 and 7554fdd.

📒 Files selected for processing (13)
  • src/components/common/DetailBackButton.tsx
  • src/components/common/ScrollToTopButton.tsx
  • src/components/estimate/detail/EstimateDetailHeader.tsx
  • src/components/estimate/detail/EstimateDetailLayout.tsx
  • src/components/estimate/detail/EstimateDetailView.tsx
  • src/components/estimate/pending/PendingEstimateDetailView.tsx
  • src/components/estimate/requests/EstimateRequestDetailView.tsx
  • src/components/layout/AppShell.tsx
  • src/components/mover/detail/MoverDetailView.tsx
  • src/hooks/useCancelEstimateRequest.ts
  • src/hooks/useDetailBackNavigation.ts
  • src/icons/index.ts
  • src/lib/constants/queryKeys.ts

Comment thread src/hooks/useDetailBackNavigation.ts Outdated

@yooseohyeon yooseohyeon 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.

작업하느라 수고하셨습니다!
탑 버튼이 적절한 위치에 잘 등장하며 등장하는 애니메이션까지 넣으신 점이 좋았습니다! 디자인도 서비스 기존 디자인과 잘 어울러지게 센스 있게 잘 만들어주신 것 같아요! 뒤로 버튼도 페이지 상단에 너무 크지 않게 위치해 사용자 입장에서 직관적이고 자연스러운 것 같습니다! (콘텐츠 흐름을 끊지 않으면서, 페이지 진입 시 바로 나갈 수 있는 버튼이 보이므로)
다만 기사 상세 페이지는 공유 기능이 있어 외부에서 해당 페이지로 바로 진입하는 케이스가 있을 수 있습니다. 이 경우에 대비해 수정이 필요한 부분이 보여 인라인 코멘트로 남겼습니다!

Comment thread src/hooks/useDetailBackNavigation.ts Outdated
Comment thread src/hooks/useDetailBackNavigation.ts Outdated

@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: 1

🧹 Nitpick comments (1)
src/lib/utils/detailNavigation.ts (1)

14-83: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

src/lib에서 브라우저 상태 접근을 분리하세요.

readInternalDetailNavigation, clearStoredInternalDetailNavigation, markInternalDetailNavigationsessionStorage에 의존하거나 이를 변경합니다. 현재 src/lib/**/*.ts 규칙의 순수 함수 조건을 만족하지 않습니다.

클라이언트 전용 storage 접근은 Hook 또는 client adapter로 이동하세요. src/lib/utils/detailNavigation.ts에는 순수한 pathname 판별 로직만 유지하세요.

As per path instructions, "src/lib/**/*.ts: 순수 함수로 작성하고 부수효과를 두지 않습니다."

🤖 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/lib/utils/detailNavigation.ts` around lines 14 - 83, Move the
sessionStorage-dependent functions readInternalDetailNavigation,
clearStoredInternalDetailNavigation, and markInternalDetailNavigation out of
detailNavigation.ts into a client-only storage adapter or Hook. Keep
detailNavigation.ts limited to pure pathname comparison and decision logic, and
update consumeInternalDetailNavigation, clearInternalDetailNavigation, and
markInternalDetailNavigationOnClick to use the adapter without introducing side
effects in src/lib.

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/components/estimate/sent/SentEstimateDetailPage.tsx`:
- Line 123: Update both loading and error branches in SentEstimateDetailPage to
pass backFallbackHref={APP_ROUTES.MOVER_ESTIMATES.SENT}, matching the normal
EstimateDetailQueryState render and preserving the page’s fallback navigation in
all states.

---

Nitpick comments:
In `@src/lib/utils/detailNavigation.ts`:
- Around line 14-83: Move the sessionStorage-dependent functions
readInternalDetailNavigation, clearStoredInternalDetailNavigation, and
markInternalDetailNavigation out of detailNavigation.ts into a client-only
storage adapter or Hook. Keep detailNavigation.ts limited to pure pathname
comparison and decision logic, and update consumeInternalDetailNavigation,
clearInternalDetailNavigation, and markInternalDetailNavigationOnClick to use
the adapter without introducing side effects in src/lib.
🪄 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: 4cc2ee82-a4ec-4c9e-b3c2-756281c463fd

📥 Commits

Reviewing files that changed from the base of the PR and between b12b5b5 and ba7345d.

📒 Files selected for processing (13)
  • src/components/common/EmptyState/EmptyState.tsx
  • src/components/estimate/pending/PendingEstimateCard.tsx
  • src/components/estimate/received/EstimateOfferCard.tsx
  • src/components/estimate/request/ActiveEstimateBlocked.tsx
  • src/components/estimate/request/EstimateRequestForm.tsx
  • src/components/estimate/requests/EstimateRequestCard.tsx
  • src/components/estimate/sent/SentEstimateDetailPage.tsx
  • src/components/estimate/sent/SentEstimatesPage.tsx
  • src/components/mover/MoverCard.tsx
  • src/components/review/MyReviewCard.tsx
  • src/hooks/useDetailBackNavigation.ts
  • src/hooks/useMoverDesignation.ts
  • src/lib/utils/detailNavigation.ts

Comment thread src/components/estimate/sent/SentEstimateDetailPage.tsx
@juengseulki
juengseulki merged commit 26f6ecd into dev Aug 4, 2026
1 check was pending
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.

2 participants