-
Notifications
You must be signed in to change notification settings - Fork 2
✨ feat: 사이드바 대시보드 생성 모달 구현 #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
""" Walkthrough대시보드 생성 모달 기능이 추가되었습니다. Zustand를 활용한 모달 상태 관리, 대시보드 생성 API 연동, 컬러 선택 기능이 구현되었으며, 사이드바 및 테스트 페이지에서 모달을 열 수 있도록 통합되었습니다. 새로운 CSS 유틸리티 클래스도 추가되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Sidebar
participant useModalStore
participant CreateDashboardModal
participant API
participant Router
User->>Sidebar: "대시보드 생성" 버튼 클릭
Sidebar->>useModalStore: openCreateDashboardModal()
useModalStore-->>CreateDashboardModal: createDashboardModalOpen = true
User->>CreateDashboardModal: 폼 입력 및 색상 선택
User->>CreateDashboardModal: "생성" 버튼 클릭
CreateDashboardModal->>API: POST /dashboard (title, color)
API-->>CreateDashboardModal: 생성된 대시보드 정보 반환
CreateDashboardModal->>Router: 상세 페이지로 이동
CreateDashboardModal->>useModalStore: closeCreateDashboardModal()
Possibly related issues
Possibly related PRs
Suggested reviewers
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! 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
🪧 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (9)
src/app/globals.css (1)
25-27:.BG-violet유틸리티의 변형(hover‧dark) 누락
다른 색상 유틸(예:.BG-blue)과 달리 hover·dark 변형이 없어 UI 일관성이 깨질 수 있습니다.-.BG-violet { - @apply bg-[#228DFF]; -} +.BG-violet { + @apply bg-[#228DFF] hover:bg-[#2172C9] dark:bg-[#228DFF] dark:hover:bg-[#2172C9]; +}src/app/shared/types/dashboard.ts (1)
35-41: 도메인 타입 파일에 UI 상태 타입이 혼재됨
ModalState는 모달 UI 전용 상태로 도메인 모델과 무관합니다.
스토어 정의 파일(useModalStore.ts) 혹은 별도uiStates.ts로 분리하면 타입 레이어가 깔끔해집니다.src/app/shared/components/common/sidebar/Sidebar.tsx (1)
7-16:handleCreateDashboard중간 래퍼 함수 불필요
openCreateDashboardModal을 그대로 전달하면 불필요한 함수 생성이 사라져 재렌더 횟수를 줄일 수 있습니다.-import { useModalStore } from '@/app/shared/store/useModalStore' +import { useModalStore } from '@/app/shared/store/useModalStore' ... - const { openCreateDashboardModal } = useModalStore() + const { openCreateDashboardModal } = useModalStore() ... - const handleCreateDashboard = () => { - openCreateDashboardModal() - }그리고 아래 JSX:
-<CreateDashboardButton onClick={handleCreateDashboard} /> +<CreateDashboardButton onClick={openCreateDashboardModal} />src/app/tester/page.tsx (1)
8-10: 상대경로 대신 alias 사용 권장
프로젝트 전역에서 alias(@/app/...)를 사용하고 있으므로 통일성을 위해 해당 import도 alias로 바꾸면 가독성이 좋아집니다.-import CreateDashboardModal from '../shared/components/common/sidebar/modal/CreateDashboardModal' -import { useModalStore } from '../shared/store/useModalStore' +import CreateDashboardModal from '@/app/shared/components/common/sidebar/modal/CreateDashboardModal' +import { useModalStore } from '@/app/shared/store/useModalStore'src/app/shared/store/useModalStore.ts (1)
3-3: 경로 표현 방식 통일 제안
다른 파일들(CreateDashboardModal.tsx등)은@/app/shared/...절대 경로 alias를 사용하고 있는데, 이곳만 상대 경로(../types/dashboard)를 사용하고 있습니다. 경로 스타일을 통일하면 리팩터링 시 유지보수가 수월합니다.-import { ModalState } from '../types/dashboard' +import { ModalState } from '@/app/shared/types/dashboard'src/app/shared/components/common/sidebar/modal/CreateDashboardModal.tsx (4)
15-17: Zustand selector + shallow 비교로 불필요한 리렌더링 최소화
스토어에서 필요한 두 값만 선택해도, selector 없이 전체 스토어를 구독하면 다른 modal 관련 상태가 추가될 때마다 모달 컴포넌트가 리렌더링됩니다. selector +shallow를 사용해 의도치 않은 렌더링을 막을 수 있습니다.-import { useModalStore } from '@/app/shared/store/useModalStore' +import { useModalStore } from '@/app/shared/store/useModalStore' +import { shallow } from 'zustand/shallow' -const { createDashboardModalOpen, closeCreateDashboardModal } = - useModalStore() +const { createDashboardModalOpen, closeCreateDashboardModal } = + useModalStore( + (state) => ({ + createDashboardModalOpen: state.createDashboardModalOpen, + closeCreateDashboardModal: state.closeCreateDashboardModal, + }), + shallow, + )
45-47: 에러 처리 향상
현재는 콘솔 로그만 남기고 사용자에게 아무 피드백이 없습니다. 토스트/알림 컴포넌트를 통해 실패 이유를 안내해 주세요. 예: 네트워크 오류, 중복 이름 등.-} catch (error) { - console.error('대시보드 생성 오류:', error) +} catch (error) { + console.error('대시보드 생성 오류:', error) + // TODO: 토스트 라이브러리로 사용자에게 에러 메시지 표시 }
76-78: 접근성(Accessibility) 속성 추가 권장
모달 백드롭에role="dialog"·aria-modal="true"·aria-labelledby등을 지정하면 스크린 리더 사용자가 현재 포커스가 모달임을 인지할 수 있습니다.-<div - className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50" - onClick={handleBackdropClick} -> +<div + role="dialog" + aria-modal="true" + aria-labelledby="create-dashboard-title" + className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50" + onClick={handleBackdropClick} +>
114-122: 체크 아이콘 컨테이너에flex클래스 누락
items-center justify-center만으로는 정렬이 적용되지 않습니다.flex를 추가해 정확히 중앙에 배치하세요.-<div className="relative size-24 items-center justify-center"> +<div className="relative size-24 flex items-center justify-center">
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
public/images/check.svgis excluded by!**/*.svg
📒 Files selected for processing (7)
src/app/globals.css(1 hunks)src/app/shared/components/common/sidebar/Sidebar.tsx(2 hunks)src/app/shared/components/common/sidebar/modal/CreateDashboardModal.tsx(1 hunks)src/app/shared/lib/axios.ts(1 hunks)src/app/shared/store/useModalStore.ts(1 hunks)src/app/shared/types/dashboard.ts(1 hunks)src/app/tester/page.tsx(3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
src/app/tester/page.tsx (2)
src/app/shared/store/useModalStore.ts (1)
useModalStore(5-14)src/app/shared/components/common/sidebar/modal/CreateDashboardModal.tsx (1)
CreateDashboardModal(13-154)
src/app/shared/components/common/sidebar/Sidebar.tsx (1)
src/app/shared/store/useModalStore.ts (1)
useModalStore(5-14)
src/app/shared/store/useModalStore.ts (1)
src/app/shared/types/dashboard.ts (1)
ModalState(37-41)
src/app/shared/components/common/sidebar/modal/CreateDashboardModal.tsx (2)
src/app/shared/store/useModalStore.ts (1)
useModalStore(5-14)src/app/shared/types/dashboard.ts (1)
CreateDashboardRequest(31-34)
🔇 Additional comments (2)
src/app/shared/lib/axios.ts (1)
2-4: 기능 영향 없는 import 순서 변경, OK
실제 로직에는 변화가 없으며 사이드 이펙트도 없습니다. 그대로 두셔도 무방합니다.src/app/shared/store/useModalStore.ts (1)
5-14: Zustand 스토어 구현은 명확하며 기능적으로 문제 없습니다.
현재 요구사항을 충족하며 타입도 올바르게 지정돼 있습니다. 👍
dkslel1225
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
모달 구현 수고하셨습니다!
모달 open/close 상태를 Zustand로 전역 관리하셨는데,
useState가 아닌, Zustand를 사용하신 이유가 궁금합니당
|
|
||
| // 모달 외부 클릭 시 닫기 | ||
| const handleBackdropClick = (e: React.MouseEvent<HTMLDivElement>) => { | ||
| if (e.target === e.currentTarget) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
e.target이랑 e.currentTarget이 각각 뭘 가리키고 있는건가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Zustand를 사용한 이유는 모달 관련 로직을 한곳에서 관리하기 쉽다고 생각했고, 추후에 다른 모달(컬럼 모달)도 비슷한 패턴으로 추가하기 쉽다고 판단해서 사용했습니다.
현재 구조에서 Sidebar와 CreateDashboardModal이 각각 독립적으로 useModalStore를 사용해서 상태를 공유하고 있는데, 이렇게 이용하면 컴포넌트 간 결합도를 낮출 수 있기 때문입니다. 만약 useState를 사용했다면 상위 컴포넌트에서 모달 상태를 관리하고 props로 전달해서 사용했었어야 했습니다.
e.target은 실제로 클릭된 요소(이벤트가 발생한 요소)이고,
e.currentTarget은 이벤트 리스너가 등록된 요소(해당 코드에서는 모달 백드롭 div)를 가리킵니다.
모달 외부/배경 클릭 시 e.target === e.currentTarget (백드롭 자체 클릭) -> 모달이 닫힘.
모달 내부 클릭 시 e.target !== e.currentTarget (자식 요소 클릭, 이벤트 버블링) -> 모달 유지
이 방식으로 모달 외부 클릭 시에만 모달을 닫고, 모달 내부 클릭 시에는 닫히지 않도록 구현했습니다.
yuj2n
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
찬호님 모달 구현 수고 많으셨습니당~!!
| import { create } from 'zustand' | ||
|
|
||
| import { ModalState } from '../types/dashboard' | ||
|
|
||
| export const useModalStore = create<ModalState>((set) => ({ | ||
| // 초기 상태 | ||
| createDashboardModalOpen: false, | ||
|
|
||
| // 모달 열기 | ||
| openCreateDashboardModal: () => set({ createDashboardModalOpen: true }), | ||
|
|
||
| // 모달 닫기 | ||
| closeCreateDashboardModal: () => set({ createDashboardModalOpen: false }), | ||
| })) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Zustand로 모달 상태 관리 해주셨군용!!
참고해서 공통 모달 컴포넌트 작성해보도록 하겠습니다~
Insung-Jo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
생성 모달 구현 수고 많으셨습니다!! 저도 글로벌 스타일에 새로 작성한 게 있어서 충돌이 일어났었는데 그 부분은 해결 했습니다~
📌 변경 사항 개요
사이드바에 대시보드 생성 모달 기능을 구현하였고, API 연동까지 완료했습니다.
✨ 요약
/dashboardsAPI 연동📝 상세 내용
1. 모달 상태관리(
useModalSotre.ts)createDashbaordModalOpen상태와 열기/닫기 액션2. 타입 정의(
dashboard.ts)CreateDashboardRequest타입 추가(title, color 필드)ModalState인터페이스 추가3. 사이드바 컴포넌트 업데이트(
Sidebar.tsx)useMdoalStore훅 연동으로 모달 열기4. 대시보드 생성 모달(
CreateDashboardModal.tsx)check.svg아이콘으로 선택 상태 표시)/dashbaordsAPI 연동/dashboard/{id}로 이동🔗 관련 이슈
#49
🖼️ 스크린샷
✅ 체크리스트
💡 참고 사항
Summary by CodeRabbit
신규 기능
스타일