Skip to content

feat: 마이페이지 예약 현황 API 연동#82

Merged
yooseolhee merged 4 commits into
developfrom
feat/reservation-situation-api
Feb 12, 2026
Merged

feat: 마이페이지 예약 현황 API 연동#82
yooseolhee merged 4 commits into
developfrom
feat/reservation-situation-api

Conversation

@yooseolhee

@yooseolhee yooseolhee commented Feb 12, 2026

Copy link
Copy Markdown
Contributor

💡 개요

마이페이지 예약 현황 API 연동

🔢 관련 이슈 링크

💻 작업내용

  • 예약 조회 API 연동
  • 예약 취소 API 연동

📌 변경사항PR

  • FEAT: 새로운 기능 추가
  • FIX: 버그/오류 수정
  • CHORE: 코드/내부 파일/설정 수정
  • DOCS: 문서 수정(README 등)
  • REFACTOR: 코드 리팩토링 (기능 변경 없음)
  • TEST: 테스트 코드 추가/수정
  • STYLE: 스타일 변경(포맷, 세미콜론 등)

🤔 추가 논의하고 싶은 내용

✅ 체크리스트

  • 브랜치는 잘 맞게 올렸는지
  • 관련 이슈를 맞게 연결했는지
  • 로컬에서 정상 동작을 확있했는지
  • 충돌이 없다(또는 브랜치에서 충돌 해결 후 PR 업데이트 완료)

Summary by CodeRabbit

  • 새로운 기능
    • API 기반 예약 조회 기능 추가 (상태별 필터 및 페이징 지원)
    • 예약 취소 기능 추가(선택적 취소 사유 입력, 취소 후 목록 갱신)
    • 예약 페이지 UI 개선 — 로딩/오류 상태 표시, 예약 카드 레이아웃 및 상세 정보 구성
    • 예약 상태와 결제 정보의 지역화된(한국어) 표시 및 상태 배지 적용

@yooseolhee yooseolhee self-assigned this Feb 12, 2026
@yooseolhee yooseolhee added the API label Feb 12, 2026
@vercel

vercel Bot commented Feb 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
eatsfine Ready Ready Preview, Comment Feb 12, 2026 6:48am

@coderabbitai

coderabbitai Bot commented Feb 12, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

마이페이지 예약 현황을 API 기반으로 전환했습니다. 신규 src/api/bookings.ts가 추가되어 예약 조회 및 취소 API 헬퍼를 제공하고, reservationPage.tsx가 해당 API를 사용하도록 변경되었습니다. 소소한 포맷 수정이 한 파일에 적용되었습니다.

Changes

Cohort / File(s) Summary
예약 API 모듈
src/api/bookings.ts
예약 관련 타입(BookingStatus, ApiBookingStatus) 및 인터페이스(Booking, BookingResponse) 추가. getBookings(status?, page)cancelBooking(bookingId, reason?) API 헬퍼 추가 (axios api 인스턴스 사용).
마이페이지 예약 현황
src/pages/myPage/reservationPage.tsx
API 연동으로 데이터 로드 흐름 변경: fetchReservations 도입, 탭별 상태 매핑, 로딩/에러/빈화면 처리, ReservationCard/InfoItem 분리, 취소 흐름(cancelBooking) 구현 및 부모 새로고침 트리거링. 기존 인메모리 필터 로직 제거.
포맷/스타일 소소 변경
src/pages/ownerPage.tsx
Import 뒤 빈 줄 추가 (포맷팅 변경).

Sequence Diagram

sequenceDiagram
    participant User as 사용자
    participant Page as ReservationPage
    participant API as bookings API
    participant Server as Backend

    User->>Page: 탭 선택 / 취소 클릭
    Page->>Page: useEffect / handleCancel 실행
    Page->>API: getBookings(status,page) / cancelBooking(id,reason)
    API->>Server: GET /bookings?status=...&page=... / PATCH /bookings/{id}
    Server-->>API: BookingResponse / 취소 응답
    API-->>Page: 매핑된 Reservation[] / 취소 결과
    Page->>Page: 상태 업데이트 (reservations, loading)
    Page-->>User: 화면에 최신 예약 목록 또는 알림 표시
Loading

🎯 Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Suggested labels

feat

Suggested reviewers

  • jjjsun
  • dew102938

검토 포인트 (버그·안정성·성능·구조 중심, 근거 + 대안)

  1. 에러 처리 및 로딩 상태 일관성
  • 근거: fetchReservations에서 네트워크 실패나 권한 오류 처리 흐름이 불명확함.
  • 대안(예):
