Skip to content

Todo 기능 구현#2

Merged
Dobbymin merged 37 commits into
mainfrom
feat#01-calendar
Dec 23, 2025
Merged

Todo 기능 구현#2
Dobbymin merged 37 commits into
mainfrom
feat#01-calendar

Conversation

@Dobbymin

Copy link
Copy Markdown
Owner

📝 요약 (Summary)

캘린더 페이지의 핵심 기능을 구현했습니다.

월별 캘린더 UI에 일정 수를 시각적으로 표시하고, 날짜 선택 시 우측 패널에서 해당 일정을 관리할 수 있도록 구현했습니다. 일정 생성, 카테고리 추가, 완료/미완료 토글 기능을 모두 연동시켰습니다.

✅ 주요 변경 사항 (Key Changes)

  • 캘린더 UI 컴포넌트 개발: CalendarDays, TodoDay 컴포넌트로 월별 캘린더 렌더링 및 일정 수 오버레이
  • 상태 관리 구축: Zustand store로 선택된 날짜 중앙 관리, useSelectedDate 훅 제공
  • 날짜별 데이터 페칭: React Query의 날짜 스코프 쿼리 키(todos.list(YYYY-MM-DD))로 캐시 최적화
  • 일정 CRUD 기능: 생성, 읽기, 완료/미완료 토글 API 구현 및 연동
  • 카테고리 추가 기능: 새 카테고리 생성 후 즉시 UI 반영(백엔드 LEFT JOIN 수정으로 빈 카테고리도 포함)

💻 상세 구현 내용 (Implementation Details)

1. 상태 관리 (Zustand)

  • useTodosStore: selectedDate 상태 및 setSelectedDate 액션 제공
  • useSelectedDate 훅: store 접근 단순화
  • YYYY-MM-DD 형식으로 통일하여 API 요청/캐시 키와 일치

2. 일정 및 카테고리 관리

  • postTodoAPI: { categoryName, todoDate, content } 페이로드로 일정 생성
  • postCategoryAPI: { categoryName, todoDate } 페이로드로 카테고리 생성
  • updateTodoAPI: PATCH 요청으로 isCompleted 상태 토글

🚀 트러블 슈팅 (Trouble Shooting)

문제 1: 새로 생성한 카테고리에 일정 추가 시 VALIDATION_ERROR

원인: API가 categoryName, todoDate, content를 모두 요구하는데, 기존 코드는 todoData, date 형식으로 전송
해결: postTodoAPI를 객체 페이로드 기반으로 수정하고, TodoSection에서 카테고리 이름을 함께 전달하도록 변경

문제 2: 새로 생성한 카테고리가 UI에 즉시 반영되지 않음

원인: 백엔드 todos_view_flat 뷰가 INNER JOIN 기반이라, 할 일이 0개인 카테고리는 행이 생성되지 않음
해결: 백엔드의 LEFT JOIN 수정으로 빈 카테고리도 포함되도록 함. 프론트는 단순 캐시 무효화(invalidateQueries)로 리페치

문제 3: 할 일 완료 표시 UI 설계

원인: 기존 UI에서 체크박스 느낌의 명확한 완료 표시 부족
해결: 꽃 아이콘 기본 상태를 white 중앙으로, 완료 시 neutral.400 + 체크마크로 변경하여 시각적 구분 강화

⚠️ 알려진 이슈 및 참고 사항 (Known Issues & Notes)

  • 할 일 완료 상태 동기화: 토글 후 optimistic UI 없이 리페치 대기하므로, 네트워크 지연 시 반응이 약간 늦을 수 있음. 필요시 onSuccess에서 낙관적 갱신 추가 고려
  • 카테고리 이름 중복 검증: 현재 프론트에서 중복 확인 없음. 백엔드 UNIQUE 제약 의존
  • 일정 수정 API 미구현: 현재는 생성과 토글(완료/미완료)만 가능, 일정 내용 수정은 미지원

📸 스크린샷 (Screenshots)

스크린샷 2025-12-24 오전 1 40 46

#️⃣ 관련 이슈 (Related Issues)

