Skip to content

Feat: 템플릿 공용 대시보드 구현 - #18

Merged
Kwon812 merged 48 commits into
developfrom
feat/#9/side-project-dashboard
Jul 8, 2026
Merged

Feat: 템플릿 공용 대시보드 구현#18
Kwon812 merged 48 commits into
developfrom
feat/#9/side-project-dashboard

Conversation

@Kwon812

@Kwon812 Kwon812 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Pull Request

작업 내용

  • 워크스페이스 용도(purpose)에 따라 대시보드 위젯 구성이 달라지는 템플릿 공용 대시보드 구현
  • 위젯 id로 데이터(위치)와 UI(렌더)를 분리 — DB엔 개인별 위치만, 위젯 설정(렌더·제약)은 코드가 소유
  • 단일 위젯 카탈로그(WIDGET_CATALOG) + 템플릿별 추가 가능 위젯 목록(TEMPLATE_WIDGETS) 구조. WidgetId를 카탈로그에서 파생해 타입으로 강제
  • 개인별 레이아웃 조회/저장 (읽기: RSC, 쓰기: 서버액션) — 현재 mock/stub, DB 연동은 후속
  • 편집 모드에서 위젯 추가/삭제/드래그/리사이즈, 빈 상태로 시작

작업 결과

  • 라우트 /workspaces/[workspaceId]/dashboard 에서 대시보드 렌더
  • 저장분이 없으면 빈 상태로 시작 → 편집 모드에서 템플릿이 허용하는 위젯만 추가 가능 → 배치가 개인별로 저장/복원
  • 위젯 크기(sm/md/lg)에 따른 밀도 변형 렌더
  • tsc --noEmit·eslint 통과

설계 요약 (위젯 id로 데이터/UI 분리)

저장 데이터            id            카탈로그(코드)
{ i:'my-tasks',  ──▶ 'my-tasks' ◀── { render:<MyTasks/>, minW, minH, title }
  x, y, w, h }
   "어디에"                              "어떻게"
        \______________ id로 매칭 ______________/
관심사 소유 저장(DB)
렌더 + 제약(minW/minH) + 기본배치 + 표시명 WIDGET_CATALOG (코드)
위치 (i, x, y, w, h) 유저 WORKSPACE_LAYOUTS.layout
템플릿별 추가 가능 위젯 TEMPLATE_WIDGETS (코드)
  • 저장은 위치만, 제약은 렌더 시 카탈로그에서 머지 → 카탈로그 제약 변경이 기존 유저에게도 반영, DB에 위젯 설정 중복 없음.

변경 사항

Added

  • src/shared/dashboard/lib/widget-size, model/template(WorkspacePurpose), model/widget(WidgetDefinition), ui/widget-card·ui/stat-card
  • src/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·DashboardEditToggle
  • src/views/dashboard/config/widget-catalog(WIDGET_CATALOG + WidgetId), config/template-widgets(TEMPLATE_WIDGETS), ui/DashboardView·DashboardGrid·AddWidgetBar
  • src/app/workspaces/[workspaceId]/dashboard/page.tsx — RSC에서 레이아웃 조회 → 뷰 주입

Changed

  • 대시보드 위젯 컴포넌트가 공용 자원(@/shared/dashboard/ui, @/shared/dashboard/lib/widget-size)을 사용하도록 정리
  • 레이아웃 조회를 클라이언트 훅 → RSC(페이지)에서 수행하고 initialLayout으로 주입 (마운트 재조회/깜빡임 제거)

Fixed

  • 해당 없음 (신규 기능)

구성

shared/dashboard/
  lib/widget-size.ts            WidgetSize, getWidgetSize
  model/template.ts             WorkspacePurpose
  model/widget.ts               WidgetDefinition (layout + title + render)
  ui/widget-card.tsx            위젯 공용 UI
  ui/stat-card.tsx

entities/dashboard-layout/
  model/dashboard-layout.types.ts   DashboardLayoutState { layout }
  api/get-dashboard-layout.ts       getDashboardLayout   (조회, RSC에서 호출)
  api/save-dashboard-layout.ts      saveDashboardLayout  (저장, 'use server')

features/dashboard/edit-layout/
  model/useDashboardLayout.ts       배치 상태(initialLayout seed) + 추가/삭제 + 저장(위치만)
  ui/EditModeBanner.tsx, ui/DashboardEditToggle.tsx

