Skip to content

feat: notFoundPage UI 구현#46

Merged
yooseolhee merged 5 commits into
developfrom
feat/notFoundPage
Feb 4, 2026
Merged

feat: notFoundPage UI 구현#46
yooseolhee merged 5 commits into
developfrom
feat/notFoundPage

Conversation

@yooseolhee

@yooseolhee yooseolhee commented Feb 3, 2026

Copy link
Copy Markdown
Contributor

💡 개요

notFoundPage UI 구현

🔢 관련 이슈 링크

💻 작업내용

-notFoundPage UI 구현
-이전으로, 홈으로 버튼 구현

📌 변경사항PR

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

🤔 추가 논의하고 싶은 내용

✅ 체크리스트

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

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 잘못된 경로로 접근할 때 사용자 친화적인 404 페이지 표시
    • 이전 페이지로 돌아가거나 홈으로 이동할 수 있는 네비게이션 옵션 추가
    • 존재하지 않는 모든 페이지에 대한 오류 처리 개선
  • 개선

    • 404 페이지 UI 및 사용성 강화

@yooseolhee yooseolhee self-assigned this Feb 3, 2026
@coderabbitai

coderabbitai Bot commented Feb 3, 2026

Copy link
Copy Markdown
📝 Walkthrough

📋 Walkthrough

라우트 설정에 catch-all 경로를 추가하고, NotFound 컴포넌트를 간단한 JSX에서 완성도 있는 React 컴포넌트로 개선했습니다. 뒤로 가기 및 홈 이동 네비게이션 로직이 추가되었습니다.

📊 Changes

Cohort / File(s) Summary
라우팅 설정
src/App.tsx
일치하지 않는 모든 경로에 대해 NotFound 컴포넌트를 렌더링하는 catch-all 라우트({ path: "*", element: <NotFound /> }) 추가.
NotFound 페이지
src/pages/NotFound.tsx
React.FC 타입 추가, useNavigate 훅 및 lucide-react 아이콘 임포트. 404 오류 페이지를 완전히 구현했으며, 뒤로 가기/홈으로 이동 버튼과 history.length 기반 네비게이션 로직 포함.

🎯 코드 리뷰 포인트

안녕하세요! 👋 NotFound 페이지 구현 고생 많으셨어요. 몇 가지 체크할 점들을 공유드립니다.

안정성 & 접근성

1️⃣ history.length 체크의 신뢰성

현재 코드에서 history.length > 1을 기반으로 뒤로 가기를 판단하고 있는데, 브라우저마다 이 값의 동작이 약간 다를 수 있습니다. 특히 새 탭에서 열린 경우나 특정 상황에서 예상과 다를 수 있어요.

제안: 더 견고하게 처리하려면:

const handleGoBack = () => {
  // history.length는 신뢰도가 100%가 아니므로, 
  // 브라우저 백 버튼 클릭 시도 후 성공 여부를 확인하는 방식도 고려
  if (window.history.length > 1) {
    window.history.back();
  } else {
    navigate('/', { replace: true });
  }
};

혹은 더 안전하게 항상 대체 옵션을 제공하는 방식도 있습니다.

2️⃣ 버튼 접근성

버튼에 aria-label 추가를 권장드립니다:

<button aria-label="이전 페이지로 돌아가기">
  <ChevronLeft />
</button>

성능 & 구조

3️⃣ 라우트 순서

App.tsx에서 catch-all 라우트(*)가 마지막에 위치하신 게 좋습니다! ✅ 이렇게 하면 더 구체적인 라우트들이 먼저 매칭되어 의도하지 않은 NotFound 페이지 노출을 방지할 수 있어요.

4️⃣ React.FC 타입

const NotFound: React.FC = () => { ... }

현대적인 React 패턴을 따르시면 더 좋습니다:

const NotFound: React.FC<{}> = () => { ... }
// 또는
const NotFound = (): React.ReactElement => { ... }

🎯 Review Effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🎉 축하시