@Dobbymin Dobbymin self-assigned this Dec 23, 2025
Copilot AI review requested due to automatic review settings December 23, 2025 16:42
@Dobbymin Dobbymin added ✨ Feature 새로운 기능 추가 및 구현하는 경우 🎨 Design UI / UX 디자인 관련 작업을 진행하는 경우 📡 API 비동기 통신 코드를 짜는 경우 labels Dec 23, 2025
@Dobbymin Dobbymin linked an issue Dec 23, 2025 that may be closed by this pull request
@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello @Dobbymin, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 Pull Request는 캘린더 페이지의 핵심 기능을 구현하여 사용자가 월별 캘린더에서 일정 수를 한눈에 확인하고, 특정 날짜를 선택하여 우측 패널에서 해당 일정을 생성, 관리, 완료/미완료 처리할 수 있도록 합니다. 이를 통해 캘린더 기반의 효율적인 일정 관리 경험을 제공합니다.

Highlights

  • 캘린더 UI 컴포넌트 개발: CalendarDays, TodoDay 컴포넌트를 통해 월별 캘린더를 렌더링하고, 각 날짜에 해당하는 일정 수를 시각적으로 오버레이하여 표시합니다.
  • 상태 관리 구축: Zustand 스토어를 활용하여 선택된 날짜를 중앙에서 관리하며, useSelectedDate 훅을 통해 쉽게 접근하고 업데이트할 수 있도록 합니다.
  • 날짜별 데이터 페칭 최적화: React Query의 날짜 스코프 쿼리 키(예: todos.list(YYYY-MM-DD))를 사용하여 날짜별 일정 데이터를 효율적으로 캐싱하고 관리합니다.
  • 일정 CRUD 기능 구현: 일정 생성, 읽기, 완료/미완료 토글 기능을 위한 API를 구현하고 프론트엔드와 연동하여 사용자가 일정을 관리할 수 있도록 합니다.
  • 카테고리 추가 기능: 새로운 카테고리를 생성하면 UI에 즉시 반영되며, 백엔드의 LEFT JOIN 수정으로 할 일이 없는 빈 카테고리도 올바르게 표시됩니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist 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.

Code Review

이 PR은 캘린더 페이지의 핵심적인 Todo 기능들을 구현했습니다. 전반적으로 Zustand를 이용한 상태 관리, React Query를 통한 데이터 페칭, 그리고 컴포넌트 구조화가 잘 이루어져 있습니다. 다만, 몇 가지 개선할 점들이 보입니다. API 에러 메시지의 구체화, 일부 훅과 컴포넌트의 성능 및 재사용성 개선, 그리고 사용자 경험(UX) 향상을 위한 제안들을 포함했습니다. 특히 window.prompt 사용과 같은 부분은 더 나은 UI/UX를 위해 개선이 필요해 보입니다. 자세한 내용은 각 파일에 대한 리뷰 코멘트를 참고해주세요.

Comment thread src/features/main/apis/category.api.ts Outdated
});

if (!response.ok) {
throw new Error("Failed to create todo");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

에러 메시지가 "Failed to create todo"로 되어 있어, 실제 기능인 카테고리 생성과 맞지 않습니다. "Failed to create category" 또는 한글로 "카테고리 생성에 실패했습니다."와 같이 명확한 메시지로 수정하는 것이 디버깅에 도움이 됩니다. 또한, 다른 API 함수들에서도 유사한 문제가 발견되었습니다. 애플리케이션 전반의 에러 메시지를 한국어로 통일하고, 각 API 기능에 맞는 구체적인 메시지를 사용하시는 것을 권장합니다.

Suggested change
throw new Error("Failed to create todo");
throw new Error("카테고리 생성에 실패했습니다");

});