const fetchReservations = async () => {
  setLoading(true);
  try {
    const status = tabStatusMap[activeTab];
    const res = await getBookings(status, 1);
    setReservations(res.reservations.map(mapper));
  } catch (e) {
    console.error('fetchReservations failed', e);
    setReservations([]);
    setError('예약 정보를 불러오지 못했습니다.');
  } finally {
    setLoading(false);
  }
};
  1. cancelBooking 성공/실패 판정 명확화
  • 근거: API 응답 형태가 불명확하면 UI에서 잘못된 성공 처리가 될 수 있음.
  • 대안: cancelBooking은 HTTP 상태와 응답 체인을 검증해 boolean 또는 표준화된 응답 타입을 반환하도록 수정. 예: { success: boolean, booking?: Booking }
  1. 상태 매핑 중앙화 필요성
  • 근거: ApiBookingStatus ↔ UI 한글 상태 간 매핑이 여러 곳에 분산되면 유지보수 부담.
  • 대안: src/api/bookings.ts 또는 별도 유틸에 매핑 함수/테이블을 두고 재사용:
export const mapApiToUiStatus = (s: ApiBookingStatus): BookingStatus => ({
  CONFIRMED: '예약 확정',
  COMPLETED: '방문 완료',
  CANCELED: '취소됨'
}[s]);
  1. 페이지네이션 미사용 감지
  • 근거: getBookings는 page 파라미터를 받지만 페이지네이션 UI/로드 더보기 로직이 없음. 예약이 많을 경우 성능/UX 문제.
  • 대안: 초기 구현에서는 페이지 1만 사용하되 TODO로 표기하거나, 무한 스크롤 / 더보기 버튼 추가 계획 수립.
  1. 컴포넌트 추출 및 재사용성
  • 근거: InfoItem이 카드 내부에서 반복 사용됨. 다른 위치에서도 쓰일 가능성.
  • 대안: 재사용 가능하면 별도 파일로 추출해 테스트/스타일 일관성 확보.

Poem

📅 API가 문을 열면 예약들이 춤추고,
🧭 탭을 누르면 데이터가 길 따라 흐르네.
🔄 취소의 클릭엔 확인과 응답이 와 닿고,
✨ 카드 하나하나가 새로 고쳐진 얼굴로 반겨주네.
🎉 작은 포맷도 반짝—전체가 깔끔해졌어요!

🚥 Pre-merge checks | ✅ 2 | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning ownerPage.tsx의 공백 추가는 #79 범위(reservationPage.tsx)와 무관한 변경사항입니다. ownerPage.tsx의 형식 변경은 범위 밖입니다. 별도 PR로 처리하거나 제거하시기 바랍니다.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive PR에서 #79의 'API 연동' 요구사항을 구현했으나, 예외처리(로딩/에러/빈화면) 완료 항목이 미흡합니다. #79의 예외처리 요구사항을 보완하거나, 별도 PR로 진행할 계획을 명시하시기 바랍니다.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 마이페이지 예약 현황 API 연동이라는 핵심 변경사항을 명확하게 요약하고 있습니다.
Description check ✅ Passed PR 설명이 템플릿을 따르고 있으며, 개요, 관련 이슈, 작업내용, 체크리스트가 모두 작성되어 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/reservation-situation-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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

🤖 Fix all issues with AI agents
In `@src/api/bookings.ts`:
- Around line 29-35: Replace the loose typing and blind assertion in
getBookings: create a small params interface (e.g., BookingParams { page:
number; status?: ApiBookingStatus }) and use it instead of params: any, and stop
using an unconditional cast to BookingResponse; instead, type the axios call
with a response shape (or check response.data.result) and validate that
response.data && response.data.result exist and match expected shape before
returning — if the result is missing or invalid, throw or return a clear
error/nullable value rather than silently casting. Target symbols: getBookings,
BookingParams (new), ApiBookingStatus, BookingResponse, and
response.data.result.

