Skip to content

[Setting/#131] ESLint 추가 규칙 및 코드 스타일 정리#138

Merged
jjjsun merged 2 commits into
developfrom
setting/#131
Apr 29, 2026
Merged

[Setting/#131] ESLint 추가 규칙 및 코드 스타일 정리#138
jjjsun merged 2 commits into
developfrom
setting/#131

Conversation

@jjjsun
Copy link
Copy Markdown
Contributor

@jjjsun jjjsun commented Apr 29, 2026

🔢 관련 이슈 링크

📌 변경사항PR

  • ✨Feature: 새로운 기능 추가
  • 🐞Bugfix: 버그/오류 수정
  • 📃Docs: 문서 수정(README 등)
  • 🔨Refactor: 코드 리팩토링 (기능 변경 없음)
  • 🧪Test: 테스트 코드 추가/수정
  • 🎨UI/UX: 디자인 및 사용성 수정
  • ⚙️Setting: 기본 세팅 작업

💻 작업내용

코드 일관성 향상을 위해 ESLint 추가 규칙과 Prettier 포맷 규칙 정리.
기존에는 기본 설정만 되어있는 상태였고, 추가로 import 구조와 자동정렬 중심으로 개선진행.

  • import 순서 기준 정리
  • import 그룹 규칙 적용
  • import 자동 정렬 규칙 추가
  • 중복 import 검사 추가
  • import 이후 개행 규칙 추가
  • Prettier 포맷 옵션 정리
    • "semi": true, //문장끝 세미콜론 붙이기
    • "singleQuote": false, //문자열에 ""사용
    • "trailingComma": "all", //마지막요소뒤에도 쉼표붙임
    • "printWidth": 100, //한줄 최대글자 100자
    • "tabWidth": 2, //들여쓰기 공백 2칸
    • "useTabs": false, //탭 문자대신 스페이스 사용
    • "bracketSpacing": true, //중괄호 양끝에 공백넣기
    • "bracketSameLine": false, // 닫는괄호 줄바꿈 관련
    • "endOfLine": "auto", //파일줄바꿈방식 OS에 맞게 자동유지
      -"quoteProps": "consistent", //객체속성에 따옴표 일관성유지
    • "arrowParens": "always", //매개변수1개여도 괄호 붙이기
    • "proseWrap": "preserve" //README 자동 줄바꿈 방지

+)추가로 import 규칙 추가 코드
"simple-import-sort/imports": "warn", // import 구문 정렬 검사
"simple-import-sort/exports": "warn", // export 구문 순서 정리
"import/newline-after-import": "warn", // import 구문 다음에 코드 한줄 띄워줌(빈 줄 추가)
"import/no-duplicates": "warn", // 중복된 import 구문 있으면 하나로 합쳐줌(중복제거)

import 작성 방식을 통일했고, 파일 저장하면 바로 코드 스타일 자동적용되도록 수정했습니다.

🪧 미완성 작업

N/A

🤔 논의 사항 및 참고 사항

pnpm lint 명령어로 lint 규칙 어긋났는지 사전점검가능하고,
import 정렬 관련 warn이 발생한 경우에는 pnpm eslint . --fix 명령어 사용해서 import구문정렬 자동수정이 가능합니다!

현재 파일 저장시 ESLint와 Prettier 자동 정렬이 적용되도록 설정되어있어서 일반적인 정렬및 규칙은 저장으로 정리되도록 설정했습니다.

✅ 체크리스트

  • 브랜치는 잘 맞게 올렸는지
  • 관련 이슈를 맞게 연결했는지
  • 로컬에서 정상 동작을 확있했는지
  • 충돌은 없는지
  • 불필요한 console.log 제거했는지

Summary by CodeRabbit

릴리스 노트

  • Chores
    • 코드 포매팅 및 임포트 구조를 개선했습니다. 전반적인 코드 가독성과 일관성을 향상시키는 내부 정리 작업으로, 사용자 환경에는 영향을 주지 않습니다.

@jjjsun jjjsun requested a review from dew102938 April 29, 2026 04:56
@jjjsun jjjsun self-assigned this Apr 29, 2026
@jjjsun jjjsun added the ⚙️ Setting 기본 세팅 작업 label Apr 29, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 29, 2026

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

Project Deployment Actions Updated (UTC)
eatsfine Ready Ready Preview, Comment Apr 29, 2026 5:41am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 29, 2026

Warning

Rate limit exceeded

@jjjsun has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 31 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f39b4fad-9658-4a89-aa1b-619009fbc1ae

📥 Commits

Reviewing files that changed from the base of the PR and between c41342e and 36269a2.

📒 Files selected for processing (14)
  • src/api/endpoints/member.ts
  • src/api/endpoints/payments.ts
  • src/components/auth/SignupDialog.tsx
  • src/components/customer-support/SupportModal.tsx
  • src/components/customer-support/support.schema.ts
  • src/components/owner/MenuManagement.tsx
  • src/components/owner/StoreSettings.tsx
  • src/components/owner/menuFormModal.tsx
  • src/components/owner/tableDashboard.tsx
  • src/components/reservation/modals/PaymentModal.tsx
  • src/components/reservation/modals/ReservationConfirmModal.tsx
  • src/components/reservation/modals/ReservationMenuModal.tsx
  • src/layouts/PublicLayout.tsx
  • src/pages/payment/FailPage.tsx
📝 Walkthrough

Walkthrough

이 PR은 ESLint와 자동 포매팅 규칙을 기반으로 100개 이상의 파일에 걸쳐 import 순서 정렬, 다중 라인 코드를 단일 라인으로 압축하는 등의 포맷팅을 일관되게 적용한 변경사항입니다. 기능적 로직은 변경되지 않았습니다.

Changes

Cohort / File(s) Summary
API 모듈 및 어댑터
src/api/*.ts, src/api/adapters/*, src/api/endpoints/*, src/api/owner/*, src/api/dto/*
Import 문 재정렬, 다중 라인 함수 시그니처/호출을 단일 라인으로 압축. 모든 엔드포인트, HTTP 메서드, 요청/응답 타입은 동일하게 유지.
인증/권한 관련 컴포넌트
src/components/auth/*, src/components/RouteGuards.tsx, src/hooks/queries/useAuth.ts
Import 통합, Zod 스키마 정의 및 JSX 에러 렌더링을 단일 라인으로 재포맷. 로그인/회원가입/비밀번호 변경 로직은 불변.
고객 지원 컴포넌트
src/components/customer-support/*
Import 재정렬, JSX 텍스트 블록 및 조건부 렌더링을 단일 라인으로 압축. 필터링 로직과 UI 동작은 유지.
메인 페이지 UI 컴포넌트
src/components/main/*
Import 재정렬, 다중 라인 className 삼항연산자와 JSX 요소를 단일 라인으로 재포맷. 레이아웃, 애니메이션, 라우팅 로직은 동일.
지도 및 오너 관련 컴포넌트
src/components/map/KakaoMap.tsx, src/components/owner/*
Import 통합/재정렬, 상태 초기화와 JSX 속성을 단일 라인으로 압축. 테이블 추가/편집, 메뉴 관리, 휴게시간 설정 로직은 유지.
예약 관련 모달 및 유틸
src/components/reservation/modals/*, src/components/reservation/parts/*
Import 재정렬, JSX 텍스트/라벨 및 조건부 렌더링 압축. 결제, 예약 확인, 메뉴 선택 로직은 불변.
UI 기본 컴포넌트
src/components/ui/*
Import 재정렬, Radix/클래스 변수 정의를 단일 라인으로 압축. 버튼, 다이얼로그, 캘린더 등의 컴포넌트 기능은 동일.
식당 관련 컴포넌트
src/components/restaurant/*, src/components/store-registration/*
Import 통합, JSX 텍스트 블록과 함수 시그니처 재포맷. 검색, 카드 렌더링, 상점 등록 로직은 유지.
훅 및 쿼리
src/hooks/*, src/query/keys.ts
Import 통합/재정렬, mutationFn 파라미터 타입 선언을 단일 라인으로 압축. React Query 설정과 API 호출 로직은 동일.
페이지 및 레이아웃
src/pages/*, src/layouts/*
Import 재정렬, 상태 초기화, 조건부 로직, JSX 렌더링을 단일 라인으로 압축. 라우팅, 데이터 페칭, UI 조건부 렌더링은 불변.
스토어 및 유틸
src/stores/*, src/utils/*, src/types/*, src/lib/*
Import 순서 정렬, 함수 시그니처와 상수 정의 재포맷. Zustand 스토어, 유틸리티 함수, 타입 정의의 로직은 동일.
앱 진입점
src/App.tsx, src/main.tsx
Import 그룹 재정렬, 라우팅 설정 유지. 앱 렌더링 로직은 불변.

🎯 Review Effort

🎯 2 (Simple) | ⏱️ ~20 minutes

⭐️ 포매팅 통일이 완성되었어요!
백여 개의 파일들이
줄을 맞춰 정렬하고,
가독성이 한층 높아졌네요.
ESLint의 손길로 단정해진
코드의 미소가 보입니다. ✨

Possibly Related PRs

Suggested Reviewers

  • dew102938
  • yooseolhee

🔍 추가 코멘트

이 PR은 코드 일관성 개선을 목표로 한 대규모 포매팅 작업입니다. 몇 가지 확인 사항이 있습니다:

✅ 긍정적 요소

  • 일관된 import 구조: 모든 파일에서 import 그룹이 통일되어 가독성이 향상되었습니다.
  • 동형적 변경(Homogeneous Changes): 거의 모든 변경이 반복적인 포매팅 규칙 적용이므로 검토가 수월합니다.
  • 기능 보존: 어떤 파일도 로직이나 동작이 변경되지 않았습니다.

📝 체크포인트

대규모 파일 변경이므로 머지 전 다음을 확인하면 좋겠습니다:

  1. Linting 통과: ESLint와 Prettier가 모든 파일에 대해 성공적으로 실행되었는지 확인

    npm run lint
    npm run format
  2. 빌드 및 타입 체크: TypeScript 컴파일 오류가 없는지 확인

    npm run build
    npm run type-check
  3. 주요 기능 테스트: 특히 다음 영역이 정상 작동하는지 확인

    • 로그인/회원가입 플로우
    • 식당 검색 및 예약 과정
    • 오너 페이지 메뉴/테이블 관리
    • 결제 프로세스
  4. Diff 검토 팁:

    • 파일별로 git diff 확인 시 실제 로직 변경이 없는지 확인
    • Import 순서와 JSX 포매팅만 변경되었는지 확인

이 작업 덕분에 앞으로 코드 리뷰와 유지보수가 훨씬 수월해질 것 같습니다! 🚀

🚥 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의 핵심 변경사항을 명확하게 반영하고 있습니다. ESLint 규칙 추가와 코드 스타일 정리라는 주요 목표를 간결하게 표현했습니다.
Linked Issues check ✅ Passed PR의 모든 변경사항이 이슈 #131의 목표와 일치합니다. import 구조 정리, 자동 정렬 규칙, Prettier 옵션 설정 등 명시된 체크리스트 항목들이 모두 반영되었습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 이슈 #131 범위 내에 있습니다. import 정렬과 코드 포맷 관련 변경으로만 구성되어 있으며, 추후 계획인 타입/폴더 네이밍이나 인터페이스 규칙 변경은 포함되지 않았습니다.
Description check ✅ Passed PR 설명이 템플릿의 필수 섹션을 모두 포함하고 있으며, 작업 내용, 체크리스트, 논의 사항이 상세하게 작성되어 있습니다.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch setting/#131

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
Review rate limit: 0/1 reviews remaining, refill in 15 minutes and 31 seconds.

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 14

Caution

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

⚠️ Outside diff range comments (7)
src/pages/myPage/subscriptionPage.tsx (1)

140-205: ⚠️ Potential issue | 🟡 Minor

플랜 목록 empty 상태 UX를 하나 추가해두면 좋아요

plans가 비는 경우 현재는 영역이 통째로 비어 보여서 사용자 입장에서 상태 파악이 어렵습니다. 페이지 컴포넌트라 empty fallback 한 줄만 있어도 UX가 훨씬 좋아집니다.

예시 코드
-      <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
-        {plans.map((plan) => {
+      {plans.length === 0 ? (
+        <div className="rounded-xl border border-gray-100 bg-white p-6 text-sm text-gray-500">
+          현재 선택 가능한 구독 플랜이 없습니다.
+        </div>
+      ) : (
+        <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
+          {plans.map((plan) => {
             const isCurrent = selectedPlan === plan.name;
             const isRecommended = plan.name === "프리미엄";
 
             return (
               ...
             );
-        })}
-      </div>
+          })}
+        </div>
+      )}

As per coding guidelines src/pages/**: 라우팅/레이아웃 영향, 로딩/에러/empty 상태 UX 확인.

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

In `@src/pages/myPage/subscriptionPage.tsx` around lines 140 - 205, Add an
explicit empty-state fallback when the plans list is empty so the UI doesn't
render a blank area: in the component that maps over plans (the block using
plans.map and referencing selectedPlan, billingCycle, handlePlanChange), check
if plans.length === 0 and render a concise placeholder (e.g., a centered message
and optional CTA) instead of the grid; ensure the fallback matches existing
styling and accessibility patterns and disables plan-interaction UI when shown.
src/pages/myPage/settingPage.tsx (1)

40-46: ⚠️ Potential issue | 🟠 Major

스위치에 접근 가능한 이름이 필요해요.

현재 role="switch"는 있지만 이름이 없어 보조기기에서 “무슨 스위치인지” 읽히지 않습니다. aria-label(또는 aria-labelledby)을 Switch에 전달해 주세요.

예시 수정 코드
-function Switch({ enabled, onClick }: { enabled: boolean; onClick: () => void }) {
+function Switch({
+  enabled,
+  onClick,
+  ariaLabel,
+}: {
+  enabled: boolean;
+  onClick: () => void;
+  ariaLabel: string;
+}) {
   return (
     <button
       type="button"
       role="switch"
       aria-checked={enabled}
+      aria-label={ariaLabel}
       onClick={onClick}
-<Switch enabled={enabled} onClick={onClick} />
+<Switch enabled={enabled} onClick={onClick} ariaLabel={label} />
-<Switch enabled={notifications.email} onClick={() => toggleNotification("email")} />
+<Switch
+  enabled={notifications.email}
+  onClick={() => toggleNotification("email")}
+  ariaLabel="이메일 알림 수신"
+/>
...
-<Switch enabled={notifications.sms} onClick={() => toggleNotification("sms")} />
+<Switch
+  enabled={notifications.sms}
+  onClick={() => toggleNotification("sms")}
+  ariaLabel="SMS 알림 수신"
+/>

Also applies to: 160-162

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

In `@src/pages/myPage/settingPage.tsx` around lines 40 - 46, The Switch component
lacks an accessible name; update the Switch signature to accept an ariaLabel (or
labelledBy) prop (e.g., add parameter ariaLabel?: string) and pass it through to
the rendered button as aria-label (or aria-labelledby) so assistive tech can
announce which switch it is; then update all call sites (including the other
Switch usage around the 160-162 area) to provide a suitable aria-label or
aria-labelledby string/ID.
src/components/main/StateSection.tsx (1)

21-25: ⚠️ Potential issue | 🟠 Major

접근성 개선 제안: 애니메이션 모션 제어 필요

현재 애니메이션이 prefers-reduced-motion 설정을 고려하지 않아 전정기관 장애가 있는 사용자에게 불편하거나 위험할 수 있습니다. Tailwind의 motion-reduce: 유틸리티를 활용해 개선할 수 있습니다.

As per coding guidelines: "컴포넌트는 단일 책임, props 타입/네이밍 명확히, 접근성(aria) 체크."

♿ 접근성 개선 예시
         <div
           className={cn(
             "flex flex-col items-center space-y-10 tracking-tight mb-20",
-            "transition-all duration-900 ease-out",
+            "motion-reduce:transition-none transition-all duration-900 ease-out",
             inView ? "opacity-100 translate-y-0" : "opacity-0 translate-y-20",
           )}
         >

라인 34-38의 stats 아이템들도 동일하게 적용:

             <div
               key={s.label}
               className={cn(
                 "text-center",
-                "transition-all duration-900 ease-out",
+                "motion-reduce:transition-none transition-all duration-900 ease-out",
                 inView ? "opacity-100 translate-y-0" : "opacity-0 translate-y-20",
               )}

이렇게 하면 사용자가 시스템 설정에서 "모션 줄이기"를 활성화했을 때 애니메이션이 비활성화됩니다.

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

In `@src/components/main/StateSection.tsx` around lines 21 - 25, The animated
container's className (the JSX using cn(...) with inView) doesn't honor users'
prefers-reduced-motion; update the className expression for the StateSection
container and for the stats item elements to include Tailwind motion-reduce
utilities (e.g. motion-reduce:transition-none and motion-reduce:transform-none
or motion-reduce:opacity-100/motion-reduce:translate-y-0) so that when
prefers-reduced-motion is enabled the component skips transitions/transform
effects; apply the same change to the stats items' className(s) that use
inView-driven opacity/translate classes to ensure all motion is suppressed for
assistive users.
src/components/store-registration/StepBusinessAuth.tsx (2)

213-223: ⚠️ Potential issue | 🟠 Major

개업일자 변경 분기에서도 businessNumber/startDate 전달이 서로 바뀌어 있습니다.

이 상태면 인증 완료 후 개업일자 수정 시 사업자번호가 오염됩니다.

수정 예시
               {...register("startDate", {
                 onChange: (e) => {
                   if (isVerified) {
-                    const { name, startDate } = getValues();
+                    const { name, businessNumber } = getValues();
                     setIsVerified(false);
                     onComplete({
                       name,
-                      businessNumber: e.target.value,
-                      startDate,
+                      businessNumber,
+                      startDate: e.target.value,
                       isVerified: false,
                     });
                   }
                 },
               })}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/store-registration/StepBusinessAuth.tsx` around lines 213 -
223, 현재 register("startDate")의 onChange 블록이 getValues()에서 { name, startDate }를
받아와 e.target.value를 businessNumber로 넘기고 있어 businessNumber와 startDate가 뒤바뀌고 있습니다;
onChange 핸들러(등록된 register("startDate") 블록)에서 const { name, businessNumber } =
getValues()로 올바른 값을 읽고 setIsVerified(false) 후 onComplete에 businessNumber:
businessNumber (또는 getValues().businessNumber)와 startDate: e.target.value를 넘기도록
수정하세요 (참조: isVerified, getValues, setIsVerified, onComplete,
register("startDate")).

168-184: ⚠️ Potential issue | 🟠 Major

사업자등록번호 변경 시 onComplete 필드 매핑이 뒤바뀌어 있어요.

현재 분기에서 e.target.valuestartDate로 전달하고 있어, 인증 후 값 수정 시 부모 상태가 잘못 저장됩니다.

수정 예시
               {...register("businessNumber", {
                 onChange: (e) => {
                   if (isVerified) {
-                    const { name, businessNumber } = getValues();
+                    const { name, startDate } = getValues();
                     setIsVerified(false);
                     onComplete({
                       name,
-                      businessNumber,
-                      startDate: e.target.value,
+                      businessNumber: e.target.value,
+                      startDate,
                       isVerified: false,
                     });
                   }
                 },
               })}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/store-registration/StepBusinessAuth.tsx` around lines 168 -
184, The onChange handler for the businessNumber input is passing e.target.value
into startDate, causing parent state to get wrong fields when a verified
business number is edited; update the handler in the register call for
"businessNumber" (the onChange inside register), so it reads const { name,
startDate } = getValues(); then setIsVerified(false); and call onComplete({
name, businessNumber: e.target.value, startDate, isVerified: false }) — i.e.,
map e.target.value to businessNumber and preserve startDate.
src/components/owner/tableDashboard.tsx (1)

244-257: ⚠️ Potential issue | 🔴 Critical

fetchLayout 이펙트가 tableData 의존성 때문에 반복 호출 루프를 만들 수 있어요.

이펙트 내부에서 setTableData(...)를 수행하면서 의존성에 tableData가 포함되어 있어, 레이아웃 재조회가 연쇄적으로 반복될 수 있습니다.

수정 예시
-          setTableData(mapTablesFromApi(layout.tables, layout.gridInfo.gridCol, tableData));
+          setTableData((prev) =>
+            mapTablesFromApi(layout.tables, layout.gridInfo.gridCol, prev),
+          );
           setCreateModalOpen(false);
@@
-  }, [storeId, tableData]);
+  }, [storeId]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/owner/tableDashboard.tsx` around lines 244 - 257, The
useEffect that defines and calls fetchLayout is currently depending on tableData
which causes a re-render loop because fetchLayout calls setTableData; remove
tableData from the dependency array and instead depend only on storeId (or other
true external deps), or if you must react to tableData changes, use a ref or a
separate effect; specifically update the useEffect containing fetchLayout (the
function named fetchLayout and the calls to setTableData and setCreateModalOpen)
to not include tableData in its dependency array to prevent repeated fetches.
src/api/bookings.ts (1)

43-48: ⚠️ Potential issue | 🟠 Major

cancelBooking 응답 타입이 열려 있어 타입 안정성이 깨질 수 있습니다

현재 response.data가 사실상 any로 흐를 수 있어 호출부에서 런타임 오류를 숨길 가능성이 있습니다. 반환 타입과 axios 제네릭을 명시해 주세요.

예시 수정안
+ interface CancelBookingResponse {
+   result: {
+     bookingId: number;
+     status: "CANCELED";
+   };
+ }

-export const cancelBooking = async (bookingId: number, reason: string = "사용자 취소") => {
-  const response = await api.patch(`/api/v1/bookings/${bookingId}/cancel`, {
+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/**: 에러 처리/타임아웃/리트라이 전략 확인, 응답 타입 안전성 유지.

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

In `@src/api/bookings.ts` around lines 43 - 48, The cancelBooking function returns
an untyped response which breaks type safety; define a specific response
interface (e.g., CancelBookingResponse) that models the API payload, annotate
api.patch with the axios generic (api.patch<CancelBookingResponse>(...)) and set
the cancelBooking signature to return Promise<CancelBookingResponse>; while here
you update types, also ensure the request uses existing shared axios options
(timeout/retry/interceptor) rather than raw calls so error/timeout/retry
behavior is preserved.
🧹 Nitpick comments (10)
src/pages/myPage/subscriptionPage.tsx (1)

181-181: 리스트 key는 문자열 단독보다 복합 key가 더 안전해요

key={feature}는 문구 중복 시 충돌 가능성이 있습니다. plan.name + index 등으로 조합하면 안정적입니다.

예시 코드
-                {plan.features.map((feature) => (
-                  <li key={feature} className="flex items-center gap-3 text-sm text-gray-600">
+                {plan.features.map((feature, idx) => (
+                  <li key={`${plan.name}-${idx}`} className="flex items-center gap-3 text-sm text-gray-600">
                     <Check size={18} className="text-blue-500" />
                     {feature}
                   </li>
                 ))}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/myPage/subscriptionPage.tsx` at line 181, The list item key
currently uses only feature (key={feature}), which can collide for duplicate
feature strings; update the map creating the <li> in subscriptionPage.tsx to use
a composite key that includes the plan identity and the item index (e.g.,
combine plan.name and the map index and feature) so each key is unique across
plans and repeated feature labels; locate the map that renders the feature
variable inside the component and replace key={feature} with a concatenation
like `${plan.name}-${index}-${feature}` (or equivalent) to ensure stable, unique
keys.
src/components/customer-support/SupportFAQ.tsx (2)

96-116: FAQ 토글 버튼에 aria-expanded 속성 추가를 권장합니다.

FAQ 아코디언 버튼에 aria-expanded 속성을 추가하면, 스크린 리더 사용자가 현재 항목의 펼쳐짐/접힘 상태를 명확히 인지할 수 있습니다.

♻️ 접근성 개선 제안
              <button
                onClick={() => toggleFaq(faq.id)}
+               aria-expanded={openFaqId === faq.id}
                className="w-full p-4 md:px-6 md:py-5 flex items-center justify-between text-left hover:bg-gray-100 transition-colors cursor-pointer"
              >

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/customer-support/SupportFAQ.tsx` around lines 96 - 116, The
FAQ toggle button lacks an aria-expanded attribute which impairs screen-reader
feedback; update the button in SupportFAQ (the element using onClick={() =>
toggleFaq(faq.id)} and checking openFaqId === faq.id) to set
aria-expanded={openFaqId === faq.id} so the button reflects expanded/collapsed
state for assistive tech, and ensure the value updates alongside the existing
toggleFaq logic (no other changes to toggleFaq necessary).

46-52: 검색 입력창에 접근성 레이블 추가를 권장합니다.

검색 입력창에 시각적 placeholder는 있지만, 스크린 리더 사용자를 위한 명시적 레이블이 없습니다. 접근성 개선을 위해 aria-label을 추가하면 좋겠습니다.

♻️ 접근성 개선 제안
          <input
            type="text"
            placeholder="궁금한 내용을 검색해보세요"
+           aria-label="FAQ 검색"
            value={searchTerm}
            onChange={(e) => setSearchTerm(e.target.value)}
            className="w-full pl-12 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none"
          />

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/customer-support/SupportFAQ.tsx` around lines 46 - 52, The
search input in SupportFAQ (the <input> that uses value={searchTerm} and
onChange={(e) => setSearchTerm(e.target.value)}) lacks an explicit accessibility
label; add an aria-label (for example "검색어 입력" or "Search FAQs") to that input
element so screen readers can identify its purpose, ensuring it remains in sync
with the existing placeholder and state handling.
src/pages/myPage/settingPage.tsx (1)

80-81: 초기 알림 상태의 타입 안전성 검증을 추가하면 더 안정적입니다.

localStorage 값이 깨졌거나 구버전 포맷이면 boolean이 아닌 값이 상태로 들어올 수 있습니다. 초기화 시점에 스키마/가드로 한 번 검증해 두는 게 안전합니다.

예시 수정 코드
+const isNotificationSettings = (value: unknown): value is NotificationSettings => {
+  if (!value || typeof value !== "object") return false;
+  const v = value as Record<string, unknown>;
+  return ["reservation", "promotion", "review", "email", "sms"].every(
+    (k) => typeof v[k] === "boolean",
+  );
+};

 const getInitialNotifications = () => {
   if (typeof window === "undefined") return defaultNotifications;

   try {
     const raw = localStorage.getItem(STORAGE_KEY);
     if (!raw) return defaultNotifications;
     const parsed = JSON.parse(raw);
-    return { ...defaultNotifications, ...parsed };
+    if (!isNotificationSettings(parsed)) return defaultNotifications;
+    return { ...defaultNotifications, ...parsed };
   } catch (e) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/myPage/settingPage.tsx` around lines 80 - 81, The initial
notification state may contain malformed values from localStorage; add a runtime
validator (e.g. isValidNotificationSettings) that checks the
NotificationSettings shape and boolean types, use it inside
getInitialNotifications (or immediately after parsing) to return either the
parsed value or a safe defaultNotifications object, and initialize both
notifications and savedNotifications with the validated result (replace direct
use of getInitialNotifications return for setSavedNotifications as well) so only
type-safe NotificationSettings enter state.
src/pages/LoginErrorPage.tsx (1)

5-38: 접근성 개선 제안 (선택사항)

현재 에러 페이지는 시각적으로 에러 상태를 잘 표현하고 있지만, 스크린 리더 사용자를 위한 추가 개선이 가능합니다. 에러 발생 시 보조 기술이 자동으로 안내할 수 있도록 ARIA live region을 추가하면 UX가 더 향상될 것 같아요.

♿ 접근성 개선 예시
 const LoginErrorPage: React.FC = () => {
   const navigate = useNavigate();
 
   return (
     <div className="min-h-screen bg-gray-50 flex items-center justify-center px-6">
-      <div className="max-w-md w-full text-center">
+      <div className="max-w-md w-full text-center" role="alert" aria-live="assertive">
         <div className="relative mb-8">
           <div className="absolute inset-0 flex items-center justify-center animate-pulse">
             <div className="w-32 h-32 bg-red-100 rounded-full"></div>
           </div>
           <div className="relative flex justify-center">
-            <AlertCircle size={60} className="text-red-600" />
+            <AlertCircle size={60} className="text-red-600" aria-hidden="true" />
           </div>
         </div>
-        <h1 className="text-5xl font-bold text-red-600 mb-4">Error</h1>
+        <h1 className="text-5xl font-bold text-red-600 mb-4" id="error-title">Error</h1>
         <h2 className="text-2xl font-semibold text-gray-900 mb-3">로그인에 실패했습니다</h2>

role="alert"aria-live="assertive"를 추가하면 스크린 리더가 에러 발생을 즉시 알려줍니다.

As per coding guidelines: src/pages/** 경로의 파일은 에러 상태 UX 확인이 필요하며, 접근성 개선은 사용자 경험 향상에 도움이 됩니다.

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

In `@src/pages/LoginErrorPage.tsx` around lines 5 - 38, The LoginErrorPage
component lacks an ARIA live region to announce the error to screen readers;
update the component (e.g., the outer container inside LoginErrorPage or the
error message element rendered by the JSX) to include an accessible live region
such as adding role="alert" and aria-live="assertive" (or create a dedicated
visually-present but screen-reader-first live region) so that assistive
technologies immediately announce the error state; ensure the attributes are
applied to the element that contains the error heading/description (the h1/h2 or
the wrapping div in LoginErrorPage) and keep visual layout unchanged.
src/components/map/KakaoMap.tsx (1)

185-185: CSS 문자열 포맷팅을 일관되게 맞춰주면 좋을 것 같아요.

현재 CSS 속성 간 공백이 일관되지 않아서 가독성이 조금 떨어져요:

  • padding 뒤에는 공백이 있는데 font-size, line-height 뒤에는 공백이 없음
  • 속성 사이 세미콜론 뒤 공백도 누락

기능상 문제는 없지만, 통일하면 더 깔끔할 것 같습니다!

✨ 포맷팅 개선 제안
-          el.style.cssText = "padding: 6px 8px; font-size:12px;line-height:1.2;";
+          el.style.cssText = "padding: 6px 8px; font-size: 12px; line-height: 1.2;";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/map/KakaoMap.tsx` at line 185, The CSS string assigned to
el.style.cssText is inconsistently spaced; update the assignment in the KakaoMap
component so property names and values use consistent spacing and include a
space after each semicolon (e.g., "padding: 6px 8px; font-size: 12px;
line-height: 1.2;") to improve readability—locate the el.style.cssText
assignment and normalize spacing around colons and semicolons accordingly.
src/api/dto/store.dto.ts (1)

3-10: 선택적 제안: DayDTO도 단일 라인 고려해볼까요?

CategoryDTO는 단일 라인으로 압축했는데, DayDTO는 여전히 멀티라인이네요. 일관성 측면에서 DayDTO도 다음처럼 단일 라인으로 정리하면 더 깔끔할 수 있어요:

선택적 제안
-export type DayDTO =
-  | "MONDAY"
-  | "TUESDAY"
-  | "WEDNESDAY"
-  | "THURSDAY"
-  | "FRIDAY"
-  | "SATURDAY"
-  | "SUNDAY";
+export type DayDTO = "MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY";

다만 가독성 차이는 선호도 문제라서 현재 상태도 괜찮습니다!

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

In `@src/api/dto/store.dto.ts` around lines 3 - 10, The DayDTO union is formatted
across multiple lines while CategoryDTO is a single-line union; to make
formatting consistent, collapse DayDTO into a single-line union (replace the
multiline union declaration for DayDTO with a compact single-line form) ensuring
the exported type name DayDTO and its string members ("MONDAY", "TUESDAY",
"WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY") remain unchanged and
keep the export modifier intact.
src/hooks/queries/useAuth.ts (1)

44-44: alert 대신 비차단형 알림(토스트)으로 바꾸는 걸 권장합니다.

Line 44의 alert는 UI를 멈추게 해서 사용자 흐름이 끊길 수 있어요. 같은 메시지는 토스트/스낵바로 처리하면 UX가 더 안정적입니다.

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

In `@src/hooks/queries/useAuth.ts` at line 44, Replace the blocking browser alert
used in useAuth.ts (the alert("사업자 인증이 완료되었습니다. \n사장님 권한 적용을 위해 반드시 재로그인해주세요.");
call) with a non-blocking toast/snackbar: import and use your app's notification
utility (eg. showToast, enqueueSnackbar, or NotificationService) inside the same
function so the same message is shown asynchronously; ensure the toast
variant/severity (info/success) and any required options (autoHideDuration,
multi-line support) are set and remove the alert call.
src/pages/myPage/storePage.tsx (1)

99-100: 로딩 상태 문구에 aria-live를 추가해 접근성을 보완해주세요.

Line 99의 로딩 메시지는 시각적으로는 충분하지만, 스크린리더 사용자에게 상태 변경이 자동 전달되지 않을 수 있어요. aria-live="polite"를 붙이면 로딩/에러/empty UX 완성도가 더 좋아집니다.

예시 코드
- <div className="py-14 text-center text-gray-400">가게 정보를 불러오는 중입니다...</div>
+ <div className="py-14 text-center text-gray-400" aria-live="polite">
+   가게 정보를 불러오는 중입니다...
+ </div>

As per coding guidelines, src/pages/**: 라우팅/레이아웃 영향, 로딩/에러/empty 상태 UX 확인.

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

In `@src/pages/myPage/storePage.tsx` around lines 99 - 100, The loading message
div (the element with className "py-14 text-center text-gray-400") should
include accessibility attributes so screen readers announce state changes; add
aria-live="polite" to that div (and optionally role="status") so the
loading/empty/error text is announced automatically to assistive technologies.
src/api/bookings.ts (1)

39-40: 중복 타입 캐스팅은 제거해도 됩니다

api.get<{ result: BookingResponse }>로 이미 타입이 보장돼서 as BookingResponse는 불필요합니다. 제거하면 타입 신뢰성이 더 명확해져요.

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

In `@src/api/bookings.ts` around lines 39 - 40, The code redundantly casts the
result despite api.get already typing the shape; remove the unnecessary "as
BookingResponse" and return response.data.result directly. Locate the call to
api.get<{ result: BookingResponse }>(), the response variable
(response.data.result) and the BookingResponse type, then change the function to
return response.data.result without the type assertion so the declared generic
is the single source of type truth.
🤖 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/api/endpoints/member.ts`:
- Around line 58-59: The change password call currently returns res.data.result
without verifying the API success flag; update the handler that calls
api.put<ApiEnvelope<ChangePasswordResponse>> (the ChangePassword endpoint in
src/api/endpoints/member.ts) to follow the same success-validation pattern used
by other endpoints: verify res.data.success (or the project’s ApiEnvelope
success indicator) and throw a descriptive error (or return a typed failure)
when it’s false, otherwise return res.data.result; ensure you also null-check
res.data and preserve ApiEnvelope/ChangePasswordResponse typings for type
safety.

In `@src/api/endpoints/payments.ts`:
- Around line 47-48: The confirmPayment call currently returns res.data.result
without checking the ApiEnvelope success/failure, so update the confirmPayment
implementation (the api.post call that returns
ApiEnvelope<PaymentConfirmResult>) to validate the envelope: check the
envelope's status/success flag and presence of result, and if the envelope
indicates failure or result is missing throw a descriptive error (including the
server message from the envelope) or return a rejected Promise; ensure any
thrown error includes the envelope.message and relevant metadata so callers can
handle failures safely.

In `@src/components/auth/SignupDialog.tsx`:
- Around line 130-131: The error message <p> elements in SignupDialog.tsx (e.g.,
the block rendering {errors.name && <p ...>{errors.name.message}</p>}) lack
accessibility attributes; update each field's input and its corresponding error
node so the input has an id and aria-describedby pointing to the error element,
and the error <p> uses role="alert" and/or aria-live="assertive" (or "polite" as
appropriate) with a unique id (e.g., nameError) so screen readers announce
validation messages; apply the same modification pattern to the other error
render sites mentioned (lines around the other {errors.*} usages) to ensure
consistent ARIA linking and live region announcements.

In `@src/components/customer-support/support.schema.ts`:
- Line 20: Update the Zod error message usage in the support schema to avoid the
deprecated `{ message: "..." }` pattern: replace occurrences on the `title` and
`content` fields (and any other z.string().min/max calls using `{ message: ...
}`) with the modern form—pass the error message string directly (e.g.,
z.string().min(1, "...").max(100, "...")) or use `{ error: "..." }` if you need
an object—so all validations in the schema (the `title` and `content` keys in
the exported schema object) use a consistent, non-deprecated error format.

In `@src/components/customer-support/SupportModal.tsx`:
- Around line 119-120: The form error messages in SupportModal lack ARIA linking
and live-region semantics; update the error <p> elements (e.g., the one rendered
for errors.name) to include role="alert" or aria-live="assertive" and give each
error a unique id (e.g., `${fieldName}-error`) and then ensure the corresponding
input element (in SupportModal) has aria-describedby pointing to that id so
screen readers detect changes; apply the same pattern for the other error
renders referenced (around lines handling errors at 135-136, 151-153, 169-170,
185-186) and keep error ids unique per field.

In `@src/components/owner/menuFormModal.tsx`:
- Around line 4-5: Combine the duplicate imports from the same module: replace
the two separate imports in menuFormModal.tsx that pull createMenus,
MenuUpdateItem, updateMenu, uploadMenuImage and deleteMenuImage from
"@/api/owner/menus" with a single consolidated import statement that imports all
those symbols together (createMenus, type MenuUpdateItem, updateMenu,
uploadMenuImage, deleteMenuImage).

In `@src/components/owner/MenuManagement.tsx`:
- Around line 51-53: The temporary ID generation in mapServerToLocal (returning
id: String(s.menuId ?? `MENU_${Date.now()}`)) can collide when multiple items
are created in the same millisecond; replace the Date.now()-only fallback with a
collision-resistant generator (e.g., use crypto.randomUUID() or a UUIDv4
library) so the id for MenuItem is unique (e.g., id: s.menuId ? String(s.menuId)
: `MENU_${<uuid>}`), ensuring mapServerToLocal and any consumers of MenuItem get
a stable, unique identifier.

In `@src/components/owner/StoreSettings.tsx`:
- Line 399: The alert message in StoreSettings.tsx currently lists "가게 이름, 설명,
전화번호, 이메일, 주소" as required but the validation only checks for 가게 이름, 설명, 전화번호;
update the message to match the actual validation or expand the validation to
include 이메일 and 주소. Locate the validation/submit handler in the StoreSettings
component (the function that triggers alert(...) at the shown diff) and either
change the alert text to "가게 이름, 설명, 전화번호는 필수 입력 항목입니다." or add checks for email
and address (and include those fields in the required validation) so the
displayed message matches the enforced rules.

In `@src/components/owner/tableDashboard.tsx`:
- Around line 685-695: Replace the clickable Pencil SVG usage with a native
interactive element: wrap or replace the Pencil component with a <button
type="button"> that carries the onClick handler (which calls
e.stopPropagation(); updateTable(id, { isEditingNum: true })), preserves the
aria-label ("테이블 번호 수정") and the visual classes (text-orange-400 fill-orange-400
cursor-pointer opacity-0 group-hover:opacity-100 transition-opacity); remove
role="button" and tabIndex since the native button provides correct keyboard
activation and semantics. Ensure any focus/visual styles remain consistent and
that tests/linters still pass after moving the onClick from the SVG to the
button.

In `@src/components/reservation/modals/PaymentModal.tsx`:
- Around line 77-80: The UI is still rendering booking.totalDeposit directly
instead of the state variable _payAmount, so updates via setPayAmount(...) never
appear; update the component to read and render the state (_payAmount)
everywhere you currently use booking.totalDeposit (and ensure the same fix at
the other occurrence around line 237), and also synchronize _payAmount with
incoming payOrder.amount (and booking?.totalDeposit) in the useEffect(s) that
currently call setPayAmount to guarantee the displayed amount matches
server-provided payOrder.amount.

In `@src/components/reservation/modals/ReservationConfirmModal.tsx`:
- Line 168: In ReservationConfirmModal, fix the user-facing spacing/ellipsis in
the two places that render the deposit text (where isCalculating, depositAmount
and formatKrw are used): replace the awkward "계산중 .." with a consistent,
user-friendly string like "계산 중…" (space between 계산 and 중 and a single ellipsis)
and ensure the rendered amount string is spaced consistently (update the
`${formatKrw(depositAmount)}원` occurrence(s) to match your UI convention, e.g.,
`${formatKrw(depositAmount)} 원` or keep it attached if that’s the project style)
in both locations so both lines show consistent punctuation and spacing.

In `@src/components/reservation/modals/ReservationMenuModal.tsx`:
- Around line 183-188: The render loop currently maps over
(["MAIN","SIDE","BEVERAGE","ALCOHOL"] as MenuCategory[]) and therefore never
renders items categorized as "OTHER" by mapMenuCategory; update the iteration to
include the OTHER category (or iterate keys from grouped) so grouped["OTHER"] is
checked and rendered; adjust the mapped array or replace it with
Object.keys(grouped) (or a typed equivalent) and continue to use
MenuCategoryLabel and grouped to derive safeLabel and list so no "OTHER" menus
are dropped.

In `@src/layouts/PublicLayout.tsx`:
- Around line 29-30: The current parse of rawId assigns parsedId = Number(rawId)
and then checks Number.isFinite(parsedId), which still allows integers >
Number.MAX_SAFE_INTEGER; update the validation so you only accept safe integers:
after converting rawId to a number (rawId -> parsedId) check
Number.isSafeInteger(parsedId) instead of Number.isFinite(parsedId) (use the
existing rawId and parsedId variables/logic in PublicLayout.tsx) so only safe
integer member IDs are accepted.

In `@src/pages/payment/FailPage.tsx`:
- Line 74: The JSX in FailPage currently renders literal semicolons between
error fragments (the expression with {code ? `code: ${code}` : null};{message ?
`message: ${message}` : null};) causing stray ";" characters; update FailPage to
avoid printing semicolons by either rendering code and message as separate
elements (e.g., render a <div> or <span> for each of the code and message when
present) or build a single string that joins non-empty parts with a separator
only when both exist (e.g., conditionally join ["code: …", "message: …"] with "
• " or similar), ensuring the unique expression currently producing semicolons
is replaced accordingly.

---

Outside diff comments:
In `@src/api/bookings.ts`:
- Around line 43-48: The cancelBooking function returns an untyped response
which breaks type safety; define a specific response interface (e.g.,
CancelBookingResponse) that models the API payload, annotate api.patch with the
axios generic (api.patch<CancelBookingResponse>(...)) and set the cancelBooking
signature to return Promise<CancelBookingResponse>; while here you update types,
also ensure the request uses existing shared axios options
(timeout/retry/interceptor) rather than raw calls so error/timeout/retry
behavior is preserved.

In `@src/components/main/StateSection.tsx`:
- Around line 21-25: The animated container's className (the JSX using cn(...)
with inView) doesn't honor users' prefers-reduced-motion; update the className
expression for the StateSection container and for the stats item elements to
include Tailwind motion-reduce utilities (e.g. motion-reduce:transition-none and
motion-reduce:transform-none or
motion-reduce:opacity-100/motion-reduce:translate-y-0) so that when
prefers-reduced-motion is enabled the component skips transitions/transform
effects; apply the same change to the stats items' className(s) that use
inView-driven opacity/translate classes to ensure all motion is suppressed for
assistive users.

In `@src/components/owner/tableDashboard.tsx`:
- Around line 244-257: The useEffect that defines and calls fetchLayout is
currently depending on tableData which causes a re-render loop because
fetchLayout calls setTableData; remove tableData from the dependency array and
instead depend only on storeId (or other true external deps), or if you must
react to tableData changes, use a ref or a separate effect; specifically update
the useEffect containing fetchLayout (the function named fetchLayout and the
calls to setTableData and setCreateModalOpen) to not include tableData in its
dependency array to prevent repeated fetches.

In `@src/components/store-registration/StepBusinessAuth.tsx`:
- Around line 213-223: 현재 register("startDate")의 onChange 블록이 getValues()에서 {
name, startDate }를 받아와 e.target.value를 businessNumber로 넘기고 있어 businessNumber와
startDate가 뒤바뀌고 있습니다; onChange 핸들러(등록된 register("startDate") 블록)에서 const { name,
businessNumber } = getValues()로 올바른 값을 읽고 setIsVerified(false) 후 onComplete에
businessNumber: businessNumber (또는 getValues().businessNumber)와 startDate:
e.target.value를 넘기도록 수정하세요 (참조: isVerified, getValues, setIsVerified,
onComplete, register("startDate")).
- Around line 168-184: The onChange handler for the businessNumber input is
passing e.target.value into startDate, causing parent state to get wrong fields
when a verified business number is edited; update the handler in the register
call for "businessNumber" (the onChange inside register), so it reads const {
name, startDate } = getValues(); then setIsVerified(false); and call
onComplete({ name, businessNumber: e.target.value, startDate, isVerified: false
}) — i.e., map e.target.value to businessNumber and preserve startDate.

In `@src/pages/myPage/settingPage.tsx`:
- Around line 40-46: The Switch component lacks an accessible name; update the
Switch signature to accept an ariaLabel (or labelledBy) prop (e.g., add
parameter ariaLabel?: string) and pass it through to the rendered button as
aria-label (or aria-labelledby) so assistive tech can announce which switch it
is; then update all call sites (including the other Switch usage around the
160-162 area) to provide a suitable aria-label or aria-labelledby string/ID.

In `@src/pages/myPage/subscriptionPage.tsx`:
- Around line 140-205: Add an explicit empty-state fallback when the plans list
is empty so the UI doesn't render a blank area: in the component that maps over
plans (the block using plans.map and referencing selectedPlan, billingCycle,
handlePlanChange), check if plans.length === 0 and render a concise placeholder
(e.g., a centered message and optional CTA) instead of the grid; ensure the
fallback matches existing styling and accessibility patterns and disables
plan-interaction UI when shown.

---

Nitpick comments:
In `@src/api/bookings.ts`:
- Around line 39-40: The code redundantly casts the result despite api.get
already typing the shape; remove the unnecessary "as BookingResponse" and return
response.data.result directly. Locate the call to api.get<{ result:
BookingResponse }>(), the response variable (response.data.result) and the
BookingResponse type, then change the function to return response.data.result
without the type assertion so the declared generic is the single source of type
truth.

In `@src/api/dto/store.dto.ts`:
- Around line 3-10: The DayDTO union is formatted across multiple lines while
CategoryDTO is a single-line union; to make formatting consistent, collapse
DayDTO into a single-line union (replace the multiline union declaration for
DayDTO with a compact single-line form) ensuring the exported type name DayDTO
and its string members ("MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY",
"SATURDAY", "SUNDAY") remain unchanged and keep the export modifier intact.

In `@src/components/customer-support/SupportFAQ.tsx`:
- Around line 96-116: The FAQ toggle button lacks an aria-expanded attribute
which impairs screen-reader feedback; update the button in SupportFAQ (the
element using onClick={() => toggleFaq(faq.id)} and checking openFaqId ===
faq.id) to set aria-expanded={openFaqId === faq.id} so the button reflects
expanded/collapsed state for assistive tech, and ensure the value updates
alongside the existing toggleFaq logic (no other changes to toggleFaq
necessary).
- Around line 46-52: The search input in SupportFAQ (the <input> that uses
value={searchTerm} and onChange={(e) => setSearchTerm(e.target.value)}) lacks an
explicit accessibility label; add an aria-label (for example "검색어 입력" or "Search
FAQs") to that input element so screen readers can identify its purpose,
ensuring it remains in sync with the existing placeholder and state handling.

In `@src/components/map/KakaoMap.tsx`:
- Line 185: The CSS string assigned to el.style.cssText is inconsistently
spaced; update the assignment in the KakaoMap component so property names and
values use consistent spacing and include a space after each semicolon (e.g.,
"padding: 6px 8px; font-size: 12px; line-height: 1.2;") to improve
readability—locate the el.style.cssText assignment and normalize spacing around
colons and semicolons accordingly.

In `@src/hooks/queries/useAuth.ts`:
- Line 44: Replace the blocking browser alert used in useAuth.ts (the alert("사업자
인증이 완료되었습니다. \n사장님 권한 적용을 위해 반드시 재로그인해주세요."); call) with a non-blocking
toast/snackbar: import and use your app's notification utility (eg. showToast,
enqueueSnackbar, or NotificationService) inside the same function so the same
message is shown asynchronously; ensure the toast variant/severity
(info/success) and any required options (autoHideDuration, multi-line support)
are set and remove the alert call.

In `@src/pages/LoginErrorPage.tsx`:
- Around line 5-38: The LoginErrorPage component lacks an ARIA live region to
announce the error to screen readers; update the component (e.g., the outer
container inside LoginErrorPage or the error message element rendered by the
JSX) to include an accessible live region such as adding role="alert" and
aria-live="assertive" (or create a dedicated visually-present but
screen-reader-first live region) so that assistive technologies immediately
announce the error state; ensure the attributes are applied to the element that
contains the error heading/description (the h1/h2 or the wrapping div in
LoginErrorPage) and keep visual layout unchanged.

In `@src/pages/myPage/settingPage.tsx`:
- Around line 80-81: The initial notification state may contain malformed values
from localStorage; add a runtime validator (e.g. isValidNotificationSettings)
that checks the NotificationSettings shape and boolean types, use it inside
getInitialNotifications (or immediately after parsing) to return either the
parsed value or a safe defaultNotifications object, and initialize both
notifications and savedNotifications with the validated result (replace direct
use of getInitialNotifications return for setSavedNotifications as well) so only
type-safe NotificationSettings enter state.

In `@src/pages/myPage/storePage.tsx`:
- Around line 99-100: The loading message div (the element with className "py-14
text-center text-gray-400") should include accessibility attributes so screen
readers announce state changes; add aria-live="polite" to that div (and
optionally role="status") so the loading/empty/error text is announced
automatically to assistive technologies.

In `@src/pages/myPage/subscriptionPage.tsx`:
- Line 181: The list item key currently uses only feature (key={feature}), which
can collide for duplicate feature strings; update the map creating the <li> in
subscriptionPage.tsx to use a composite key that includes the plan identity and
the item index (e.g., combine plan.name and the map index and feature) so each
key is unique across plans and repeated feature labels; locate the map that
renders the feature variable inside the component and replace key={feature} with
a concatenation like `${plan.name}-${index}-${feature}` (or equivalent) to
ensure stable, unique keys.
🪄 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

Run ID: 8900fcbf-e4d2-477f-b6cd-a5e1b45c638a

📥 Commits

Reviewing files that changed from the base of the PR and between 4f691b0 and c41342e.

⛔ Files ignored due to path filters (7)
  • .prettierrc is excluded by none and included by none
  • eslint.config.js is excluded by none and included by none
  • index.html is excluded by none and included by none
  • package.json is excluded by none and included by none
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml and included by none
  • tsconfig.json is excluded by none and included by none
  • vite.config.ts is excluded by none and included by none
📒 Files selected for processing (116)
  • src/App.tsx
  • src/api/adapters/store.adapter.ts
  • src/api/api.error.ts
  • src/api/auth.ts
  • src/api/axios.ts
  • src/api/bookings.ts
  • src/api/dto/store.dto.ts
  • src/api/endpoints/bookings.ts
  • src/api/endpoints/member.ts
  • src/api/endpoints/menus.ts
  • src/api/endpoints/payments.ts
  • src/api/endpoints/reservations.ts
  • src/api/inquiry.ts
  • src/api/menu.ts
  • src/api/owner/menus.ts
  • src/api/owner/reservation.ts
  • src/api/owner/storeLayout.ts
  • src/api/owner/stores.ts
  • src/api/owner/table.ts
  • src/api/store.ts
  • src/components/RouteGuards.tsx
  • src/components/auth/ChangePasswordDiaLog.tsx
  • src/components/auth/LoginDialog.tsx
  • src/components/auth/Signup.schema.ts
  • src/components/auth/SignupDialog.tsx
  • src/components/auth/WithdrawDialog.tsx
  • src/components/customer-support/SupportCompleteModal.tsx
  • src/components/customer-support/SupportFAQ.tsx
  • src/components/customer-support/SupportHero.tsx
  • src/components/customer-support/SupportModal.tsx
  • src/components/customer-support/support.schema.ts
  • src/components/main/CtaSection.tsx
  • src/components/main/FeatureCard.tsx
  • src/components/main/FeatureSection.tsx
  • src/components/main/Footer.tsx
  • src/components/main/ForOwnerSection.tsx
  • src/components/main/ForUserSection.tsx
  • src/components/main/Header.tsx
  • src/components/main/Hero.tsx
  • src/components/main/ProblemSection.tsx
  • src/components/main/StateSection.tsx
  • src/components/map/KakaoMap.tsx
  • src/components/owner/AddTableModal.tsx
  • src/components/owner/BreakTimeModal.tsx
  • src/components/owner/MenuManagement.tsx
  • src/components/owner/StoreSettings.tsx
  • src/components/owner/TableCreateModal.tsx
  • src/components/owner/menuFormModal.tsx
  • src/components/owner/tableDashboard.tsx
  • src/components/owner/tableDetailModal.tsx
  • src/components/reservation/modals/PaymentModal.tsx
  • src/components/reservation/modals/ReservationCompleteModal.tsx
  • src/components/reservation/modals/ReservationConfirmModal.tsx
  • src/components/reservation/modals/ReservationMenuModal.tsx
  • src/components/reservation/modals/ReservationModal.tsx
  • src/components/reservation/parts/TableMap.tsx
  • src/components/restaurant/RestaurantCard.tsx
  • src/components/restaurant/RestaurantDetailModal.tsx
  • src/components/restaurant/RestaurantList.tsx
  • src/components/restaurant/RestaurantListSkeleton.tsx
  • src/components/store-registration/CompleteModal.tsx
  • src/components/store-registration/ConfirmModal.tsx
  • src/components/store-registration/Menu.schema.ts
  • src/components/store-registration/MenuItemInput.tsx
  • src/components/store-registration/RegistrationStepper.tsx
  • src/components/store-registration/StepBusinessAuth.tsx
  • src/components/store-registration/StepMenuRegistration.tsx
  • src/components/store-registration/StepStoreInfo.tsx
  • src/components/store-registration/StoreInfo.schema.ts
  • src/components/store-registration/StoreTransform.utils.ts
  • src/components/ui/button.tsx
  • src/components/ui/calendar.tsx
  • src/components/ui/checkbox.tsx
  • src/components/ui/dialog.tsx
  • src/components/ui/label.tsx
  • src/components/ui/popover.tsx
  • src/components/ui/separator.tsx
  • src/hooks/common/useConfirmClose.ts
  • src/hooks/queries/useAuth.ts
  • src/hooks/queries/useMenu.ts
  • src/hooks/queries/useStore.ts
  • src/hooks/reservation/useAvailableTables.ts
  • src/hooks/reservation/useAvailableTimes.ts
  • src/hooks/reservation/useCreateBooking.ts
  • src/hooks/reservation/useMenus.ts
  • src/hooks/store/useRestaurantDetail.ts
  • src/hooks/store/useSearchStores.ts
  • src/layouts/PublicLayout.tsx
  • src/layouts/myPageLayout.tsx
  • src/lib/kakao.ts
  • src/lib/utils.ts
  • src/main.tsx
  • src/pages/CustomerSupportPage.tsx
  • src/pages/LoginErrorPage.tsx
  • src/pages/NotFound.tsx
  • src/pages/OAuthCallbackPage.tsx
  • src/pages/ReservationCompletePage.tsx
  • src/pages/SearchPage.tsx
  • src/pages/myPage/MyInfoPage.tsx
  • src/pages/myPage/StoreRegistrationPage.tsx
  • src/pages/myPage/reservationPage.tsx
  • src/pages/myPage/settingPage.tsx
  • src/pages/myPage/storePage.tsx
  • src/pages/myPage/subscriptionPage.tsx
  • src/pages/ownerPage.tsx
  • src/pages/payment/FailPage.tsx
  • src/pages/payment/SuccessPage.tsx
  • src/query/keys.ts
  • src/stores/useAuthStore.ts
  • src/types/booking.ts
  • src/types/kakao.d.ts
  • src/types/restaurant.ts
  • src/utils/menu.ts
  • src/utils/phoneNumber.ts
  • src/utils/reservation.ts
  • src/utils/time.ts

Comment thread src/api/endpoints/member.ts
Comment thread src/api/endpoints/payments.ts
Comment thread src/components/auth/SignupDialog.tsx
Comment thread src/components/customer-support/support.schema.ts Outdated
Comment thread src/components/customer-support/SupportModal.tsx
Comment thread src/components/reservation/modals/PaymentModal.tsx Outdated
Comment thread src/components/reservation/modals/ReservationConfirmModal.tsx Outdated
Comment thread src/components/reservation/modals/ReservationMenuModal.tsx Outdated
Comment thread src/layouts/PublicLayout.tsx Outdated
Comment thread src/pages/payment/FailPage.tsx Outdated
Copy link
Copy Markdown
Contributor

@dew102938 dew102938 left a comment

Choose a reason for hiding this comment

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

확인했습니다 수고하셨습니다!!

@jjjsun jjjsun merged commit e85bf04 into develop Apr 29, 2026
4 checks passed
@jjjsun jjjsun deleted the setting/#131 branch April 29, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚙️ Setting 기본 세팅 작업

Projects

None yet

Development

Successfully merging this pull request may close these issues.

⚙️ [Setting] import 구조 및 기본 포맷 설정

2 participants