Skip to content

design: 예약 모달 UX 개선#111

Merged
jjjsun merged 4 commits into
developfrom
design/reservation-ux
Feb 19, 2026
Merged

design: 예약 모달 UX 개선#111
jjjsun merged 4 commits into
developfrom
design/reservation-ux

Conversation

@jjjsun

@jjjsun jjjsun commented Feb 19, 2026

Copy link
Copy Markdown
Contributor

💡 개요

예약 flow 모달들 열리고 닫힐때 애니메이션 추가해서 UX개선

🔢 관련 이슈 링크

💻 작업내용

  • 공통 모달 애니메이션 훅(useModalPresence)추가
  • backdrop, panel 유틸 추가
  • 예약 관련 모달에 적용
  • 닫힘 시에도 자연스럽게 사라지도록 언마운트 지연 처리

📌 변경사항PR

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

🤔 추가 논의하고 싶은 내용

  • N/A

✅ 체크리스트

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

Summary by CodeRabbit

릴리스 노트

  • Style
    • 모든 예약 및 음식점 관련 모달 창에 부드러운 입장/퇴장 애니메이션 추가
    • 모달 백드롭과 패널의 투명도 및 크기 변환 효과로 더욱 자연스러운 시각적 전환 제공

@jjjsun jjjsun self-assigned this Feb 19, 2026
@jjjsun jjjsun added the design label Feb 19, 2026
@vercel

vercel Bot commented Feb 19, 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 19, 2026 6:50pm

@coderabbitai

coderabbitai Bot commented Feb 19, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

새로운 모달 애니메이션 기능을 위해 useModalPresence 훅과 modalMotion 유틸리티를 도입하고, 예약 관련 모달 6개에 동일한 패턴으로 적용하여 진입/종료 애니메이션을 구현합니다.

Changes

Cohort / File(s) Summary
모달 상태 관리 훅
src/hooks/common/useModalPresence.ts, src/hooks/common/useModalMotion.ts
모달의 렌더링 생명주기(rendered, entered)를 관리하는 새로운 훅들 추가. useModalPresence는 애니메이션 지속시간(기본 220ms)을 고려하여 닫기 시 딜레이 처리.
모션 클래스 유틸리티
src/utils/modalMotion.ts
배경과 패널에 적용할 모션 클래스를 생성하는 순수 함수 추가. 불투명도와 스케일 전환으로 애니메이션 구현.
예약 모달 컴포넌트
src/components/reservation/modals/PaymentModal.tsx, ReservationCompleteModal.tsx, ReservationConfirmModal.tsx, ReservationMenuModal.tsx, ReservationModal.tsx
모든 예약 모달에 useModalPresence 훅을 적용하고 backdropMotionClass, panelMotionClass를 className에 병합하여 애니메이션 지원.
레스토랑 상세 모달
src/components/restaurant/RestaurantDetailModal.tsx
예약 모달과 동일 패턴으로 모션 클래스 적용. 로딩/에러 분기 모두에서 일관된 애니메이션 처리.

Sequence Diagram

sequenceDiagram
    participant User
    participant Modal as Modal Component
    participant Presence as useModalPresence
    participant Animation as panelMotionClass
    participant DOM as Rendered DOM

    User->>Modal: open = true
    Modal->>Presence: useModalPresence(true, 220)
    Presence->>Presence: rendered = true
    Note over Presence: requestAnimationFrame
    Presence->>Presence: entered = true
    Presence-->>Modal: { rendered: true, entered: true }
    
    Modal->>Animation: panelMotionClass(true)
    Animation-->>Modal: motion classes (opacity, scale)
    Modal->>DOM: render with motion classes
    DOM-->>User: modal appears with animation

    User->>Modal: open = false
    Modal->>Presence: useModalPresence(false, 220)
    Presence->>Presence: entered = false
    Presence-->>Modal: { rendered: true, entered: false }
    
    Modal->>Animation: panelMotionClass(false)
    Animation-->>Modal: motion classes (opacity, scale hidden)
    Modal->>DOM: update with exit animation
    
    Note over Presence: setTimeout(220ms)
    Presence->>Presence: rendered = false
    Presence-->>Modal: { rendered: false, entered: false }
    Modal->>DOM: unmount
    DOM-->>User: modal disappears
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • feat: 예약중 메뉴선택 UI추가 #39 — 동일한 예약 및 모달 컴포넌트들을 수정하며 모달 렌더링/종료 흐름을 변경하므로 연관성이 높음.
  • feat: 예약 API 연동 #55 — 동일한 모달 컴포넌트들(PaymentModal, ReservationConfirmModal 등)을 수정하며 이 PR의 useModalPresence/useModalMotion 적용과 관련됨.

Suggested labels

feat

Suggested reviewers

  • yooseolhee
  • dew102938

Poem

🎬 모달이 춤을 춘다네~
열릴 땐 부드럽게, 닫힐 땐 우아하게
220ms의 시간 속에서
예약의 꿈이 피어나고... 🌸
애니메이션은 사용자를 행복하게 한다 ✨


💬 팀원들을 위한 리뷰 포인트

좋은 점:

  • ✅ 일관된 패턴으로 모든 모달에 적용되어 유지보수성 좋음
  • ✅ 모달 진입/종료 애니메이션으로 UX 개선
  • ✅ 새로운 훅과 유틸로 관심사 분리 잘됨

체크포인트:

  1. 타임아웃 정리 필수useModalPresence에서 타임아웃을 ref로 관리하고 있는데, 컴포넌트 언마운트나 의존성 변경 시 항상 정리되는지 확인 필요합니다. 🔍

  2. requestAnimationFrame 정리entered 상태 설정할 때 requestAnimationFrame을 사용 중인데, cleanup 함수에서 정리되고 있는지 검토 권장합니다.

    useEffect(() => {
      let frameId: number | null = null;
      let timeoutId: NodeJS.Timeout | null = null;
      
      if (open) {
        frameId = requestAnimationFrame(() => {
          setEntered(true);
        });
      } else {
        setEntered(false);
        timeoutId = setTimeout(() => {
          setRendered(false);
        }, durationMs);
      }
      
      return () => {
        if (frameId !== null) cancelAnimationFrame(frameId);
        if (timeoutId !== null) clearTimeout(timeoutId);
      };
    }, [open, durationMs]);
  3. 모달 초기 렌더링 검증rendered 상태가 false일 때 조건부 렌더링으로 전체 모달이 DOM에서 제거되는데, 초기 로드 시 깜빡임 없이 동작하는지 테스트 권장입니다.

  4. 애니메이션 지속시간 상수화 — 모든 모달에서 220을 하드코딩하고 있는데, 별도의 상수로 분리하면 나중에 일괄 수정이 쉬울 것 같습니다. 👍

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
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.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 예약 모달 UX 개선이라는 주요 변경사항을 명확하게 전달하고 있습니다.
Description check ✅ Passed PR 설명이 개요, 관련 이슈, 작업내용, 변경사항 등 템플릿의 주요 섹션을 모두 포함하고 있습니다.
Linked Issues check ✅ Passed 이슈 #100의 UX 개선 목표를 달성하기 위해 모달 애니메이션 훅, 유틸 함수를 추가하고 예약 관련 모달 6개에 적용했습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 이슈 #100의 모달 애니메이션 및 UX 개선 범위 내에 있습니다.

✏️ 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 design/reservation-ux

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.

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

수고하셨습니다!!

@jjjsun jjjsun merged commit 4a2d3bb into develop Feb 19, 2026
2 checks passed
@jjjsun jjjsun deleted the design/reservation-ux branch February 19, 2026 18:55

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

Caution

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

⚠️ Outside diff range comments (6)
src/components/reservation/modals/ReservationCompleteModal.tsx (1)

