feat: 가게 설정 테이블 이미지 삭제 UI 처리 및 삭제 확인 모달 추가#113
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughStoreSettings의 테이블 이미지 관리를 URL 배열에서 Changes
Sequence Diagram(s)sequenceDiagram
participant User as 사용자
participant UI as StoreSettings (클라이언트)
participant API as frontend API 모듈
participant Server as Backend
participant Storage as ObjectStorage
rect rgba(200,220,255,0.5)
User->>UI: 이미지 추가 / 삭제 표시 (로컬)
UI->>UI: newFiles 추가 / deletedIds에 ID 추가
end
rect rgba(200,255,200,0.5)
User->>UI: 저장 클릭
UI->>API: deleteTableImages(tableImageIds)
API->>Server: DELETE /api/v1/stores/{id}/table-images (body: tableImageIds)
Server->>Storage: 이미지 삭제
Server-->>API: ApiResponse<{ tableImageId }>
API-->>UI: 삭제 결과 반환
end
rect rgba(255,240,200,0.5)
UI->>API: uploadTableImages(newFiles)
API->>Server: POST /api/v1/stores/{id}/table-images (multipart)
Server->>Storage: 이미지 업로드
Storage-->>Server: 저장된 URL / id
Server-->>API: ApiResponse<TableImagesResponse> (tableImages: TableImage[])
API-->>UI: 갱신된 tableImages 반환
UI->>UI: newFiles/deletedIds 리셋, 화면 갱신
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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 (2)
src/components/owner/StoreSettings.tsx (2)
408-427:⚠️ Potential issue | 🟠 Major
URL.createObjectURL을 렌더 함수 안에서 직접 호출하면 메모리 누수가 납니다.
URL.createObjectURL()을 인라인으로 호출하면 렌더마다 새로운 blob URL이 생성되어 정리되지 않는 메모리 누수가 발생합니다.onLoad에서revokeObjectURL을 부르더라도, 리렌더마다 URL이 바뀌어 브라우저 캐시가 이전 URL과 새 URL이 같은 이미지를 가리킨다는 걸 알지 못해 이미지가 깜빡일 수 있습니다. 또한onLoad이벤트 전에 컴포넌트가 언마운트되면 URL이 절대 해제되지 않습니다.
useEffect로 미리보기 URL을 생성·관리하고 cleanup에서 해제하는 방식으로 변경하세요.🔧 권장 수정 방법 — useEffect로 previewUrls 별도 관리
+ const [previewUrls, setPreviewUrls] = useState<string[]>([]); + + useEffect(() => { + const urls = newFiles.map((file) => URL.createObjectURL(file)); + setPreviewUrls(urls); + return () => { + urls.forEach((url) => URL.revokeObjectURL(url)); + }; + }, [newFiles]); {/* 기존 newFiles.map 블록 */} - {newFiles.map((file, index) => { - const previewUrl = URL.createObjectURL(file); - return ( - <div key={`new-${file.name}-${index}`} className="relative"> - <img - src={previewUrl} - alt="미리보기" - className="w-full h-32 object-cover rounded-lg" - onLoad={() => URL.revokeObjectURL(previewUrl)} - /> + {previewUrls.map((previewUrl, index) => ( + <div key={`new-${newFiles[index]?.name}-${index}`} className="relative"> + <img + src={previewUrl} + alt="미리보기" + className="w-full h-32 object-cover rounded-lg" + />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/owner/StoreSettings.tsx` around lines 408 - 427, The preview blob URLs are being created inline inside the render (URL.createObjectURL in the newFiles.map), causing leaks and flicker; instead, create and store a previewUrls state (array) for newFiles, generate each URL inside a useEffect that runs when newFiles changes (using URL.createObjectURL for each file), update handleDeleteImage to remove the corresponding previewUrl when a file is deleted, and revoke all generated URLs in the useEffect cleanup (using URL.revokeObjectURL) to ensure proper cleanup on unmount or when newFiles changes; update the JSX to use previewUrls[index] as the img src rather than calling URL.createObjectURL inline.
433-438:⚠️ Potential issue | 🟡 Minor이메일과 주소는 수정 불가능하도록 막거나, alert 메시지를 수정해야 합니다.
현재 세 가지 문제가 있어요:
- 유효성 검사 로직 불일치:
isValid()는storeName,description,phone만 확인하지만, 실패 시 alert에는 "이메일, 주소"도 필수라고 안내합니다.- 저장되지 않는 필드들: 사용자가 이메일과 주소를 수정할 수 있는데,
updateStore()API는 이 두 필드를 지원하지 않아서 변경사항이 저장되지 않습니다.- 혼란스러운 UX: 입력 필드가 활성화되어 있어서 사용자는 이 정보들을 저장할 수 있다고 생각하지만 실제로는 안 됩니다.
- if (!isValid()) { - alert("가게 이름, 설명, 전화번호, 이메일, 주소는 필수 입력 항목입니다."); + if (!isValid()) { + alert("가게 이름, 설명, 전화번호는 필수 입력 항목입니다.");추가로, 이메일과 주소를 정말로 수정하도록 하려면:
- 백엔드 API를 업데이트해서
updateStore()에address파라미터 추가- 또는 이 두 필드를
disabled처리해서 수정 불가능하게 변경현재로서는 적어도 alert 메시지는 실제 검증 로직과 맞춰야 합니다.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/owner/StoreSettings.tsx` around lines 433 - 438, The alert text in the onClick handler is inconsistent with the validation in isValid() and with updateStore() behavior: isValid() currently checks only storeName, description, phone, but the alert mentions email and address which are neither validated nor saved; instruct to either (A) update isValid() to include email and address and also extend updateStore() to accept and persist email and address (update API and the component calls), or (B) make the email and address input fields readOnly/disabled in StoreSettings and change the alert text to only list the actual required fields (storeName, description, phone); locate references to isValid(), updateStore(), and the email/address input elements in StoreSettings.tsx to implement the chosen fix so validation, UI state, and persistence are consistent.
🧹 Nitpick comments (1)
src/components/owner/StoreSettings.tsx (1)
116-120:handleDeleteImage의_tableId?파라미터는 제거해도 됩니다.이 함수는 현재
handleDeleteImage(undefined, index)형태로만 호출되고,_tableId는 전혀 사용되지 않습니다. 서명을 단순화하면 호출 측에서의 혼란을 줄일 수 있어요.- const handleDeleteImage = (_tableId?: number, fileIndex?: number) => { + const handleDeleteImage = (fileIndex?: number) => { if (fileIndex !== undefined) { setNewFiles((prev) => prev.filter((_, i) => i !== fileIndex)); } };그리고 호출부도 함께 업데이트해 주세요:
- onClick={() => handleDeleteImage(undefined, index)} + onClick={() => handleDeleteImage(index)}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/owner/StoreSettings.tsx` around lines 116 - 120, Remove the unused optional _tableId parameter from the handleDeleteImage signature and update its implementation to accept only fileIndex (e.g., handleDeleteImage(fileIndex?: number)), then find and update all call sites that currently call handleDeleteImage(undefined, index) to call handleDeleteImage(index) (or handleDeleteImage() where appropriate); ensure any TypeScript types/interfaces referencing handleDeleteImage are updated accordingly so the project still compiles.
🤖 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/owner/stores.ts`:
- Line 108: The code directly accesses res.data.result.tableImageUrls which can
throw if result is null/undefined; update the return to use optional chaining
and a safe default (e.g., return res.data?.result?.tableImageUrls ?? []),
ensuring ApiResponse<T> safety when result may be null.
In `@src/components/owner/StoreSettings.tsx`:
- Around line 388-404: The delete button inside StoreSettings (the <button> that
calls setDeletedUrls and shows the confirm) is missing an explicit type which
can default to submit inside a form; update that button to include type="button"
and add an accessible label (e.g., aria-label or a clear text alternative) to
match the new-file delete button behavior and ensure correct non-submitting
behavior and improved accessibility when this component is placed inside a form.
- Around line 469-486: getTableImages(storeId) is called without error handling;
wrap the await getTableImages(storeId) call in a try-catch (similar to the
uploadTableImages block) and on error alert the user (e.g. "설정 저장에 실패했습니다.") and
return so the success alert isn't shown; only call setTableImageUrls,
setNewFiles([]) and setDeletedUrls(new Set()) when getTableImages succeeds. Use
the existing function names getTableImages, setTableImageUrls, setNewFiles, and
setDeletedUrls to locate where to add the try-catch.
- Around line 57-65: Initial load uses getStore() while later saves call
getTableImages() — change the useEffect that currently calls getStore(storeId)
to also call getTableImages(storeId) (or replace tableImageUrls assignment with
the getTableImages response) so both code paths use the same source (refer to
useEffect, getStore, getTableImages, setTableImageUrls). Move blob preview URL
creation out of render: create and store preview URLs in state and revoke them
in a cleanup useEffect (manage URLs created by URL.createObjectURL and call
URL.revokeObjectURL on unmount or when a file is removed instead of generating
in the map render). Wrap the getTableImages(storeId) call in try/catch where
it’s awaited so failures don’t still show the success alert (surround the const
urls = await getTableImages(...) with error handling and proper user
feedback/logging). Align validation: update isValid() to include email and
address or change the alert text to match the current checked fields (modify
isValid). Include address in the payload sent by updateStore(...) so edited
address is saved (add address to the updateStore call). Add type="button" to
existing image delete buttons for consistent behavior (match new file delete
button). Finally, remove the unused _tableId parameter from handleDeleteImage if
it’s not used (or use it if intended).
---
Outside diff comments:
In `@src/components/owner/StoreSettings.tsx`:
- Around line 408-427: The preview blob URLs are being created inline inside the
render (URL.createObjectURL in the newFiles.map), causing leaks and flicker;
instead, create and store a previewUrls state (array) for newFiles, generate
each URL inside a useEffect that runs when newFiles changes (using
URL.createObjectURL for each file), update handleDeleteImage to remove the
corresponding previewUrl when a file is deleted, and revoke all generated URLs
in the useEffect cleanup (using URL.revokeObjectURL) to ensure proper cleanup on
unmount or when newFiles changes; update the JSX to use previewUrls[index] as
the img src rather than calling URL.createObjectURL inline.
- Around line 433-438: The alert text in the onClick handler is inconsistent
with the validation in isValid() and with updateStore() behavior: isValid()
currently checks only storeName, description, phone, but the alert mentions
email and address which are neither validated nor saved; instruct to either (A)
update isValid() to include email and address and also extend updateStore() to
accept and persist email and address (update API and the component calls), or
(B) make the email and address input fields readOnly/disabled in StoreSettings
and change the alert text to only list the actual required fields (storeName,
description, phone); locate references to isValid(), updateStore(), and the
email/address input elements in StoreSettings.tsx to implement the chosen fix so
validation, UI state, and persistence are consistent.
---
Nitpick comments:
In `@src/components/owner/StoreSettings.tsx`:
- Around line 116-120: Remove the unused optional _tableId parameter from the
handleDeleteImage signature and update its implementation to accept only
fileIndex (e.g., handleDeleteImage(fileIndex?: number)), then find and update
all call sites that currently call handleDeleteImage(undefined, index) to call
handleDeleteImage(index) (or handleDeleteImage() where appropriate); ensure any
TypeScript types/interfaces referencing handleDeleteImage are updated
accordingly so the project still compiles.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/api/owner/stores.ts (1)
135-152:⚠️ Potential issue | 🟠 Major백엔드 API 응답 구조에 맞춰 반환 타입 정확히 정리해 주세요.
현재
deleteTableImages는 여러 개 ID를 삭제하지만(tableImageIds: number[]), 반환 타입이 단건(ApiResponse<{ tableImageId: number }>)으로 선언되어 있습니다.서버가 실제로 어떤 응답을 주는지에 따라:
- 삭제된 모든 ID를 반환한다면:
Promise<ApiResponse<{ tableImageIds: number[] }>>- 아무것도 반환하지 않는다면:
Promise<ApiResponse<void>>지금은
StoreSettings.tsx에서 반환값을 사용하지 않아 문제가 없지만, 나중에 삭제 결과를 활용할 때 타입 불일치로 버그가 생길 수 있습니다. 백엔드 API 스펙을 확인하고 정확한 타입으로 정의해 두면 좋겠습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/api/owner/stores.ts` around lines 135 - 152, The deleteTableImages function's return type is incorrect for batch deletes; verify the backend API spec and update the signature and generic types accordingly (change Promise<ApiResponse<{ tableImageId: number }>> and the api.delete generic) to either Promise<ApiResponse<{ tableImageIds: number[] }>> if the server returns all deleted IDs, or Promise<ApiResponse<void>> if it returns no body; also adjust any callers (e.g., StoreSettings.tsx) to match the chosen shape.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@src/api/owner/stores.ts`:
- Around line 135-152: The deleteTableImages function's return type is incorrect
for batch deletes; verify the backend API spec and update the signature and
generic types accordingly (change Promise<ApiResponse<{ tableImageId: number }>>
and the api.delete generic) to either Promise<ApiResponse<{ tableImageIds:
number[] }>> if the server returns all deleted IDs, or
Promise<ApiResponse<void>> if it returns no body; also adjust any callers (e.g.,
StoreSettings.tsx) to match the chosen shape.
---
Duplicate comments:
In `@src/components/owner/StoreSettings.tsx`:
- Around line 487-492: Wrap the getTableImages(storeId) call in its own
try-catch: after performing the save/delete/upload steps and calling
setDeletedIds(new Set()) and setNewFiles([]), call alert("설정이 저장되었습니다."); then
attempt to refresh images by calling getTableImages(storeId) inside a try block
and call setTableImages(imgs) on success; in the catch, log the error and show a
user-facing error/notification indicating that the settings were saved but the
image refresh failed (so the user knows the save succeeded even if re-fetching
images failed), referencing getTableImages, setTableImages, setDeletedIds,
setNewFiles, and the existing alert.
- Around line 128-130: The form validation in isValid() currently only checks
storeName, description, and phone but the submit-time alert (the alert call that
currently says "이메일, 주소는 필수 입력 항목입니다") contradicts that; fix by either: (A)
extending isValid() to also validate email and address (e.g., include trimmed
checks for email and address alongside storeName, description, phone) and ensure
any submission logic uses the updated isValid(), or (B) change the alert message
at submission to accurately reflect the actual required fields (storeName,
description, phone) so the user sees consistent guidance; update the same
message used around the submit/validation block (the alert call referenced in
the review) to keep both locations consistent.
- Around line 410-429: The new-files preview currently has its delete button
commented out and creates blob URLs inside the render loop, causing both UX and
memory-leak issues: un-comment or restore the delete button that calls
handleDeleteImage(newFiles, index) (or the existing handleDeleteImage signature)
so users can remove a selected file, and move URL.createObjectURL(file) out of
the render path—generate preview URLs once (e.g., in a useMemo or useEffect that
maps newFiles -> previewUrls state) and revoke the old URLs in the cleanup or
when newFiles change (instead of relying solely on the img onLoad revoke);
reference newFiles, handleDeleteImage, URL.createObjectURL, and the img onLoad
revoke to locate and apply these fixes.
- Around line 445-450: updateStore 호출에서 address가 빠져 서버에 반영되지 않습니다; 수정하려면 컴포넌트의
상태/변수명(address)을 포함해 updateStore(storeId, {...}) 호출에 address: address를 추가하고,
필요하면 updateStore의 요청 바디 타입(서버/클라이언트 타입 정의)을 업데이트해 백엔드가 지원하는지 확인하세요; 변경은
updateStore 호출이 있는 블록(참조되는 심볼: updateStore, storeId, storeName, description,
phone)와 관련 타입 정의만 수정하면 됩니다.
There was a problem hiding this comment.
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 (1)
src/components/owner/StoreSettings.tsx (1)
433-435:⚠️ Potential issue | 🟡 Minor저장 버튼에
type="button"속성이 없어요.
<button>의 기본 타입은submit이에요. 나중에 이 컴포넌트가<form>안에 포함될 경우 의도치 않게 폼 제출이 트리거될 수 있어요.🛠️ 제안 수정
<button + type="button" onClick={async () => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/owner/StoreSettings.tsx` around lines 433 - 435, The Save button in StoreSettings.tsx is missing an explicit type, so its default behavior is submit which can accidentally submit a surrounding form; update the button element that has the inline async onClick handler (the Save button in the div with className "flex justify-end mb-20") to include type="button" to prevent unintended form submission while preserving the existing onClick logic.
🧹 Nitpick comments (1)
src/components/owner/StoreSettings.tsx (1)
119-121: 주석 처리된 코드는 제거하는 게 깔끔해요.
handleDeleteImage주석은 더 이상 필요 없는 코드예요. 버전 관리는 git이 담당하니 과감하게 삭제해도 돼요.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/owner/StoreSettings.tsx` around lines 119 - 121, Remove the commented-out handleDeleteImage block (the lines that define // const handleDeleteImage = (fileIndex: number) => { ... } and its body) since it's dead code; simply delete that commented code and any related redundant comments referencing handleDeleteImage or setNewFiles to keep StoreSettings clean and rely on git history for recovery.
🤖 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/owner/StoreSettings.tsx`:
- Around line 420-427: The delete button for newly added files is commented out,
preventing users from removing wrongly selected files; restore an interactive
delete mechanism by re-enabling a button in the render and wiring it to an
index-based remover: ensure the button calls handleDeleteImage(undefined, index)
(or implement/removeImageAtIndex(index) if needed) and that handleDeleteImage
(or the new function) updates the component state holding uploadedFiles/images
(e.g., via setImages(prev => prev.filter((_, i) => i !== index))) so the UI
removes the correct item without a refresh; update the JSX in StoreSettings.tsx
to include the button with accessible attributes and the existing X icon.
- Around line 389-406: The delete button lacks an accessible name; update the
button in the image rendering block to include an aria-label that identifies
which image will be deleted (use the provided idx or other image identifier),
e.g., set aria-label={`삭제 이미지 ${idx + 1}`} or include img.tableImageId so screen
readers can distinguish items, while keeping the existing onClick behavior that
calls setDeletedIds (refer to setDeletedIds and img.tableImageId to locate the
handler and image data).
- Around line 61-89: The current IIFE lumps both getStore(storeId) and
getTableImages(storeId) into one try/catch so any failure shows the same generic
"가게 정보를 불러오는데 실패했습니다." message; split the operations and handle errors
separately by wrapping getStore(...) in its own try/catch (or await it first and
only then call getTableImages(...) with its own try/catch) so you can show
distinct alerts/logs (e.g., "가게 기본 정보를 불러오는데 실패했습니다." for getStore and "테이블
이미지들을 불러오는데 실패했습니다." for getTableImages), include/error-log the caught error
object in each catch, and ensure state updates for store fields (setStoreName,
setDescription, setPhone, setAddress, setClosedDays, setOpenTime, setCloseTime)
still occur when images fail so image errors don’t overwrite or hide the loaded
store data.
In `@src/components/reservation/modals/ReservationModal.tsx`:
- Around line 151-152: The current early-return in ReservationModal.tsx treats
any timesQuery.isError as a "closed day" message; update the logic in the
component (where timesQuery is checked) to distinguish error types: when
timesQuery.error indicates a network/client/server failure (inspect
timesQuery.error, HTTP status or error.name) return a neutral message like "일시적인
문제로 이용할 수 없습니다. 잠시 후 다시 시도해주세요" and an empty times array, while only returning
"휴무일 입니다. 다른 날짜를 선택해주세요" when the response explicitly indicates no available
times (e.g., a 200 response with empty times or a domain-specific flag). Ensure
you reference and use timesQuery.isError, timesQuery.error, and the existing
code path that handles successful responses to implement these differentiated
messages.
---
Outside diff comments:
In `@src/components/owner/StoreSettings.tsx`:
- Around line 433-435: The Save button in StoreSettings.tsx is missing an
explicit type, so its default behavior is submit which can accidentally submit a
surrounding form; update the button element that has the inline async onClick
handler (the Save button in the div with className "flex justify-end mb-20") to
include type="button" to prevent unintended form submission while preserving the
existing onClick logic.
---
Duplicate comments:
In `@src/components/owner/StoreSettings.tsx`:
- Around line 488-492: The call to getTableImages(storeId) in the save flow is
unprotected and can throw, so wrap the await getTableImages(storeId) call in a
try-catch around the block that sets state (setTableImages, setDeletedIds,
setNewFiles) and shows the success alert; on error, log/report the error (e.g.,
console.error or a toast/processLogger), show a failure alert/message to the
user, and return early so you do not reset state or show "설정이 저장되었습니다."; locate
this logic near getTableImages, setTableImages, setDeletedIds, setNewFiles and
ensure the catch displays an error and prevents the success path from running.
- Around line 128-130: isValid() currently only checks storeName, description,
phone (and returns truthy strings) while the alert copy and updateStore payload
omit email and address; update isValid() to explicitly validate email and
address are non-empty (and return a boolean), adjust the alert message text used
where validation fails to list the exact required fields, and include email and
address in the payload built/posted by updateStore so edited values are sent to
the server; reference/modify the isValid() function and the updateStore payload
construction to make these changes.
- Around line 410-418: You’re creating blob URLs inside newFiles.map using
URL.createObjectURL (previewUrl) which can leak memory on re-renders; instead,
generate and store preview URLs in state (e.g., a previews Map keyed by file or
index) in a useEffect that runs when newFiles changes, and revoke the URLs in
the effect cleanup (or when a file is removed) using URL.revokeObjectURL;
replace the inline createObjectURL/onLoad pattern in StoreSettings (the
newFiles.map block and previewUrl usage) with reading from that previews state
so URLs are created once and properly cleaned up.
---
Nitpick comments:
In `@src/components/owner/StoreSettings.tsx`:
- Around line 119-121: Remove the commented-out handleDeleteImage block (the
lines that define // const handleDeleteImage = (fileIndex: number) => { ... }
and its body) since it's dead code; simply delete that commented code and any
related redundant comments referencing handleDeleteImage or setNewFiles to keep
StoreSettings clean and rely on git history for recovery.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/components/owner/StoreSettings.tsx (1)
29-37:dayMapToApi타입을Record<string, string>으로 좁혀주세요.값이 전부 문자열인데
any로 지정되어 있어 타입 안전성이 낮아져요.♻️ 제안 수정
-const dayMapToApi: Record<string, any> = { +const dayMapToApi: Record<string, string> = {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/owner/StoreSettings.tsx` around lines 29 - 37, The dayMapToApi constant currently uses an overly broad type Record<string, any>; narrow its type to Record<string, string> to reflect that all values are strings and improve type safety—update the declaration of dayMapToApi (the constant named dayMapToApi) to use Record<string, string> and ensure any usages still type-check (adjust keys/types where needed).
🤖 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/owner/StoreSettings.tsx`:
- Around line 422-428: The new-file delete button is missing an accessible
label; update the button element that calls handleDeleteImage(index) (the one
with class "... bg-red-500 ...") to include an aria-label that uniquely
identifies the file (e.g., include the index or the file name if available) so
screen readers can announce which file will be deleted; mirror the pattern used
by the existing image delete button (the earlier delete button at Line ~392) to
ensure consistent accessible text.
---
Duplicate comments:
In `@src/components/owner/StoreSettings.tsx`:
- Around line 63-69: The component never loads or saves the store's email and is
also missing address in the update payload: when handling getStore() response
(in the useEffect that calls getStore/store loader) call setEmail(store.email ??
"") alongside setAddress(store.address ?? "") and other setters, and when
calling updateStore include both email and address in the payload sent to
updateStore so the edited values persist; ensure the payload shape matches the
StoreDetail/updateStore signature (use the same property names as StoreDetail).
- Around line 129-131: The current isValid() only checks storeName, description,
and phone but the save button alert warns that email and address are required;
either update isValid() to also validate email and address (e.g., include
email.trim() and address.trim() checks and any format checks for email) or
change the alert text in the save handler that shows the message to reflect the
actual required fields; locate isValid() and the save button handler (the
function that triggers the alert on save) and make one of these two consistent
with the intended requirement.
- Around line 412-420: The component currently calls URL.createObjectURL inline
during render for each item in newFiles and revokes it in onLoad, causing
leaking and racey revokes; instead, in StoreSettings.tsx create preview URLs
inside a useEffect that runs when newFiles changes (map files ->
URL.createObjectURL and setPreviewUrls state), use those stored previewUrls for
the <img> src (remove inline createObjectURL and onLoad revoke), and revoke URLs
in the useEffect cleanup and whenever an individual file is removed (also revoke
on component unmount) so no blob URLs persist or get revoked prematurely; update
references to newFiles and the image rendering logic to read from the
previewUrls state.
- Around line 61-90: Split the combined API call IIFE into two separate
try-catch blocks so failures are reported per-call: call getStore inside its own
try/catch and on success setStoreName, setDescription, setPhone, setAddress and
business hours (open/close and setClosedDays); separately call getTableImages
inside its own try/catch and on success call setTableImages, setDeletedIds(new
Set()), and setNewFiles([]); in each catch show a specific alert message (e.g.,
"가게 정보를 불러오는데 실패했습니다." for getStore and "테이블 이미지를 불러오는데 실패했습니다." for
getTableImages) so users see which fetch failed.
- Around line 490-494: The call to getTableImages lacks error handling so if it
fails the success alert and state resets (setTableImages, setDeletedIds,
setNewFiles) never occur; wrap the getTableImages call in a try/catch and ensure
state resets and alert("설정이 저장되었습니다.") still run on overall success of the save
flow even if image reload fails—i.e., call setDeletedIds(new Set()),
setNewFiles([]) and show the success alert regardless, then in the catch
handle/log the getTableImages error and optionally setTableImages to an empty
array or keep previous images and surface a non-blocking error message about
failing to refresh images; refer to getTableImages, setTableImages,
setDeletedIds, setNewFiles and the alert call when making the change.
---
Nitpick comments:
In `@src/components/owner/StoreSettings.tsx`:
- Around line 29-37: The dayMapToApi constant currently uses an overly broad
type Record<string, any>; narrow its type to Record<string, string> to reflect
that all values are strings and improve type safety—update the declaration of
dayMapToApi (the constant named dayMapToApi) to use Record<string, string> and
ensure any usages still type-check (adjust keys/types where needed).
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/owner/StoreSettings.tsx (1)
449-453:⚠️ Potential issue | 🟠 Major
address필드가 저장 요청에 포함되지 않으니 수정이 필요해요.현재
updateStore호출이{storeName, description, phoneNumber}세 개 필드만 포함하는데, 서버에서 조회한address값이 저장되지 않아요. 사용자가 주소를 수정해도 반영되지 않으므로 데이터 손실 버그입니다.// 현재 (lines 449-453) await updateStore(storeId, { storeName, description, phoneNumber: phone, // address가 빠져있음 }); // 수정 필요 await updateStore(storeId, { storeName, description, phoneNumber: phone, address, });한편
setEmail()호출이 없어요. UI에만 존재하는 고아 필드인 것 같습니다. 백엔드에서 실제로 이메일을 지원할 건지, 아니면 이 입력 필드를 제거할 건지 팀과 함께 정리하면 좋을 것 같아요.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/owner/StoreSettings.tsx` around lines 449 - 453, The updateStore call is missing the address field so server-side address changes are not saved; modify the payload passed to updateStore (the call using updateStore(storeId, { storeName, description, phoneNumber: phone, ... })) to include address (e.g. address: address) so the component's address state is sent, and while here note that email appears to be an orphan field (no setEmail or StoreDetail.email) so either add loading/sync logic (setEmail from StoreDetail and include email in update payload) or remove the email input after team confirmation; search for updateStore, storeId, storeName, description, phone, address, email, and setEmail to locate the spots to change.
🧹 Nitpick comments (2)
src/components/owner/StoreSettings.tsx (2)
29-37:Record<string, any>→Record<string, string>으로 좁혀주세요.값이 전부 요일 문자열인데
any로 선언되어 있어요.string으로 좁히면 실수로 다른 타입이 들어가는 걸 컴파일 시점에 잡을 수 있어요.♻️ 타입 수정 제안
-const dayMapToApi: Record<string, any> = { +const dayMapToApi: Record<string, string> = {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/owner/StoreSettings.tsx` around lines 29 - 37, Change the type of the dayMapToApi mapping from a permissive Record<string, any> to a stricter Record<string, string> so the values (e.g., "MONDAY", "TUESDAY", etc.) are type-checked as strings; locate the dayMapToApi constant and update its type annotation accordingly to prevent non-string values from being assigned.
393-404: PR 제목의 "삭제 확인 모달"이 실제로는window.confirm()이에요.
window.confirm()은 앱 디자인과 통일되지 않고, 메인 스레드를 블로킹하며 일반적으로 좋지 않은 UX 관행이에요. 지금 당장 동작에 문제는 없지만, 이후에 커스텀 모달로 교체할 계획이라면 이슈로 트래킹해 두는 걸 추천해요.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/owner/StoreSettings.tsx` around lines 393 - 404, The onClick handler for image deletion currently uses window.confirm (inside the onClick that calls setDeletedIds and references img.tableImageId), which is blocking and inconsistent with app design; replace this with a non-blocking, styled confirmation flow: introduce state (e.g., showDeleteConfirm and pendingDeleteId) and a ConfirmationModal component, update the onClick to set pendingDeleteId = img.tableImageId and showDeleteConfirm = true, and then perform the setDeletedIds update only when the modal's confirm callback runs (or cancel on close) so the UI remains non-blocking and consistent with app styling.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@src/components/owner/StoreSettings.tsx`:
- Around line 449-453: The updateStore call is missing the address field so
server-side address changes are not saved; modify the payload passed to
updateStore (the call using updateStore(storeId, { storeName, description,
phoneNumber: phone, ... })) to include address (e.g. address: address) so the
component's address state is sent, and while here note that email appears to be
an orphan field (no setEmail or StoreDetail.email) so either add loading/sync
logic (setEmail from StoreDetail and include email in update payload) or remove
the email input after team confirmation; search for updateStore, storeId,
storeName, description, phone, address, email, and setEmail to locate the spots
to change.
---
Duplicate comments:
In `@src/components/owner/StoreSettings.tsx`:
- Around line 129-131: The validation in isValid() only checks storeName,
description, and phone but the alert text requires email and address too; update
isValid() to also verify email.trim() and address.trim() (or the actual
prop/state names used for email and address in this component) and update the
duplicate validation block around the other occurrence (lines referenced in the
review) so both validation functions match the alert message, ensuring both
places use the same set of fields.
- Around line 491-494: The call to getTableImages in the StoreSettings component
lacks error handling and can produce unhandled Promise rejections; wrap the
await getTableImages(storeId) call in a try/catch, on success call
setTableImages(imgs), setDeletedIds(new Set()), and setNewFiles([]) as before,
and in the catch block log the error and surface user feedback (e.g., call your
existing toast/notification or set an error state) so the user sees a failure
message instead of an unhandled rejection; ensure you reference getTableImages,
setTableImages, setDeletedIds, and setNewFiles when making the change.
- Around line 61-90: Split the combined data fetch into two separate try/catch
blocks: one that calls getStore(...) and updates store state (setStoreName,
setDescription, setPhone, setAddress, setOpenTime, setCloseTime, setClosedDays)
with its own catch and specific error alert, and a second that calls
getTableImages(...) and calls setTableImages (and then setDeletedIds(new Set())
and setNewFiles([])) with its own catch and distinct error alert; keep the async
IIFE structure but ensure the second fetch runs after the first succeeds so
error messages for getStore and getTableImages are reported independently.
- Around line 412-421: The code calls URL.createObjectURL directly inside the
JSX map (previewUrl = URL.createObjectURL(file)) which creates blobs on each
render; move creation and revocation into component state/effects: in
StoreSettings.tsx create a previewUrls state mapped from newFiles (e.g., compute
an array of URLs when newFiles changes in a useEffect), call
URL.createObjectURL(file) once per file there, store those strings and use
previewUrls[index] in the map (referencing the previewUrl variable used in the
JSX), and revoke old URLs in the cleanup of that effect (and when a file is
removed) instead of revoking in onLoad.
---
Nitpick comments:
In `@src/components/owner/StoreSettings.tsx`:
- Around line 29-37: Change the type of the dayMapToApi mapping from a
permissive Record<string, any> to a stricter Record<string, string> so the
values (e.g., "MONDAY", "TUESDAY", etc.) are type-checked as strings; locate the
dayMapToApi constant and update its type annotation accordingly to prevent
non-string values from being assigned.
- Around line 393-404: The onClick handler for image deletion currently uses
window.confirm (inside the onClick that calls setDeletedIds and references
img.tableImageId), which is blocking and inconsistent with app design; replace
this with a non-blocking, styled confirmation flow: introduce state (e.g.,
showDeleteConfirm and pendingDeleteId) and a ConfirmationModal component, update
the onClick to set pendingDeleteId = img.tableImageId and showDeleteConfirm =
true, and then perform the setDeletedIds update only when the modal's confirm
callback runs (or cancel on close) so the UI remains non-blocking and consistent
with app styling.
* 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>
💡 개요
가게 설정 테이블 이미지 삭제 UI 처리 및 삭제 확인 모달 추가
🔢 관련 이슈 링크
💻 작업내용
📌 변경사항PR
🤔 추가 논의하고 싶은 내용
✅ 체크리스트
Summary by CodeRabbit
개선 사항
버그 수정