const handleCreateCategory = () => {
const name = window.prompt("추가할 카테고리 이름을 입력해주세요.");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

window.prompt()를 사용하여 사용자 입력을 받는 것은 현대적인 웹 애플리케이션의 사용자 경험(UX)과 어울리지 않으며, UI 커스터마이징이 불가능합니다. Chakra UI의 Modal이나 PopoverInput 컴포넌트를 조합하여 더 나은 사용자 경험을 제공하는 입력창을 구현하는 것을 강력히 권장합니다.

Comment on lines +15 to +17
dayjs.extend(weekday);
dayjs.extend(isoWeek);
dayjs.extend(weekOfYear);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

dayjs.extend() 함수가 컴포넌트 함수 내에서 호출되고 있어, 컴포넌트가 리렌더링될 때마다 불필요하게 실행됩니다. 플러그인 확장은 애플리케이션 로드 시 한 번만 실행되면 충분하므로, 이 코드를 모듈의 최상단(import문 아래)으로 이동시켜 성능 저하를 방지하는 것이 좋습니다.

Comment on lines +24 to +25
const [activeInputId, setActiveInputId] = useState<number | null>(null);
const [inputValue, setInputValue] = useState("");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

현재 inputValue 상태가 모든 카테고리의 할 일 추가 입력창에서 공유되고 있습니다. 이로 인해 한 카테고리에서 텍스트를 입력한 후 다른 카테고리의 입력창을 열면 이전에 입력한 내용이 그대로 남아있어 사용자 경험을 해칠 수 있습니다. 카테고리를 변경할 때 입력값을 초기화하거나, 각 카테고리별로 입력 상태를 관리하는 것이 좋습니다. 예를 들어, 카테고리 버튼의 onClick 핸들러에서 setInputValue("")를 호출하여 입력창을 초기화할 수 있습니다.

Comment on lines +4 to +11
const selectedDate = useTodosStore((state) => state.selectedDate);
const setSelectedDate = useTodosStore((state) => state.setSelectedDate);

const updateSelectedDate = (date: string | null) => {
setSelectedDate(date);
};

return { selectedDate, updateSelectedDate };

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

updateSelectedDate 함수가 useSelectedDate 훅이 렌더링될 때마다 새로 생성되고 있습니다. 이 함수가 useEffect의 의존성 배열에 사용되거나 메모이제이션된 컴포넌트의 prop으로 전달될 경우 불필요한 리렌더링을 유발할 수 있습니다. Zustand의 setter 함수는 안정적이므로, setSelectedDate를 직접 사용하거나 useCallback으로 감싸서 안정적인 함수를 반환하는 것이 좋습니다. 더 간단하고 효율적인 방법은 setSelectedDate를 직접 가져와서 반환하는 것입니다.

  const selectedDate = useTodosStore((state) => state.selectedDate);
  const updateSelectedDate = useTodosStore((state) => state.setSelectedDate);

  return { selectedDate, updateSelectedDate };


export const updateTodoAPI = async (todoId: number, isCompleted: boolean) => {
const response = await fetch(`${BASE_URL}/api/todos/${todoId}`, {
method: "PUT",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

PR 설명에서는 PATCH 요청으로 isCompleted 상태를 토글한다고 되어 있는데, 실제 코드에서는 PUT 메소드를 사용하고 있습니다. PATCH는 리소스의 일부만 수정할 때 사용하는 것이 의미상 더 적절합니다. 백엔드 API가 PATCH를 지원한다면 메소드를 변경하는 것을 고려해보세요. 만약 PUT이 의도된 것이라면 PR 설명을 수정하여 일관성을 맞추는 것이 좋겠습니다.

Suggested change
method: "PUT",
method: "PATCH",

export * from "./calendar";
export * from "./category";
export * from "./link";
export * from "./category";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

./category 모듈이 중복으로 export 되고 있습니다. 불필요한 코드는 제거하여 코드 청결성을 유지하는 것이 좋습니다.

// 오늘 날짜 여부
const isToday = dayjs().format("YYYYMMDD") === current.format("YYYYMMDD");
// 보여질 날짜가 아닌 경우 (다른 달의 날짜인 경우)
const isNone = current.format("MM") === viewDate.format("MM") ? "" : "none";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

isNone 변수에 문자열("" 또는 "none")을 할당하여 삼항 연산자에서 사용하는 방식은 코드의 가독성을 떨어뜨릴 수 있습니다. current.format("MM") !== viewDate.format("MM")와 같이 boolean 값을 반환하는 isOutOfMonth 같은 변수를 선언하여 명시적으로 true/false를 사용하면 코드를 이해하기가 더 쉬워집니다. 이후 opacity={isOutOfMonth ? 0 : 1}와 같이 사용할 수 있습니다.

Suggested change
const isNone = current.format("MM") === viewDate.format("MM") ? "" : "none";
const isOutOfMonth = current.format("MM") !== viewDate.format("MM");

Comment thread src/features/main/ui/TodoSection.tsx Outdated
Comment on lines +30 to +45
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: requestDate ? TODO_QUERY_KEYS.todos.list(requestDate) : TODO_QUERY_KEYS.todos.all,
});
},
});

const { mutate: updateTodoMutate } = useMutation({
mutationFn: ({ todoId, isCompleted }: { todoId: number; isCompleted: boolean }) =>
updateTodoAPI(todoId, isCompleted),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: requestDate ? TODO_QUERY_KEYS.todos.list(requestDate) : TODO_QUERY_KEYS.todos.all,
});
},
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