38-39: ⚠️ Potential issue | 🟡 Minor

console.log 디버그 로그가 남아 있어요 — 머지 전에 제거해야 합니다.

console.log("[complete] draft=", draft);
console.log("[complete] time=", draft.time);

draft 객체에 개인정보(예약 정보)가 포함될 수 있어서 프로덕션 콘솔에 노출되면 안 됩니다.

✏️ 수정 제안
-  console.log("[complete] draft=", draft);
-  console.log("[complete] time=", draft.time);
   const timeText = toHHmm(time);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/reservation/modals/ReservationCompleteModal.tsx` around lines
38 - 39, Remove the two debug console.log statements that print the reservation
draft (console.log("[complete] draft=", draft) and console.log("[complete]
time=", draft.time)) from ReservationCompleteModal.tsx; either delete them
entirely or replace with a safe, environment-gated logger (e.g., only log when
process.env.NODE_ENV !== 'production') or log non-sensitive, masked fields
instead so no PII/booking details from the draft object are emitted to
production consoles.
src/components/reservation/modals/PaymentModal.tsx (1)

192-197: ⚠️ Potential issue | 🟡 Minor

aria-labelReservationConfirmModal과 동일해요 — 스크린리더가 두 모달을 구분할 수 없습니다.

ReservationConfirmModal(line 98)과 PaymentModal(line 196) 모두 aria-label="예약 내용 확인모달"을 사용하고 있어요. 이 모달은 결제 화면이니 스크린리더 사용자가 어떤 모달인지 명확히 알 수 있도록 레이블을 다르게 설정해야 합니다.

✏️ 수정 제안
-      aria-label="예약 내용 확인모달"
+      aria-label="예약금 결제 모달"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/reservation/modals/PaymentModal.tsx` around lines 192 - 197,
The PaymentModal div uses the same aria-label as ReservationConfirmModal so
screen readers can't distinguish them; update the PaymentModal's dialog element
(the div with role="dialog" in PaymentModal component) to use a distinct,
descriptive aria-label such as "결제 확인 모달" or "결제 정보 확인모달" so it clearly
identifies this as the payment modal to assistive tech; ensure only the
PaymentModal's dialog label is changed and ReservationConfirmModal's label is
left intact.
src/components/reservation/modals/ReservationModal.tsx (1)

170-188: ⚠️ Potential issue | 🔴 Critical

모달에 포커스 트랩과 키보드 네비게이션이 없어요 — 접근성 이슈입니다.

현재 모달은 ARIA 속성(role="dialog", aria-modal="true", aria-label)은 있지만, 키보드 사용자 접근성이 부족해요. 포커스가 모달로 이동하지 않고, Tab 키로 모달 밖 요소에 접근 가능하며, Escape 키도 먹지 않습니다. ARIA Authoring Practices Guide에서는 다이얼로그 모달에 포커스 트랩을 명시적으로 권장합니다.

필수 구현:

  1. 모달 열릴 때 → 첫 포커스 가능 요소(또는 모달 컨테이너)로 포커스 이동
  2. Tab / Shift+Tab → 모달 내 포커스 요소 순환 (밖으로 탈출 불가)
  3. Escape 키 → 모달 닫기 (handleRequestClose 호출)
  4. 모달 닫힐 때 → 트리거 요소로 포커스 복귀

프로젝트에 @radix-ui/react-dialog(v1.1.15)가 이미 설치되어 있습니다. 이를 사용하면 포커스 트랩이 자동으로 제공되므로, @radix-ui/react-dialog로 마이그레이션하거나 @react-aria/focus 같은 검증된 라이브러리를 도입하세요.

이 이슈는 이 PR의 모든 모달(ReservationModal, ReservationConfirmModal, ReservationMenuModal, PaymentModal, ReservationCompleteModal)에 공통으로 해당됩니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/reservation/modals/ReservationModal.tsx` around lines 170 -
188, The ReservationModal currently lacks keyboard focus management; update
ReservationModal to use `@radix-ui/react-dialog` (or an equivalent focus-trap
implementation) so that when the modal opens focus moves into the modal,
Tab/Shift+Tab cycles only through modal focusable elements, Escape calls
handleRequestClose, and on close focus returns to the triggering element;
specifically replace the existing top-level container (the element with
role="dialog" and aria-modal="true") with Radix Dialog primitives (Dialog.Root,
Dialog.Trigger kept outside, Dialog.Overlay for the backdrop, Dialog.Content for
the panel) or wire an equivalent focus-trap that 1) focuses the first tabbable
or the container on mount, 2) adds keyboard handlers to intercept Tab/Shift+Tab
and keep focus inside, 3) listens for Escape to call handleRequestClose, and 4)
saves/restores the trigger element focus on unmount; apply the same migration
pattern to ReservationConfirmModal, ReservationMenuModal, PaymentModal, and
ReservationCompleteModal.
src/components/restaurant/RestaurantDetailModal.tsx (3)

141-148: ⚠️ Potential issue | 🟡 Minor

에러 상태 X 버튼에 aria-label이 없어요

loading 브랜치의 X 버튼(Line 111)에는 aria-label="모달 닫기"가 있는데, error 브랜치의 X 버튼은 빠져 있어요. <X /> 아이콘 단독으로는 스크린 리더가 의미를 파악하기 어려워요.

코딩 가이드라인에 따르면 컴포넌트는 접근성(aria) 체크가 필요해요.

♿ 제안 수정
 <button
   type="button"
+  aria-label="모달 닫기"
   className="p-2 rounded-lg hover:bg-gray-100"
   onClick={() => onOpenChange(false)}
 >
   <X />
 </button>

As per coding guidelines, src/components/** 파일은 접근성(aria) 체크가 요구돼요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/restaurant/RestaurantDetailModal.tsx` around lines 141 - 148,
The error branch's close button in RestaurantDetailModal (the button wrapping
the <X /> icon inside the error render) is missing an aria-label; update the
button rendered in the error branch (the same element that calls
onOpenChange(false)) to include aria-label="모달 닫기" (matching the loading branch)
so screen readers can identify the control and satisfy the component
accessibility checks.

210-216: ⚠️ Potential issue | 🟡 Minor

성공 상태 X 버튼도 aria-label이 없어요

loading 브랜치와 일관성을 맞추려면 success 브랜치의 X 버튼에도 aria-label="모달 닫기"가 필요해요.

♿ 제안 수정
 <button
   type="button"
+  aria-label="모달 닫기"
   onClick={() => onOpenChange(false)}
   className="p-2 rounded-lg hover:bg-gray-100 transition-colors cursor-pointer"
 >
   <X />
 </button>