🚀 길 잃은 사용자들을 위해
멋진 NotFound 페이지를 지었네요!
손 잡고 집으로 돌아가는 기분,
UI도 로직도 모두 아름답다 ✨
이제 404도 즐거운 경험!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 PR의 주요 변경사항을 명확하게 설명하고 있습니다. 'notFoundPage UI 구현'은 NotFound 페이지 UI를 새로 구현한 변경사항을 정확하게 반영합니다.
Description check ✅ Passed PR 설명이 템플릿의 모든 필수 섹션을 포함하고 있습니다. 개요, 관련 이슈, 작업내용, 변경사항 분류, 체크리스트가 모두 작성되어 있습니다.
Linked Issues check ✅ Passed PR의 코드 변경사항이 #45의 요구사항을 충족합니다. UI 구성, 라우팅 연결, 네비게이션 기능, 404 페이지 구현이 모두 완료되었습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 NotFound 페이지 UI 구현이라는 범위 내에 있습니다. 추가적인 범위 밖의 변경사항은 없습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

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

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🤖 Fix all issues with AI agents
In `@src/components/owner/menuFormModal.tsx`:
- Around line 42-52: The handleSubmit currently does Number(formData.price)
which yields 0 for empty string and NaN for invalid input; add validation in
handleSubmit to trim and check formData.price is non-empty and that parsedPrice
= Number(formData.price) (or parseFloat) isFinite and not NaN before calling
onSubmit, and if invalid prevent submission (do not call onSubmit/onClose) and
surface an error (e.g., set a local validation state or call a provided onError)
so the user can correct it; keep using editingMenu?.id, editingMenu?.isActive
and editingMenu?.isSoldOut when building the payload passed to onSubmit.

In `@src/components/owner/menuManagement.tsx`:
- Around line 83-88: deleteCategory currently removes the category but leaves
menus pointing to the deleted category id, creating orphaned menus; update
deleteCategory to also update menus by calling setMenus and mapping over
previous menus to replace any menu.category === id with 'ALL' (or the default
category id used by the app), then proceed to setCategories and
setActiveCategory('ALL') as before; reference deleteCategory, setMenus,
setCategories, and setActiveCategory when making this change.
- Around line 106-120: The click handler is unsafely casting dynamic category
IDs to CategoryType which can break at runtime; update the active category state
and related signatures to accept both known CategoryType values and dynamic
string IDs (e.g., change the activeCategory/state setter type from CategoryType
to string | CategoryType and adjust any consumers such as the filtering logic),
ensure cat.id is typed as string | CategoryType where categories are built
(including handleAddCategory which generates "CAT_${Date.now()}"), and remove
the cast in setActiveCategory so you call setActiveCategory(cat.id) with correct
types throughout (affecting functions: setActiveCategory, handleAddCategory,
categories.map, and any filters that read activeCategory).

In `@src/components/owner/ownerHeader.tsx`:
- Line 1: Add an explicit React import so the React.FC type is available: update
the top of ownerHeader.tsx to import React (e.g., import React from 'react'; or
import type { FC } from 'react' and update the component signature accordingly)
to ensure the React.FC type used in the ownerHeader component is resolved at
compile time.

In `@src/components/owner/storeSettings.tsx`:
- Around line 214-222: The toggle button for the no-show policy uses the wrong
state in its accessibility attribute: change the aria-checked reference from
sameDayBooking to noShowPolicy so the switch reflects
setNoShowPolicy/noShowPolicy correctly (update the button that calls
setNoShowPolicy and the aria-checked prop to use noShowPolicy instead of
sameDayBooking) to ensure screen readers receive the actual toggle state.

In `@src/components/owner/tableCreateModal.tsx`:
- Around line 24-39: The cols/rows inputs allow 0 or negative values; add native
min="1" to both number inputs and update their onChange handlers (cols ->
setCols, rows -> setRows) to parse, clamp to >=1 (e.g., Math.max(1,
Number(...))) to ensure internal state never becomes <1; additionally, before
calling onConfirm in the modal confirm handler, validate that cols and rows are
>=1 and short-circuit (or surface a validation error) if not, so an invalid
table is never created.

In `@src/components/owner/tableDashboard.tsx`:
- Line 276: In the TableDashboard component replace the invalid Tailwind class
token in the cancel/delete button JSX (currently written as bg-[`#FF6B6B`]) with
the correct syntax bg-[`#FF6B6B`] and remove the placeholder "..." token,
replacing it with the actual utility classes you want (e.g., padding, rounded,
hover/focus states like p-2 rounded-md hover:opacity-90 focus:outline-none) so
the button renders with proper styling; locate the JSX button that renders <X
size={14}/> to update its className.
- Around line 84-91: The startEditingCapacity helper captures
originalMinCapacity/originalMaxCapacity but is never used; locate where code
calls updateTable(id, { isEditingCapacity: true }) and replace that call with
startEditingCapacity(id) so the originalMinCapacity and originalMaxCapacity are
saved via getTableData before toggling edit mode; alternatively, if you prefer
to keep the inline call, update that site to also set originalMinCapacity:
table.minCapacity and originalMaxCapacity: table.maxCapacity by calling
getTableData(id) first (use function names getTableData, updateTable, and
startEditingCapacity to find the relevant spots).
🧹 Nitpick comments (17)
src/pages/myPage/storePage.tsx (1)

