feat: 보낸 견적 요청 취소 기능 추가 - #60
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
상세 본문을 w-220으로 넓히고 콘텐츠 블록을 가운데 모아 좌측 치우침을 줄인다. Co-authored-by: Cursor <cursoragent@cursor.com>
취소 가능 상태 헬퍼를 공용화하고, Header를 아이콘+텍스트 버튼으로 바꾼다. Co-authored-by: Cursor <cursoragent@cursor.com>
기사님 코멘트를 상세 정보 하단에 연결하고, PENDING|OPEN일 때 Trash로 요청 취소를 제공한다. Co-authored-by: Cursor <cursoragent@cursor.com>
📝 WalkthroughWalkthrough견적 요청 취소 API와 mutation 훅을 추가했습니다. 상세 화면에 취소 버튼과 확인 모달을 연결했습니다. 취소 성공 후 목록으로 이동하고 일회성 완료 토스트를 표시합니다. 상세 레이아웃, 댓글 표시와 공통 헤더 반응형 동작도 변경했습니다. Changes견적 요청 취소
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant EstimateRequestDetailView
participant useEstimateRequestCancelFlow
participant EstimateRequestCancelConfirmModal
participant useCancelEstimateRequest
participant cancelEstimateRequest
participant EstimateRequestsPageClient
EstimateRequestDetailView->>useEstimateRequestCancelFlow: 취소 모달 열기
useEstimateRequestCancelFlow->>EstimateRequestCancelConfirmModal: 모달 상태 전달
EstimateRequestCancelConfirmModal->>useEstimateRequestCancelFlow: 취소 확인
useEstimateRequestCancelFlow->>useCancelEstimateRequest: 취소 mutation 실행
useCancelEstimateRequest->>cancelEstimateRequest: DELETE 요청 전송
cancelEstimateRequest-->>useCancelEstimateRequest: 취소 결과 반환
useEstimateRequestCancelFlow->>EstimateRequestsPageClient: sessionStorage 플래그 저장 후 목록 이동
EstimateRequestsPageClient->>EstimateRequestsPageClient: 플래그 읽기 및 삭제
EstimateRequestsPageClient-->>EstimateRequestDetailView: 취소 완료 Toast 표시
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (5)
src/components/estimate/detail/EstimateDetailActions.tsx (1)
82-99: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value취소 아이콘 버튼 스타일이 중복됩니다.
EstimateRequestDetailView의 헤더 취소 버튼도 동일한border-border-default·hover:bg-background-hover·focus-visible:ring-*·disabled:*조합을 사용합니다. 공통 취소 버튼 컴포넌트나cvavariant 로 추출하면 두 화면의 상태 스타일이 어긋나지 않습니다. 급한 변경은 아닙니다.🤖 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/EstimateDetailActions.tsx` around lines 82 - 99, Extract the duplicated cancel-button styling from EstimateDetailActions and EstimateRequestDetailView into a shared cancel button component or cva variant, then reuse it in both buttons. Preserve the existing border, hover, focus-visible, disabled, layout, and loading-state behavior.src/components/estimate/pending/PendingEstimateDetailView.tsx (1)
90-96: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
comment.trim()판정이 두 곳에 중복됩니다.
EstimateDetailView와 동일합니다. 구분선 조건과EstimateDetailComment내부 조건이 각각trim()을 평가합니다. 구분선을EstimateDetailComment안으로 옮겨 판정을 한 곳으로 모아 주세요.🤖 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/pending/PendingEstimateDetailView.tsx` around lines 90 - 96, Move the conditional divider from the layout around EstimateDetailComment into the EstimateDetailComment component so comment.trim() is evaluated in only one place. Update PendingEstimateDetailView to render EstimateDetailComment without its separate divider condition, while preserving the existing divider and comment visibility behavior.src/components/estimate/detail/EstimateDetailView.tsx (1)
93-99: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
comment.trim()판정이 두 곳에 중복됩니다.여기서 구분선 표시를 위해
data.comment.trim()을 평가하고,EstimateDetailComment내부에서도 다시comment.trim()을 평가합니다. 두 조건이 어긋나면 코멘트 없이 구분선만 남습니다. 구분선을EstimateDetailComment상단으로 옮기면 판정이 한 곳으로 모입니다.🤖 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/EstimateDetailView.tsx` around lines 93 - 99, EstimateDetailView의 중복된 data.comment.trim() 판정을 제거하고, 구분선 렌더링을 EstimateDetailComment 내부 상단으로 이동하세요. 코멘트 표시와 구분선이 동일한 trim 결과를 사용하도록 하며, EstimateDetailView에서는 EstimateDetailComment에 comment만 전달하는 기존 흐름을 유지하세요.src/components/estimate/detail/EstimateDetailComment.tsx (1)
7-42: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
SentEstimateComment를EstimateDetailComment로 통합해 주세요.두 컴포넌트의 본문 마크업과 spacing·타이포가 중복됩니다. 통합할 때
comment.trim()과 빈 문자열 렌더링 제외 동작, 고유한aria-labelledbyID를 유지하세요.🤖 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/EstimateDetailComment.tsx` around lines 7 - 42, SentEstimateComment와 EstimateDetailComment의 중복 본문 구조를 하나의 공통 컴포넌트로 통합하세요. 통합 컴포넌트는 comment.trim() 결과를 렌더링하고 빈 문자열이면 null을 반환하며, 기존 spacing·타이포를 유지해야 합니다. EstimateDetailComment의 고유한 aria-labelledby ID도 보존하고 두 사용처가 통합 컴포넌트를 재사용하도록 수정하세요.Source: Coding guidelines
src/styles/tokens.theme.css (1)
270-273: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value미사용 토큰을 제거해 주세요.
--spacing-185와--spacing-210은 선언만 존재하고 사용처가 없습니다.lg:w-220에 필요한--spacing-220만 유지해 주세요.🤖 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/styles/tokens.theme.css` around lines 270 - 273, Remove the unused --spacing-185 and --spacing-210 declarations from the spacing tokens, while retaining --spacing-220 for the lg:w-220 usage.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/detail/EstimateDetailActions.tsx`:
- Around line 58-67: Update the isConfirmed branch in EstimateDetailActions so a
confirmed estimate with showCancel enabled still renders the cancellation action
alongside the price block. Preserve the existing price-only behavior when
cancellation is unavailable, and ensure the returned layout does not become
empty when EstimateDetailView sets canCancelRequest.
In `@src/components/estimate/detail/EstimateDetailLayout.tsx`:
- Around line 17-18: Update the change-history comments in EstimateDetailLayout
to accurately state the width change as lg:w-185 → lg:w-220 (740→880), replacing
the incorrect lg:w-210 and 840→880 references while preserving the note that
only the desktop content width changes.
- Around line 16-20: EstimateDetailLayout의 mainClassName과 rowClassName에서 데스크톱 컬럼
합계가 max-w-container-desktop의 1200px를 넘지 않도록 조정하세요. lg:w-220을 lg:w-210으로 되돌리거나
lg:gap-40을 줄여 mainClassName, asideClassName, rowClassName의 고정 너비와 간격 합계를 1200px
이하로 유지하고, lg:shrink-0 동작은 보존하세요.
In `@src/components/estimate/detail/EstimateDetailView.tsx`:
- Around line 41-76: Extract the duplicated cancellation flow into a shared
useEstimateRequestCancelFlow(estimateRequestId) hook, centralizing modal and
Toast state, closeCancelModal, useCancelEstimateRequest callbacks,
sessionStorage tracking, navigation, focus restoration, and duplicate-execution
prevention. Replace the corresponding cancellation state and mutation blocks in
src/components/estimate/detail/EstimateDetailView.tsx lines 41-76 and
src/components/estimate/pending/PendingEstimateDetailView.tsx lines 40-73 with
the shared hook while preserving each component’s existing usage.
- Around line 57-59: Update EstimateDetailView’s cancel-modal flow so closing
the modal restores focus to the cancel button. Create and pass a ref for the
cancel button through EstimateDetailActions, then focus that element in
closeCancelModal after setting the modal closed, or reuse the shared Modal
trigger-focus behavior if available.
In `@src/components/estimate/pending/PendingEstimateDetailView.tsx`:
- Around line 54-56: Update closeCancelModal in PendingEstimateDetailView so
closing the cancel modal restores focus to the cancel button instead of only
updating modal state. Add a ref to the cancel button and focus it after setting
the modal closed, matching the existing behavior in EstimateRequestDetailView.
In `@src/components/estimate/requests/EstimateRequestsPageClient.tsx`:
- Around line 15-29: Update the toast state initialization in
EstimateRequestsPageClient to useState(null) and import/use useEffect for
post-mount handling. Move the readCanceledToastMessage call into the effect so
sessionStorage access and removal occur after mounting, then set the returned
message only when present, preserving the existing key and message behavior.
In `@src/hooks/useCancelEstimateRequest.ts`:
- Around line 34-56: Update the onSuccess handler in useCancelEstimateRequest to
also invalidate QUERY_KEYS.ESTIMATES.DETAIL_ROOT, SENT_LIST_ROOT, and
SENT_DETAIL alongside the existing estimate list invalidations, ensuring all
affected estimate detail and sent-estimate prefix caches are refreshed after
cancellation.
---
Nitpick comments:
In `@src/components/estimate/detail/EstimateDetailActions.tsx`:
- Around line 82-99: Extract the duplicated cancel-button styling from
EstimateDetailActions and EstimateRequestDetailView into a shared cancel button
component or cva variant, then reuse it in both buttons. Preserve the existing
border, hover, focus-visible, disabled, layout, and loading-state behavior.
In `@src/components/estimate/detail/EstimateDetailComment.tsx`:
- Around line 7-42: SentEstimateComment와 EstimateDetailComment의 중복 본문 구조를 하나의 공통
컴포넌트로 통합하세요. 통합 컴포넌트는 comment.trim() 결과를 렌더링하고 빈 문자열이면 null을 반환하며, 기존
spacing·타이포를 유지해야 합니다. EstimateDetailComment의 고유한 aria-labelledby ID도 보존하고 두
사용처가 통합 컴포넌트를 재사용하도록 수정하세요.
In `@src/components/estimate/detail/EstimateDetailView.tsx`:
- Around line 93-99: EstimateDetailView의 중복된 data.comment.trim() 판정을 제거하고, 구분선
렌더링을 EstimateDetailComment 내부 상단으로 이동하세요. 코멘트 표시와 구분선이 동일한 trim 결과를 사용하도록 하며,
EstimateDetailView에서는 EstimateDetailComment에 comment만 전달하는 기존 흐름을 유지하세요.
In `@src/components/estimate/pending/PendingEstimateDetailView.tsx`:
- Around line 90-96: Move the conditional divider from the layout around
EstimateDetailComment into the EstimateDetailComment component so comment.trim()
is evaluated in only one place. Update PendingEstimateDetailView to render
EstimateDetailComment without its separate divider condition, while preserving
the existing divider and comment visibility behavior.
In `@src/styles/tokens.theme.css`:
- Around line 270-273: Remove the unused --spacing-185 and --spacing-210
declarations from the spacing tokens, while retaining --spacing-220 for the
lg:w-220 usage.
🪄 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: 642070a5-7478-4e0d-9720-4abeac52d7ed
⛔ Files ignored due to path filters (1)
src/icons/trash.svgis excluded by!**/*.svg
📒 Files selected for processing (19)
src/components/estimate/detail/EstimateDetailActions.tsxsrc/components/estimate/detail/EstimateDetailComment.tsxsrc/components/estimate/detail/EstimateDetailDriverSummary.tsxsrc/components/estimate/detail/EstimateDetailHeader.tsxsrc/components/estimate/detail/EstimateDetailLayout.tsxsrc/components/estimate/detail/EstimateDetailView.tsxsrc/components/estimate/pending/PendingEstimateDetailView.tsxsrc/components/estimate/requests/EstimateRequestCancelConfirmModal.tsxsrc/components/estimate/requests/EstimateRequestDetailView.tsxsrc/components/estimate/requests/EstimateRequestsPageClient.tsxsrc/components/estimate/requests/estimateRequestCancelToast.tssrc/components/estimate/sent/SentEstimateDetailPage.tsxsrc/hooks/useCancelEstimateRequest.tssrc/icons/index.tssrc/lib/api/estimateRequests.tssrc/lib/constants/apiRoutes.tssrc/lib/constants/errorCodes.tssrc/lib/utils/estimateFormat.tssrc/styles/tokens.theme.css
yooseohyeon
left a comment
There was a problem hiding this comment.
작업하느라 수고하셨습니다! 견적 요청 취소를 한 경우 견적 요청이 취소되었다는 걸 "취소됨"을 통해 상세 페이지에서 알려주고 있는 점도 좋았습니다!
대기 견적에서도 견적 요청 취소가 가능한데, 이 경우 기사가 보낸 견적을 거절하는 게 아니라 본인이 작성한 견적 요청을 취소한다는 점을 조금 더 명시하면 좋을 것 같습니다! 다만 안내가 모달에 이미 나와있기 때문에 괜찮을 수도 있을 것 같습니다!
취소 플로우를 공통 훅으로 묶고, Header 취소를 액션 영역으로 옮기며 Desktop 폭 overflow를 해소한다. Co-authored-by: Cursor <cursoragent@cursor.com>
Desktop 좌우 분할을 xl로 옮기고 GNB·Trash/Primary 높이를 맞춰 태블릿 오버플로를 방지한다. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
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 112-115: Update the Header component’s mobile navigation flow
around the hidden nav and navLinks so screens below the md breakpoint expose an
accessible menu trigger. Add a button with type="button" that opens and closes
the mobile menu, support keyboard activation and appropriate expanded state, and
render the existing navLinks in the opened mobile menu while preserving the
desktop navigation behavior.
In `@src/components/estimate/detail/EstimateDetailLayout.tsx`:
- Line 20: EstimateDetailLayout의 asideClassName에서 xl:overflow-clip을 제거하세요. 취소
버튼의 focus-visible:ring-2가 aside 경계에서 잘리지 않도록 overflow 클리핑은 없애고, 가로 overflow 제한은
기존 레이아웃 폭 설정으로 유지하세요.
🪄 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: 0f3dbcab-2260-43ee-894c-278acc4ae60c
📒 Files selected for processing (7)
src/components/common/Header/Header.tsxsrc/components/estimate/detail/EstimateDetailActions.tsxsrc/components/estimate/detail/EstimateDetailHeader.tsxsrc/components/estimate/detail/EstimateDetailLayout.tsxsrc/components/estimate/detail/EstimateDetailView.tsxsrc/components/estimate/pending/PendingEstimateDetailView.tsxsrc/components/estimate/requests/EstimateRequestDetailView.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
- src/components/estimate/detail/EstimateDetailView.tsx
- src/components/estimate/detail/EstimateDetailHeader.tsx
- src/components/estimate/pending/PendingEstimateDetailView.tsx
📋 작업 내용
PENDING/OPEN상태일 때 견적 요청 soft cancel 기능을 추가합니다.🔥 변경 사항
DELETE /estimate-requests/:id연동 (cancelEstimateRequest,useCancelEstimateRequest)견적 요청 취소하기버튼 노출 (PENDING/OPEN만)comment필드로 기사님 코멘트 표시 (빈 값이면 섹션·Divider 숨김)상세 정보 → Divider → 기사님 코멘트[Trash] [견적 확정하기](estimateRequest.status가PENDING/OPEN일 때만 Trash)견적이 확정되었습니다aside 문구 제거,확정견적Badge 유지lg:w-220(880px) + 콘텐츠 중앙 정렬✅ 체크리스트
📷 스크린샷 (선택)
🔗 관련 이슈
Closes #
💬 To Reviewer
estimateId)이 아니라 연결된estimateRequest.id로 요청 전체를 soft cancel합니다.PENDING/OPEN만 사용합니다.Trash+ Primary)와 aside 견적가 표시 분기(lg만)를 봐주시면 좋습니다.Summary by CodeRabbit