As per coding guidelines, src/components/** 파일은 접근성(aria) 체크가 요구돼요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/restaurant/RestaurantDetailModal.tsx` around lines 210 - 216,
The success-branch close button in RestaurantDetailModal.tsx (the <button> that
calls onOpenChange(false) and renders <X />) lacks an aria-label; update that
button to include aria-label="모달 닫기" to match the loading branch and satisfy
accessibility checks for components under src/components/**.

125-173: ⚠️ Potential issue | 🟠 Major

status === "error" 브랜치에 애니메이션 클래스가 빠져 있어요 — PR의 핵심 목표가 누락됐어요!

idle/loading 브랜치와 success 브랜치에는 backdropMotionClass(entered) + panelMotionClass(entered)이 적용됐지만, error 브랜치만 하드코딩된 클래스("absolute inset-0 bg-black/40")를 그대로 사용하고 있어요. 덕분에 에러 상태에서 모달을 닫을 때는 애니메이션 없이 뚝 사라져서 UX가 일관되지 않아요.

✨ error 브랜치 애니메이션 적용 제안
 if (status === "error") {
   return (
     <div
       className="fixed inset-0 z-50 flex items-center justify-center p-4"
       role="dialog"
       aria-modal="true"
       aria-label="식당 상세 오류"
     >
       <button
         type="button"
-        className="absolute inset-0 bg-black/40"
+        className={backdropMotionClass(entered)}
+        aria-label="모달 닫기"
         onClick={() => onOpenChange(false)}
       />
-      <div className="relative z-10 w-[92vw] max-w-3xl rounded-2xl bg-white shadow-xl p-6">
+      <div
+        className={cn(
+          "relative z-10 w-[92vw] max-w-3xl rounded-2xl bg-white shadow-xl p-6",
+          panelMotionClass(entered),
+        )}
+      >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/restaurant/RestaurantDetailModal.tsx` around lines 125 - 173,
The error branch in RestaurantDetailModal (the status === "error" return) uses a
hardcoded backdrop class ("absolute inset-0 bg-black/40") and plain panel
classes, so add the same animation classes used in the other branches: replace
the hardcoded backdrop button class with backdropMotionClass(entered) and add
panelMotionClass(entered) to the modal panel wrapper (the div with "relative
z-10 ...") so the error modal uses the same enter/exit animations; ensure you
reference the same entered state/variable and the existing backdropMotionClass
and panelMotionClass helpers used in idle/loading and success branches and keep
onOpenChange/unmount behavior identical.
🧹 Nitpick comments (1)
src/components/restaurant/RestaurantDetailModal.tsx (1)

6-6: useModalMotion import이 사용되지 않아요 — 제거하는 게 좋을 것 같아요!

useModalMotion이 import되어 있지만 실제로 컴포넌트 어디에서도 호출되지 않아요. entered 값은 useModalPresence에서 이미 내려오고 있으니, 이 import은 안전하게 삭제할 수 있어요.

🧹 불필요한 import 제거 제안
-import { useModalMotion } from "@/hooks/common/useModalMotion";
 import { backdropMotionClass, panelMotionClass } from "@/utils/modalMotion";
 import { cn } from "@/lib/utils";
 import { useModalPresence } from "@/hooks/common/useModalPresence";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/restaurant/RestaurantDetailModal.tsx` at line 6, Remove the
unused import useModalMotion from RestaurantDetailModal.tsx: locate the import
line that references useModalMotion and delete it (the component already
receives entered from useModalPresence, so no call to useModalMotion exists);
ensure no other references to useModalMotion remain in the file and run a quick
lint/compile to confirm the unused-import warning is gone.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/reservation/modals/ReservationMenuModal.tsx`:
- Around line 141-146: The backdrop button in ReservationMenuModal is missing
the z-0 class which other modals use; update the className call in the button
that uses cn(backdropMotionClass(entered)) to include "z-0" (i.e.,
cn(backdropMotionClass(entered), "z-0")) so it matches
ReservationModal/ReservationConfirmModal/PaymentModal; locate the button element
in ReservationMenuModal (the element with aria-label="모달 닫기" and
onClick={handleRequestClose}) and add the "z-0" argument to the cn(...)
invocation.
- Around line 147-152: The outer modal container currently mixes
"overflow-y-auto" and "overflow-hidden" in the cn(...) call (the div using
panelMotionClass(entered)), causing conflicting CSS; remove "overflow-y-auto"
from that outer div and keep "overflow-hidden" there, and ensure the inner
scrolling container (the inner div with className="overflow-y-auto ...") remains
responsible for vertical scrolling so the modal follows the intended pattern in
ReservationMenuModal.

In `@src/hooks/common/useModalMotion.ts`:
- Around line 1-15: `useModalMotion` is dead code—delete the unused hook file
src/hooks/common/useModalMotion.ts and remove any exports/imports referencing
the exported function useModalMotion (ensure no barrel/index re-exports remain).
Verify that all modal components use useModalPresence and run a quick
project-wide import search for "useModalMotion" to confirm complete removal.

In `@src/utils/modalMotion.ts`:
- Around line 9-14: panelMotionClass currently uses the non-existent Tailwind
class "will-change-opacity" so no CSS is generated; update panelMotionClass to
replace the invalid class with a Tailwind arbitrary will-change value that
includes both transform and opacity (e.g. use the arbitrary syntax to produce
will-change: transform, opacity) so the browser can optimize both opacity and
scale transitions together.

---

Outside diff comments:
In `@src/components/reservation/modals/PaymentModal.tsx`:
- Around line 192-197: The PaymentModal div uses the same aria-label as
ReservationConfirmModal so screen readers can't distinguish them; update the
PaymentModal's dialog element (the div with role="dialog" in PaymentModal
component) to use a distinct, descriptive aria-label such as "결제 확인 모달" or "결제
정보 확인모달" so it clearly identifies this as the payment modal to assistive tech;
ensure only the PaymentModal's dialog label is changed and
ReservationConfirmModal's label is left intact.

In `@src/components/reservation/modals/ReservationCompleteModal.tsx`:
- Around line 38-39: Remove the two debug console.log statements that print the
reservation draft (console.log("[complete] draft=", draft) and
console.log("[complete] time=", draft.time)) from ReservationCompleteModal.tsx;
either delete them entirely or replace with a safe, environment-gated logger
(e.g., only log when process.env.NODE_ENV !== 'production') or log
non-sensitive, masked fields instead so no PII/booking details from the draft
object are emitted to production consoles.

In `@src/components/reservation/modals/ReservationModal.tsx`:
- Around line 170-188: The ReservationModal currently lacks keyboard focus
management; update ReservationModal to use `@radix-ui/react-dialog` (or an
equivalent focus-trap implementation) so that when the modal opens focus moves
into the modal, Tab/Shift+Tab cycles only through modal focusable elements,
Escape calls handleRequestClose, and on close focus returns to the triggering
element; specifically replace the existing top-level container (the element with
role="dialog" and aria-modal="true") with Radix Dialog primitives (Dialog.Root,
Dialog.Trigger kept outside, Dialog.Overlay for the backdrop, Dialog.Content for
the panel) or wire an equivalent focus-trap that 1) focuses the first tabbable
or the container on mount, 2) adds keyboard handlers to intercept Tab/Shift+Tab
and keep focus inside, 3) listens for Escape to call handleRequestClose, and 4)
saves/restores the trigger element focus on unmount; apply the same migration
pattern to ReservationConfirmModal, ReservationMenuModal, PaymentModal, and
ReservationCompleteModal.

In `@src/components/restaurant/RestaurantDetailModal.tsx`:
- Around line 141-148: The error branch's close button in RestaurantDetailModal
(the button wrapping the <X /> icon inside the error render) is missing an
aria-label; update the button rendered in the error branch (the same element
that calls onOpenChange(false)) to include aria-label="모달 닫기" (matching the
loading branch) so screen readers can identify the control and satisfy the
component accessibility checks.
- Around line 210-216: The success-branch close button in
RestaurantDetailModal.tsx (the <button> that calls onOpenChange(false) and
renders <X />) lacks an aria-label; update that button to include aria-label="모달
닫기" to match the loading branch and satisfy accessibility checks for components
under src/components/**.
- Around line 125-173: The error branch in RestaurantDetailModal (the status ===
"error" return) uses a hardcoded backdrop class ("absolute inset-0 bg-black/40")
and plain panel classes, so add the same animation classes used in the other
branches: replace the hardcoded backdrop button class with
backdropMotionClass(entered) and add panelMotionClass(entered) to the modal
panel wrapper (the div with "relative z-10 ...") so the error modal uses the
same enter/exit animations; ensure you reference the same entered state/variable
and the existing backdropMotionClass and panelMotionClass helpers used in
idle/loading and success branches and keep onOpenChange/unmount behavior
identical.

---

Nitpick comments:
In `@src/components/restaurant/RestaurantDetailModal.tsx`:
- Line 6: Remove the unused import useModalMotion from
RestaurantDetailModal.tsx: locate the import line that references useModalMotion
and delete it (the component already receives entered from useModalPresence, so
no call to useModalMotion exists); ensure no other references to useModalMotion
remain in the file and run a quick lint/compile to confirm the unused-import
warning is gone.

Comment on lines 141 to 146
<button
type="button"
className="absolute inset-0 bg-black/50"
className={cn(backdropMotionClass(entered))}
aria-label="모달 닫기"
onClick={handleRequestClose}
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

백드롭 버튼에 z-0이 빠져 있어요 — 다른 모달과 일치하지 않습니다.

ReservationModal, ReservationConfirmModal, PaymentModal은 모두 cn(backdropMotionClass(entered), "z-0")을 사용하지만, 여기서는 cn(backdropMotionClass(entered))만 적용돼 있어요. 패널이 z-10이라 DOM 순서상 현재도 동작하긴 하지만, 의도가 명확하지 않아 나중에 레이어 조정이 필요할 때 실수 여지가 생깁니다.

✏️ 수정 제안
-        className={cn(backdropMotionClass(entered))}
+        className={cn(backdropMotionClass(entered), "z-0")}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button
type="button"
className="absolute inset-0 bg-black/50"
className={cn(backdropMotionClass(entered))}
aria-label="모달 닫기"
onClick={handleRequestClose}
/>
<button
type="button"
className={cn(backdropMotionClass(entered), "z-0")}
aria-label="모달 닫기"
onClick={handleRequestClose}
/>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/reservation/modals/ReservationMenuModal.tsx` around lines 141
- 146, The backdrop button in ReservationMenuModal is missing the z-0 class
which other modals use; update the className call in the button that uses
cn(backdropMotionClass(entered)) to include "z-0" (i.e.,
cn(backdropMotionClass(entered), "z-0")) so it matches
ReservationModal/ReservationConfirmModal/PaymentModal; locate the button element
in ReservationMenuModal (the element with aria-label="모달 닫기" and
onClick={handleRequestClose}) and add the "z-0" argument to the cn(...)
invocation.

Comment on lines +147 to +152
<div
className={cn(
panelMotionClass(entered),
"flex flex-col relative z-10 w-[92vw] max-w-4xl max-h-[calc(100vh-96px)] overflow-y-auto rounded-2xl bg-white shadow-xl overflow-hidden",
)}
>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

overflow-y-autooverflow-hidden이 같은 요소에 함께 적용되어 있어요.

"flex flex-col relative z-10 w-[92vw] ... overflow-y-auto ... shadow-xl overflow-hidden"

overflow-hidden(overflow: hidden)과 overflow-y-auto(overflow-y: auto)를 함께 쓰면 CSS 우선순위에 따라 동작이 모호해져요. ReservationModal의 패턴(overflow-hidden 은 outer, overflow-y-auto 는 내부 스크롤 <div>)을 따르는 것이 의도를 더 명확하게 표현합니다.

Line 171의 내부 <div className="overflow-y-auto ..."> 가 실제 스크롤을 담당하게 하려면:

✏️ 수정 제안
       className={cn(
         panelMotionClass(entered),
-        "flex flex-col relative z-10 w-[92vw] max-w-4xl max-h-[calc(100vh-96px)] overflow-y-auto rounded-2xl bg-white shadow-xl overflow-hidden",
+        "flex flex-col relative z-10 w-[92vw] max-w-4xl max-h-[calc(100vh-96px)] overflow-hidden rounded-2xl bg-white shadow-xl",
       )}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div
className={cn(
panelMotionClass(entered),
"flex flex-col relative z-10 w-[92vw] max-w-4xl max-h-[calc(100vh-96px)] overflow-y-auto rounded-2xl bg-white shadow-xl overflow-hidden",
)}
>
<div
className={cn(
panelMotionClass(entered),
"flex flex-col relative z-10 w-[92vw] max-w-4xl max-h-[calc(100vh-96px)] overflow-hidden rounded-2xl bg-white shadow-xl",
)}
>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/reservation/modals/ReservationMenuModal.tsx` around lines 147
- 152, The outer modal container currently mixes "overflow-y-auto" and
"overflow-hidden" in the cn(...) call (the div using panelMotionClass(entered)),
causing conflicting CSS; remove "overflow-y-auto" from that outer div and keep
"overflow-hidden" there, and ensure the inner scrolling container (the inner div
with className="overflow-y-auto ...") remains responsible for vertical scrolling
so the modal follows the intended pattern in ReservationMenuModal.

Comment on lines +1 to +15
import { useEffect, useState } from "react";

export function useModalMotion(open: boolean) {
const [entered, setEntered] = useState(false);

useEffect(() => {
if (!open) {
setEntered(false);
return;
}
const id = requestAnimationFrame(() => setEntered(true));
return () => cancelAnimationFrame(id);
}, [open]);
return { entered };
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# useModalMotion을 사용하는 모든 위치 확인
rg "useModalMotion" --type=ts --type=tsx -B2 -A2

Repository: Eatsfine/FE

Length of output: 82


🏁 Script executed:

# useModalPresence 구현 확인
find . -name "*useModalPresence*" -type f

Repository: Eatsfine/FE

Length of output: 93


🏁 Script executed:

# hooks 디렉토리 구조 확인
find src/hooks -name "*.ts" -o -name "*.tsx"

Repository: Eatsfine/FE

Length of output: 597


🏁 Script executed:

# useModalMotion 사용 위치 다시 검색 (파일 타입 수정)
rg "useModalMotion" -B2 -A2

Repository: Eatsfine/FE

Length of output: 373


🏁 Script executed:

# useModalPresence 구현 확인
cat -n src/hooks/common/useModalPresence.ts

Repository: Eatsfine/FE

Length of output: 1205


🏁 Script executed:

# useModalMotion 전체 코드 확인
cat -n src/hooks/common/useModalMotion.ts

Repository: Eatsfine/FE

Length of output: 528


🏁 Script executed:

# useModalMotion 임포트를 사용하는 컴포넌트 찾기
rg "from.*useModalMotion|import.*useModalMotion" -B1 -A5

Repository: Eatsfine/FE

Length of output: 37


🏁 Script executed:

# useModalMotion 사용처 전체 검색
rg "useModalMotion" --no-filename

Repository: Eatsfine/FE

Length of output: 102


🏁 Script executed:

# 혹시 놓친 부분이 있을 수 있으니 더 광범위하게 검색
rg "useModalMotion" --no-heading

Repository: Eatsfine/FE

Length of output: 137


🏁 Script executed:

# 파일 시스템에서도 검색
grep -r "useModalMotion" src/ --include="*.ts" --include="*.tsx"

Repository: Eatsfine/FE

Length of output: 137


🏁 Script executed:

# hooks/common/index.ts나 export 파일 확인
find src -name "index.ts" -o -name "index.tsx" | xargs grep -l "useModalMotion" 2>/dev/null || echo "No index files export useModalMotion"

Repository: Eatsfine/FE

Length of output: 91


🏁 Script executed:

# useModalPresence 실제 사용 확인
rg "useModalPresence" --no-heading

Repository: Eatsfine/FE

Length of output: 1612


🏁 Script executed:

# RestaurantDetailModal.tsx가 존재하고 뭘 사용하는지 확인
find . -name "RestaurantDetailModal.tsx" -type f

Repository: Eatsfine/FE

Length of output: 108


useModalMotion은 코드베이스에서 사용되지 않는 죽은 코드입니다. 삭제하는 것을 추천드려요.

확인해보니 useModalMotion을 import하는 파일이 전혀 없습니다. RestaurantDetailModal.tsx를 포함해서 모든 모달 컴포넌트가 useModalPresence를 사용하고 있어요.

// RestaurantDetailModal.tsx
import { useModalPresence } from "@/hooks/common/useModalPresence";  ← useModalPresence 사용
const { rendered, entered } = useModalPresence(open);

// PaymentModal.tsx, ReservationModal.tsx 등도 모두 useModalPresence 사용

사실 useModalMotion은 처음부터 만들어졌지만 실제로 사용되지 않은 채로 남겨진 것으로 보입니다. 필요 없는 코드가 증가하면 나중에 유지보수할 때 혼란을 주므로 src/hooks/common/useModalMotion.ts 파일을 삭제해주면 좋겠습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/common/useModalMotion.ts` around lines 1 - 15, `useModalMotion` is
dead code—delete the unused hook file src/hooks/common/useModalMotion.ts and
remove any exports/imports referencing the exported function useModalMotion
(ensure no barrel/index re-exports remain). Verify that all modal components use
useModalPresence and run a quick project-wide import search for "useModalMotion"
to confirm complete removal.

Comment thread src/utils/modalMotion.ts
Comment on lines +9 to +14
export function panelMotionClass(entered: boolean) {
return [
"transition-all duration-200 ease-out",
"will-change-transform will-change-opacity",
entered ? "opacity-100 scale-100" : "opacity-0 scale-[0.96]",
].join(" ");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Tailwind CSS v3 will-change utilities built-in classes documentation

💡 Result:

Tailwind CSS v3 includes built-in will-change utilities (no plugin needed):

  • will-change-autowill-change: auto;
  • will-change-scrollwill-change: scroll-position;
  • will-change-contentswill-change: contents;
  • will-change-transformwill-change: transform; [1][2]

You can also use:

  • Arbitrary values: will-change-[top,left]
  • CSS variable shorthand: will-change-(--my-props) (expands to will-change: var(--my-props)) [1]

Docs: “will-change” (Interactivity) page in the Tailwind CSS documentation. [1]


🌐 Web query:

Tailwind CSS v3 arbitrary values will-change syntax will-change-[transform,opacity]

💡 Result:

In Tailwind CSS v3, you can use an arbitrary value to set a comma‑separated will-change list like this:

<div class="will-change-[transform,opacity]"></div>

That generates:

will-change: transform, opacity;

Tailwind documents the arbitrary value form as will-change-[<value>] (example shown with top,left). [1] The underlying CSS syntax for multiple will-change values is a comma-separated list (e.g. transform, opacity). [2]

If you only need a single value, Tailwind also provides built-ins like will-change-transform. [1]


will-change-opacity는 Tailwind v3에 없는 클래스예요 — CSS가 생성되지 않습니다.

Tailwind v3의 기본 will-change 유틸리티는 will-change-auto, will-change-scroll, will-change-contents, will-change-transform 네 가지뿐이에요. will-change-opacity는 포함되지 않아서 실제 CSS는 생성되지 않고 그냥 DOM 클래스만 남게 됩니다. 브라우저가 opacity 변화를 미리 최적화할 기회를 놓치는 거죠.

패널에서 opacity와 scale이 함께 변화하므로, Tailwind의 임의값 문법을 사용해서 두 속성을 모두 힌트로 줄 수 있어요.

✏️ 수정 방법
 export function panelMotionClass(entered: boolean) {
   return [
     "transition-all duration-200 ease-out",
-    "will-change-transform will-change-opacity",
+    "will-change-[transform,opacity]",
     entered ? "opacity-100 scale-100" : "opacity-0 scale-[0.96]",
   ].join(" ");
 }

이렇게 하면 브라우저가 will-change: transform, opacity;를 받아서 두 속성 모두 미리 최적화할 수 있어요.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function panelMotionClass(entered: boolean) {
return [
"transition-all duration-200 ease-out",
"will-change-transform will-change-opacity",
entered ? "opacity-100 scale-100" : "opacity-0 scale-[0.96]",
].join(" ");
export function panelMotionClass(entered: boolean) {
return [
"transition-all duration-200 ease-out",
"will-change-[transform,opacity]",
entered ? "opacity-100 scale-100" : "opacity-0 scale-[0.96]",
].join(" ");
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/modalMotion.ts` around lines 9 - 14, panelMotionClass currently
uses the non-existent Tailwind class "will-change-opacity" so no CSS is
generated; update panelMotionClass to replace the invalid class with a Tailwind
arbitrary will-change value that includes both transform and opacity (e.g. use
the arbitrary syntax to produce will-change: transform, opacity) so the browser
can optimize both opacity and scale transitions together.

jjjsun added a commit that referenced this pull request Feb 20, 2026
* docs: add issue template (#3)

* docs: add PR template (#4)

PR 템플릿 추가

* feat: 식당검색/조회 UI구현 (#8)

* feat: 식당검색/조회 UI구현

* feat: 지도 영역 위에 마커 표시 추가, 검색 결과리스트 UI수정, mock데이터추가및수정

* feat: 로그인/회원가입 UI 및 입력 폼 구현

* chore: 사용하지 않는 Form 컴포넌트 삭제

* style: 체크박스, 회원가입/로그인 이동 버튼, 닫기 버튼 UX 개선

* chore: add shadcn ui components (popover, calendar) and update separator,button (#12)

공용 컴포넌트 추가 및 수정

* chore: add shadcn ui components (popover/calendar) (#13)

* chore: add shadcn ui components (popover, calendar) and update separator,button

* chore: add shadcn ui components (popover, calendar, separator) and deps

* feat: mypage UI 구현(내 정보, 계정 설정, 결제수단, 구독 관리, 예약 현황, 내 가게 관리)

* feat: 고객센터 페이지 레이아웃 및 히어로 섹션(문의 모달) 구현

* feat: 메인 FAQ 섹션 구현

* style: 히어로 섹션 텍스트 줄바꿈(break-keep) 적용

* style: 페이지 레이아웃 간격 수정, 문의하기 폼 텍스트 속성(break-keep) 추가

* feat: 문의처 정보 섹션 구현

* feat: 식당예약 UI구현 (#17)

* wip: reservePage

* wip: reservation modal skeleton

* wip: reserve page

* feat:reserveConfirmModal

* feat:예약 확정 모달 추가

* chore:한국날짜 기준 지난 날짜는 선택불가 기능 추가

* feat:예약금결제모달 구조 UI구현

* style: 예약금 선결제 모달 디자인 구현

* feat:예약시 좌석배치도 추가

* feat:테이블 배치도 기능 구현완료

* feat: 식당id에 따라 존재하지 않는 좌석유형 클릭불가 기능 추가, 흐림처리 추가

* chore: 해당없는 좌석유형 숨김, 예약확인모달- 수정하기 버튼클릭시 기존 선택값유지되도록 설정, 결제수단 버튼 기본값 삭제, style: ReservationConfirmModal.tsx height max 설정

* chore: 결제하기 모달 이탈방지 알림 추가, 다른 예약모달과 코드 동일한 루틴으로 변경

* chore: 예약확정모달에서 테이블번호 추가

* feat: 헤더에 뒤로가기(홈) 버튼 추가

* chore: 식당검색페이지 코드 개선 (#21)

* chore:잇츠파인로고 파일형식 변경

* chore:식당검색 상단을 Layout으로 따로 빼고, logo 넣어서 홈으로가는 링크 추가

* docs: 로고 화질 개선

* refactor:favicon 경로수정

* chore: mypage 리뷰 반영 코드 수정

* fix: 이미지 경로 오류수정 (#23)

* docs: modify PR template filename (#27)

PR템플릿명 수정

* chore: add CodeRabbit config (#29)

* chore: add CodeRabbit config

* chore:coderabbit 말투수정

* chore: coderabbit 오타수정및 필터링에 .coderabbit.yaml추가

* feat: 메인페이지 UI구현 (#25)

* wip: main page header

* feat:mainPage 기본 UI 구현완료

* chore: header부분 Hero.tsx지나서 scrolled 적용되도록 기능 구현

* chore: 스크롤시 떠오르는 효과 구현

* chore: Button에 nav기능추가

* chore: header부분 mobile크기로 변경시 햄버거 나오도록 구현, ForOwnerSection 모바일크기 맞춰서 나오도록 수정

* chore: 오타및 공백수정

* chore: footer 섹션에 max너비 추가

* chore: Header 모바일메뉴 열렸을때, 버튼 크기/폰트 크기/배경색 수정

* chore:영상 스크린 리더 불필요한 읽힘제거

* chore:불필요한 코드 제거

* chore: Feature 카드 컴포넌트 분리

* chore:Header 모바일 변하는 시점 수정 및 모바일에서 길어짐현상 제거

* chore: Join대신 cn으로 통일

* chore: 모바일 화면에서 줄바꿈 자연스럽도록 수정

* chore: header 수정

* chore: 배경용 iframe에 키보드 포커스 제거

* chore: useInView 수정

* chore: 적용되지않는 tailwind 클래스 수정, 주석 수정

* chore: CtaSection.tsx 불필요한/적용안되는 코드 삭제및수정

* refactor: 코드 가독성을 높이기 위한 수정진행

* feat: 새 가게 등록 1단계(사업자 인증) UI 구현

* feat: 새 가게 등록 2단계(가게 정보) UI 구현 및 페이지 경로를 myPage 하위로 이동

* feat: 새 가게 등록 3단계(메뉴 등록) UI 구현

* style: cursor-pointer 추가, 단계별 연결선 스타일 개선, 하단 버튼 여백 개선

* fix: 이미지 메모리 누수, 가격 변환 로직, 폼 접근성 이슈 수정

* feat: 가게 등록 이탈/완료 모달 구현 및 사업자 인증 UX 개선

* feat: phoneNumber 유틸 함수 추가, 가게 정보 폼 적용

* feat: 정기 휴무일 선택 UI 및 스키마 추가

* feat: 예약 정책 UI 및 스키마 추가

* refactor: type=button 지정, aria-label 및 invalid 추가, Label 컴포넌트 적용, console.log 삭제

* fix: 비동기 언마운트 버그 수정, 접근성 개선

* chore: global 스타일 적용 (#33)

* chore: 글로벌 style 세팅(shadcn테마, 폰트, 토큰, 기본 타이포세팅)

* chore: cn 유틸리티를 lib/utils로 통일

* chore: axios 인스턴스 및 요청/응답 인터셉터 설정

* chore: Tanstack Query QueryClient 전역 설정 추가

* chore: API연동 대비 query key관리(keys.ts)추가, 폴더구조 정리

* fix:QueryClientProvider 중복 제거후, queryClient 단일화

* chore:border 중복스타일 제거

* chore: 스위치 버튼에 포커스표시와 ARIA 속성 추가로 접근성 개선

* fix:타이포 기본 적용 조건 수정

* chore: global.css 수정

* chore: owner 쿼리키에 중간키 추가

* chore: 쿼리 키에 넣을 params를 직렬화 가능한 타입으로 제한

* feat: 메뉴/예약금 type 및 mock데이터/hooks 추가 (#35)

* feat:내가게관리 UI 구현

* feat: 예약중 메뉴선택 UI추가 (#39)

* chore: 예약금정책 변경에 따른 코드수정

* feat: 메뉴선택 UI로 이동 구현

* feat: 예약시 메뉴선택 UI모달추가 및 예약금을 메뉴총액대비 예약금률 적용하도록 수정

* chore: hooks 호출 순서 꺠뜨리는 조건부 return 수정, draft 변경시 selectedMenus 상태 동기화누락 수정, aria-label 수정

* chore:오타수정, open prop에 따른 조건부 랜덜이 누락

* chore: 메뉴 최대수량일때 증가버튼 비활성화되도록 기능추가

* style: 너비/패딩 수정

* style: 메뉴선택모달하단부분 예약금 블루색깔추가, 메뉴총액은 가로로 위치변경

* chore: 모바일 너비처리를 위한 코드추가(이전 작업범위)

* chore: 메뉴선택에서 우측상단 X 아이콘은 모달닫기로 수정, 하단에 다음버튼 왼쪽에 이전으로 이동하는 버튼추가

* chore: 식당예약모달에서 우측상단 X아이콘 모달닫기로 수정

* chore: 예약모든 모달 X아이콘 클리시 창닫기로 모드수정, 창닫기알림창 훅 새로 생성해서 모든 모달에 적용

* refactore:주석삭제

* chore: 모달이외지역클릭시 닫기 -> hooks사용으로 변경

* chore:예약금 표시비율 통일

* chore: axios 기본 세팅, 인증/에러 처리 인프라 구축

* refactor: 타입 단언을 타입 가드로 교체

* fix: 콘솔 로그의 오해 소지가 있는 변수명 수정

* [chore]내 가게 관리 리뷰 반영 수정

* chore: 내 가게 관리 리뷰 반영 수정2

* chore:대시보드 추가 수정 밑 버튼 이동 경로 설정

* feat:notFoundPage UI 구현

* style: notFoundPage 버튼, 이모지 스타일 변경

* chore: 내 가게 관리 coderabbit 반영 수정

* chore: notFoundPage coderabbit 반영 수정

* chore:내 가게 관리 coderabbit 반영 수정 2

* fix: 마이페이지 동작 버그 수정 및 내정보 편집 UX 개선 (#43)

* fix:마이페이지에서 뒤로가기 작동되도록 수정

* chore: 마이페이지 상단에 제목 선택시 홈으로 가도록 기능 추가

* style: 마이페이지 안 내정보 부분 디자인 수정

* fix: 전화번호에 number타입만 사용되도록 phoneNumber함수사용

* fix: 내정보 수정가능한 정보들 취소 누를시 원상복구가능하도록 기능 추가

* fix: 이미지 file기반으로 전환

* style: 마이페이지 내에 settingPage 스타일수정

* style: myInfoPage 내에 text-md 제거

* style: 마이페이지 스타일통일 및 text위치통일

* chore: 내 가게 관리 리뷰 반영 수정 및 마이페이지 연결 (+마이페이지 수정)

* chore: 내 가게 관리 coderabbit 반영 수정3

* chore: 내 가게 관리 휴무일 반영 수정 및 리뷰 반영 수정

* [chore]메인화면 내 가게 관리 연결

* chore: 오류페이지 리뷰 반영 수정

* chore: 내가게관리 메뉴관리 수정

* feat : 카카오맵 연동 및 검색 결과 마커 자동으로 이동되도록 구현 (#48)

* refactor: 식당 Summary/Detail 타입 및 DTO/어뎁터 추가

* refactor: 식당 mock을 검색용(Summary)와 상세정보용(Detail)로 분리

* feat: 식당 상세 모달에서 로딩/에러 상태 및 재시도 흐름 추가

* feat: 카카오맵 SDK 로드 및 SearchPage 지도 랜더링 연결

* refactor: 모달 닫기와 전체 초기화 로직 분리

* feat: 지도 중심 이동 및 선택 상태 유지

* feat: 카카오맵 bounds 자동 조정 및 선택 이동 UX 개선

* fix: 코드래빗 피드백 수정, SDK 로드 분리

* chore: 상태변수이용해서 SDK 로딩완료추척

* fix: SDK 참조 오류 수정

* refactor: 스크린리더 정보 추가

* chore: SDK 로딩 실패시 UX개선

* chore: 로고 교체 및 PublicLayout 헤더 통합 (#50)

* chore:로고 변경, PublicLayout에 로그아웃 버튼추가

* refactor: PublicLayout으로 헤더 통합 및 마이페이지 레이아웃 중첩 적용

* chore: 폴더 구조정리, README 업데이트 (#52)

* feat: 회원가입 Role 선택 UI 추가, 스키마 업데이트

* feat: 로그인/회원가입(이메일) API 연동, Axios 인터셉터 구현

* feat: 소셜 로그인 연동 준비 (API 및 모달 핸들러)

* feat: 로그인/회원가입 모달 내 소셜 로그인(Kakao, Google) 기능 적용

* refactor: 로그인/회원가입 로직 Zustand, React Query 도입

* feat: 로그인 상태에 따른 헤더 UI 분기 처리 및 로그아웃 연동

* refactor: 인증/로그아웃 로직 개선, AI 피드백 반영

* refactor: 회원가입 역할 선택 UI 제거, role 'customer' 고정

* refactor: 로그인 UI에서 아이디/비번 찾기 제거

* fix: API 환경변수 통일, 타임아웃 설정, 에러 정규화, 카카오 키 검증 추가

* refactor: 소셜 로그인 SDK 제거 및 OAuth2 방식 전환, 콜백/에러 페이지 구현

* refactor: 소셜 로그인 리다이렉트 URL 확정

* fix: 소셜 로그인 시 서버 URL 설정 확인 로직 추가

* refactor: 회원가입/로그인 API 스펙 Swagger 기준으로 최신화

* style: 회원가입 모달 내 불필요한 약관 안내 문구 제거

* fix: API 명세 반영(isSuccess, /reissue), Refresh 로직 단순화, Auth 타입 강화

* fix: postRefresh 함수에 누락된 isSuccess 검증 로직 추가

* feat: 에러 유틸 함수 추가, 로그인/회원가입 적용

* fix: postSignup 응답 형식을 실제 API 명세에 맞춰 수정 (ApiResponse 제거)

* refactor: 사업자 인증 단계 리팩토링 (스키마 분리 및 개업일자 검증 추가)

* feat: 사업자 인증 API 연동

* refactor: 스웨거 맞춰 스키마, ui 수정 / 이미 인증된 사업자도 식당 등록 단계 진행되도록 개선

* refactor: 스웨거 맞춰 메뉴 등록 스키마, ui 수정

* feat: 식당 등록 API 연동, 데이터 변환 로직 구현

* feat: 내가게관리 대시보드 API 연동 (미완)

* feat:내가게관리 사장 대시보드 API 연동

* fix: 변수 이름 수정

* feat: 식당 대표 이미지 등록 API 연동

* feat: 메뉴 등록 API 연동, 사장 인증 후 권한 갱신을 위한 로그아웃 로직 추가

* feat: 내가게관리 메뉴관리 API 연동

* feat : 예약 API 연동 (#55)

* feat: 예약조회 API endpoints 추가

* chore: 예약 가능시간/테이블 조회 queryKey 추가

* fix: 메뉴 목록 매핑/훅 반환값 정리 및 예약금 계산 오류 수정

* chore: 예약 생성 훅 및 테이블 선택 타입 정리 복구

* 무제한 토큰 설정/예약 모달 테이블 배치도 API 연동 및 좌석 타입 매핑 추가

* fix: 좌석유형 변경시 옵션 사라지는 문제 수정

* fix: 인원/날짜/시간대 재설정시 좌석유형/테이블번호 리셋 설정

* fix: 예약 가능 테이블 조회 연동 및 좌석 없음 상태 처리

* fix: 예약 모달 storeId기반으로 바꾸고, mock 레스토랑제거

* fix: 가게 검색 리스트 API 응답 구조 반영

* fix: 가게 검색 결과 식당명 표시 오류 수정

* chore: 카카오맵 랜더링 이슈 디버깅 로그/relayout추가 (미해결)

* fix: 예약확인모달에서 좌석번호 뜨도록 수정

* chore: 예약 결제 전환중 500발생(서버 zero date 의심, 문의중)

* fix: 예약 생성 요청 서버 오류 해결

* fix: 예약 생성 후 결제 모달로 정상 전환되도록 booking 상태 전달

* feat: 결제 모달 이전 버튼 추가, 예약금률 서버값 연동

* chore:예약확인모달 날짜형식 서버에 문의중(미해결)

* chore: API baseURL 통일 및 v1 엔드포인트 경로 정리

* chore: API baseURL 통일 및 v1 엔드포인트 경로 재정리

* feat: 토스 결제 요청/승인 플로우연동 및 성공시 이동 UX개선

* feat: 결제 실패시 사유 표시 페이지 UX 보강

* fix: 결제성공 페이지 hightlight 덮어쓰기 버그 수정및 오타수정

* feat: 결제 리다이렉트 성공/실패 처리 및 완료 UX 연결

* feat: 토스 결제 위젯 랜더링 및 결제 요청 연결

* feat: 결제 실패 페이지 UI 개선 및 에러 코드별 메세지 처리

* feat: 결제 실패 페이지 UI 개선 및 bookingId 기반 이동처리

* fix: 결제 플로우 안정화

- SuccessPage: 결제 승인(confirm) 중복 호출 방지(ranRef)

- 결제 위젯 초기화/렌더링 흐름 개선

- FailPage: 쿼리 파라미터 대응/이동 처리 보완

* fix: 결제 모달 하나로 통일

* fix: 로그아웃시 userId를 null값으로 변경

* fix: 다른 페이 버튼 안눌리는 오류 수정

* fix: 코드래빗 endpoint관련 수정

* fix: 코드래빗 수정사항적용

* fix: 코드래빗 수정사항 반영 및 불필요한 코드제거

* chore: 코드래빗 수정사항 반영

* fix: 최소인원 최대인원 같은테이블은 하나로 표기하도록 수정, 불필요한 코드 및 주석 제거

* fix: 코드래빗 수정사항 반영

* chore: 코드래빗 수정사항적용(오타및 코드효율성)

* fix: mock데이터 관련 타입제거

* chore: 코드래빗 수정사항 반영

* fix: member info 응답 구조에 맞게 userId 파싱 수정 및 인증 리다이렉트 버그 해결

* fix: 완료모달에서 time 이 undefined로뜨는 에러 수정(draft 타입형식오류)

* chore: 카카오맵 지도오류 해결중(미해결)

* fix: 식당검색시 지도 타일오류 수정

* fix: 검색 결과 주소 기반으로 지도 마커에 표시되도록 수정

* refactor: 미사용 RestaurantMarker 컴포넌트 삭제

* fix: 지도에서 마커 선택할때 해당 위치로 센터 이동

* fix: 파일 삭제 오류 재복구

* feat: 접근 제어 구현

* feat: 내가게관리 가게 설정탭 API 연동

* refactor: 라우팅 접근 제어 안정성 강화, 리다이렉트 UX 개선

* refactor: PrivateRoute 내 불필요한 alert 제거

* fix: Zustand 하이드레이션 상태 업데이트 방식 수정 (안티패턴 해결)

* refactor: 스웨거에 맞춰 문의하기 폼 스키마 및 UI 필드명 동기화

* feat: 1:1 문의 등록 API 연동

* fix: replace 옵션 추가

* refactor: CategoryEnum 명칭 중복 방지를 위해 Menu/Store용으로 각각 분리

* refactor: getValues() 사용, input id 연결

* refactor: 영업 시간 변환 유틸 함수의 암묵적 기본값 제거, 필수값 검증 로직 추가

* refactor: 가게 등록 로직을 mutateAsync, try-catch 패턴으로 변경하여 에러 처리 강화

* fix: 메뉴 가격 유효성 검사 정규식 수정 (0 허용, 불필요한 선행 0 차단)

* fix: 가게 대표 이미지 유효성 검사 강화

* docs: TODO 주석 추가

* chore: 내가게관리 사장 대시보드 코드래빗 반영 수정

* chore: 내가게관리 대시보드 테이블 유형 추가

* chore: 내가게관리 시간슬롯 UI 변경

* chore: 내가게관리 대시보드 코드래빗 반영 수정2

* chore: 메뉴 관리 카테고리 제외

* fix: 메뉴 삭제 알림오류 수정

* chore: 모달 스타일 수정

* refactor: 지오코딩 실패 시 등록 차단 로직 구현

* refactor: 정기 휴무일 접근성 개선

* chore: 가게 설정 코드래빗 반영 수정

* feat: ESC키 핸들러 추가, 모달에 role, aria-modal 등 속성 추가

* fix: 주소 데이터 변환 시 발생할 수 있는 문자열 결합 오류 방지

* refactor: 불필요한 any 타입 캐스팅 제거

* chore: 메뉴관리 코드래빗 반영 수정

* feat: 마이페이지 비밀번호변경/회원탈퇴 API연동 (#71)

* feat: 마이페이지 계정설정 API연동(비밀번호변경/회원탈퇴)

* refactor: 미저장 파일 저장

* WIP: 미저장 파일 저장

* fix: 코드래빗 수정사항 반영

* fix: 회원탈퇴 메세지 프론트에서 처리중(내일 아침중으로 백서버배포후 수정예정)

* fix:코드래빗 수정사항 반영

* fix:폰넘버 지역번호 자릿수 해결로직추가

* feat: 마이페이지 내 정보 조회/수정 API연동 (#63)

* feat:마이페이지 내 정보 조회/수정 API연동

* chore: 프로필이미지 업로드 API연동(500에러터짐 문의중)

* fix: 이미지 파일형식 삭제

* fix: 아이디 제거, 코드래빗 수정사항 반영, 서버 이미지업로드오류 해결중

* fix: 코드래빗 수정사항 반영

* fix: 폰넘버 02 자릿수 로직 추가

* refactor: 주석 제거

* fix: 코드래빗 수정사항 반영

* fix: 마이페이지 내 결제수단 관리 탭 삭제 (#73)

* chore: 코드래빗 반영 수정

* chore: 로고/아이콘 변경 (#75)

* chore: 메인페이지 헤더 로고변경

* chore: publicLayout 로고 변경

* chore: icon수정 및 UX완성도 고도화작업진행

* chore: 로고+텍스트 Link로 요소 변경

* fix: mock데이터 삭제, 주석 삭제, 안쓰는 데이터 삭제 (#77)

* fix:mock데이터 삭제, 주석 삭제, 안쓰는 데이터 삭제

* style:이미지 파일 추가

* fix: 코드래빗 수정사항 반영

* fix: build수정

* fix: build수정

* fix:build 수정

* fix:build수정

* fix: MyInfoPage 대소문자 정리

* fix:배포용 파일명 대소문자 통일

* chore: trigger vercel redeploy

* fix: ownerpage 에러 수정

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

* chore: 코드래빗반영 수정

* fix: 배포후 에러 수정 (#81)

* fix: Vercel에 SPA rewrite 설정

* fix:메인페이지 하단 사장님으로 등록하기 링크추가

* fix: 메인 하단에 사용하지 않는 링크들 이동 막아둠

* fix: 불필요한 버튼 제거, 버튼 텍스트 수정

* refactor: 주석제거

* fix: 마이페이지 내 계정설정 알림관련 저장 기능 수정

* fix: 코드래빗 수정사항 적용

* refactor: 버튼 디자인 수정

* fix: 예약금 환불불가 안내사항 추가

* feat: 마이페이지 내 가게 관리 내 가게 조회 API 연동

* chore: 코드래빗 반영 수정

* chore: 사용되지 않는 변수 수정

* chore: 코드래빗 반영 수정

* fix: 주소 유효성 검사 타이밍 수정, 지역 제한 에러 핸들링 추가

* fix: 영업 시간 유효성 검사 제한 해제

* style: css 수정

* style: 헤더 수정

* remove: 헤더 소개 삭제

* remove: block 삭제

* fix: 예약 시간 간격 로직 개선

* fix: 매뉴 모달 카테고리 매핑 오류 수정 (#92)

* fix: 메뉴 카테고리 매핑으로 메뉴 모달 오류 해결

* fix: axios수정

* docs: readme 최종결과물 링크추가, 폴더구조정리 (#95)

* feat: 식당검색 리스트 스켈레톤 UI 추가, 식당카드에 별점관련 내용 제거 (#97)

* feat: RestaurantListSkeleton 추가

* feat: RestaurantCard 스켈레톤 UI 추가

* feat: SearchPage 로딩 스켈레톤 UI추가, isFetching 기반 상태 분기 정리

* feat: 검색 결과 로딩 UX 개선

* fix: 별점 관련 내용 제거

* chore: 코드래빗 수정사항 반영

* docs: README 서비스 소개/팀소개 추가 (#99)

* docs: README 서비스 소개/팀소개 추가

* docs: README 수정

* docs: img 삭제

* feat: 사업자 인증 대표자명 필드 추가, 예외 처리 보완

* refactor: 네이티브 confirm 창을 커스텀 ConfirmModal로 교체

* refactor: 코드래빗 피드백 반영

* refactor: 코드래빗 피드백 반영

* refactor: 코드래빗 피드백 반영

* fix: 토스페이먼츠 고객키값 2글자 미만 오류수정 (#105)

* style: 줄바꿈 수정

* feat: 식당 테이블 이미지 등록, 삭제 ui 구현 및 api 연동

* fix: 가게 검색시 좌표 응답 매핑 추가 (#108)

* fix: 검색 좌표 누락 대비해서 NaN으로 임시 처리

* fix: 가게 검색 좌표 응답 매핑 추가 및 지오코딩 fallback 유지

* fix: 카카오맵 마커 목록에서 location 필수 타입으로 좁혀서 빌드 오류 해결

* fix: 좌표가 0이 될때의 오류 방지 처리, toNum과 normalizeLatLng 함수 의존성배열경고피하기 위해 컴포넌트 외부로 이동, 지도컨테이너 접근성 개선

* refactor: 코드래빗 피드백 반영

* design: 예약 모달 UX 개선 (#111)

* wip: 닫기 UX 구현중(미적용함.미완성)

* design: 모달 열고닫을떄 애니메이션 추가

* chore: return 조건 오류 수정

* fix: 사용하지않는 import 구문삭제하여 build error해결

* feat: 가게 설정 테이블 이미지 삭제 UI 처리 및 삭제 확인 모달 추가 (#113)

* feat: 가게 설정 테이블 이미지 삭제 UI처리 및 삭제 확인 모달 추가

* wip: 서버에서 tableId내려오면 바로 교체

* fix: 가게 설정 테이블 이미지 서버 배포 연동완료

* chore: 코드래빗 수정사항 반영

* fix: 휴무일 클릭시 서버에러 오류를 휴무일로 메세지 변경

* fix: build 오류 해결

* chore: 코드래빗 수정사항 반영

* chore: button에 aria-label

---------

Co-authored-by: Dew <eidnwq@gmail.com>
Co-authored-by: unknown <tjfgml8054@naver.com>
@jjjsun jjjsun added the 🎨 Design UI/UX label Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Design] 예약 모달 UX 개선

2 participants