Feat: 템플릿 공용 대시보드 구현 - #18
Merged
Merged
Conversation
There was a problem hiding this comment.
Actionable comments posted: 13
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/workspaces/`[workspaceId]/dashboard/page.tsx:
- Around line 4-22: The DashboardPage route still hardcodes
purpose="side-project" even though getWorkspace has been introduced, so wire
DashboardPage to fetch the workspace via getWorkspace(workspaceId) and pass its
purpose into DashboardView instead of the fixed value. Use the existing symbols
getWorkspace, DashboardPage, and DashboardView to locate the change, and keep
the current fallback behavior only if the workspace purpose cannot be resolved.
In `@src/entities/side-project/backlog-item/model/backlog-item.ts`:
- Around line 11-15: `BacklogItem` lacks a stable unique identifier, so items
are currently identified by `title` alone and can cause React key collisions in
downstream usage like `Backlog.tsx`. Add an `id` field to the `BacklogItem`
interface and propagate it through the data model and any mock/backing data
creation so each item has a unique identifier. Then update the list rendering
logic that uses `item.title` as the key to use the new `id` from `BacklogItem`
instead.
In `@src/features/dashboard/edit-layout/ui/DashboardEditToggle.tsx`:
- Around line 19-24: In DashboardEditToggle, the editing state styles mix
hardcoded hex colors with theme tokens; replace the `bg-[`#4f39f6`]` and
`hover:bg-[`#4530d9`]` classes with the appropriate brand/theme token equivalents
used elsewhere in the same `cn(...)` block so all toggle variants stay
consistent and centrally controllable.
In `@src/shared/dashboard/lib/widget-size.ts`:
- Around line 8-13: The threshold values in getWidgetSize are hardcoded magic
numbers, so extract them into named constants to make the sizing logic easier to
read and maintain. Update the wLevel and hLevel calculations in getWidgetSize to
use descriptive constants such as SM_MAX_W, MD_MAX_W, SM_MAX_H, and MD_MAX_H,
keeping the existing behavior unchanged.
In `@src/views/dashboard/ui/DashboardGrid.tsx`:
- Around line 18-26: `DashboardGrid`에서 별도로 정의한 `useIsClient`는
`useContainerWidth()`가 이미 제공하는 `mounted`와 중복되는 SSR 게이팅입니다. `useIsClient`와 그
`useSyncExternalStore` 사용을 제거하고, `DashboardGrid` 내부의 렌더 조건과 `mounted` 기반 로직을
`useContainerWidth`의 `mounted`로 직접 대체하세요. 특히 `isClient && width > 0` 형태의 분기들은 모두
`mounted && width > 0`로 바꾸고, 관련된 중복 조건도 함께 정리해 주세요.
- Around line 93-116: 편집 모드의 이동/삭제 컨트롤이 hover에만 의존해 키보드 접근성이 깨져 있습니다.
DashboardGrid의 editMode 블록에서 드래그 핸들, 크기 뱃지, 삭제 버튼이 포커스 시에도 노출되도록
focus/focus-within 또는 focus-visible 상태를 추가하고, 특히 삭제 버튼(onRemove)과 이동
핸들(GripVertical)이 탭 이동 시 보이게 수정하세요. 현재의 group-hover 전용 노출을 유지하되 키보드 포커스에서도 동일하게
표시되도록 클래스와 상태 처리를 보완하면 됩니다.
In `@src/widgets/side-project/dashboard-backlog/ui/Backlog.tsx`:
- Around line 12-28: The sm view in Backlog assumes mockBacklog always has at
least one item, so destructuring into top and immediately reading
top.priority/top.title can crash on an empty array. Update Backlog to guard the
empty state before rendering the small-size branch, and render a safe fallback
when mockBacklog has no items; keep the same pattern in the sm branches of
RecentNotes and TodaySchedule if they use the same destructuring approach.
In `@src/widgets/side-project/dashboard-calendar/ui/Calendar.tsx`:
- Around line 50-89: The Calendar component is hardcoding the same
weekday/today/event colors in multiple places, so extract those repeated values
into shared constants or theme tokens. Update the Calendar UI logic that renders
WEEKDAYS, the day cell span, and the event dot to reference named color symbols
instead of inline hex strings, similar to how SCHEDULE_TYPE_COLOR centralizes
styling elsewhere. This keeps the styling consistent and makes future color
changes easier.
In `@src/widgets/side-project/dashboard-my-tasks/ui/MyTasks.tsx`:
- Around line 30-48: The task list in MyTasks uses task.title as the React key,
which can break reconciliation when titles are duplicated. Add a stable unique
id field to the Task model used by mockTasks, update the data shape accordingly,
and change the li key in the MyTasks map to task.id so each item is identified
reliably.
In `@src/widgets/side-project/dashboard-recent-notes/ui/RecentNotes.tsx`:
- Around line 16-27: In RecentNotes, the sm-size render path assumes
mockMeetingNotes[0] always exists, which can make latest undefined and crash
when accessing latest.title. Update the RecentNotes component to guard the
empty-array case before rendering the small widget, using the
latest/mockMeetingNotes access in the size === 'sm' branch and falling back to a
safe empty state or alternate content when there is no note available.
- Around line 35-46: `RecentNotes`에서 `mockMeetingNotes.map`의 list key가
`note.title`이라 중복될 수 있으니, `MeetingNote`에 안정적인 `id`를 추가하고 그 값을 key로 사용하도록 수정하세요.
`MeetingNote` 타입/데이터 정의와 `RecentNotes.tsx`의 렌더링을 함께 업데이트해 동일한 제목이 있어도 항목이 올바르게
구분되게 하세요.
In `@src/widgets/side-project/dashboard-sprint-summary/ui/SprintSummary.tsx`:
- Line 6: The destructuring in SprintSummary is order-dependent and can map the
wrong values if sprintStats changes shape. Update SprintSummary to stop using
positional assignment for planned/done/remaining and instead derive each value
by looking up the matching item by id from sprintStats before rendering. Use the
existing SprintSummary component and sprintStats data access points to make the
mapping explicit and resilient to reordering.
In `@src/widgets/side-project/dashboard-today-schedule/ui/TodaySchedule.tsx`:
- Around line 14-35: The sm-sized branch in TodaySchedule’s rendering assumes
mockTodaySchedule always has at least one item, so destructuring next from an
empty array can crash when accessing next.type, next.title, or next.time. Add a
defensive empty-state guard before using next, and render a safe fallback or
skip the “다음 일정” UI when there are no items; apply the same protection pattern
used in RecentNotes.tsx to keep the component resilient.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 1671fb55-056c-4cdd-b17b-c9b0e5bfa3d1
📒 Files selected for processing (51)
.gitignoresrc/app/workspaces/[workspaceId]/dashboard/page.tsxsrc/entities/dashboard-layout/api/get-dashboard-layout.tssrc/entities/dashboard-layout/api/save-dashboard-layout.tssrc/entities/dashboard-layout/index.tssrc/entities/dashboard-layout/model/dashboard-layout.types.tssrc/entities/side-project/backlog-item/index.tssrc/entities/side-project/backlog-item/model/backlog-item.tssrc/entities/side-project/meeting-note/index.tssrc/entities/side-project/meeting-note/model/meeting-note.tssrc/entities/side-project/schedule-event/index.tssrc/entities/side-project/schedule-event/model/schedule-event.tssrc/entities/side-project/sprint/index.tssrc/entities/side-project/sprint/model/sprint.tssrc/entities/side-project/task/index.tssrc/entities/side-project/task/model/task.tssrc/entities/work-schedule/lib/count-schedules-by-weekday.tssrc/entities/work-schedule/lib/get-work-members-by-weekday.tssrc/entities/workspace/api/get-workspace.tssrc/entities/workspace/index.tssrc/features/dashboard/edit-layout/index.tssrc/features/dashboard/edit-layout/model/useDashboardLayout.tssrc/features/dashboard/edit-layout/ui/DashboardEditToggle.tsxsrc/features/dashboard/edit-layout/ui/EditModeBanner.tsxsrc/features/manage-work-schedule/model/use-work-schedule-state.tssrc/features/manage-work-schedule/ui/WorkShiftSettingsPanel.tsxsrc/shared/dashboard/lib/widget-size.tssrc/shared/dashboard/model/template.tssrc/shared/dashboard/model/widget.tssrc/shared/dashboard/ui/stat-card.tsxsrc/shared/dashboard/ui/widget-card.tsxsrc/views/dashboard/config/template-widgets.tssrc/views/dashboard/config/widget-catalog.tsxsrc/views/dashboard/index.tssrc/views/dashboard/ui/AddWidgetBar.tsxsrc/views/dashboard/ui/DashboardGrid.tsxsrc/views/dashboard/ui/DashboardView.tsxsrc/widgets/side-project/dashboard-backlog/index.tssrc/widgets/side-project/dashboard-backlog/ui/Backlog.tsxsrc/widgets/side-project/dashboard-calendar/index.tssrc/widgets/side-project/dashboard-calendar/ui/Calendar.tsxsrc/widgets/side-project/dashboard-my-tasks/index.tssrc/widgets/side-project/dashboard-my-tasks/ui/MyTasks.tsxsrc/widgets/side-project/dashboard-recent-notes/index.tssrc/widgets/side-project/dashboard-recent-notes/ui/RecentNotes.tsxsrc/widgets/side-project/dashboard-sprint-summary/index.tssrc/widgets/side-project/dashboard-sprint-summary/ui/SprintSummary.tsxsrc/widgets/side-project/dashboard-today-schedule/index.tssrc/widgets/side-project/dashboard-today-schedule/ui/TodaySchedule.tsxsrc/widgets/side-project/dashboard-velocity/index.tssrc/widgets/side-project/dashboard-velocity/ui/Velocity.tsx
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/workspaces/`[workspaceId]/dashboard/page.tsx:
- Line 19: The stale TODO comment in the dashboard page is no longer accurate
now that `workspace.purpose` is being used. Remove or rewrite the comment in
`page.tsx` near the workspace purpose logic so it matches the current
implementation and does not mention the old hardcoded side-project behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: e75e2ffa-e402-4228-b628-c96e68e2c1a1
📒 Files selected for processing (22)
src/app/workspaces/[workspaceId]/dashboard/page.tsxsrc/entities/side-project/backlog-item/index.tssrc/entities/side-project/backlog-item/model/backlog-item.mock.tssrc/entities/side-project/backlog-item/model/backlog-item.types.tssrc/entities/side-project/meeting-note/index.tssrc/entities/side-project/meeting-note/model/meeting-note.mock.tssrc/entities/side-project/meeting-note/model/meeting-note.types.tssrc/entities/side-project/schedule-event/index.tssrc/entities/side-project/schedule-event/model/schedule-event.mock.tssrc/entities/side-project/schedule-event/model/schedule-event.types.tssrc/entities/side-project/sprint/index.tssrc/entities/side-project/sprint/model/sprint.mock.tssrc/entities/side-project/sprint/model/sprint.types.tssrc/entities/side-project/task/index.tssrc/entities/side-project/task/model/task.mock.tssrc/entities/side-project/task/model/task.types.tssrc/shared/dashboard/model/template.types.tssrc/shared/dashboard/model/widget.types.tssrc/views/dashboard/config/template-widgets.tssrc/views/dashboard/config/widget-catalog.tsxsrc/views/dashboard/ui/DashboardGrid.tsxsrc/views/dashboard/ui/DashboardView.tsx
💤 Files with no reviewable changes (2)
- src/shared/dashboard/model/widget.types.ts
- src/shared/dashboard/model/template.types.ts
This was referenced Jul 9, 2026
Merged
Merged
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request
작업 내용
WIDGET_CATALOG) + 템플릿별 추가 가능 위젯 목록(TEMPLATE_WIDGETS) 구조.WidgetId를 카탈로그에서 파생해 타입으로 강제작업 결과
/workspaces/[workspaceId]/dashboard에서 대시보드 렌더tsc --noEmit·eslint통과설계 요약 (위젯 id로 데이터/UI 분리)
WIDGET_CATALOG(코드)WORKSPACE_LAYOUTS.layoutTEMPLATE_WIDGETS(코드)변경 사항
Added
src/shared/dashboard/—lib/widget-size,model/template(WorkspacePurpose),model/widget(WidgetDefinition),ui/widget-card·ui/stat-cardsrc/entities/dashboard-layout/—model/dashboard-layout.types(DashboardLayoutState),api/get-dashboard-layout(조회),api/save-dashboard-layout(저장, 'use server')src/features/dashboard/edit-layout/—useDashboardLayout훅(배치 상태·추가/삭제·저장),EditModeBanner·DashboardEditTogglesrc/views/dashboard/—config/widget-catalog(WIDGET_CATALOG + WidgetId),config/template-widgets(TEMPLATE_WIDGETS),ui/DashboardView·DashboardGrid·AddWidgetBarsrc/app/workspaces/[workspaceId]/dashboard/page.tsx— RSC에서 레이아웃 조회 → 뷰 주입Changed
@/shared/dashboard/ui,@/shared/dashboard/lib/widget-size)을 사용하도록 정리initialLayout으로 주입 (마운트 재조회/깜빡임 제거)Fixed
구성
데이터 흐름 (읽기=RSC / 쓰기=서버액션):
동작
saveDashboardLayout(서버액션)로 유저별 저장 → 다음 방문 때 복원.getWidgetSize).팀원 사용 가이드
건드리는 파일은 카탈로그 + 템플릿 목록이 중심. 엔진/훅/영속화는 수정 불필요.
① 기존 템플릿의 위젯 구성 변경
src/views/dashboard/config/template-widgets.ts의 해당purpose배열만 수정.② 새 위젯 추가 (엔티티(데이터) → 위젯 → 등록 순서)
src/entities/<슬라이스>/<이름>/model/<이름>.ts: 타입 + mock 데이터 (추후 API/DB로 교체할 자리)index.ts: Public API exportsrc/widgets/<슬라이스>/dashboard-<이름>/ui/<Component>.tsx:@/entities/<슬라이스>/<이름>에서 데이터 가져와 렌더 (필요 시sizeprop, 공용 UI는@/shared/dashboard/ui)index.ts: 컴포넌트 exportsrc/views/dashboard/config/widget-catalog.tsx에{ layout, title, render }추가 →WidgetId에 자동 포함src/views/dashboard/config/template-widgets.ts의 노출할purpose배열에 id 추가실행화면
테스트
tsc/eslint통과, 브라우저 동작 확인 필요리뷰 체크리스트
feature/*->develop, 배포 시develop또는release/*->main)Type/#issue-number/description형식을 따릅니다.console.log, 주석, 임시 코드를 제거했습니다.tsc --noEmit·eslint통과)리뷰 요청사항
initialLayout주입 방식특이사항
후속 작업 (TODO)
getDashboardLayout/saveDashboardLayout/getWorkspaceSupabase 연동 (+ 세션user_id, 저장 debounce)purpose하드코딩 →getWorkspace().purpose관련 이슈
Closes #9
Summary by CodeRabbit
.gitignore에CLAUDE.md무시 항목을 추가했습니다.