109-188: 빈 상태(empty state) 처리 고려해주세요

현재 shops 배열이 하드코딩되어 있지만, 추후 API 연동 시 가게 목록이 비어있을 때의 UX가 필요해요. 코딩 가이드라인에서도 로딩/에러/empty 상태 확인을 권장하고 있어요.

이슈 #45 체크리스트에 "예외처리: 로딩 / 에러 / 빈 화면"이 포함되어 있으니, 해당 작업 시 함께 처리하시면 될 것 같아요!

💡 빈 상태 처리 예시
 {/* 가게 리스트 */}
 <div className="space-y-4 mb-8">
+  {shops.length === 0 ? (
+    <div className="text-center py-12 text-gray-500">
+      <Store size={48} className="mx-auto mb-4 text-gray-300" />
+      <p>등록된 가게가 없습니다.</p>
+      <p className="text-sm mt-1">새 가게를 등록해보세요!</p>
+    </div>
+  ) : (
   {shops.map((shop) => (
     // ... existing code
   ))}
+  )}
 </div>
src/components/owner/menuFormModal.tsx (2)

4-10: any 타입 사용으로 타입 안전성이 떨어져요.

onSubmiteditingMenuany 타입을 사용하면 컴파일 타임에 타입 오류를 잡기 어렵고, 유지보수 시 실수가 발생하기 쉬워요. 명확한 타입 정의를 권장드려요.

♻️ 타입 정의 예시
+interface MenuData {
+  id: string;
+  name: string;
+  category: string;
+  price: number;
+  description: string;
+  isActive: boolean;
+  isSoldOut: boolean;
+}
+
 interface MenuFormModalProps {
   isOpen: boolean;
   onClose: () => void;
-  onSubmit: (menuData: any) => void;
+  onSubmit: (menuData: MenuData) => void;
   categories: { id: string; label: string }[];
-  editingMenu?: any; // 수정 시 전달받을 데이터
+  editingMenu?: MenuData | null;
 }

54-64: 모달 접근성(a11y) 개선이 필요해요.

스크린 리더 사용자를 위해 모달에 role="dialog"aria-modal, aria-labelledby 속성을 추가하면 좋겠어요. 닫기 버튼에도 aria-label이 있으면 더 좋아요.

♿ 접근성 개선 예시
-    <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-sm">
-      <div className="bg-white w-full max-w-lg rounded-2xl shadow-2xl overflow-hidden animate-in fade-in zoom-in duration-200 border border-gray-100">
+    <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-sm" role="presentation">
+      <div 
+        role="dialog"
+        aria-modal="true"
+        aria-labelledby="menu-form-title"
+        className="bg-white w-full max-w-lg rounded-2xl shadow-2xl overflow-hidden animate-in fade-in zoom-in duration-200 border border-gray-100"
+      >
         <div className="flex justify-between items-center px-8 py-6 border-b border-gray-50">
-          <h3 className="text-xl text-gray-900">
+          <h3 id="menu-form-title" className="text-xl text-gray-900">
             {editingMenu ? '메뉴 수정' : '새 메뉴 등록'}
           </h3>
-          <button onClick={onClose} className="p-2 text-gray-400 hover:text-gray-600 transition-colors">
+          <button onClick={onClose} aria-label="닫기" className="p-2 text-gray-400 hover:text-gray-600 transition-colors">
src/components/owner/menuManagement.tsx (1)

122-173: 메뉴가 없을 때 빈 화면(empty state) UX가 없어요.

filteredMenus가 비어있을 때 사용자에게 아무것도 보여주지 않으면 혼란스러울 수 있어요. 빈 상태 안내 메시지를 추가하면 UX가 개선돼요.

✨ Empty state 추가 예시
       {/* 메뉴 카드 그리드 */}
       <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-12">