createTodoMutateupdateTodoMutateonSuccess 핸들러에서 쿼리를 무효화하는 로직이 중복되고 있습니다. 또한, requestDateselectedDate ?? dayjs().format("YYYY-MM-DD")로 인해 항상 문자열 값을 가지므로, requestDate ? ... : ... 조건문은 불필요합니다. 이 로직을 별도의 함수로 추출하여 중복을 제거하고, 불필요한 조건문을 삭제하여 코드를 간결하게 만들 수 있습니다.

Comment thread src/features/main/utils/month.ts Outdated
Comment on lines +18 to +20
export const changeMonth = (setViewDate: (date: Dayjs) => void, viewDate: Dayjs, action: MonthChangeAction): void => {
setViewDate(getChangedMonth(viewDate, action));
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

changeMonth 함수가 export되고 있지만, 프로젝트 내에서 사용되지 않는 것으로 보입니다. 불필요한 코드는 혼란을 줄 수 있으므로, 사용하지 않는다면 제거하는 것이 좋습니다.

Copilot AI 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.

Pull request overview

This PR implements the core TODO functionality for a calendar application, enabling users to visualize and manage daily tasks. The implementation follows Feature-Sliced Design architecture with proper separation between entities, features, and shared layers.

Key Changes:

  • Calendar UI with monthly view and todo count visualization overlay
  • Date selection state management using Zustand with React Query for data fetching
  • Complete CRUD operations for todos and categories with API integration

Reviewed changes

Copilot reviewed 48 out of 54 changed files in this pull request and generated 20 comments.

Show a summary per file
File Description
src/features/main/ui/TodoSection.tsx Main todo management UI with create, toggle, and display functionality
src/features/main/ui/CalendarSection.tsx Calendar view component with date selection and month navigation
src/features/main/apis/todos.api.ts Todo API endpoints for CRUD operations
src/features/main/apis/category.api.ts Category creation API endpoint
src/features/main/components/features/calendar/* Calendar UI components (CalendarDays, CalendarHeader, CalendarWeekdays)
src/features/main/components/features/category/Category.tsx Category creation UI component
src/features/main/hooks/useGetTodos.ts React Query hooks for fetching todos
src/entities/todos/model/store/useTodosStore.ts Zustand store for selected date state management
src/entities/todos/model/hooks/useTodos.ts Custom hook wrapper for selected date state
src/entities/todos/model/types/todos.type.ts TypeScript types for Todo, Category, and related data structures
src/shared/constants/base-url.ts API base URL configuration
src/widgets/layouts/components/navigator/Navigator.tsx Updated navigation icons from outline to colored versions
package.json Added immer dependency for Zustand middleware
eslint.config.js Added prettier/prettier rule configuration
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

});

const handleCreateCategory = () => {
const name = window.prompt("추가할 카테고리 이름을 입력해주세요.");

Copilot AI Dec 23, 2025

Copy link

Choose a reason for hiding this comment

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

Using window.prompt for category creation is not user-friendly and blocks the entire UI. Consider replacing this with a proper modal dialog or inline input component for better UX and accessibility. Window.prompt also has accessibility issues as it's not screen-reader friendly and doesn't support modern form validation.

Copilot uses AI. Check for mistakes.

export const useGetTodos = (date?: string) => {
return useQuery({
queryKey: TODO_QUERY_KEYS.todos.list(date ?? ""),

Copilot AI Dec 23, 2025

Copy link

Choose a reason for hiding this comment

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

The query key structure is inconsistent. When date is an empty string, it still creates a query key ["todos", ""] which may lead to unexpected caching behavior. Consider using a different key structure or ensuring date is always a valid string or undefined.

Copilot uses AI. Check for mistakes.
Comment thread src/features/main/ui/TodoSection.tsx Outdated
Comment on lines +89 to +109
<Box cursor="pointer" onClick={() => toggleTodoStatus(todo.todosId, todo.isCompleted)}>
<Flex
alignItems="center"
justifyContent="center"
borderRadius="full"
boxSize={8}
position="relative"
>
<Icon as={PiFlowerFill} color={todo.isCompleted ? "primary" : "neutral.400"} boxSize={8} />
<Flex
position="absolute"
alignItems="center"
justifyContent="center"
boxSize={5}
borderRadius="full"
bg={todo.isCompleted ? "primary" : "neutral.400"}
>
{todo.isCompleted && <Icon as={FiCheck} color="white" boxSize={4} />}
</Flex>
</Flex>
</Box>

Copilot AI Dec 23, 2025

Copy link

Choose a reason for hiding this comment

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

Missing ARIA labels or semantic HTML for the todo completion button. Screen readers won't be able to convey the purpose or state of this interactive element. Consider adding aria-label with dynamic text indicating the todo content and completion state (e.g., "Mark 'task name' as complete" or "Mark 'task name' as incomplete").

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +28
const handleCreateCategory = () => {
const name = window.prompt("추가할 카테고리 이름을 입력해주세요.");
if (!name) return;

createCategoryMutate(name);

Copilot AI Dec 23, 2025

Copy link

Choose a reason for hiding this comment

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

Missing input validation for empty or whitespace-only category names. Users can create categories with just spaces or empty strings after trimming. Add validation in handleCreateCategory to check if the trimmed name is empty before calling the mutation.

Copilot uses AI. Check for mistakes.
export * from "./calendar";
export * from "./category";
export * from "./link";
export * from "./category";

Copilot AI Dec 23, 2025

Copy link

Choose a reason for hiding this comment

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

The duplicate export of "category" should be removed. This will cause a linting warning and is redundant.

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +26
const changeMonth = (action: MonthChangeAction) => {
setViewDate(getChangedMonth(viewDate, action));
};

Copilot AI Dec 23, 2025

Copy link

Choose a reason for hiding this comment

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

The changeMonth function shadows the imported utility function of the same name from line 18. This creates confusion and potential bugs. The local function on line 24 should be renamed to avoid this naming conflict (e.g., handleChangeMonth or onMonthChange).

Copilot uses AI. Check for mistakes.
@@ -0,0 +1 @@
export const BASE_URL = "http://localhost:8081";

Copilot AI Dec 23, 2025

Copy link

Choose a reason for hiding this comment

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

The BASE_URL is hardcoded to localhost. This will break in production environments. Consider using environment variables (e.g., import.meta.env.VITE_API_BASE_URL) to make the API URL configurable across different environments.

Copilot uses AI. Check for mistakes.
Comment thread src/features/main/ui/TodoSection.tsx Outdated
rounded="full"
size="sm"
colorScheme="primary"
onClick={() => setActiveInputId(activeInputId === category.categoryId ? null : category.categoryId)}

Copilot AI Dec 23, 2025

Copy link

Choose a reason for hiding this comment

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

The input value is not cleared when the active input changes. If a user types in one category's input, then clicks another category's plus button, the previously typed text will appear in the new input. This should be cleared when activeInputId changes.

Copilot uses AI. Check for mistakes.
Comment thread src/features/main/ui/TodoSection.tsx Outdated
boxSize={8}
position="relative"
>
<Icon as={PiFlowerFill} color={todo.isCompleted ? "primary" : "neutral.400"} boxSize={8} />

Copilot AI Dec 23, 2025

Copy link

Choose a reason for hiding this comment

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

The color logic for completed todos appears inverted. When isCompleted is true, the icon color is "primary", but when false, it's "neutral.400". Looking at line 104, the center background also uses "primary" for completed state. However, the PR description mentions the icon should be "white" as default and "neutral.400 + checkmark" when completed. The current implementation doesn't match this description.

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +22
const { mutate: createCategoryMutate } = useMutation({
mutationFn: (categoryName: string) => postCategoryAPI(categoryName, requestDate),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: TODO_QUERY_KEYS.todos.list(requestDate) });
},
});

Copilot AI Dec 23, 2025

Copy link

Choose a reason for hiding this comment

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

There's no error handling in the Category component for failed mutation. When category creation fails, the user receives no feedback. Add an onError callback to the mutation configuration to display error messages.

Copilot uses AI. Check for mistakes.
@Dobbymin
Dobbymin merged commit 14cbcaa into main Dec 23, 2025
1 check passed
@Dobbymin
Dobbymin deleted the feat#01-calendar branch December 23, 2025 18:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📡 API 비동기 통신 코드를 짜는 경우 🎨 Design UI / UX 디자인 관련 작업을 진행하는 경우 ✨ Feature 새로운 기능 추가 및 구현하는 경우

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Calendar 구현

2 participants