Conversation
포크한 레포에 작동 테스틀 위해 연결 스토리북 형태도 세팅함
구조 수정 및 tailwind prefix에 맞게 mapping
이전 패키지 버전에선 빌드가 안 됐음.
(이전 커밋에서 GoalCard에서 pb추가) TodoBottomSheet는 바텀탭바 존재에 따라 위치 변경 가능하도록 수정. 추가로, 여기서, 기본 subGoal 지정.
발표할 때 필요할 것 같아서.
컴포넌트들 props변경에 따른 에러 수정.
shared내부에 동일한 것으로 복제했습니다.
onboarding에서 Link를 통해 이동 fetch 시 로컬스토리지에서 access token사용하도록 변경 메인 페이지 수정
WalkthroughThis update introduces a comprehensive main page redesign and a robust goal/todo management system, including new React components, Zustand state stores, custom hooks, and API abstraction layers. It establishes an MSW-powered mock backend for local development and adds Storybook stories for UI components. The update also refines utility functions, documentation, and configuration for development and production environments. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant MainPage
participant GoalMenuContainer
participant GoalCard
participant API
participant MSW
User->>MainPage: Load page
MainPage->>GoalMenuContainer: Render and fetch goal list
GoalMenuContainer->>API: GET /v1/goals
API-->>MSW: Request intercepted (dev)
MSW-->>API: Mocked response (goal list)
API-->>GoalMenuContainer: Return goal list
GoalMenuContainer->>MainPage: User selects goal
MainPage->>GoalCard: Render with selected goalId
GoalCard->>API: GET /v1/goals/:goalId/sub-goals/all
API-->>MSW: Request intercepted (dev)
MSW-->>API: Mocked response (goal detail + todos)
API-->>GoalCard: Return goal + sub-goals + todos
User->>GoalCard: Add/Edit/Toggle Todo
GoalCard->>API: POST/PUT/PATCH /v1/sub-goals/:subGoalId/todo or /v1/todos/:todoId
API-->>MSW: Request intercepted (dev)
MSW-->>API: Mocked response (update DB)
API-->>GoalCard: Return updated data
GoalCard->>GoalMenuContainer: Optionally trigger refetch
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
npm error Exit handler never called! ✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 24
🔭 Outside diff range comments (2)
components/main/GoalMenuContainer/GoalMenuContainer.tsx (1)
1-76: Add missing Storybook file for GoalMenuContainerA Storybook entry is required for every new component. Please add:
- File:
components/main/GoalMenuContainer/GoalMenuContainer.stories.tsx
- Include at least one story named
Primarydemonstrating the default rendering ofGoalMenuContainer.components/main/MainHeader/MainHeader.tsx (1)
1-32: Add missing Storybook file for MainHeaderThe
MainHeadercomponent incomponents/main/MainHeader/MainHeader.tsxdoes not have a corresponding Storybook file. Please addcomponents/main/MainHeader/MainHeader.stories.tsxwith the first story named Primary. For example:import React from "react"; import MainHeader from "./MainHeader"; export default { title: "MainHeader", component: MainHeader, }; export const Primary = { args: { daysOfServiceUse: 1, }, };
- File to create:
• components/main/MainHeader/MainHeader.stories.tsx- First example name: Primary
🧹 Nitpick comments (36)
lib/common/fetchTemplate.ts (4)
1-1: Remove unused variable.The
tmpTokenvariable is declared but never used, creating dead code.-const tmpToken = ""; -
3-9: Add explicit return type annotation.The function should have an explicit return type annotation for better type safety and documentation.
-const templateFetch = async <T>( +const templateFetch = async <T>( apiUrl: string, method: "GET" | "PUT" | "PATCH" | "POST" | "DELETE", body?: object, onFetchNonOk?: (fetchRes: Response) => void, onErrorCatch?: (error: unknown) => void, -) => { +): Promise<T | undefined> => {
30-31: Use consistent language for comments.Mix Korean and English comments in the same codebase reduces readability and maintainability.
- // onFetchNonOk에서 throw을 안 할수도 있어서 + // onFetchNonOk might not throw an error
36-39: Improve error logging with structured information.The current error logging provides minimal debugging information. Consider logging more structured data.
} catch (e) { if (onErrorCatch) onErrorCatch(e); - console.error(`fetch error: ${e}`); + console.error('templateFetch error:', { + url: apiUrl, + method, + error: e instanceof Error ? e.message : e + }); }types/todoList.ts (1)
7-7: Nit: re-export inline
You can shorten to a single line export for brevity:export type TodoItemsInfo = Omit<TodoItemProps, "onReportedClick" | "onChecked"> & { id: string; };components/shared/Button/Button.tsx (2)
2-2: Consistent utility path
The relative import works, but other files still use the alias"@/lib/utils". Consider standardising on one style to avoid churn and accidental path breaks during moves.
34-35: Minor comment alignment
The comment for the medium size variant still lists “8px 16px” padding, but the class ispx-4 py-2(16px 8px). Update the comment for accuracy.components/shared/Modal/ModalAddingSubGoal/ModalAddingSubGoal.tsx (1)
81-83: State update OK – consider handler extraction
Inline handler is fine, though extracting tohandleChangeavoids re-creation on every render and keeps JSX terse.hooks/useModal.ts (1)
20-20: Simplify the boolean conversion.The ternary operator is redundant when converting to boolean.
- const isOpened = useModalStore((state) => (state.Modal ? true : false)); + const isOpened = useModalStore((state) => !!state.Modal);utils/date2String.ts (1)
1-7: Suggest variable naming improvement and add documentation.The function logic is correct, but consider these improvements:
Variable naming: The variable
dateon line 4 represents the day of the month, which could be confusing. Consider renaming todayfor clarity.Add JSDoc documentation: The function would benefit from documentation explaining its purpose, parameters, and return value.
+/** + * Converts a Date object to a formatted string with custom separator + * @param dateValue - The Date object to format + * @param spliter - The separator to use between year, month, and day + * @returns Formatted string in YYYY{spliter}MM{spliter}DD format + */ const date2StringWithSpliter = (dateValue: Date, spliter: string) => { const year = dateValue.getFullYear(); const month = dateValue.getMonth() + 1; - const date = dateValue.getDate(); - return `${year}${spliter}${String(month).padStart(2, "0")}${spliter}${String(date).padStart(2, "0")}`; + const day = dateValue.getDate(); + return `${year}${spliter}${String(month).padStart(2, "0")}${spliter}${String(day).padStart(2, "0")}`; };mocks/handlers.ts (1)
1-2: Remove unused imports.The imports
HttpResponse,delay,httpfrom "msw" andtodofrom "node:test" are not used in this file.-import { HttpResponse, delay, http } from "msw"; -import { todo } from "node:test"; import goalHandlers from "./apiHandlers/goalHandlers"; import todoHandlers from "./apiHandlers/todoHandlers"; import subGoalHandlers from "./apiHandlers/subGoalHandlers"; import cheerHandlers from "./apiHandlers/cheerHandlers"; import pointsHandlers from "./apiHandlers/pointsHandlers";components/_mocks/MSWComponent.tsx (1)
5-22: Missing Storybook files for the component.Based on the coding guidelines, components should have corresponding Storybook files. This MSW component might benefit from a story to demonstrate its initialization behavior.
Do you want me to generate a Storybook file for this component or open an issue to track this requirement?
app/layout.tsx (1)
8-9: Remove unused imports.The imports for
SWRConfigandBottomTabBarare not used in the component and should be removed to maintain clean code.-import { SWRConfig } from "swr"; -import { BottomTabBar } from "@/components/shared";components/main/GoalTitleArea/GoalTitleArea.tsx (2)
10-21: Remove unnecessary Fragment wrapper and clean up commented code.The Fragment wrapper is unnecessary since you're returning a single element. Also, remove the commented-out code.
Apply this diff:
return ( - <> - <div className="self-stretch h-10 inline-flex justify-start items-center gap-2"> + <div className="self-stretch h-10 inline-flex justify-start items-center gap-2"> <p className="flex-1 justify-center text-label-strong text-lg font-bold font-['SUIT_Variable'] leading-relaxed"> {goalTitle} </p> <div className="w-6 h-6 relative overflow-hidden"> <RightArrowSvg width={24} height={24} /> - {/* <div className="w-1 h-2 left-[10px] top-[8px] absolute outline-[1.50px] outline-offset-[-0.75px] outline-Color-gray-80"></div> */} </div> - </div> - </> + </div> );
4-6: Consider adding missing Storybook story.According to the coding guidelines, components should have associated Storybook stories. Consider adding a story file for this component.
Would you like me to generate a Storybook story for this component?
components/shared/BottomSheets/TodoResultBottomSheet/TodoResultBottomSheet.tsx (2)
11-13: Complete the overlay click handler implementation.The commented out
resetBottomSheet()function suggests incomplete implementation. The overlay should close the modal when clicked.<Drawer.Overlay - onClick={() => { - // resetBottomSheet(); - }} + onClick={onClose} className="fixed inset-0 bg-black/10 z-10" />
17-19: Add content to the empty Drawer.Content.The drawer content is currently empty, which suggests incomplete implementation. Consider adding placeholder content or a clear TODO comment.
<Drawer.Content className={`z-20 h-[585px] relative bg-background-alternative rounded-tl-lg rounded-tr-lg shadow-[0px_0px_4px_0px_rgba(0,0,0,0.24)] overflow-hidden`} -> +> + {/* TODO: Add todo result content */} </Drawer.Content>components/shared/README.md (1)
63-64: Fix bare URL formatting in documentation links.The static analysis tool correctly identified that these URLs should be properly formatted as markdown links.
-- [시작하기] https://10th-motimo-storybook.vercel.app/?path=/docs/introduction--docs -- [예시] https://10th-motimo-storybook.vercel.app/?path=/docs/components-test--docs +- [시작하기](https://10th-motimo-storybook.vercel.app/?path=/docs/introduction--docs) +- [예시](https://10th-motimo-storybook.vercel.app/?path=/docs/components-test--docs)components/main/GoalCard/GoalCard.stories.tsx (2)
1-1: Remove the template comment.The plop template comment should be removed from the final code.
-// plop-templates/story.tsx.hbs
25-34: Consider adding meaningful args and argTypes.The Primary story has empty argTypes and args, which limits its usefulness for demonstrating the component's capabilities. Consider adding relevant props based on the GoalCard component's interface.
export const Primary: Story = { argTypes: { - // 예시: backgroundColor: { control: 'color', description: '컴포넌트 배경색' }, + // Add actual prop controls based on GoalCard's interface }, args: { - // Primary 스토리에만 적용될 Props + // Add meaningful default props }, };hooks/main/queries/useTodoList.ts (2)
9-9: Remove unused mockFetcher.The
mockFetchervariable is defined but never used, creating dead code.-const mockFetcher = async () => {};
26-43: Consider removing commented code or adding explanation.The commented-out
mutateWithConversionfunction adds noise to the codebase. Either remove it if it's no longer needed, or add a comment explaining why it's preserved for future use.If this code is intended for future use, add a comment explaining the purpose:
+// TODO: Implement optimistic updates with data transformation +// This function will convert TodoItemsInfo back to TodoRs format for mutations // const mutateWithConversion = (Otherwise, remove the commented code entirely.
components/main/GoalMenuContainer/GoalMenuContainer.tsx (1)
64-64: Remove commented code.The commented-out
updateGoalIdcall should be removed since the effect at line 26-28 already handles this functionality.onSelected={() => { setSelectedGoalIdx(idx); - // updateGoalId(goalMenuInfo.goalId); }}app/page.tsx (1)
6-14: Clean up unused imports and finalize temporary implementation.Several imported components are commented out in the JSX but still present in the imports. Consider removing unused imports or uncommenting the components if they're needed.
Additionally, the temporary constant
tmpDaysOfServiceUsesuggests this is incomplete - consider implementing proper service usage tracking.-import { AppBar } from "@/components/shared"; -import GoalInfo from "@/components/shared/GoalInfo/GoalInfo"; -import TodoList from "@/components/main/TodoList/TodoList"; -import GoalTitleArea from "@/components/main/GoalTitleArea/GoalTitleArea"; - -import GoalMenuContainer from "@/components/main/GoalMenuContainer/GoalMenuContainer"; -import Banner from "@/components/shared/Banner/Banner"; -import GoalCard from "@/components/main/GoalCard/GoalCard"; -import MainHeader from "@/components/main/MainHeader/MainHeader"; +import GoalMenuContainer from "@/components/main/GoalMenuContainer/GoalMenuContainer"; +import GoalCard from "@/components/main/GoalCard/GoalCard"; +import MainHeader from "@/components/main/MainHeader/MainHeader"; + +// TODO: Uncomment when these components are integrated +// import { AppBar } from "@/components/shared"; +// import GoalInfo from "@/components/shared/GoalInfo/GoalInfo"; +// import TodoList from "@/components/main/TodoList/TodoList"; +// import GoalTitleArea from "@/components/main/GoalTitleArea/GoalTitleArea"; +// import Banner from "@/components/shared/Banner/Banner";components/main/GoalCard/GoalCard.tsx (1)
37-44: Improve date calculation robustness.The date calculation could fail with invalid dates or timezone issues. Consider adding error handling.
-const goalLeftDate = Math.floor( - (new Date(goalWithSubGoalTodo.dueDate ?? "").getTime() - - new Date().getTime()) / - 1000 / - 24 / - 60 / - 60, -); +const goalLeftDate = useMemo(() => { + if (!goalWithSubGoalTodo.dueDate) return 0; + try { + const dueDate = new Date(goalWithSubGoalTodo.dueDate); + const now = new Date(); + const diffTime = dueDate.getTime() - now.getTime(); + return Math.floor(diffTime / (1000 * 60 * 60 * 24)); + } catch (error) { + console.error('Invalid due date:', goalWithSubGoalTodo.dueDate); + return 0; + } +}, [goalWithSubGoalTodo.dueDate]);mocks/apiHandlers/goalHandlers.ts (1)
20-22: Standardize error handling and internationalize error messages.Consider using consistent error handling patterns and English error messages for better maintainability.
-const errMsg = "존재하지 않는 골 id임"; -console.error(errMsg); -throw new Error(errMsg); +const errMsg = "Goal not found"; +console.error(errMsg, { goalId: updatedGoal.id }); +return createErrorResponse(errMsg, 404);Apply similar patterns to other error cases throughout the file.
Also applies to: 76-77, 92-94
mocks/apiHandlers/todoHandlers.ts (1)
12-12: Consider using English error messages for consistency.The Korean error messages ("못찾음") might be inconsistent with the rest of the codebase. Consider using English error messages for better maintainability.
Apply this diff to use English error messages:
- throw new Error("못찾음"); + throw new Error("Todo not found");Also applies to: 26-26, 41-41, 48-48, 62-62, 77-77
hooks/main/queries/useGoalWithSubGoalTodo.ts (2)
25-25: Simplify the ternary operator.The ternary operator is unnecessary and can be simplified to a direct boolean assignment.
Apply this diff to simplify the code:
- reported: todoInfo.todoResultId ? true : false, + reported: Boolean(todoInfo.todoResultId),
11-13: Consider using a more descriptive type name.The type name
ConvertedGoalWithSubGoalTodocould be more descriptive about what the conversion entails.Consider renaming to:
-type ConvertedGoalWithSubGoalTodo = Omit<GoalWithSubGoalTodoRs, "subGoals"> & { - subGoals: TodoListProps[]; -}; +type GoalWithTodoListProps = Omit<GoalWithSubGoalTodoRs, "subGoals"> & { + subGoals: TodoListProps[]; +};mocks/apiHandlers/subGoalHandlers.ts (1)
14-14: Consider using English error messages for consistency.Similar to the todo handlers, the Korean error messages ("못찾음") might be inconsistent with the rest of the codebase.
Apply this diff to use English error messages:
- throw new Error("못찾음"); + throw new Error("SubGoal not found");Also applies to: 41-41, 62-62
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx (3)
251-259: Use optional chaining for cleaner code.The conditional check can be simplified using optional chaining.
Apply this diff to use optional chaining:
- nullabeTodoInfo && - nullabeTodoInfo.setTodoInfo((prev) => ({ - ...prev, - subGoalTitle: subGoalTitle, - subGoalId: subGoalId, - })); + nullabeTodoInfo?.setTodoInfo((prev) => ({ + ...prev, + subGoalTitle: subGoalTitle, + subGoalId: subGoalId, + }));
336-337: Consider moving utility function to a shared utils module.The date formatting utility function could be moved to a shared utils module for better reusability.
Consider creating a
utils/dateUtils.tsfile:export const formatDateWithDots = (date: Date): string => `${date.getFullYear()}.${String(date.getMonth() + 1).padStart(2, "0")}.${String(date.getDate()).padStart(2, "0")}`;
23-38: Consider using more descriptive type names.The type definitions could be more descriptive about their purpose and differences.
Consider renaming for better clarity:
-type TodoInfoForSubmission = { +type CompleteTodoInfo = { /** id값이 존재한다면 수정, 없다면 추가로 봐야 함. */ id?: string; todo: string; date: Date; subGoalTitle: string; subGoalId: string; }; -type TodoInfo = { +type PartialTodoInfo = { id?: TodoInfoForSubmission["todo"]; todo: TodoInfoForSubmission["todo"]; date?: TodoInfoForSubmission["date"]; subGoalTitle?: TodoInfoForSubmission["subGoalTitle"]; subGoalId?: TodoInfoForSubmission["subGoalId"]; };components/main/TodoList/TodoList.stories.tsx (1)
12-25: Consider moving the detailed description to component documentation.The lengthy description with implementation details might be better placed in the component's JSDoc or README rather than in the Storybook story.
Consider moving this to the component file's JSDoc or a separate documentation file, and keeping only essential usage information in the story description.
components/main/TodoList/TodoList.tsx (2)
189-189: Use optional chaining for cleaner code.Replace the
mutate && mutate()pattern with optional chaining:-mutate && mutate(); +mutate?.();This applies to lines 189, 321, and 342.
Also applies to: 321-321, 342-342
330-335: Simplify with optional chaining.const initTodoInfo = { - date: info?.targetDate ?? new Date(), - subGoalId: subGoalId ?? "", - subGoalTitle: subGoalTitle ?? "", + date: info.targetDate ?? new Date(), + subGoalId: subGoalId ?? "", + subGoalTitle: subGoalTitle ?? "", todo: info?.title, id: info?.id, };Since
infois required (not optional in the props), you don't need optional chaining fortargetDate.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (18)
api/generated/motimo/Api.tsis excluded by!**/generated/**components/shared/public/Calendar.svgis excluded by!**/*.svgcomponents/shared/public/Carrot_Down_MD.svgis excluded by!**/*.svgcomponents/shared/public/Paper_Plane.svgis excluded by!**/*.svgcomponents/shared/public/check.svgis excluded by!**/*.svgpackage-lock.jsonis excluded by!**/package-lock.jsonpublic/Caret_Down_MD.svgis excluded by!**/*.svgpublic/images/Bell.svgis excluded by!**/*.svgpublic/images/Caret_Down_MD.svgis excluded by!**/*.svgpublic/images/Caret_Up_MD.svgis excluded by!**/*.svgpublic/images/Chevron_Right_MD.svgis excluded by!**/*.svgpublic/images/Edit_Pencil_01.svgis excluded by!**/*.svgpublic/images/Trash_Full.svgis excluded by!**/*.svgpublic/images/file.svgis excluded by!**/*.svgpublic/images/globe.svgis excluded by!**/*.svgpublic/images/next.svgis excluded by!**/*.svgpublic/images/vercel.svgis excluded by!**/*.svgpublic/images/window.svgis excluded by!**/*.svg
📒 Files selected for processing (64)
api/generator.mjs(1 hunks)app/layout.tsx(3 hunks)app/onboarding/_components/CompletionScreen.tsx(3 hunks)app/onboarding/page.tsx(4 hunks)app/page.tsx(3 hunks)components/_mocks/MSWComponent.tsx(1 hunks)components/main/GoalCard/GoalCard.stories.tsx(1 hunks)components/main/GoalCard/GoalCard.tsx(1 hunks)components/main/GoalMenuContainer/GoalMenuContainer.tsx(1 hunks)components/main/GoalTitleArea/GoalTitleArea.tsx(1 hunks)components/main/MainHeader/MainHeader.tsx(1 hunks)components/main/TodoList/TodoList.stories.tsx(1 hunks)components/main/TodoList/TodoList.tsx(1 hunks)components/shared/AppBar/AppBar.tsx(5 hunks)components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.stories.tsx(1 hunks)components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx(1 hunks)components/shared/BottomSheets/TodoResultBottomSheet/TodoResultBottomSheet.tsx(1 hunks)components/shared/BottomTabBar/BottomTabBar.tsx(2 hunks)components/shared/Button/Button.tsx(3 hunks)components/shared/ButtonRound/ButtonRound.tsx(3 hunks)components/shared/Checkbox/Checkbox.tsx(1 hunks)components/shared/GoalInfo/GoalInfo.tsx(1 hunks)components/shared/GoalMenu/GoalMenu.tsx(1 hunks)components/shared/Modal/ModalAddingSubGoal/ModalAddingSubGoal.tsx(1 hunks)components/shared/Modal/_compound/Modal.tsx(1 hunks)components/shared/Modal/_compound/ModalButton.tsx(1 hunks)components/shared/README.md(3 hunks)components/shared/SegmentedControl/SegmentedControl.tsx(3 hunks)components/shared/SnackBar/SnackBar.tsx(4 hunks)components/shared/Toast/Toast.tsx(1 hunks)components/shared/TodoItem/TodoItem.tsx(3 hunks)components/shared/package.json(2 hunks)components/shared/utils/utils.ts(1 hunks)hooks/main/queries/useGoalList.ts(1 hunks)hooks/main/queries/useGoalWithSubGoalTodo.ts(1 hunks)hooks/main/queries/useTodoList.ts(1 hunks)hooks/main/useOptimisticToggle.ts(1 hunks)hooks/useModal.ts(2 hunks)lib/common/fetchTemplate.ts(1 hunks)lib/main/cheersFetching.ts(1 hunks)lib/main/goalFetching.ts(1 hunks)lib/main/pointsFetching.ts(1 hunks)lib/main/subGoalFetching.ts(1 hunks)lib/main/todoFetching.ts(1 hunks)mocks/apiHandlers/cheerHandlers.ts(1 hunks)mocks/apiHandlers/db.ts(1 hunks)mocks/apiHandlers/goalHandlers.ts(1 hunks)mocks/apiHandlers/pointsHandlers.ts(1 hunks)mocks/apiHandlers/subGoalHandlers.ts(1 hunks)mocks/apiHandlers/todoHandlers.ts(1 hunks)mocks/apiHandlers/utils.ts(1 hunks)mocks/browser.ts(1 hunks)mocks/handlers.ts(1 hunks)mocks/index.ts(1 hunks)mocks/server.ts(1 hunks)next.config.ts(3 hunks)package.json(4 hunks)plopfile.js(1 hunks)public/mockServiceWorker.js(1 hunks)stores/useActiveTodoBottomSheet.ts(1 hunks)stores/useGoalStore.ts(1 hunks)stores/useModalStore.ts(1 hunks)types/todoList.ts(1 hunks)utils/date2String.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
`components/**/*`: Component should be created in components/
components/**/*: Component should be created in components/
📄 Source: CodeRabbit Inference Engine (.cursor/rules/global-rule.mdc)
List of files the instruction was applied to:
components/shared/GoalInfo/GoalInfo.tsxcomponents/shared/GoalMenu/GoalMenu.tsxcomponents/shared/Modal/_compound/Modal.tsxcomponents/shared/ButtonRound/ButtonRound.tsxcomponents/shared/Button/Button.tsxcomponents/shared/Checkbox/Checkbox.tsxcomponents/shared/Modal/ModalAddingSubGoal/ModalAddingSubGoal.tsxcomponents/shared/utils/utils.tscomponents/shared/package.jsoncomponents/shared/Modal/_compound/ModalButton.tsxcomponents/shared/AppBar/AppBar.tsxcomponents/shared/SnackBar/SnackBar.tsxcomponents/shared/TodoItem/TodoItem.tsxcomponents/_mocks/MSWComponent.tsxcomponents/shared/SegmentedControl/SegmentedControl.tsxcomponents/shared/BottomSheets/TodoResultBottomSheet/TodoResultBottomSheet.tsxcomponents/main/GoalTitleArea/GoalTitleArea.tsxcomponents/main/GoalCard/GoalCard.stories.tsxcomponents/shared/README.mdcomponents/shared/BottomTabBar/BottomTabBar.tsxcomponents/main/TodoList/TodoList.tsxcomponents/shared/Toast/Toast.tsxcomponents/main/GoalMenuContainer/GoalMenuContainer.tsxcomponents/main/MainHeader/MainHeader.tsxcomponents/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.stories.tsxcomponents/main/GoalCard/GoalCard.tsxcomponents/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsxcomponents/main/TodoList/TodoList.stories.tsx
`components/**/*.stories.{js,jsx,ts,tsx}`: If Component is created, add storybook files as well. The first example name of storybook should be `Primary` not `Default`
components/**/*.stories.{js,jsx,ts,tsx}: If Component is created, add storybook files as well.
The first example name of storybook should bePrimarynotDefault
📄 Source: CodeRabbit Inference Engine (.cursor/rules/global-rule.mdc)
List of files the instruction was applied to:
components/main/GoalCard/GoalCard.stories.tsxcomponents/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.stories.tsxcomponents/main/TodoList/TodoList.stories.tsx
🧠 Learnings (11)
next.config.ts (1)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/icons/**/* : For icon and svg, create component at components/icons.
components/shared/package.json (2)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : If Component is created, add storybook files as well.
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : The first example name of storybook should be `Primary` not `Default`
components/_mocks/MSWComponent.tsx (1)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : If Component is created, add storybook files as well.
plopfile.js (3)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : If Component is created, add storybook files as well.
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : The first example name of storybook should be `Primary` not `Default`
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/icons/**/* : For icon and svg, create component at components/icons.
components/main/GoalTitleArea/GoalTitleArea.tsx (1)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/icons/**/* : For icon and svg, create component at components/icons.
components/main/GoalCard/GoalCard.stories.tsx (2)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : The first example name of storybook should be `Primary` not `Default`
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : If Component is created, add storybook files as well.
components/shared/README.md (2)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : The first example name of storybook should be `Primary` not `Default`
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : If Component is created, add storybook files as well.
package.json (2)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : If Component is created, add storybook files as well.
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : The first example name of storybook should be `Primary` not `Default`
app/page.tsx (1)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : The first example name of storybook should be `Primary` not `Default`
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.stories.tsx (2)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : If Component is created, add storybook files as well.
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : The first example name of storybook should be `Primary` not `Default`
components/main/TodoList/TodoList.stories.tsx (2)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : If Component is created, add storybook files as well.
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : The first example name of storybook should be `Primary` not `Default`
🧬 Code Graph Analysis (29)
types/todoList.ts (1)
components/shared/TodoItem/TodoItem.tsx (1)
TodoItemProps(102-102)
mocks/index.ts (2)
mocks/server.ts (1)
server(4-4)mocks/browser.ts (1)
worker(4-4)
lib/main/cheersFetching.ts (2)
lib/common/fetchTemplate.ts (1)
templateFetch(42-42)api/generated/motimo/Api.ts (1)
CheerPhraseRs(350-356)
mocks/server.ts (1)
mocks/handlers.ts (1)
handlers(9-24)
lib/main/pointsFetching.ts (2)
lib/common/fetchTemplate.ts (1)
templateFetch(42-42)api/generated/motimo/Api.ts (1)
PointRs(247-254)
mocks/apiHandlers/utils.ts (1)
api/generated/motimo/Api.ts (1)
HttpResponse(425-429)
mocks/browser.ts (1)
mocks/handlers.ts (1)
handlers(9-24)
components/shared/Modal/_compound/ModalButton.tsx (1)
components/shared/Button/Button.tsx (1)
ButtonProps(4-10)
components/shared/AppBar/AppBar.tsx (1)
components/shared/utils/utils.ts (1)
cn(4-6)
components/shared/SnackBar/SnackBar.tsx (1)
components/shared/utils/utils.ts (1)
cn(4-6)
components/_mocks/MSWComponent.tsx (1)
mocks/index.ts (1)
initMsw(1-9)
mocks/apiHandlers/pointsHandlers.ts (2)
mocks/apiHandlers/db.ts (1)
myMainDB(191-191)api/generated/motimo/Api.ts (1)
HttpResponse(425-429)
mocks/apiHandlers/cheerHandlers.ts (2)
mocks/apiHandlers/db.ts (1)
myMainDB(191-191)api/generated/motimo/Api.ts (1)
HttpResponse(425-429)
app/layout.tsx (1)
components/_mocks/MSWComponent.tsx (1)
MSWComponent(5-22)
components/shared/SegmentedControl/SegmentedControl.tsx (1)
components/shared/utils/utils.ts (1)
cn(4-6)
components/shared/BottomTabBar/BottomTabBar.tsx (1)
components/shared/utils/utils.ts (1)
cn(4-6)
components/shared/Toast/Toast.tsx (3)
components/shared/index.ts (1)
Toast(10-10)components/shared/utils/utils.ts (1)
cn(4-6)lib/utils.ts (1)
cn(4-6)
stores/useActiveTodoBottomSheet.ts (1)
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx (1)
TodoInfoForSubmission(229-229)
hooks/main/queries/useGoalList.ts (2)
lib/main/goalFetching.ts (1)
getAllGoals(68-68)components/main/GoalMenuContainer/GoalMenuContainer.tsx (1)
GoalMenuInfo(75-75)
hooks/main/queries/useTodoList.ts (2)
types/todoList.ts (1)
TodoItemsInfo(7-7)lib/main/subGoalFetching.ts (1)
getTodosOnSubGoal(47-47)
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.stories.tsx (1)
components/main/TodoList/TodoList.stories.tsx (1)
Primary(92-104)
lib/main/subGoalFetching.ts (2)
api/generated/motimo/Api.ts (2)
TodoCreateRq(99-112)TodoRs(179-212)lib/common/fetchTemplate.ts (1)
templateFetch(42-42)
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx (1)
components/shared/Button/Button.tsx (1)
Button(77-77)
mocks/apiHandlers/todoHandlers.ts (2)
mocks/apiHandlers/db.ts (1)
myMainDB(191-191)api/generated/motimo/Api.ts (1)
HttpResponse(425-429)
mocks/apiHandlers/goalHandlers.ts (3)
mocks/apiHandlers/utils.ts (1)
createErrorResponse(6-6)mocks/apiHandlers/db.ts (1)
myMainDB(191-191)api/generated/motimo/Api.ts (1)
HttpResponse(425-429)
hooks/main/queries/useGoalWithSubGoalTodo.ts (4)
api/generated/motimo/Api.ts (1)
GoalWithSubGoalTodoRs(313-332)components/main/TodoList/TodoList.tsx (1)
TodoListProps(151-151)lib/main/goalFetching.ts (1)
getGoalWithSubGoalTodo(73-73)types/todoList.ts (1)
TodoItemsInfo(7-7)
mocks/apiHandlers/subGoalHandlers.ts (2)
mocks/apiHandlers/db.ts (1)
myMainDB(191-191)api/generated/motimo/Api.ts (1)
HttpResponse(425-429)
lib/main/goalFetching.ts (2)
api/generated/motimo/Api.ts (6)
GoalUpdateRq(34-49)GoalListRs(280-283)GoalCreateRq(114-138)SubGoalCreateRq(140-155)GoalDetailRs(285-311)GoalWithSubGoalTodoRs(313-332)lib/common/fetchTemplate.ts (1)
templateFetch(42-42)
lib/main/todoFetching.ts (3)
lib/common/fetchTemplate.ts (1)
templateFetch(42-42)utils/date2String.ts (1)
date2StringWithSpliter(7-7)api/generated/motimo/Api.ts (1)
TodoRs(179-212)
🪛 markdownlint-cli2 (0.17.2)
components/shared/README.md
63-63: Bare URL used
(MD034, no-bare-urls)
64-64: Bare URL used
(MD034, no-bare-urls)
🪛 Biome (1.9.4)
components/main/TodoList/TodoList.tsx
[error] 196-197: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 330-331: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 332-333: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 358-358: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
components/main/GoalMenuContainer/GoalMenuContainer.tsx
[error] 20-20: Unexpected empty object pattern.
(lint/correctness/noEmptyPattern)
components/main/GoalCard/GoalCard.tsx
[error] 93-94: Unnecessary use of boolean literals in conditional expression.
Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with
(lint/complexity/noUselessTernary)
[error] 109-110: Unnecessary use of boolean literals in conditional expression.
Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with
(lint/complexity/noUselessTernary)
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx
[error] 254-261: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
mocks/apiHandlers/todoHandlers.ts
[error] 103-104: Avoid the use of spread (...) syntax on accumulators.
Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.
(lint/performance/noAccumulatingSpread)
[error] 105-105: Avoid the use of spread (...) syntax on accumulators.
Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.
(lint/performance/noAccumulatingSpread)
mocks/apiHandlers/goalHandlers.ts
[error] 144-145: Avoid the use of spread (...) syntax on accumulators.
Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.
(lint/performance/noAccumulatingSpread)
hooks/main/queries/useGoalWithSubGoalTodo.ts
[error] 25-25: Unnecessary use of boolean literals in conditional expression.
Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with
(lint/complexity/noUselessTernary)
components/main/TodoList/TodoList.stories.tsx
[error] 103-104: Avoid the use of spread (...) syntax on accumulators.
Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.
(lint/performance/noAccumulatingSpread)
public/mockServiceWorker.js
[error] 288-288: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: chromatic-test
🔇 Additional comments (70)
plopfile.js (1)
15-16: LGTM! Appropriate exclusion patterns added.The exclusion of icon components and completed component groups from story generation is sensible, as these typically don't require interactive Storybook stories. This aligns with the coding guidelines for icon components.
components/shared/GoalMenu/GoalMenu.tsx (1)
65-65: LGTM! Proper type export for reusability.Exporting the
GoalMenuPropstype enables type sharing with other components, which is a good TypeScript practice for maintaining type consistency across the codebase.api/generator.mjs (1)
22-22: LGTM! Consistent HTTP client choice.Switching from "axios" to "fetch" aligns with the new
templateFetchutility function and reduces external dependencies by using the native fetch API.components/shared/Modal/_compound/Modal.tsx (1)
26-26: LGTM! Proper z-index stacking for modal backdrop.Adding
z-20ensures the modal backdrop appears above other UI elements, which is essential for proper modal behavior and user experience.stores/useModalStore.ts (1)
1-1: Directive is appropriate
Adding"use client";is necessary for Zustand stores consumed in React Client Components under the Next 13+ app router. No further action required.types/todoList.ts (1)
1-5: Confirmidduplication withTodoItemProps
IfTodoItemPropsalready contains an optionalid, intersecting with{ id: string }makes it required, which is usually intended but could introduce silent type-narrowing. Double-check the source definition to ensure this is desirable for every caller.components/shared/Checkbox/Checkbox.tsx (1)
11-12: Good addition
shrink-0prevents flex shrink and fixes layout jitter next to text. Looks correct.components/shared/utils/utils.ts (1)
1-6: LGTM! Standard utility for Tailwind class merging.This is a well-implemented utility function that combines
clsxfor conditional class handling andtwMergefor resolving Tailwind CSS conflicts. This is a common and recommended pattern in React projects using Tailwind CSS.mocks/apiHandlers/utils.ts (1)
3-6: LGTM! Reusable error response utility for MSW.This utility function provides a consistent way to generate error responses across mock handlers. The implementation is correct and follows MSW best practices.
app/onboarding/_components/CompletionScreen.tsx (2)
84-86: Verify dual navigation behavior.The button now has both a
Linkwrapper (navigating to "/") and anonClickhandler (onComplete). This dual navigation setup could cause race conditions or unexpected behavior.Please verify that this is the intended behavior and that the
onCompletehandler doesn't perform navigation that conflicts with theLinkcomponent.
71-73: Minor formatting improvement.Clean formatting change that improves readability without affecting functionality.
components/shared/package.json (3)
3-3: Version update to stable release.Good progression from pre-release to stable version, indicating the shared UI package is now production-ready.
17-18: Verify React 19 compatibility.The upgrade from React 18 to React 19 is a major version change that could introduce breaking changes. Please ensure all components in the shared UI package are compatible with React 19.
23-24: Consider the impact of enforcing React 19.Changing from flexible version ranges (
>=18) to a specific major version (^19.0.0) makes React 19 a hard requirement. This could be a breaking change for consumers still using React 18.Consider whether this restriction is necessary or if a more flexible range would be appropriate.
mocks/browser.ts (1)
1-4: LGTM! Standard MSW browser setup.This is a clean and correct implementation of MSW worker setup for the browser environment. The pattern of importing handlers and spreading them into
setupWorkerfollows MSW best practices.mocks/server.ts (1)
1-4: LGTM! Clean MSW server setup.The server setup follows MSW best practices with proper imports and handler configuration.
lib/main/pointsFetching.ts (1)
4-10: Address TODO comments for production readiness.The function lacks error handling and the return type may need conversion. Consider implementing:
- Try-catch blocks with appropriate error handling
- Toast notifications for user feedback
- Type validation/conversion if needed
Since this is noted as incomplete, please ensure error handling is implemented before merging to production.
mocks/index.ts (1)
1-9: LGTM! Proper MSW environment detection and initialization.The function correctly detects the runtime environment and initializes MSW appropriately with dynamic imports to prevent bundling issues.
hooks/useModal.ts (1)
29-29: LGTM! Good addition of modal state visibility.The
isOpenedproperty provides a clean way for components to check modal visibility state.components/shared/GoalInfo/GoalInfo.tsx (1)
12-13: LGTM! Calendar icon centering improvement.The addition of
justify-center items-centerclasses properly centers the calendar icon within its container, improving the visual alignment of the component.components/shared/Toast/Toast.tsx (2)
8-21: Code formatting improvements look good.The function signature consolidation and JSX formatting with trailing commas enhance code readability and maintainability.
1-1: ✅ Import path verified – no issues found
- The relative import (
components/shared/utils/utils.ts) exports the samecnfunction as the original absolute path (lib/utils.ts).- Formatting changes are purely cosmetic and consistent with the project’s refactoring.
All good to merge.
components/shared/TodoItem/TodoItem.tsx (4)
49-49: Good responsive design improvement.Changing from fixed width
w-72tow-fullmakes the component more flexible and responsive to different container sizes.
55-55: Better layout control with max-width constraint.The change from
"flex-1 self-stretch"to"max-w-full"provides better control over the label's maximum width, preventing potential overflow issues.
67-67: Appropriate removal of flex-1 class.Removing the
"flex-1"class from the paragraph while keeping"truncate"ensures proper text truncation without unnecessary flex behavior.
110-110: Essential styling addition for icon visibility.Adding the
"text-white"class ensures the CheckSvg icon is visible against the background, improving the component's visual clarity.mocks/apiHandlers/pointsHandlers.ts (1)
1-12: Well-structured mock API handler implementation.The implementation correctly follows MSW patterns and integrates well with the broader mock infrastructure. The handler properly:
- Uses the correct HTTP method and endpoint pattern
- Accesses the mock database appropriately
- Returns a properly formatted JSON response
- Exports the handler in the expected format
This complements the other mock handlers introduced in this PR and supports the frontend development workflow.
components/shared/AppBar/AppBar.tsx (3)
1-1: LGTM: Import path change improves consistency.The change from alias import to relative import aligns with the project's import strategy and maintains consistency across components.
27-36: LGTM: Improved JSX formatting with trailing commas.The multi-line formatting with trailing commas enhances readability and makes future modifications easier by reducing diff noise.
49-55: LGTM: Consistent JSX formatting applied.The conditional rendering blocks are now properly formatted with parentheses and multi-line structure, improving code readability.
Also applies to: 72-78
mocks/handlers.ts (1)
9-24: LGTM: Clean handlers aggregation.The handlers are properly organized and spread into a single array for easy consumption by MSW setup.
hooks/main/useOptimisticToggle.ts (1)
3-11: LGTM: Well-implemented optimistic toggle hook.The hook properly uses React's
useOptimisticwith a clean toggle reducer and returns a properly typed tuple. The implementation is concise and reusable.components/shared/Modal/_compound/ModalButton.tsx (1)
4-5: Excellent interface improvement for type consistency.The change from
ButtonHTMLAttributes<HTMLButtonElement>toOmit<ButtonProps, "children">is a great improvement that:
- Maintains consistency with the shared
ButtonPropsinterface- Prevents potential prop conflicts by explicitly omitting
children- Leverages the existing button prop structure while allowing the
textprop to handle contentcomponents/shared/SnackBar/SnackBar.tsx (2)
1-1: Consistent import path refactoring.The change from absolute import
@/lib/utilsto relative import../utils/utilsaligns with the broader refactoring effort to standardize utility imports across shared components.
20-25: Improved JSX formatting with trailing commas.The multiline JSX formatting with trailing commas enhances readability and follows modern React formatting conventions.
app/layout.tsx (2)
42-42: Proper MSWComponent integration for development mocking.The conditional rendering of
MSWComponentonly in development mode is the correct approach for setting up API mocking without affecting production builds.
28-28: Good addition of full width/height classes.Adding
w-full h-fullclasses to the html element ensures proper viewport coverage for the application layout.components/shared/SegmentedControl/SegmentedControl.tsx (2)
1-1: Consistent import path standardization.The change to relative import path
../utils/utilsmaintains consistency with the broader refactoring effort across shared components.
22-27: Improved JSX formatting consistency.The multiline JSX formatting with trailing commas improves readability and maintains consistency with modern React formatting standards across the shared components.
Also applies to: 40-47
stores/useGoalStore.ts (1)
1-22: Well-implemented Zustand store for goal management.The
useGoalStoreimplementation demonstrates excellent practices:
- Clean, simple interface with proper TypeScript typing
- Appropriate use of
string | nullfor the goalId state- Clear naming conventions for state and updater function
- Proper Zustand store creation pattern
- Helpful documentation comment explaining the purpose
This provides a solid foundation for managing the selected goal state across the application.
components/shared/BottomTabBar/BottomTabBar.tsx (1)
1-1: Good improvement to navigation.The addition of Next.js
Linkcomponents and the switch to relative imports aligns with the overall codebase improvements. The navigation URLs are properly structured for the main app sections.Also applies to: 5-5
components/shared/ButtonRound/ButtonRound.tsx (1)
1-1: Good formatting improvements and consistent import path.The changes improve code readability with better formatting and align with the consistent move to relative imports for utility functions across the codebase.
Also applies to: 13-23
package.json (1)
13-13: Good alignment with new architecture.The script change to use
.mjsand the MSW configuration properly support the new API generation approach and mock service worker setup introduced in the PR.Also applies to: 70-74
app/onboarding/page.tsx (1)
19-19: Good formatting improvements.The arrow function parameter formatting improves code readability and consistency.
Also applies to: 23-23, 27-27
hooks/main/queries/useGoalList.ts (1)
8-16: LGTM! Well-structured data transformation.The hook properly handles the data transformation from API response to UI format with good use of optional chaining and nullish coalescing for safe property access.
mocks/apiHandlers/db.ts (1)
1-191: Excellent mock database structure with comprehensive test data.The mock database provides:
- Well-structured relational data with proper ID references
- Comprehensive coverage of all entity types (goals, subGoals, todos, todoResults, cheer, points)
- Realistic test scenarios including completion states and progress tracking
- Intentionally long content for UI testing (todo12 title)
This will support robust testing of the entire goal/todo management system.
next.config.ts (3)
10-10: Good fix for missing comma in webpack configuration.The added comma properly terminates the rule test property.
26-26: Good fix for missing comma in webpack configuration.The added comma properly terminates the use property array.
49-60: External proxy URL is reachableChecked via
curl -I http://motimo.kro.kr:8080/v1/health– it returnsHTTP/1.1 401, confirming the host is up and responding. No changes required to the rewrite configuration.components/shared/README.md (3)
1-3: Good improvement from generic template to project-specific content.The updated title and description make the README more relevant to the actual project.
30-33: Proper package name specification in installation instructions.The installation instructions now correctly specify
motimo-shared-uiinstead of placeholder text.
70-70: Good update to project-specific issue reporting URL.The issue reporting link now correctly points to the actual project repository.
stores/useActiveTodoBottomSheet.ts (1)
5-21: Clean and well-structured Zustand store implementation.The store follows Zustand best practices with clear type definitions and proper state management. The
setIsActivefunction correctly handles both the boolean state and optional content initialization.components/main/MainHeader/MainHeader.tsx (1)
12-16: Good implementation with clear improvement path.The component correctly implements client-side data fetching with SWR, and the comment about moving to RSC shows good architectural awareness. The error handling with default values is appropriate.
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.stories.tsx (1)
34-53: Excellent adherence to coding guidelines.The story file correctly follows the established guidelines:
- Uses "Primary" as the first story name (not "Default")
- Includes proper Meta configuration
- Provides multiple scenarios for testing different states
The documentation note about portal usage is helpful for users.
mocks/apiHandlers/todoHandlers.ts (5)
5-20: LGTM! Well-structured PUT handler with proper error handling.The handler correctly updates todos in the mock database and includes proper error handling for missing todos.
22-40: LGTM! Comprehensive DELETE handler with cascade deletion.The handler properly removes todos from both the
todosarray and cleans up references insubGoals. The cascade deletion logic is well-implemented.
42-54: LGTM! Simple and correct GET handler for todo results.The handler follows the expected pattern with proper error handling.
56-71: LGTM! POST handler correctly creates new todo results.The handler properly generates new IDs and creates todo result entries with the correct structure.
73-87: LGTM! PATCH handler correctly toggles completion status.The toggle logic is straightforward and correctly implemented.
hooks/main/queries/useGoalWithSubGoalTodo.ts (1)
15-46: LGTM! Well-structured data transformation hook.The hook correctly uses SWR for data fetching and provides comprehensive data transformation from the API response to the expected component props format. The mapping logic properly handles null/undefined values with fallbacks.
mocks/apiHandlers/subGoalHandlers.ts (3)
5-30: LGTM! Well-implemented POST handler for creating todos under sub-goals.The handler correctly creates new todos, assigns them to sub-goals, and maintains consistency between the
subGoalsandtodostables in the mock database.
32-52: LGTM! Simple and correct PATCH handler for toggling sub-goal completion.The toggle logic is straightforward and correctly implemented with proper error handling.
54-72: LGTM! Correct GET handler for retrieving todos by sub-goal.The handler properly filters todos associated with a specific sub-goal and returns the correct data structure.
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx (1)
78-104: LGTM! Well-structured component with proper state management.The component correctly uses React Context to share state between nested components and implements proper state reset functionality.
components/main/TodoList/TodoList.stories.tsx (2)
27-46: LGTM! Well-structured Storybook configuration.The story metadata is properly configured with appropriate title, documentation, and follows the coding guidelines with
Primaryas the first example name.
92-150: LGTM! Comprehensive story variants covering different use cases.The story variants effectively demonstrate different states of the TodoList component, including edge cases like empty lists and long lists for testing scroll behavior.
lib/main/goalFetching.ts (2)
19-23: Good type safety implementation!The function correctly uses the type parameter for
templateFetch.
48-64: Well-typed fetch functions!Both functions correctly specify type parameters for
templateFetch.public/mockServiceWorker.js (1)
1-345: Skip review - generated file.This is a generated Mock Service Worker file that should not be modified per the header comment.
| const updateTodo = async (todoId: string, body: UpdateTodoBody) => { | ||
| await templateFetch(`/v1/todos/${todoId}`, "PUT", { | ||
| ...body, | ||
| date: body.date ? date2StringWithSpliter(body.date, "-") : undefined, | ||
| }); | ||
| }; | ||
| const toggleTodo = async (todoId: string) => { | ||
| await templateFetch(`/v1/todos/${todoId}/completion`, "PATCH"); | ||
| }; | ||
| const deleteTodo = async (todoId: string) => { | ||
| await templateFetch(`/v1/todos/${todoId}`, "DELETE"); | ||
| }; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add return types for better type safety.
These functions should have explicit return types:
-const updateTodo = async (todoId: string, body: UpdateTodoBody) => {
+const updateTodo = async (todoId: string, body: UpdateTodoBody): Promise<void> => {
await templateFetch(`/v1/todos/${todoId}`, "PUT", {
...body,
date: body.date ? date2StringWithSpliter(body.date, "-") : undefined,
});
};
-const toggleTodo = async (todoId: string) => {
+const toggleTodo = async (todoId: string): Promise<void> => {
await templateFetch(`/v1/todos/${todoId}/completion`, "PATCH");
};
-const deleteTodo = async (todoId: string) => {
+const deleteTodo = async (todoId: string): Promise<void> => {
await templateFetch(`/v1/todos/${todoId}`, "DELETE");
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const updateTodo = async (todoId: string, body: UpdateTodoBody) => { | |
| await templateFetch(`/v1/todos/${todoId}`, "PUT", { | |
| ...body, | |
| date: body.date ? date2StringWithSpliter(body.date, "-") : undefined, | |
| }); | |
| }; | |
| const toggleTodo = async (todoId: string) => { | |
| await templateFetch(`/v1/todos/${todoId}/completion`, "PATCH"); | |
| }; | |
| const deleteTodo = async (todoId: string) => { | |
| await templateFetch(`/v1/todos/${todoId}`, "DELETE"); | |
| }; | |
| const updateTodo = async (todoId: string, body: UpdateTodoBody): Promise<void> => { | |
| await templateFetch(`/v1/todos/${todoId}`, "PUT", { | |
| ...body, | |
| date: body.date ? date2StringWithSpliter(body.date, "-") : undefined, | |
| }); | |
| }; | |
| const toggleTodo = async (todoId: string): Promise<void> => { | |
| await templateFetch(`/v1/todos/${todoId}/completion`, "PATCH"); | |
| }; | |
| const deleteTodo = async (todoId: string): Promise<void> => { | |
| await templateFetch(`/v1/todos/${todoId}`, "DELETE"); | |
| }; |
🤖 Prompt for AI Agents
In lib/main/todoFetching.ts around lines 12 to 23, the async functions
updateTodo, toggleTodo, and deleteTodo lack explicit return types. Add explicit
return types such as Promise<void> to each function declaration to improve type
safety and clarity.
| const postTodoResult = async (todoId: string) => { | ||
| await templateFetch(`/v1/todos/${todoId}/result`, "POST"); | ||
| }; | ||
| const deleteTodoResult = async (todoResultId: string) => { | ||
| await templateFetch(`/v1/todos/result/${todoResultId}`, "DELETE"); | ||
| }; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add explicit return types.
-const postTodoResult = async (todoId: string) => {
+const postTodoResult = async (todoId: string): Promise<void> => {
await templateFetch(`/v1/todos/${todoId}/result`, "POST");
};
-const deleteTodoResult = async (todoResultId: string) => {
+const deleteTodoResult = async (todoResultId: string): Promise<void> => {
await templateFetch(`/v1/todos/result/${todoResultId}`, "DELETE");
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const postTodoResult = async (todoId: string) => { | |
| await templateFetch(`/v1/todos/${todoId}/result`, "POST"); | |
| }; | |
| const deleteTodoResult = async (todoResultId: string) => { | |
| await templateFetch(`/v1/todos/result/${todoResultId}`, "DELETE"); | |
| }; | |
| const postTodoResult = async (todoId: string): Promise<void> => { | |
| await templateFetch(`/v1/todos/${todoId}/result`, "POST"); | |
| }; | |
| const deleteTodoResult = async (todoResultId: string): Promise<void> => { | |
| await templateFetch(`/v1/todos/result/${todoResultId}`, "DELETE"); | |
| }; |
🤖 Prompt for AI Agents
In lib/main/todoFetching.ts around lines 34 to 39, the async functions
postTodoResult and deleteTodoResult lack explicit return types. Add the return
type Promise<void> to both functions to clearly indicate they return a promise
that resolves to void.
| const getTodoResult = async (todoId: string) => { | ||
| const todoResult = await templateFetch<TodoRs>( | ||
| `/v1/todos/${todoId}/result`, | ||
| "GET", | ||
| ); | ||
|
|
||
| return todoResult ?? {}; | ||
| }; |
There was a problem hiding this comment.
Avoid returning empty object - loses type safety.
Returning {} when todoResult is null/undefined breaks type safety. Consider returning null or undefined instead:
-const getTodoResult = async (todoId: string) => {
+const getTodoResult = async (todoId: string): Promise<TodoRs | null> => {
const todoResult = await templateFetch<TodoRs>(
`/v1/todos/${todoId}/result`,
"GET",
);
- return todoResult ?? {};
+ return todoResult ?? null;
};This maintains type safety and allows callers to properly handle the absence of data.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const getTodoResult = async (todoId: string) => { | |
| const todoResult = await templateFetch<TodoRs>( | |
| `/v1/todos/${todoId}/result`, | |
| "GET", | |
| ); | |
| return todoResult ?? {}; | |
| }; | |
| const getTodoResult = async (todoId: string): Promise<TodoRs | null> => { | |
| const todoResult = await templateFetch<TodoRs>( | |
| `/v1/todos/${todoId}/result`, | |
| "GET", | |
| ); | |
| return todoResult ?? null; | |
| }; |
🤖 Prompt for AI Agents
In lib/main/todoFetching.ts around lines 26 to 33, the function getTodoResult
returns an empty object {} when todoResult is null or undefined, which breaks
type safety. Modify the function to return null or undefined instead of {}, so
the return type remains consistent and callers can handle the absence of data
properly.
| onChecked={async () => { | ||
| toggleChecekdOptimistically(); | ||
| updateOptimisticCheckedLen && updateOptimisticCheckedLen(1); | ||
|
|
||
| await toggleTodo(info.id); | ||
| mutate && mutate(); | ||
| }} |
There was a problem hiding this comment.
Fix optimistic checked count logic.
The optimistic update always increments by 1, but it should decrement when unchecking:
onChecked={async () => {
toggleChecekdOptimistically();
- updateOptimisticCheckedLen && updateOptimisticCheckedLen(1);
+ updateOptimisticCheckedLen && updateOptimisticCheckedLen(checked ? -1 : 1);
await toggleTodo(info.id);
mutate && mutate();
}}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In components/main/TodoList/TodoList.tsx around lines 316 to 322, the optimistic
update logic for the checked count always increments by 1 regardless of whether
the item is being checked or unchecked. Modify the updateOptimisticCheckedLen
call to increment by 1 when checking and decrement by 1 when unchecking, based
on the current checked state before toggling.
BottomTabBar 불필요 key제거 TodoList className정리, scroll 되도록 수정, 불필요 낙관적 업데이트 제거
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
components/main/TodoList/TodoList.tsx (1)
318-319: Re-enable the optimistic checked count update logic.The commented code appears to address a previous review comment about fixing optimistic update logic. The optimistic count update should be re-enabled to provide proper UI feedback when checking/unchecking todos.
- // updateOptimisticCheckedLen && - // updateOptimisticCheckedLen(checked ? -1 : +1); + updateOptimisticCheckedLen && + updateOptimisticCheckedLen(checked ? -1 : +1);
🧹 Nitpick comments (6)
components/main/TodoList/TodoList.tsx (6)
183-184: Use optional chaining to simplify the conditional check.The static analysis tool correctly identifies that this can be simplified using optional chaining.
- if (!goalId) return; - - const mutateResult = await createNewSubGoalOnGoal(goalId, { + const mutateResult = await createNewSubGoalOnGoal(goalId, {Wait, this change would be incorrect as it would still call the function with undefined goalId. Let me reconsider:
- if (!goalId) return; - - const mutateResult = await createNewSubGoalOnGoal(goalId, { + if (!goalId) return; + + const mutateResult = await createNewSubGoalOnGoal(goalId, {Actually, the current code is correct. The optional chaining suggestion from the static analysis tool is not applicable here since we need to return early if goalId is undefined.
332-335: Use optional chaining for cleaner null checks.The static analysis tool correctly identifies opportunities to use optional chaining for cleaner code.
- date: info?.targetDate ?? new Date(), - subGoalId: subGoalId ?? "", - subGoalTitle: subGoalTitle ?? "", - todo: info?.title, + date: info?.targetDate ?? new Date(), + subGoalId: subGoalId ?? "", + subGoalTitle: subGoalTitle ?? "", + todo: info?.title,Actually, the current code already uses optional chaining appropriately. The static analysis tool might be suggesting a different pattern, but the current implementation is correct and readable.
241-241: Consider using a more semantic height constraint.The fixed height of
h-80(320px) might not be ideal for all screen sizes. Consider using a more flexible approach.- <div className="self-stretch h-80 flex flex-col justify-start items-start gap-2 overflow-y-auto overflow-x-hidden"> + <div className="self-stretch max-h-80 flex flex-col justify-start items-start gap-2 overflow-y-auto overflow-x-hidden">This allows the container to be smaller than 320px when there are fewer items while still maintaining the maximum height constraint.
364-367: Use proper line height utilities instead of inline styles.Mixing Tailwind classes with inline styles can lead to inconsistencies. Consider using Tailwind's line height utilities.
- <p - className=" whitespace-pre-wrap text-center justify-center text-label-alternative text-xs font-medium font-['SUIT_Variable'] leading-none " - style={{ lineHeight: "140%" }} - > + <p className="whitespace-pre-wrap text-center justify-center text-label-alternative text-xs font-medium font-['SUIT_Variable'] leading-relaxed">The
leading-relaxedclass provides 1.625 line height which is close to 140% and maintains consistency with the Tailwind design system.
34-34: Remove commented import or add explanation.The commented import should either be removed if not needed or uncommented if it will be used.
-// import { createNewTodoOnSubGoal } from "@/lib/main/subGoalFetching";If this import will be needed for future functionality, consider adding a TODO comment explaining when it will be used.
384-387: Remove unused/mysterious div element.This div appears to be leftover from design tools or serves no clear purpose. It should be removed to clean up the code.
- <div - data-type="normal" - className="w-40 h-9 left-0 top-0 absolute" - ></div>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
components/main/TodoList/TodoList.tsx(1 hunks)components/shared/BottomTabBar/BottomTabBar.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- components/shared/BottomTabBar/BottomTabBar.tsx
🧰 Additional context used
📓 Path-based instructions (1)
`components/**/*`: Component should be created in components/
components/**/*: Component should be created in components/
📄 Source: CodeRabbit Inference Engine (.cursor/rules/global-rule.mdc)
List of files the instruction was applied to:
components/main/TodoList/TodoList.tsx
🧠 Learnings (1)
components/main/TodoList/TodoList.tsx (1)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: For every styling, use tailwind css.
🧬 Code Graph Analysis (1)
components/main/TodoList/TodoList.tsx (4)
types/todoList.ts (1)
TodoItemsInfo(7-7)api/generated/motimo/Api.ts (1)
TodoRs(179-212)lib/main/goalFetching.ts (1)
createNewSubGoalOnGoal(70-70)lib/main/todoFetching.ts (2)
toggleTodo(48-48)deleteTodo(45-45)
🪛 Biome (1.9.4)
components/main/TodoList/TodoList.tsx
[error] 196-197: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 333-334: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 359-359: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: chromatic-test
🔇 Additional comments (1)
components/main/TodoList/TodoList.tsx (1)
63-149: LGTM! Well-structured component with proper state management.The main TodoList component is well-implemented with proper use of React hooks, context, and conditional rendering. The optimistic updates pattern is correctly set up and the component handles various states appropriately.
| type="button" | ||
| className="justify-start text-white text-sm font-semibold font-['Pretendard'] leading-tight" | ||
| > | ||
| 목표 상세페이지로 이동 | ||
| </button> |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add proper button functionality or disable the button.
The button has no onClick handler, which makes it non-functional. Either add the navigation logic or disable the button if the functionality is not yet implemented.
<button
type="button"
className="justify-start text-white text-sm font-semibold font-['Pretendard'] leading-tight"
+ onClick={() => {
+ // TODO: Navigate to goal detail page
+ }}
>
목표 상세페이지로 이동
</button>Alternatively, if the functionality is not ready:
<button
type="button"
+ disabled
className="justify-start text-white text-sm font-semibold font-['Pretendard'] leading-tight"
>
목표 상세페이지로 이동
</button>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| type="button" | |
| className="justify-start text-white text-sm font-semibold font-['Pretendard'] leading-tight" | |
| > | |
| 목표 상세페이지로 이동 | |
| </button> | |
| type="button" | |
| className="justify-start text-white text-sm font-semibold font-['Pretendard'] leading-tight" | |
| onClick={() => { | |
| // TODO: Navigate to goal detail page | |
| }} | |
| > | |
| 목표 상세페이지로 이동 | |
| </button> |
🤖 Prompt for AI Agents
In components/main/TodoList/TodoList.tsx around lines 378 to 382, the button
lacks an onClick handler, making it non-functional. To fix this, either add the
appropriate onClick handler to implement the navigation logic to the 목표 상세페이지
or, if the functionality is not ready, add the disabled attribute to the button
to prevent user interaction.
AppBar보다 BottomSheet와 Modal이 z-index 높도록 수정
body자체를 scrollbar에 의해 layout shift발생하지 않게 수정하고, bottom sheet에도 적용했습니다. component/shared 패키지 버전 수정에 따른 lock파일 변경이 추가로 있습니다. bottom tabbar의 fixed로 인해 modal과의 z-index차이를 조정했습니다. 상단 AppBar관련해서 배너 상단에 공간을 만들어 ui겹침을 제거했습니다.
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
app/globals.css (1)
35-37: Consider alternative approaches for preventing scrollbar layout shifts.While
width: 100vw; overflow-x: hidden;prevents layout shifts, using100vwcan cause issues on mobile browsers where the viewport width includes the scrollbar width, potentially creating horizontal scrolling problems.Consider these alternative approaches:
- /* 스크롤바 layout shift안되게 수정 */ - width: 100vw; - overflow-x: hidden; + /* 스크롤바 layout shift안되게 수정 */ + width: 100%; + overflow-x: hidden;Or use the more modern CSS approach:
- /* 스크롤바 layout shift안되게 수정 */ - width: 100vw; - overflow-x: hidden; + /* 스크롤바 layout shift안되게 수정 */ + width: 100%; + overflow-x: hidden; + scrollbar-gutter: stable;app/page.tsx (1)
52-64: Remove commented-out code blocks.The commented-out code blocks should be removed to keep the codebase clean, especially since this appears to be leftover from development.
- {/* <div className="flex justify-end w-full"> - <AppBar type="main" /> - </div> - <Banner - title="목표는 멀어도 나는 계속 가는 중" - tag="모티모와 함께 한 지 1일차" - /> */}- {/* <div className="w-full flex-1 p-4 bg-background-normal inline-flex flex-col justify-start items-start gap-2 "> - <GoalTitleArea goalTitle="6개월 안에 책 50권 읽기" /> - <GoalInfo leftDateNum={180} leftTodoNum={0} /> - <TodoList initTodoItemsInfo={[]} todoTotalLen={0} /> - </div> */}components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx (1)
253-260: Simplify null checking with optional chaining.The explicit null check can be simplified using optional chaining for better readability and modern JavaScript practices.
- nullabeTodoInfo && - nullabeTodoInfo.setTodoInfo((prev) => ({ - ...prev, - subGoalTitle: subGoalTitle, - subGoalId: subGoalId, - })); + nullabeTodoInfo?.setTodoInfo((prev) => ({ + ...prev, + subGoalTitle: subGoalTitle, + subGoalId: subGoalId, + }));
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (6)
app/globals.css(2 hunks)app/layout.tsx(3 hunks)app/page.tsx(3 hunks)components/main/MainHeader/MainHeader.tsx(1 hunks)components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx(1 hunks)components/shared/Modal/_compound/Modal.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- components/shared/Modal/_compound/Modal.tsx
- app/layout.tsx
- components/main/MainHeader/MainHeader.tsx
🧰 Additional context used
📓 Path-based instructions (1)
`components/**/*`: Component should be created in components/
components/**/*: Component should be created in components/
📄 Source: CodeRabbit Inference Engine (.cursor/rules/global-rule.mdc)
List of files the instruction was applied to:
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx
🧠 Learnings (1)
app/page.tsx (1)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : The first example name of storybook should be `Primary` not `Default`
🪛 Biome (1.9.4)
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx
[error] 256-263: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: chromatic-test
🔇 Additional comments (6)
app/page.tsx (2)
17-17: Component rename aligns with PR objectives.The component rename from
HometoMainproperly reflects the main page functionality described in the PR objectives.
44-72: Excellent modular component structure.The new main page structure with separate components (
MainHeader,GoalMenuContainer,GoalCard,BottomTabBar) provides good separation of concerns and aligns perfectly with the PR objectives of completing the main page functionality.components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx (4)
56-76: Well-implemented utility function.The
makeDefaultTodoBottomSheetInfofunction properly handles both initialization scenarios with appropriate fallbacks and null safety checks.
78-228: Solid component architecture and state management.The main component demonstrates good React patterns with proper state management, form handling, and lifecycle methods. The conditional rendering and event handling are well-structured.
287-335: Well-implemented date picker component.The
BottomSheetDatecomponent properly manages date selection state and provides a clean user interface for date picking with appropriate cancel/confirm actions.
337-339: Clean date formatting utility.The
date2stringSplitByDotfunction correctly formats dates with proper zero-padding. The inline comment explains the rationale for its placement.
| </div> | ||
| ); | ||
| } | ||
| const tmpDaysOfServiceUse = 1; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Replace hardcoded temporary value with proper implementation.
The hardcoded tmpDaysOfServiceUse = 1 should be replaced with actual service usage calculation or fetched from an API.
Consider implementing proper days calculation:
- const tmpDaysOfServiceUse = 1;
+ const daysOfServiceUse = useMemo(() => {
+ // Calculate actual days since service registration
+ const registrationDate = new Date(/* get from user data */);
+ const now = new Date();
+ return Math.floor((now.getTime() - registrationDate.getTime()) / (1000 * 60 * 60 * 24));
+ }, []);Or fetch from an API endpoint if available.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In app/page.tsx at line 41, replace the hardcoded temporary value
`tmpDaysOfServiceUse = 1` with a dynamic calculation of the actual days of
service use or fetch this value from an appropriate API endpoint. Implement
logic to compute the days based on relevant data or integrate an API call to
retrieve the accurate service usage duration.
| type TodoInfo = { | ||
| id?: TodoInfoForSubmission["todo"]; | ||
| todo: TodoInfoForSubmission["todo"]; | ||
| date?: TodoInfoForSubmission["date"]; | ||
| subGoalTitle?: TodoInfoForSubmission["subGoalTitle"]; | ||
| subGoalId?: TodoInfoForSubmission["subGoalId"]; | ||
| }; |
There was a problem hiding this comment.
Fix type reference error.
The id property in TodoInfo type references the wrong field from TodoInfoForSubmission. It should reference the id field, not the todo field.
type TodoInfo = {
- id?: TodoInfoForSubmission["todo"];
+ id?: TodoInfoForSubmission["id"];
todo: TodoInfoForSubmission["todo"];
date?: TodoInfoForSubmission["date"];
subGoalTitle?: TodoInfoForSubmission["subGoalTitle"];
subGoalId?: TodoInfoForSubmission["subGoalId"];
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| type TodoInfo = { | |
| id?: TodoInfoForSubmission["todo"]; | |
| todo: TodoInfoForSubmission["todo"]; | |
| date?: TodoInfoForSubmission["date"]; | |
| subGoalTitle?: TodoInfoForSubmission["subGoalTitle"]; | |
| subGoalId?: TodoInfoForSubmission["subGoalId"]; | |
| }; | |
| type TodoInfo = { | |
| id?: TodoInfoForSubmission["id"]; | |
| todo: TodoInfoForSubmission["todo"]; | |
| date?: TodoInfoForSubmission["date"]; | |
| subGoalTitle?: TodoInfoForSubmission["subGoalTitle"]; | |
| subGoalId?: TodoInfoForSubmission["subGoalId"]; | |
| }; |
🤖 Prompt for AI Agents
In components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx around
lines 32 to 38, the TodoInfo type incorrectly sets the id property to reference
TodoInfoForSubmission["todo"]. Change this to reference
TodoInfoForSubmission["id"] instead to fix the type reference error.
엔터로 입력하면 높이 이상해지는 버그 수정했습니다. focus관련한 버그여서 blur처리로 수정했습니다.
반환값을 보고 결과를 판단하도록 로직을 짰는데, 반환하지 않아서 제대로 작동하지 않았었습니당.
주소 동적 연결되게 수정 및 msw 주석처리. 이외 자잘한 오류 정리
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (3)
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx (1)
32-38: Fix type reference error.The
idproperty inTodoInfotype references the wrong field fromTodoInfoForSubmission. It should reference theidfield, not thetodofield.type TodoInfo = { - id?: TodoInfoForSubmission["todo"]; + id?: TodoInfoForSubmission["id"]; todo: TodoInfoForSubmission["todo"]; date?: TodoInfoForSubmission["date"]; subGoalTitle?: TodoInfoForSubmission["subGoalTitle"]; subGoalId?: TodoInfoForSubmission["subGoalId"]; };components/main/TodoList/TodoList.tsx (2)
379-384: Add proper button functionality or disable the button.The button has no onClick handler, which makes it non-functional. Either add the navigation logic or disable the button if the functionality is not yet implemented.
<button type="button" + onClick={() => { + // TODO: Navigate to goal detail page + }} className="justify-start text-white text-sm font-semibold font-['Pretendard'] leading-tight" > 목표 상세페이지로 이동 </button>Alternatively, if the functionality is not ready:
<button type="button" + disabled className="justify-start text-white text-sm font-semibold font-['Pretendard'] leading-tight" > 목표 상세페이지로 이동 </button>
317-325: Fix optimistic checked count logic and remove commented code.The optimistic update logic has issues and there's commented code that should be addressed.
onChecked={async () => { startTransition(async () => { toggleChecekdOptimistically(); + updateOptimisticCheckedLen && updateOptimisticCheckedLen(checked ? -1 : 1); await toggleTodo(info.id); mutate && mutate(); }); - // updateOptimisticCheckedLen && - // updateOptimisticCheckedLen(checked ? -1 : +1); }}The optimistic update should be moved inside the
startTransitionto ensure consistency.
🧹 Nitpick comments (6)
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx (3)
96-102: Improve the blur handling and add error handling.The current blur handling uses type assertion which can be unsafe. Consider using a more type-safe approach.
const resetBottomSheet = () => { setIsActivated(false); setVisibleSelect(false); setShowDate(false); setTodoInfo(makeDefaultTodoBottomSheetInfo(subGoals)); - inputRef.current && (inputRef.current as HTMLInputElement).blur(); + if (inputRef.current) { + (inputRef.current as HTMLInputElement).blur(); + } };
266-276: Use optional chaining for better code safety.The current conditional logic can be simplified using optional chaining.
onClick={() => { - nullabeTodoInfo && - nullabeTodoInfo.setTodoInfo((prev) => ({ - ...prev, - subGoalTitle: subGoalTitle, - subGoalId: subGoalId, - })); + nullabeTodoInfo?.setTodoInfo((prev) => ({ + ...prev, + subGoalTitle: subGoalTitle, + subGoalId: subGoalId, + })); }}
351-353: Move utility function to a proper location.The utility function
date2stringSplitByDotis defined inline but would be better placed in a dedicated utils module for reusability.Consider moving this function to a shared utility module:
// utils/dateUtils.ts export const date2stringSplitByDot = (date: Date) => `${date.getFullYear()}.${String(date.getMonth() + 1).padStart(2, "0")}.${String(date.getDate()).padStart(2, "0")}`;Then import and use it in this component.
components/main/TodoList/TodoList.tsx (3)
186-194: Use optional chaining for better code safety.The current conditional logic can be simplified using optional chaining.
onAddSubGoal={async (subGoal: string) => { // mutateResult가 네트워크 fail에서는 undefined가 나와야 함. if (!goalId) return; const mutateResult = await createNewSubGoalOnGoal(goalId, { title: subGoal, }); if (mutateResult) { - mutate && mutate(); + mutate?.(); closeModal(); } }}
332-340: Use optional chaining for better code safety.The current conditional logic can be simplified using optional chaining.
const initTodoInfo = { - date: info?.targetDate, + date: info?.targetDate, subGoalId: subGoalId ?? "", subGoalTitle: subGoalTitle ?? "", todo: info?.title, id: info?.id, };This specific line is already using optional chaining correctly, but the static analysis hint might be referring to other usages in the same area.
274-276: Fix typo in function name.There's a typo in the function name
toggleChecekdOptimistically- it should betoggleCheckedOptimistically.-const [checked, toggleChecekdOptimistically] = useOptimisticToggle( +const [checked, toggleCheckedOptimistically] = useOptimisticToggle( info.checked ?? false, );Make sure to update all references to this function throughout the component.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
app/layout.tsx(3 hunks)components/main/TodoList/TodoList.tsx(1 hunks)components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx(1 hunks)components/shared/TodoItem/TodoItem.tsx(4 hunks)lib/main/todoFetching.ts(1 hunks)next.config.ts(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- app/layout.tsx
- components/shared/TodoItem/TodoItem.tsx
- next.config.ts
- lib/main/todoFetching.ts
🧰 Additional context used
📓 Path-based instructions (1)
`components/**/*`: Component should be created in components/
components/**/*: Component should be created in components/
📄 Source: CodeRabbit Inference Engine (.cursor/rules/global-rule.mdc)
List of files the instruction was applied to:
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsxcomponents/main/TodoList/TodoList.tsx
🧠 Learnings (1)
components/main/TodoList/TodoList.tsx (1)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: For every styling, use tailwind css.
🧬 Code Graph Analysis (2)
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx (1)
components/shared/Button/Button.tsx (1)
Button(77-77)
components/main/TodoList/TodoList.tsx (4)
types/todoList.ts (1)
TodoItemsInfo(7-7)api/generated/motimo/Api.ts (1)
TodoRs(179-212)lib/main/goalFetching.ts (1)
createNewSubGoalOnGoal(70-70)lib/main/todoFetching.ts (2)
toggleTodo(53-53)deleteTodo(50-50)
🪛 Biome (1.9.4)
components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx
[error] 270-277: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
components/main/TodoList/TodoList.tsx
[error] 197-198: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 333-333: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 361-361: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: chromatic-test
| onSubmit={async (e) => { | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| if (todoInfo.subGoalTitle) { | ||
| const submitRes = await onSubmitTodo( | ||
| todoInfo as TodoInfoForSubmission, | ||
| ); | ||
|
|
||
| submitRes && resetBottomSheet(); | ||
| } | ||
| // else의 경우 에러 메시지를 넣어야 할 수도 있음 | ||
| }} |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add proper error handling for form submission.
The form submission lacks comprehensive error handling. Consider adding user feedback for failed submissions.
onSubmit={async (e) => {
e.preventDefault();
e.stopPropagation();
if (todoInfo.subGoalTitle) {
+ try {
const submitRes = await onSubmitTodo(
todoInfo as TodoInfoForSubmission,
);
submitRes && resetBottomSheet();
+ } catch (error) {
+ console.error('Failed to submit todo:', error);
+ // Add user notification here
+ }
}
- // else의 경우 에러 메시지를 넣어야 할 수도 있음
+ else {
+ // Add validation error handling here
+ }
}}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| onSubmit={async (e) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| if (todoInfo.subGoalTitle) { | |
| const submitRes = await onSubmitTodo( | |
| todoInfo as TodoInfoForSubmission, | |
| ); | |
| submitRes && resetBottomSheet(); | |
| } | |
| // else의 경우 에러 메시지를 넣어야 할 수도 있음 | |
| }} | |
| onSubmit={async (e) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| if (todoInfo.subGoalTitle) { | |
| try { | |
| const submitRes = await onSubmitTodo( | |
| todoInfo as TodoInfoForSubmission, | |
| ); | |
| submitRes && resetBottomSheet(); | |
| } catch (error) { | |
| console.error('Failed to submit todo:', error); | |
| // Add user notification here | |
| } | |
| } else { | |
| // Add validation error handling here | |
| } | |
| }} |
🤖 Prompt for AI Agents
In components/shared/BottomSheets/TodoBottomSheet/TodoBottomSheet.tsx around
lines 154 to 165, the onSubmit handler does not handle errors from the
onSubmitTodo call. Update the handler to catch any errors during submission and
provide user feedback, such as displaying an error message or notification, when
the submission fails. Ensure that the error handling does not block the form's
normal flow and resets or maintains the form state appropriately.
| onDelete={async () => { | ||
| await deleteTodo(info.id); | ||
| mutate && mutate(); | ||
| }} |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add error handling for delete operation.
The delete operation lacks error handling which could lead to silent failures.
onDelete={async () => {
+ try {
await deleteTodo(info.id);
mutate && mutate();
+ } catch (error) {
+ console.error('Failed to delete todo:', error);
+ // Add user notification here
+ }
}}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| onDelete={async () => { | |
| await deleteTodo(info.id); | |
| mutate && mutate(); | |
| }} | |
| onDelete={async () => { | |
| try { | |
| await deleteTodo(info.id); | |
| mutate && mutate(); | |
| } catch (error) { | |
| console.error('Failed to delete todo:', error); | |
| // Add user notification here | |
| } | |
| }} |
🤖 Prompt for AI Agents
In components/main/TodoList/TodoList.tsx around lines 343 to 346, the onDelete
async function calls deleteTodo without any error handling, which may cause
silent failures. Wrap the deleteTodo call in a try-catch block, and in the catch
block handle or log the error appropriately to ensure any failure during
deletion is captured and can be addressed.
| await toggleTodo(info.id); | ||
| mutate && mutate(); | ||
| }); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add error handling for toggle operation.
The toggle operation lacks error handling which could lead to inconsistent state.
startTransition(async () => {
toggleChecekdOptimistically();
+ try {
await toggleTodo(info.id);
mutate && mutate();
+ } catch (error) {
+ console.error('Failed to toggle todo:', error);
+ // Revert optimistic update here
+ toggleChecekdOptimistically();
+ }
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| await toggleTodo(info.id); | |
| mutate && mutate(); | |
| }); | |
| startTransition(async () => { | |
| toggleChecekdOptimistically(); | |
| try { | |
| await toggleTodo(info.id); | |
| mutate && mutate(); | |
| } catch (error) { | |
| console.error('Failed to toggle todo:', error); | |
| // Revert optimistic update here | |
| toggleChecekdOptimistically(); | |
| } | |
| }); |
🤖 Prompt for AI Agents
In components/main/TodoList/TodoList.tsx around lines 320 to 322, the toggleTodo
function call lacks error handling, which may cause inconsistent state if the
operation fails. Wrap the await toggleTodo(info.id) call in a try-catch block,
and in the catch block, handle the error appropriately, such as logging the
error or showing a user notification. This ensures that any failure during the
toggle operation is managed gracefully without breaking the app flow.
* feat: 메인 페이지 제작중 관련 svg설정 next turbopack에 적용 * feat: 메인 페이지 제작에 필요한 컴포넌트 추가 제작 GoalMenuContainer, GoalTItleArea. TodoList는 todoItem이 빈 배열이라 checkedLen필요 없을 때를 고려해 수정함. * feat: 일부 공유 컴포넌트 반응형으로 수정 고정 너비가 아니라 full로 수정함. 고정 크기일 필요가 없어보여서 임시로 수정. 추후 디자이너가 결정한 것으로 수정 가능. * feat: 메인페이지 추가 컴포넌트 AppBar 제작 * feat: msw 적용하기 * feat: 메인 페이지 제작 관련 컴포넌트 수정 svg들 폴더 위치 변경 * feat: 배너 컴포넌트 반응형으로 수정 * feat: 모달 컴포넌트 및 관련 훅과 스토어 생성 (진행중) 모달 공통 컴포넌트와 파생 컴포넌트 제작. 공통에서 종속적인 부분이 있어 합성 컴포넌트로 제작. 모달 전역 관리를 위해 zustand와 커스텀 훅을 사용. svgr관련 세팅 대해 브랜치 꼬여서 임시 저장. * feat: TodoList 접힌 상황 추가 및 api에 대한 추상화 타입 적용. 비동기 미처리. api 변동과 무관하게 사용될 타입을 생성해 적용했습니다. api의 반환 타입을 이로 변환하는 로직을 fetch함수 만들 때 적용 예정입니다. * feat: AppBar삭제 및 패키지 재설치 공유 컴포넌트에 있었어서 AppBar는 삭제함. * feat: 불필요 컴포넌트 제거(ModalAddingSubGoal겹침) * feat: 모달 버튼 공용 컴포넌트의 것으로 수정 * feat: 메인 페이지 TodoList 모달 연결 * feat: todoList관련 데이터 페칭 연결 임시 * feat: api generation 스크립트 수정 및 재생성 * feat: 날짜 타입 문자열로 변환하는 유틸 함수 제작 * feat: todo와 subGoal관련 fetching 함수 제작 이곳에 타입 변환 존재합니다 * feat: api generator fetch기반으로 변경 후 재생성 * feat: todo, todolist관련 swr 훅 제작 * feat: TodoItem 체크에 대한 낙관적 업데이트위한 훅 제작 기본 useOptimistic은 action인자가 필요하지만, 체크는 toggle이라 필요 없어서 따로 제작했습니다. 깔끔하게 만들기 위해서용. * feat: TodoList 비동기 onEdit제외 연결 onEdit은 바텀 시트 제작 후 연결. * feat: TodoList subGoal추가 관련 비동기 수정 mutate 적용 * feat: 스토리북 generation 예외 추가 완성된 도메인 및 영역은 제외시킴. * feat: shared 모노레포 구조에서 react 관련 버전 프로젝트 루트와 일치 shared에서 bottom sheet컴포넌트 제작에 외부 라이브러리 사용할 때, 버전 불일치 생겨서. * feat: check svg 수정 관련 연관 컴포넌트 TodoItem 수정 svg 색상을 외부에서 주입하도록 바꿔서, 기존에 사용하던 TodoItem에서 흰색 주입하도록 했습니다. * feat: TodoBottomSheet 완성 비동기 동작의 책임을 외부에 넘겼습니다. * feat: 데이터 페칭 이후 타입 변환의 책임을 비동기 훅으로 변경 비동기 훅은 도메인 별로 커스텀 가능한 것이기 때문에 변경했습니다. * feat: goal 관련 fetching함수 제작 * feat: TodoBottomSheet 동작 수정 초기값 바뀌는 동작 외부에서 key로 제어하지 않고, 내부에서 useEffect로 제어하도록 변경함. key로 제어하면 remount때문에 애니메이션 이상해서. * feat: todo, goal, subGoal에 대한 fethcing과 쿼리 훅 생성 데이터 처리를 쿼리 훅 내부에서 하도록 수정. mutate는 대부분 낙관적 업데이트로 사용하지 않기 때문에 변환 로직으로 덮어쓰지 않았음. * feat: TodoBottomSheet활성화, 선택된 goal관련 zustand store생성 이들 데이터는 멀리 떨어진 컴포넌트 사이에서 사용되기 때문에 전역 상태 사용함. * feat: msw모킹 위한 api 및 db 생성 * feat: 메인 페이지 goal관련 데이터 갖는 GoalCard 컴포넌트 생성 (진행중) * feat: 메인 페이지에 필요한 컴포넌트 생성 및 수정 MainHeader, GoalMenuContainer (임시) 문구 api연결은 아직 안했고, 컴포넌트 구분만 해뒀습니다. GoalMenuContainer는 선택에 대해 zustand로 전역 상태 처리하도록 수정했습니다. * feat: 메인 페이지 연결을 위한 자잘한 수정 fetchTemplate는 위치 변경으로 인한 수정. GoalMenu는 api연결에 필요한 타입 export TodoItem은 UI가 반응형으로 동작하도록 수정 * feat: TodoList 메인페이지 api연결을 위한 수정 쿼리 훅과 zustand 사용해 동작하도록 수정함. edit버튼 클릭에 대한 동작 추가함. UI반응형으로 동작하도록 w-full로 수정함. * fix: 바텀 시트 todo추가 동작 수정, 바텀시트 선택된 subgoal 버튼에 보이도록 수정 todo추가 동작 수정에 대해서, 기존 분기처리 잘못해 update를 실행하던 것을 create실행하도록 수정 * fix: TodoBottomSheet 상태 초기화 수정 initTodoInfo를 매번 object 새로 생성해 넘겨줘서 useEffect가 동작했음. 이에 컴폰너트 내부에서 분해해서 사용하도록 수정함. * feat: GoalCard 모달이 존재하면 바텀시트 닫도록 수정. 이렇지 않으면 dialog가 rule로 지정된 바텀시트에 focus-trap이 걸림. * feat: useModal 수정 바텀시트 사용할 때 모달의 사용을 알 수 있도록 isOpen을 추가함. * feat: TodoList에서 ModalAddingSubGoal 동작 관련 연결 subgoal을 추가할 수 있도록 api제작 및 연결 * fix: 자잘한 UI 에러 수정 * feat: 페칭 및 훅 자잘한 수정 use client추가 및 타입 수정 * feat: useTodoList undefined도 가능하도록 수정. 사용하는 입장에서 undefined반환 값으로 처리 분기할 수 있도록. * feat: cheer, point 관련 fetching 제작 goalFetching에서 불필요 부분 삭제 * feat: 모킹 구조 변경 및 points, cheer 핸들러 추가 관리하기 쉽도록 분리했습니다. * feat: 불필요 부분 삭제 콘솔 제거 및 element정리 * feat: fetch 동작에서 헤더 설정 수정 get요청에서도 authorization등 적용되도록 수정 * feat: 목표 추가 버튼 제작 모달 클릭 후 페이지 이동은 아직 구현하지 않았습니다. 해당 페이지 구현 마친 후 라우팅 추가하겠습니다. * feat: GoalCard와 useGoalWithSubGoalTodo대해 타입 및 props명 변경에 따른 수정 * feat: BottomTabBar Link추가로 페이지 이동할 수 있도록 함. * feat: main페이지에 BottomTabBar추가에 따른 UI수정 (이전 커밋에서 GoalCard에서 pb추가) TodoBottomSheet는 바텀탭바 존재에 따라 위치 변경 가능하도록 수정. 추가로, 여기서, 기본 subGoal 지정. * feat: main page에서 bottom tab bar관련 불필요 패딩 제거. * feat: 로컬 개발 시 msw사용하도록 수정 발표할 때 필요할 것 같아서. * feat: 시연 전 ui 수정사항 반영 * feat: 스토리북 빌드 에러 수정 컴포넌트들 props변경에 따른 에러 수정. * feat: shared 모노 레포 관련 유틸 함수 처리 shared내부에 동일한 것으로 복제했습니다. * feat: 페이지 이동 관련 수정 onboarding에서 Link를 통해 이동 fetch 시 로컬스토리지에서 access token사용하도록 변경 메인 페이지 수정 * fix: PR 전 정리 BottomTabBar 불필요 key제거 TodoList className정리, scroll 되도록 수정, 불필요 낙관적 업데이트 제거 * feat: AppBar 상단 고정 및 관련해 z-index 수정 AppBar보다 BottomSheet와 Modal이 z-index 높도록 수정 * feat: 메인페이지 bottom tab bar추가 및 bottom sheet와 함께 모바일 넓이에 맞게 조정 body자체를 scrollbar에 의해 layout shift발생하지 않게 수정하고, bottom sheet에도 적용했습니다. component/shared 패키지 버전 수정에 따른 lock파일 변경이 추가로 있습니다. bottom tabbar의 fixed로 인해 modal과의 z-index차이를 조정했습니다. 상단 AppBar관련해서 배너 상단에 공간을 만들어 ui겹침을 제거했습니다. * fix: TodoBottomSheet 버그 수정 엔터로 입력하면 높이 이상해지는 버그 수정했습니다. focus관련한 버그여서 blur처리로 수정했습니다. * fix: fetching 반환값 반환하도록 해서 이후 동작 연결되도록 수정 반환값을 보고 결과를 판단하도록 로직을 짰는데, 반환하지 않아서 제대로 작동하지 않았었습니당. * feat: dev서버 배포 전 프록시 및 msw수정 주소 동적 연결되게 수정 및 msw 주석처리. 이외 자잘한 오류 정리
목표 추가는 상세 페이지 쪽과 연결되어 있어서,
상세 페이지 제작하며 추가할 생각입니다.
컴포넌트 변경
Summary by CodeRabbit
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Chores
Tests
Refactor
Style