-        {filteredMenus.map(menu => (
+        {filteredMenus.length === 0 ? (
+          <div className="col-span-full text-center py-12 text-gray-400">
+            등록된 메뉴가 없습니다. 메뉴를 추가해 주세요.
+          </div>
+        ) : filteredMenus.map(menu => (
           <div
             key={menu.id}

As per coding guidelines: src/pages/**: 로딩/에러/empty 상태 UX 확인.

src/components/owner/tableDetailModal.tsx (4)

9-9: 사용되지 않는 props와 state가 있어요.

onManageReservation prop과 setTableImageUrl setter가 선언만 되고 사용되지 않아요. 향후 구현 예정이 아니라면 제거하거나, 예정이라면 TODO 주석을 남겨두면 좋겠어요.

🧹 정리 예시
 interface Props {
   tableNumber: number;
   onClose: () => void;
   breakTimes: BreakTime[];
-  onManageReservation?: () => void; 
+  // TODO: 예약 관리 기능 추가 시 사용
+  // onManageReservation?: () => void; 
 }

또는 사용하지 않는다면:

-  const [tableImageUrl, setTableImageUrl] = useState<string | null>(null);
+  const tableImageUrl: string | null = null; // 이미지 업로드 기능 추가 시 state로 변경

Also applies to: 91-91


45-49: 시간 문자열 비교 방식이 취약할 수 있어요.

time >= bt.start && time < bt.end 같은 문자열 비교는 "09:00" < "9:00" 같은 포맷 불일치 시 잘못된 결과를 줄 수 있어요. 현재 코드에서는 padStart로 포맷팅하고 있어서 괜찮지만, 외부에서 받는 breakTimes 포맷이 다를 경우 문제가 될 수 있어요.

🛡️ 더 안전한 비교 방식
const timeToMinutes = (time: string): number => {
  const [h, m] = time.split(':').map(Number);
  return h * 60 + m;
};

const isBreakTime = (time: string, breakTimes: BreakTime[]) => {
  const timeMinutes = timeToMinutes(time);
  return breakTimes.some(
    (bt) => timeMinutes >= timeToMinutes(bt.start) && timeMinutes < timeToMinutes(bt.end)
  );
};

94-98: 모달 접근성(a11y) 개선이 필요해요.

role="dialog", aria-modal="true", aria-labelledby 속성을 추가하면 스크린 리더 사용자가 모달임을 인식할 수 있어요.

♿ 접근성 개선 예시
     <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-[100] p-4"
     onClick={onClose}>
-      <div className="bg-white w-full max-w-2xl rounded-lg shadow-2xl overflow-hidden flex flex-col max-h-[90vh] animate-in zoom-in-95 duration-200"
+      <div 
+        role="dialog"
+        aria-modal="true"
+        aria-labelledby="table-detail-title"
+        className="bg-white w-full max-w-2xl rounded-lg shadow-2xl overflow-hidden flex flex-col max-h-[90vh] animate-in zoom-in-95 duration-200"
       onClick={(e)=>e.stopPropagation()}>

그리고 헤더의 h3에 id 추가:

-            <h3 className="text-lg text-gray-900">
+            <h3 id="table-detail-title" className="text-lg text-gray-900">

209-214: 비활성화된 날짜 버튼의 cursor 스타일이 중복 적용돼요.

disabled 상태에서 cursor-not-allowed를 적용하고 있지만, 같은 className에 cursor-pointer도 함께 있어요. CSS 특성상 나중에 선언된 것이 우선하지만, 명확하게 분리하는 게 좋아요.

✨ 스타일 정리
-                    <button key={day} disabled={isPast} onClick={() => { setSelectedFullDate(dateObj); setStep('SLOTS'); }} className={`cursor-pointer h-14 rounded-xl border-2 flex flex-col items-center justify-center font-bold transition-all ${isPast ? 'bg-gray-50 border-gray-50 text-gray-300 cursor-not-allowed' : isTodayFlag ? 'bg-blue-50 border-gray-200 text-black shadow-lg hover:border-blue-300' : 'bg-white border-gray-100 text-gray-700 hover:border-blue-300 hover:bg-blue-50'}`}>
+                    <button key={day} disabled={isPast} onClick={() => { setSelectedFullDate(dateObj); setStep('SLOTS'); }} className={`h-14 rounded-xl border-2 flex flex-col items-center justify-center font-bold transition-all ${isPast ? 'bg-gray-50 border-gray-50 text-gray-300 cursor-not-allowed' : isTodayFlag ? 'bg-blue-50 border-gray-200 text-black shadow-lg hover:border-blue-300 cursor-pointer' : 'bg-white border-gray-100 text-gray-700 hover:border-blue-300 hover:bg-blue-50 cursor-pointer'}`}>
src/pages/NotFound.tsx (1)

33-39: "이전으로" 버튼의 엣지 케이스를 고려해볼 수 있어요.

사용자가 404 페이지를 직접 URL로 접근한 경우(히스토리가 없는 경우) navigate(-1)이 브라우저 기본 동작에 따라 아무 일도 안 하거나 예상치 못한 페이지로 이동할 수 있어요. 큰 문제는 아니지만 참고하세요.

🛡️ 히스토리 체크 예시 (선택사항)
+  const handleGoBack = () => {
+    if (window.history.length > 1) {
+      navigate(-1);
+    } else {
+      navigate('/');
+    }
+  };
+
   return (
     // ...
           <button
-            onClick={() => navigate(-1)}
+            onClick={handleGoBack}
             className="flex items-center justify-center gap-2 px-6 py-3 border border-gray-300 rounded-xl bg-white text-gray-700 font-medium hover:bg-gray-50 transition-all active:scale-95"
           >
src/components/owner/ownerHeader.tsx (1)

25-42: 탭 네비게이션 접근성을 개선할 수 있어요.

탭 UI에 role="tablist", role="tab", aria-selected 속성을 추가하면 스크린 리더 사용자가 탭 네비게이션임을 인식할 수 있어요.

♿ 접근성 개선 예시
-        <nav className="flex gap-5 pt-4 px-5">
+        <nav role="tablist" className="flex gap-5 pt-4 px-5">
           {tabs.map(tab => (
             <button
               key={tab.key}
+              role="tab"
+              aria-selected={activeTab === tab.key}
               onClick={() => onChangeTab(tab.key)}
               className={`pb-4 px-2 text-md transition-all relative ${
                 activeTab === tab.key
                   ? 'text-blue-600'
                   : 'text-gray-900 hover:text-gray-900'
               }`}
             >

As per coding guidelines: src/components/**: 접근성(aria) 체크.

src/pages/ownerPage/ownerPage.tsx (2)

71-81: 중복된 조건문 제거 필요

activeTab === 'settings'activeTab === 'menu' 조건이 외부 블록과 내부에서 중복 체크되고 있어요. 불필요한 코드입니다.

♻️ 중복 조건 제거 제안
       {activeTab === 'dashboard' && <TableDashboard />}
       {activeTab === 'settings' && (
         <div className="max-w-7xl mx-auto text-gray-500">
-          {activeTab === 'settings' && <StoreSettings />}
+          <StoreSettings />
         </div>
       )}
       {activeTab === 'menu' && (
         <div className="max-w-7xl mx-auto text-gray-500">
-          {activeTab === 'menu' && <MenuManagement />}
+          <MenuManagement />
         </div>
       )}

23-65: 탭 접근성(A11y) 개선 권장

탭 네비게이션에 적절한 ARIA 속성이 없어서 스크린 리더 사용자가 탭 구조를 인식하기 어려워요. role="tablist", role="tab", aria-selected 등을 추가하면 좋겠습니다.

♿ 접근성 개선 예시
-          <nav className="flex gap-5 pt-4 px-5">
+          <nav className="flex gap-5 pt-4 px-5" role="tablist" aria-label="가게 관리 탭">
             <button
               onClick={() => setActiveTab('dashboard')}
+              role="tab"
+              aria-selected={activeTab === 'dashboard'}
               className={`pb-4 px-2 text-md transition-all relative ${
                 activeTab === 'dashboard' ? 'text-blue-600' : 'text-gray-900 hover:text-gray-900'
               }`}
             >

나머지 탭 버튼들에도 동일하게 role="tab"aria-selected 속성을 추가해 주세요.

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

src/components/owner/storeSettings.tsx (1)

39-97: 입력 필드와 라벨 연결 권장

<label><input>htmlFor/id로 연결되어 있지 않아요. 라벨 클릭 시 입력 필드에 포커스가 가지 않고, 접근성 측면에서도 개선이 필요합니다. 현재는 동작에 큰 문제는 없지만, 향후 개선하면 좋겠어요.

♿ 예시
           <div>
-            <label className={labelStyle}>가게 이름</label>
+            <label htmlFor="storeName" className={labelStyle}>가게 이름</label>
             <input 
+              id="storeName"
               type="text" 
               value={storeName} 
src/components/owner/tableCreateModal.tsx (1)

18-18: 닫기 버튼 접근성 개선

닫기 버튼에 aria-label이 없어서 스크린 리더 사용자가 버튼의 용도를 알기 어려워요.

♿ 접근성 속성 추가
-        <button onClick={onClose} className="absolute right-6 top-6 text-gray-400"><X /></button>
+        <button onClick={onClose} aria-label="닫기" className="absolute right-6 top-6 text-gray-400"><X /></button>
src/components/owner/tableDashboard.tsx (2)

334-343: 영업시간 하드코딩됨

BreakTimeModalopenTimecloseTime이 하드코딩되어 있어요. StoreSettings에서 설정한 영업시간과 동기화되지 않으면 사용자 혼란이 생길 수 있습니다. 향후 상태 관리(Context나 전역 상태)로 연동하는 것을 고려해 주세요.


22-22: 들여쓰기 일관성

Line 22의 breakTimes 상태 선언이 다른 상태들과 들여쓰기가 다릅니다. 코드 일관성을 위해 정렬해 주세요.

♻️ 들여쓰기 수정
   const [isBreakModalOpen, setIsBreakModalOpen] = useState(false);
-const [breakTimes, setBreakTimes] = useState<BreakTime[]>([]);
+  const [breakTimes, setBreakTimes] = useState<BreakTime[]>([]);
   const [tableData, setTableData] = useState<Record<number, TableInfo>>({});
src/components/owner/BreakTimeModal.tsx (1)

32-34: 닫기 버튼 접근성 개선

닫기 버튼에 aria-label이 없어서 스크린 리더 사용자에게 버튼 용도가 전달되지 않아요.

♿ 접근성 속성 추가
-        <button onClick={onClose} className="absolute right-4 top-4 hover:text-gray-500 cursor-pointer">
+        <button onClick={onClose} aria-label="닫기" className="absolute right-4 top-4 hover:text-gray-500 cursor-pointer">
           <X />
         </button>

Comment thread src/components/owner/menuFormModal.tsx
Comment thread src/components/owner/menuManagement.tsx Outdated
Comment thread src/components/owner/menuManagement.tsx
Comment thread src/components/owner/ownerHeader.tsx
Comment thread src/components/owner/storeSettings.tsx
Comment thread src/components/owner/tableCreateModal.tsx
Comment thread src/components/owner/tableDashboard.tsx
Comment thread src/components/owner/tableDashboard.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/pages/NotFound.tsx`:
- Around line 33-39: The Back button currently calls navigate(-1) directly in
the NotFound component, which can misbehave when there is no prior history;
update the button's onClick handler to check browser history (e.g.,
window.history.length) or navigation capability before calling navigate(-1) and
provide a safe fallback route (e.g., navigate('/') or navigate('/home')) so
users who land directly on the 404 are routed into the app instead of leaving
it.
🧹 Nitpick comments (1)
src/pages/NotFound.tsx (1)

13-14: 접근성: 움직임 민감도(motion sensitivity)를 고려해주세요.

animate-pulse 애니메이션이 계속 반복되는데, 전정기관 장애가 있거나 움직임에 민감한 사용자에게 불편을 줄 수 있어요. prefers-reduced-motion 미디어 쿼리를 고려하면 좋을 것 같습니다.

♻️ Tailwind에서 motion-reduce 유틸리티 활용 예시
-          <div className="absolute inset-0 flex items-center justify-center animate-pulse">
+          <div className="absolute inset-0 flex items-center justify-center animate-pulse motion-reduce:animate-none">

이렇게 하면 사용자가 시스템 설정에서 "움직임 줄이기"를 활성화한 경우 애니메이션이 비활성화됩니다.

Comment thread src/pages/NotFound.tsx

@jjjsun jjjsun left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

에러페이지 잘 구성해주신것같아요! 좋습니다! 아래 코멘트 남긴것만 추가해주시면 될것같아요!

Comment thread src/pages/NotFound.tsx Outdated
Comment thread src/pages/NotFound.tsx Outdated
Comment thread src/pages/NotFound.tsx Outdated
Comment thread src/App.tsx Outdated
@jjjsun jjjsun added the feat label Feb 3, 2026

@jjjsun jjjsun left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

넵! 고생하셨어요!!

@yooseolhee yooseolhee merged commit 7d4832b into develop Feb 4, 2026
1 check passed
@jjjsun jjjsun deleted the feat/notFoundPage branch February 9, 2026 20:04
@coderabbitai coderabbitai Bot mentioned this pull request Feb 11, 2026
11 tasks
@jjjsun jjjsun changed the title feat:notFoundPage UI 구현 feat: notFoundPage UI 구현 Feb 18, 2026
@jjjsun jjjsun added the ✨ Feature 새로운 기능 추가 label Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 새로운 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] NotFound 페이지 UI 구현

2 participants