views/dashboard/
  config/widget-catalog.tsx         WIDGET_CATALOG(id 키) + WidgetId 파생
  config/template-widgets.ts        TEMPLATE_WIDGETS: purpose → WidgetId[]
  ui/DashboardView.tsx              엔진: purpose로 스코프 + id 조인 렌더
  ui/DashboardGrid.tsx, ui/AddWidgetBar.tsx

app/workspaces/[workspaceId]/dashboard/page.tsx   RSC에서 레이아웃 조회 → DashboardView 주입

데이터 흐름 (읽기=RSC / 쓰기=서버액션):

page(RSC): initialLayout = await getDashboardLayout(workspaceId, 'dashboard')   # 서버에서 읽기
  → <DashboardView key={workspaceId} purpose workspaceId initialLayout />
       ├ useDashboardLayout(...)     # initialLayout으로 시작, 변경 시 saveDashboardLayout (서버액션)
       ├ TEMPLATE_WIDGETS[purpose]   # 이 템플릿이 허용하는 위젯 (추가 메뉴 스코프)
       └ WIDGET_CATALOG[id]          # id로 렌더 조인

동작

  • 레이아웃을 서버(RSC)에서 조회해 주입 → 첫 렌더에 이미 데이터가 있어 마운트 후 재조회/깜빡임 없음.
  • 저장분이 없으면 빈 상태로 시작하고, 편집 모드에서 템플릿이 허용하는 위젯을 추가해 구성.
  • 배치(드래그/리사이즈)·추가/삭제는 saveDashboardLayout(서버액션)로 유저별 저장 → 다음 방문 때 복원.
  • 위젯 크기에 따라 sm/md/lg 밀도 변형 렌더(getWidgetSize).

팀원 사용 가이드

건드리는 파일은 카탈로그 + 템플릿 목록이 중심. 엔진/훅/영속화는 수정 불필요.

① 기존 템플릿의 위젯 구성 변경

  • src/views/dashboard/config/template-widgets.ts 의 해당 purpose 배열만 수정.

② 새 위젯 추가 (엔티티(데이터) → 위젯 → 등록 순서)

왜 데이터 엔티티부터 만드나?
위젯(UI)은 "어떻게 보이는지"만 담당하고, 데이터(타입 + 소스)는 하위 레이어인 엔티티가 소유합니다. 이렇게 분리하면 —

  • mock → 실제 API/DB 교체 시 위젯 코드는 그대로, 엔티티만 바꾸면 됨
  • 같은 데이터를 여러 위젯/화면이 공유 (예: taskMyTasks·Backlog가 함께 사용)
  • FSD 레이어 방향(shared ← entities ← features ← widgets ← views) 유지 — 위젯이 데이터를 인라인하면 방향이 깨지고 재사용·테스트가 어려워짐
  1. 데이터 엔티티src/entities/<슬라이스>/<이름>/
    • model/<이름>.ts : 타입 + mock 데이터 (추후 API/DB로 교체할 자리)
    • index.ts : Public API export
  2. 위젯 컴포넌트src/widgets/<슬라이스>/dashboard-<이름>/
    • ui/<Component>.tsx : @/entities/<슬라이스>/<이름>에서 데이터 가져와 렌더 (필요 시 size prop, 공용 UI는 @/shared/dashboard/ui)
    • index.ts : 컴포넌트 export
  3. 카탈로그 등록src/views/dashboard/config/widget-catalog.tsx{ layout, title, render } 추가 → WidgetId에 자동 포함
  4. 템플릿 연결src/views/dashboard/config/template-widgets.ts 의 노출할 purpose 배열에 id 추가

실행화면

스크린샷 2026-07-07 오후 5 11 18 스크린샷 2026-07-07 오후 5 11 27 스크린샷 2026-07-07 오후 5 12 05

테스트

  • 로컬 실행 확인 — tsc/eslint 통과, 브라우저 동작 확인 필요
  • 주요 시나리오 확인 — 빈 시작 → 위젯 추가 → 드래그/리사이즈/삭제 → 저장분 복원
  • 영향 범위 확인 — 대시보드 슬라이스 신규 추가, 기존 위젯/엔티티 컴포넌트 로직 변경 없음(import 경로만)