In `@src/pages/myPage/reservationPage.tsx`:
- Line 24: The two useState declarations are combined on one line which hurts
readability; split the single line "const [reservations, setReservations] =
useState<Reservation[]>([]); const [loading, setLoading] = useState(false);"
into two separate statements so that "const [reservations, setReservations] =
useState<Reservation[]>([]);" and "const [loading, setLoading] =
useState(false);" each appear on their own line (referencing the
reservations/setReservations and loading/setLoading hooks in
reservationPage.tsx).
- Around line 46-47: Remove the stray debug console.log and the unnecessary
unsafe cast: delete the console.log("fetchReservations status:", apiStatus) and
call getBookings(apiStatus) without using "as any"; apiStatus already matches
the expected union type ("CONFIRMED" | "COMPLETED" | "CANCELED" | undefined) so
pass it directly to getBookings to restore type safety in reservationPage.tsx.
- Around line 49-56: The mapping over data.bookingList can throw if bookingList
is null/undefined; update the mapped creation in reservationPage.tsx to
defensively handle missing lists by using a default empty array (e.g., replace
data.bookingList.map(...) with (data.bookingList ?? []).map(...) or
data.bookingList?.map(...) ?? []) so mapped: Reservation[] is always created
from an array and avoid runtime errors; keep the same field mappings (id ->
bookingId, shopName -> storeName, etc.) and ensure people/time/payment fall back
as before.
- Around line 74-78: Add an explicit error state and show an error UI when the
API call fails: declare a state like const [error, setError] = useState<string |
null>(null) in reservationPage.tsx, set setError(errorMessage) inside the catch
block where console.error("예약 내역 조회 실패", error) is called, clear error
(setError(null)) when starting the fetch (before setLoading(true)), and update
the component render logic to show a dedicated error view when error is non-null
instead of the empty/“no data” screen; keep setLoading(false) in finally so
loading still resolves.
🧹 Nitpick comments (7)
src/api/bookings.ts (2)

37-39: cancelBooking의 반환 타입이 any로 추론됩니다.

response.data는 타입이 지정되지 않아 호출 측에서 타입 안전성이 보장되지 않습니다. 반환 타입을 명시하거나 제네릭을 활용해 주세요.

