feat: 견적요청 API 연동 및 토스트 피드백 추가 - #12
Conversation
견적요청 폼을 백엔드 POST API에 연결하고, 인증 토큰 처리와 성공/실패 토스트를 추가했다. Co-authored-by: Cursor <cursoragent@cursor.com>
📝 WalkthroughWalkthrough인증 API와 메모리 기반 토큰 관리, Axios 토큰 갱신, 견적 요청 페이로드 변환 및 제출 흐름이 추가되었습니다. 견적 요청 폼은 주소 객체, ZIP 검증, 로그인·mutation 상태와 토스트 피드백을 관리합니다. Changes견적 요청 흐름
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant EstimateRequestForm
participant login
participant axiosInstance
participant createEstimateRequest
participant Toast
EstimateRequestForm->>login: 로그인 상태 확보
login->>axiosInstance: AUTH.LOGIN 또는 AUTH.REFRESH 요청
axiosInstance-->>login: accessToken 반환 및 저장
EstimateRequestForm->>createEstimateRequest: 견적 페이로드 제출
createEstimateRequest->>axiosInstance: ESTIMATE_REQUESTS POST
axiosInstance-->>createEstimateRequest: 성공 또는 오류 반환
createEstimateRequest-->>EstimateRequestForm: 제출 결과 전달
EstimateRequestForm->>Toast: 결과 메시지 표시
Toast-->>EstimateRequestForm: durationMs 후 onClose 호출
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
src/components/common/Toast.tsx (1)
44-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReplace arbitrary design values with project token utilities.
z-[60],h-[60px],max-w-[640px],rounded-[16px], and the raw shadow bypass the shared scale. Prefer existing token utilities (for example,rounded-16) and retain arbitrary values only where no token can represent the Figma requirement.As per coding guidelines, “Use the project's existing design tokens for colors, fonts, spacing, radius, and shadows instead of hardcoding design values.”
🤖 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/Toast.tsx` around lines 44 - 49, Update the Toast container classes in the component around the cn call to replace arbitrary z-index, height, width, radius, and shadow values with the closest existing project token utilities. Retain arbitrary values only when no matching token exists, while preserving the current layout and appearance.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/estimate/EstimateRequestForm.tsx`:
- Around line 22-26: Remove the TEST_CUSTOMER credentials and the automatic
authentication/retry flow in EstimateRequestForm, including the effects and
submission logic that use them. Require a valid authenticated session before
allowing request submission; otherwise redirect the visitor to the existing
sign-in flow, preserving normal behavior for already authenticated users.
In `@src/lib/api/auth.ts`:
- Around line 31-34: Reject unsuccessful HTTP-200 envelopes before treating
either operation as successful: in src/lib/api/auth.ts lines 31-34, update login
to validate data.success before setAuthTokens and throw on failure; in
src/lib/api/estimateRequest.ts lines 68-75, validate the response success flag
and throw on false so React Query invokes onError. Preserve the existing success
handling when the flag is true.
In `@src/lib/auth/token.ts`:
- Around line 14-16: Update setAuthTokens so it no longer writes
tokens.refreshToken to localStorage via REFRESH_TOKEN_KEY; preserve only the
browser-readable access-token handling and move refresh-token persistence to the
existing secure, HttpOnly, SameSite cookie mechanism, or add that mechanism if
none exists.
---
Nitpick comments:
In `@src/components/common/Toast.tsx`:
- Around line 44-49: Update the Toast container classes in the component around
the cn call to replace arbitrary z-index, height, width, radius, and shadow
values with the closest existing project token utilities. Retain arbitrary
values only when no matching token exists, while preserving the current layout
and appearance.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 11bc6e48-7feb-419e-8d5b-128310287089
📒 Files selected for processing (8)
src/components/common/Toast.tsxsrc/components/estimate/EstimateRequestForm.tsxsrc/lib/api/auth.tssrc/lib/api/axiosInstance.tssrc/lib/api/estimateRequest.tssrc/lib/auth/token.tssrc/lib/constants/apiRoutes.tssrc/lib/utils/date.ts
juengseulki
left a comment
There was a problem hiding this comment.
📋 PR 리뷰
견적 요청 폼을 백엔드 API에 연결하고 요청 결과를 토스트로 안내하는 작업 확인했습니다.
👍 좋았던 점
- 견적 요청 API 호출을 별도 파일로 분리하여 폼 컴포넌트가 HTTP 요청 세부 구현을 직접 담당하지 않도록 구성한 점이 좋았습니다.
- 화면의
small,home,office값을 백엔드 Enum인SMALL,HOME,OFFICE로 변환하는 책임을 API 계층에 둔 점이 적절했습니다. - 카카오 주소 결과를 백엔드의
from,to스키마에 맞게 변환하는 함수가 분리되어 있어 요청 데이터 구성이 명확했습니다. - 날짜 변환 로직을 공통 날짜 유틸로 분리하여 폼 안에서 직접 문자열을 조합하지 않은 점도 좋았습니다.
- 요청 중에는 버튼을 비활성화하고 문구를
요청 중...으로 변경하여 중복 제출을 방지한 점이 좋았습니다. - 토스트에
role="status"와aria-live="polite"를 적용하여 메시지가 보조 기술에도 전달되도록 고려한 점도 확인했습니다. - 요청 인터셉터에서 Access Token을 공통으로 추가하도록 구성하여 인증이 필요한 API마다 헤더를 반복 작성하지 않도록 한 점이 좋았습니다.
🔍 확인 및 제안
- 현재 모든 실패 상황에 기존 견적 확인을 안내하는 동일한 토스트가 표시되므로, 기본 실패 메시지와 오류별 메시지를 구분하면 좋을 것 같습니다.
- 토스트 노출 시간 3초는 일반적인 성공·실패 안내를 읽기에 크게 짧아 보이지 않습니다. 다만 실패 메시지가 두 문장 이상으로 길어진다면 4초 정도로 늘리거나 닫기 버튼을 제공하는 방안도 고려할 수 있습니다.
API 요청 데이터 변환과 공통 인증 헤더 적용은 역할에 맞게 잘 분리되어 있었습니다. 다만 테스트 계정 정보와 자동 로그인 로직은 사용자 인증과 실제 데이터 생성에 직접 영향을 주고 클라이언트에 계정 정보가 노출되는 문제도 있으므로, 추후 작업으로 넘기기보다 이번 PR에서 제거한 뒤 병합하는 것이 필요해 보입니다. 수고하셨습니다! 😊
XSS에 노출되는 refresh 토큰 저장을 제거하고, 실패 토스트는 오류 코드에 맞게 표시합니다. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/lib/api/getApiError.ts`:
- Around line 21-22: Update the Error handling in getApiError so custom API
errors preserve and return their code alongside the message. Ensure
estimateRequest’s success:false path throws that custom error with both code and
message, and change downstream error branching to use error.code rather than
comparing error.message.
🪄 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: ca33fb87-4196-45c8-b0c5-051757017b15
📒 Files selected for processing (6)
src/components/estimate/EstimateRequestForm.tsxsrc/lib/api/auth.tssrc/lib/api/axiosInstance.tssrc/lib/api/estimateRequest.tssrc/lib/api/getApiError.tssrc/lib/auth/token.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/lib/api/estimateRequest.ts
- src/components/estimate/EstimateRequestForm.tsx
| }, durationMs); | ||
|
|
||
| return () => window.clearTimeout(timer); | ||
| }, [open, durationMs, onClose]); |
There was a problem hiding this comment.
deps에 message가 없어서 토스트가 떠 있는 동안 새 토스트를 띄우면 타이머가 리셋되지 않고 일찍 닫힐 수 있을 것 같아요.
deps에 message를 추가하는 것도 좋을 것 같습니다!
| if (!data.success) { | ||
| throw new Error(data.error?.message || data.message || "견적 요청이 실패하였습니다."); | ||
| } |
There was a problem hiding this comment.
여기서 message만 Error에 담겨서 code가 사용되지 않는 것 같습니다.
이 경우 ACTIVE_REQUEST_EXISTS 분기가 동작하지 않을 수 있어서, 서버에서 에러 응답이 어떤 형태로 내려오는지 한번 확인해보시면 좋을 것 같습니다!
📋 작업 내용
🔥 변경 사항
src/components/common/Toast.tsx: 견적요청 성공/실패 메시지를 화면 상단에 띄우는 공통 토스트 컴포넌트
src/components/estimate/EstimateRequestForm.tsx: 선택한 이사 유형·날짜·출발지/도착지를 백엔드 POST 형식으로 보내고, 제출 결과에 따라 토스트를 띄우도록 연결 (현재는 로그인 후 테스트를 위해 하드코딩으로 계정 포함 -> 추후 삭제 예정)
src/lib/api/auth.ts: 백엔드 로그인 API(/auth/login)를 호출하여 로그인 성공 시 access/refresh 토큰을 저장해 이후 API 요청에서 사용
src/lib/api/axiosInstance.ts: 기존 파일 중 요청 인터셉터에서 access token을 Authorization: Bearer 헤더에 자동으로 붙여, 인증이 필요한 API를 공통으로 호출할 수 있도록 로직 추가
src/lib/api/estimateRequest.ts: 프론트 선택값(small/home/office, Date, 주소 객체)을 백엔드 스키마(SMALL/HOME/OFFICE, YYYY-MM-DD, from/to 주소)로 변환해 POST /estimate-requests로 전송
src/lib/auth/token.ts: access/refresh 토큰을 localStorage에 저장·조회·삭제하는 유틸
src/lib/constants/apiRoutes.ts: 백엔드 실제 경로에 맞게 인증 관련 라우트(LOGIN, LOGOUT, SIGN_UP_CUSTOMER 등)를 수정·추가한 파일
src/lib/utils/date.ts: 날짜 유틸에 formatDateToISODate를 추가(Date 객체를 백엔드 moveDate 형식인 YYYY-MM-DD 문자열로 변환)
✅ 체크리스트
📷 스크린샷 (선택)
🔗 관련 이슈
Closes #
💬 To Reviewer
하드 코딩 계정 삭제 예정
const TEST_CUSTOMER = {
email: "customer1@test.com",
password: "Moving123!",
} as const;
async function ensureLogin() 페이지 로드 시 자동로그인 관련 로직 삭제 예정
Summary by CodeRabbit