리뷰 체크리스트

  • PR base branch가 올바릅니다. (feature/* -> develop, 배포 시 develop 또는 release/* -> main)
  • 브랜치명이 Type/#issue-number/description 형식을 따릅니다.
  • 커밋 메시지가 컨벤션을 따릅니다.
  • 불필요한 console.log, 주석, 임시 코드를 제거했습니다.
  • 타입 에러와 린트 에러를 확인했습니다. (tsc --noEmit·eslint 통과)
  • CodeRabbit 1차 리뷰를 확인했습니다.
  • CodeRabbit 리뷰 반영 후 Discord에 공유했습니다.
  • 최소 1명 이상의 approve 후 merge합니다.

의도된 임시 코드 (후속 PR에서 제거/교체)

  • get-dashboard-layout.ts: mock 저장 레이아웃 반환 (DB select 대체 예정)
  • save-dashboard-layout.ts: no-op stub (DB upsert 대체 예정)
  • page.tsx: purpose="side-project" 하드코딩 (db연동시 getWorkspace().purpose로 교체 예정)

리뷰 요청사항

  • 위젯 id로 데이터/UI를 분리한 설계가 합리적인지 (DB=위치, 코드=렌더/제약, id 조인)
  • 읽기(RSC)/쓰기(서버액션) 경계initialLayout 주입 방식
  • 임시 코드(mock/stub/하드코딩) 는 인지된 상태이며 후속 DB 연동 PR에서 정리 예정

특이사항

  • 템플릿 별 겹치는 엔티티, 위젯들을 공통으로 안빼고 각 구조 내 side-project폴더안에 넣어두었습니다.( 겹침방지) 추 후 확인하면서 같이 맞추면 될 것 같습니다

후속 작업 (TODO)

  • getDashboardLayout/saveDashboardLayout/getWorkspace Supabase 연동 (+ 세션 user_id, 저장 debounce)
  • 페이지 purpose 하드코딩 → getWorkspace().purpose

관련 이슈

Closes #9

Summary by CodeRabbit

  • New Features
    • 대시보드 편집 모드가 추가되어 위젯 추가/이동/크기 조절/삭제와 레이아웃 저장 흐름을 제공합니다.
    • 템플릿별 위젯 범위 및 위젯 카탈로그를 도입해 목적에 맞는 구성을 선택할 수 있습니다.
    • 백로그, 오늘 일정, 최근 회의록, 스프린트 요약, 진행 속도, 내 작업, 캘린더 위젯을 새로 제공합니다.
  • Bug Fixes
    • 위젯 크기 산정 및 그리드 렌더링 타이밍 개선으로 화면 불일치를 줄였습니다.
  • Chores
    • 문서 제외를 위해 .gitignoreCLAUDE.md 무시 항목을 추가했습니다.

Kwon812 added 30 commits July 6, 2026 16:23

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3a83ba0 and 9adc954.

📒 Files selected for processing (51)
  • .gitignore
  • src/app/workspaces/[workspaceId]/dashboard/page.tsx
  • src/entities/dashboard-layout/api/get-dashboard-layout.ts
  • src/entities/dashboard-layout/api/save-dashboard-layout.ts
  • src/entities/dashboard-layout/index.ts
  • src/entities/dashboard-layout/model/dashboard-layout.types.ts
  • src/entities/side-project/backlog-item/index.ts
  • src/entities/side-project/backlog-item/model/backlog-item.ts
  • src/entities/side-project/meeting-note/index.ts
  • src/entities/side-project/meeting-note/model/meeting-note.ts
  • src/entities/side-project/schedule-event/index.ts
  • src/entities/side-project/schedule-event/model/schedule-event.ts
  • src/entities/side-project/sprint/index.ts
  • src/entities/side-project/sprint/model/sprint.ts
  • src/entities/side-project/task/index.ts
  • src/entities/side-project/task/model/task.ts
  • src/entities/work-schedule/lib/count-schedules-by-weekday.ts
  • src/entities/work-schedule/lib/get-work-members-by-weekday.ts
  • src/entities/workspace/api/get-workspace.ts
  • src/entities/workspace/index.ts
  • src/features/dashboard/edit-layout/index.ts
  • src/features/dashboard/edit-layout/model/useDashboardLayout.ts
  • src/features/dashboard/edit-layout/ui/DashboardEditToggle.tsx
  • src/features/dashboard/edit-layout/ui/EditModeBanner.tsx
  • src/features/manage-work-schedule/model/use-work-schedule-state.ts
  • src/features/manage-work-schedule/ui/WorkShiftSettingsPanel.tsx
  • src/shared/dashboard/lib/widget-size.ts
  • src/shared/dashboard/model/template.ts
  • src/shared/dashboard/model/widget.ts
  • src/shared/dashboard/ui/stat-card.tsx
  • src/shared/dashboard/ui/widget-card.tsx
  • src/views/dashboard/config/template-widgets.ts
  • src/views/dashboard/config/widget-catalog.tsx
  • src/views/dashboard/index.ts
  • src/views/dashboard/ui/AddWidgetBar.tsx
  • src/views/dashboard/ui/DashboardGrid.tsx
  • src/views/dashboard/ui/DashboardView.tsx
  • src/widgets/side-project/dashboard-backlog/index.ts
  • src/widgets/side-project/dashboard-backlog/ui/Backlog.tsx
  • src/widgets/side-project/dashboard-calendar/index.ts
  • src/widgets/side-project/dashboard-calendar/ui/Calendar.tsx
  • src/widgets/side-project/dashboard-my-tasks/index.ts
  • src/widgets/side-project/dashboard-my-tasks/ui/MyTasks.tsx
  • src/widgets/side-project/dashboard-recent-notes/index.ts
  • src/widgets/side-project/dashboard-recent-notes/ui/RecentNotes.tsx
  • src/widgets/side-project/dashboard-sprint-summary/index.ts
  • src/widgets/side-project/dashboard-sprint-summary/ui/SprintSummary.tsx
  • src/widgets/side-project/dashboard-today-schedule/index.ts
  • src/widgets/side-project/dashboard-today-schedule/ui/TodaySchedule.tsx
  • src/widgets/side-project/dashboard-velocity/index.ts
  • src/widgets/side-project/dashboard-velocity/ui/Velocity.tsx

Comment thread src/app/workspaces/[workspaceId]/dashboard/page.tsx
Comment thread src/entities/side-project/backlog-item/model/backlog-item.types.ts Outdated
Comment thread src/features/dashboard/edit-layout/ui/DashboardEditToggle.tsx
Comment thread src/shared/dashboard/lib/widget-size.ts
Comment thread src/views/dashboard/ui/DashboardGrid.tsx Outdated
Comment thread src/widgets/side-project/dashboard-my-tasks/ui/MyTasks.tsx Outdated
Comment thread src/widgets/side-project/dashboard-recent-notes/ui/RecentNotes.tsx
Comment thread src/widgets/side-project/dashboard-recent-notes/ui/RecentNotes.tsx
Comment thread src/widgets/side-project/dashboard-sprint-summary/ui/SprintSummary.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9adc954 and 0e49270.

📒 Files selected for processing (22)
  • src/app/workspaces/[workspaceId]/dashboard/page.tsx
  • src/entities/side-project/backlog-item/index.ts
  • src/entities/side-project/backlog-item/model/backlog-item.mock.ts
  • src/entities/side-project/backlog-item/model/backlog-item.types.ts
  • src/entities/side-project/meeting-note/index.ts
  • src/entities/side-project/meeting-note/model/meeting-note.mock.ts
  • src/entities/side-project/meeting-note/model/meeting-note.types.ts
  • src/entities/side-project/schedule-event/index.ts
  • src/entities/side-project/schedule-event/model/schedule-event.mock.ts
  • src/entities/side-project/schedule-event/model/schedule-event.types.ts
  • src/entities/side-project/sprint/index.ts
  • src/entities/side-project/sprint/model/sprint.mock.ts
  • src/entities/side-project/sprint/model/sprint.types.ts
  • src/entities/side-project/task/index.ts
  • src/entities/side-project/task/model/task.mock.ts
  • src/entities/side-project/task/model/task.types.ts
  • src/shared/dashboard/model/template.types.ts
  • src/shared/dashboard/model/widget.types.ts
  • src/views/dashboard/config/template-widgets.ts
  • src/views/dashboard/config/widget-catalog.tsx
  • src/views/dashboard/ui/DashboardGrid.tsx
  • src/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

Comment thread src/app/workspaces/[workspaceId]/dashboard/page.tsx Outdated

@wjswlgh96 wjswlgh96 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

코드 확인했습니다~ 고생하셨습니다^^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 사이드 프로젝트 대시보드 구현

2 participants