♻️ 개선 제안
-export const cancelBooking = async (bookingId: number, reason: string = "사용자 취소") => {
-  const response = await api.patch(`/api/v1/bookings/${bookingId}/cancel`, { reason });
-  return response.data;
+interface CancelBookingResponse {
+  // API 응답 구조에 맞게 필드 정의
+  isSuccess: boolean;
+  message: string;
+}
+
+export const cancelBooking = async (bookingId: number, reason: string = "사용자 취소"): Promise<CancelBookingResponse> => {
+  const response = await api.patch<CancelBookingResponse>(`/api/v1/bookings/${bookingId}/cancel`, { reason });
+  return response.data;
 };

As per coding guidelines, src/api/**: 응답 타입 안전성 유지.


3-3: BookingStatus 타입은 사용되지 않으니 제거해도 괜찮습니다.

BookingStatus가 export되었지만 코드 전체에서 실제로 import되거나 사용되는 곳이 없네요. ApiBookingStatus는 API 응답을 위해 실제로 사용 중이니, 혼동을 피하고 코드를 깔끔하게 유지하기 위해 미사용 타입은 제거하는 것을 권장합니다.

src/pages/myPage/reservationPage.tsx (5)

26-79: 들여쓰기가 일관되지 않습니다.

fetchReservations 함수 내부에서 try 블록의 들여쓰기(4칸)와 switch 문의 case 들여쓰기(6칸 → 8칸으로 바뀜)가 혼재되어 있어요. 포맷터(Prettier 등)를 한번 돌려주시면 깔끔해질 것 같습니다.


81-83: useEffect의 의존성 배열에 fetchReservations가 빠져 있어 ESLint 경고가 발생할 수 있습니다.

fetchReservations가 컴포넌트 내부에 정의되어 있고 activeTab을 클로저로 캡처하므로, react-hooks/exhaustive-deps 규칙에 위배됩니다. useCallback으로 감싸거나, fetchReservationsuseEffect 안으로 인라인하는 방법이 있습니다.

다만, fetchReservationsonCancel 콜백으로도 사용하고 있으므로 useCallback이 더 적합합니다.

♻️ useCallback 적용 예시
const fetchReservations = useCallback(async () => {
  // ... 기존 로직
}, [activeTab]);

useEffect(() => {
  fetchReservations();
}, [fetchReservations]);

4-5: 같은 모듈에서의 import를 하나로 합칠 수 있어요.

♻️ 개선 제안
-import { getBookings } from "@/api/bookings";
-import { cancelBooking } from "@/api/bookings";
+import { getBookings, cancelBooking } from "@/api/bookings";

114-124: 페이지네이션 미지원 — 현재 항상 1페이지만 조회합니다.

getBookings API는 page 파라미터를 지원하고, BookingResponse에는 totalPage, isLast 등 페이지네이션 정보가 있지만, 현재 UI에서는 항상 첫 페이지만 요청하고 있어요. 예약이 많은 사용자의 경우 일부 데이터만 보이게 됩니다. 당장은 아니더라도 후속 작업으로 페이지네이션이나 무한 스크롤을 고려해 주세요.


129-145: 취소 후 목록 새로고침 시 race condition 가능성이 있습니다.

handleCancel에서 cancelBooking 성공 후 onCancel()(= fetchReservations)을 호출하는데, 컴포넌트가 unmount된 상태에서 setLoading(false)가 호출될 수 있습니다 (예: 탭 전환 등). 현재로서는 React 18+에서 경고만 발생하고 실질적 오류는 없지만, 안정성을 위해 AbortController나 unmount 체크를 고려할 수 있어요.

또한, confirm()alert()는 브라우저 네이티브 다이얼로그라 UX가 제한적입니다. 프로젝트에 모달 컴포넌트가 있다면 그쪽으로 전환하는 것도 좋겠습니다.

Comment thread src/api/bookings.ts Outdated
Comment thread src/pages/myPage/reservationPage.tsx Outdated
Comment thread src/pages/myPage/reservationPage.tsx Outdated
Comment thread src/pages/myPage/reservationPage.tsx Outdated
Comment thread src/pages/myPage/reservationPage.tsx

@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

🤖 Fix all issues with AI agents
In `@src/pages/myPage/reservationPage.tsx`:
- Line 152: The div's className uses an invalid Tailwind class
`transition-hover`; replace it with a valid transition utility such as
`transition-shadow` (or `transition`) so `hover:shadow-md` will animate smoothly
— update the div with the `className="rounded-2xl border border-gray-200 p-6
transition-shadow hover:shadow-md"` (or `transition`) in the component that
renders this div (e.g., the reservation page component).
🧹 Nitpick comments (3)
src/pages/myPage/reservationPage.tsx (3)

4-5: 같은 모듈에서 import를 두 번 하고 있어요.

한 줄로 합치면 깔끔합니다.

♻️ 개선 제안
-import { getBookings } from "@/api/bookings";
-import { cancelBooking } from "@/api/bookings";
+import { getBookings, cancelBooking } from "@/api/bookings";

83-85: useEffect의 의존성 배열에 fetchReservations가 누락되어 있어요.

fetchReservationsactiveTab 클로저를 캡처하는 함수인데, 의존성 배열에 activeTab만 있어 동작은 합니다. 하지만 react-hooks/exhaustive-deps 린트 규칙에 걸릴 수 있고, 향후 함수에 다른 state 의존성이 추가되면 stale closure 버그로 이어질 수 있습니다.

useCallback으로 감싸거나, effect 내부에 fetch 로직을 인라인하는 방식을 권장합니다.

♻️ useCallback 적용 예시
+import { useCallback } from "react";

// ...

-const fetchReservations = async () => {
+const fetchReservations = useCallback(async () => {
   // ... 기존 로직
-};
+}, [activeTab]);

 useEffect(() => {
   fetchReservations();
-}, [activeTab]);
+}, [fetchReservations]);

136-149: confirm() / alert() 사용은 기능상 문제없지만, 추후 커스텀 모달로 전환을 권장해요.

브라우저 네이티브 다이얼로그는 스타일링이 불가능하고, 접근성(키보드 포커스 복원 등) 면에서도 제약이 있습니다. 현재 단계에서는 괜찮지만, UI 구성 태스크(이슈 #79)에서 같이 개선하시면 좋겠습니다.

Comment thread src/pages/myPage/reservationPage.tsx

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

확인했습니다!

@yooseolhee yooseolhee merged commit ba2df0a into develop Feb 12, 2026
3 checks passed
@jjjsun jjjsun deleted the feat/reservation-situation-api branch February 12, 2026 12:40
@jjjsun jjjsun changed the title Feat: 마이페이지 예약 현황 API 연동 feat: 마이페이지 예약 현황 API 연동 Feb 18, 2026
@jjjsun jjjsun added ✨ Feature 새로운 기능 추가 📪 API 서버 API 연결, 통신 labels Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📪 API 서버 API 연결, 통신 ✨ Feature 새로운 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 마이페이지 예약 현황 API 연동

2 participants