-
Notifications
You must be signed in to change notification settings - Fork 3
Feat: 템플릿 공용 대시보드 구현 #18
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
Merged
Merged
Changes from all commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
ea973d6
chore: CLAUDE.md gitignore 추가
Kwon812 4f2ee1c
feat: 위젯 공통 카드 및 AppShell 레이아웃 슬롯 추가
Kwon812 60034fc
feat: 스프린트 요약 카드 위젯 추가 (스프린트+통계 포인트)
Kwon812 08a1f30
feat: 내 업무 리스트 위젯 추가
Kwon812 a454e99
refactor: entities 레이어로 기존 위젯분리
Kwon812 1a0b6d5
feat: 벨로시티 막대 차트 위젯 추가
Kwon812 75139f3
feat: 백로그 위젯 추가
Kwon812 eae3629
feat: 최근 회의록 위젯 추가
Kwon812 dc1b477
feat: 대시보드 뷰 조립 및 라우트 연결 (react-grid-layout 그리드 + 편집)
Kwon812 d8acd1e
refactor: AppShell을 워크스페이스 layout으로 이동
Kwon812 b32c64d
refactor: 엔티티를 모델용으로 축소하고 UI를 각 위젯으로 이동
Kwon812 676c6c8
feat: 위젯 크기 판정 유틸 및 내 업무·회의록 sm 변형 추가
Kwon812 ebc9533
refactor: 사이드프로젝트 템플릿 코드를 레이어별 side-project 그룹으로 격리
Kwon812 9889579
refactor: 편집 인터랙션을 edit-dashboard-layout feature로 분리
Kwon812 6f425b1
feat: 오늘 일정 위젯 sm 변형 및 추가
Kwon812 35bbc33
feat: 내 업무·회의록·오늘 일정 위젯 lg 변형 및 모델 확장
Kwon812 066fe52
fix: 위젯 크기 판정에 높이 반영 및 리스트 오버플로 스크롤 처리
Kwon812 c4e3016
feat: 수정모드 레이아웃 추가
Kwon812 4ce6082
Merge remote-tracking branch 'origin/develop' into feat/#9/side-proje…
Kwon812 0d00aa3
feat: 사이드바, 헤더 적용
Kwon812 99a1389
fix: 기존 사이드바 수정
Kwon812 0aac056
feat: 캘린더 위젯 추가
Kwon812 70ec7ca
refactor: 레이아웃 영속화를 localStorage에서 DB 서버액션(TODO)으로 이관
Kwon812 246a2f4
refactor: 대시보드 페이지 뷰 이름 변경
Kwon812 7f0a2b9
feat: 위젯이 없을 때 빈 상태 안내 추가
Kwon812 db9d74d
refactor: 템플릿 공용 대시보드 엔진으로 분리하고 위젯 카탈로그 도입
Kwon812 6308910
Merge remote-tracking branch 'origin/develop' into feat/#9/side-proje…
Kwon812 8345d7d
fix: 중복 import 수정
Kwon812 9b7ec86
refactor: 대시보드 공용 UI를 shared/dashboard/ui로 이관
Kwon812 08ef1ee
refactor: 저장은 위젯 위치만, 제약은 카탈로그에서 머지해 데이터/UI 분리 순수화
Kwon812 0afd621
refactor: 레이아웃 조회를 RSC로 올리고 initialLayout 주입(마운트 페칭 제거)
Kwon812 e06f3e7
feat: todo 추가
Kwon812 9adc954
style:prettier 적용
Kwon812 b22558a
refactor: 타입용 파일명 .types.ts로 통일
Kwon812 0e49270
fix: getWorkspace()로 purpose동적 연결
Kwon812 cdf671d
fix: 편집토글버튼 색상값 토큰으로 수정
Kwon812 feea5b1
fix: todo제거
Kwon812 df58e1d
refactor: useContainerWidth의 mounted로 클라이언트 마운트 보장
Kwon812 e4c7e74
refactor: 엔티티에 id 추가하고 리스트 key를 id 기준으로 교체
Kwon812 ce3ff0f
Merge remote-tracking branch 'origin/develop' into feat/#9/side-proje…
Kwon812 ed1748f
refactor: task·backlog를 sprint 엔티티로 통합
Kwon812 21b52b2
Merge remote-tracking branch 'origin/develop' into feat/#9/side-proje…
Kwon812 7423801
feat: 최근 공지 위젯 추가
Kwon812 c86fd8c
refactor: Task를 sprint에서 독립 슬라이스로 분리
Kwon812 d039620
feat: 백로그,태스크 type 명시
Kwon812 a07900b
style: prettier
Kwon812 6a029c0
Merge remote-tracking branch 'origin/develop' into feat/#9/side-proje…
Kwon812 c751585
feat: 최근자료 위젯추가
Kwon812 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,5 +42,6 @@ next-env.d.ts | |
|
|
||
| # agent files (개인 작업용) | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| .agents/ | ||
| .claude/ | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| // 워크스페이스 대시보드 라우트 — 레이아웃은 서버(RSC)에서 조회해 initialLayout으로 주입한다. | ||
| // (레이아웃 조회 키: user_id + workspace_id + page_type / 저장분 없으면 빈 대시보드로 시작) | ||
| // purpose는 추가 가능한 위젯을 템플릿별로 거르는 데만 쓰인다. | ||
| import { getDashboardLayout } from '@/entities/dashboard-layout'; | ||
| import { DashboardView } from '@/views/dashboard'; | ||
| import { getMockWorkspaceById } from '@/entities/workspace'; | ||
|
|
||
| interface DashboardPageProps { | ||
| params: Promise<{ workspaceId: string }>; | ||
| } | ||
|
|
||
| export default async function DashboardPage({ params }: DashboardPageProps) { | ||
| const { workspaceId } = await params; | ||
|
|
||
| const workspace = getMockWorkspaceById(workspaceId)!; | ||
|
|
||
| const initialLayout = await getDashboardLayout(workspaceId, 'dashboard'); | ||
| return ( | ||
| <DashboardView | ||
| key={workspaceId} | ||
| workspaceId={workspaceId} | ||
| purpose={workspace.purpose} | ||
| initialLayout={initialLayout} | ||
| /> | ||
| ); | ||
| } | ||
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // 대시보드 레이아웃 조회 — DB 연동 자리. | ||
| // 저장분이 없으면(신규) 빈 레이아웃으로 시작한다 — 템플릿 기반 기본값/폴백은 두지 않는다. | ||
|
|
||
| import type { DashboardLayoutState } from '../model/dashboard-layout.types'; | ||
|
|
||
| // TODO: DB 연동 — WORKSPACE_LAYOUTS에서 (workspace_id, user_id(세션), page_type) 기준 select | ||
| export async function getDashboardLayout( | ||
| workspaceId: string, | ||
| pageType: string, | ||
| ): Promise<DashboardLayoutState> { | ||
| void workspaceId; | ||
| void pageType; | ||
| // 임시 목 저장분 — DB의 layout jsonb를 흉내낸다. 위치(i,x,y,w,h)만 담고, | ||
| // 제약(minW/minH)은 저장하지 않는다(렌더 시 카탈로그에서 머지됨). | ||
| return { | ||
| layout: [], | ||
| }; | ||
| } |
16 changes: 16 additions & 0 deletions
16
src/entities/dashboard-layout/api/save-dashboard-layout.ts
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // 대시보드 레이아웃 저장 — DB 연동 자리(서버액션). | ||
| // layout jsonb 한 행 = DashboardLayoutState 통째. 드래그 중 잦은 호출은 debounce 필요. | ||
| 'use server'; | ||
|
|
||
| import type { DashboardLayoutState } from '../model/dashboard-layout.types'; | ||
|
|
||
| // TODO: DB 연동 — WORKSPACE_LAYOUTS upsert (workspace_id, user_id(세션), page_type, layout) | ||
| export async function saveDashboardLayout( | ||
| workspaceId: string, | ||
| pageType: string, | ||
| state: DashboardLayoutState, | ||
| ): Promise<void> { | ||
| void workspaceId; | ||
| void pageType; | ||
| void state; | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| // dashboard-layout 엔티티의 Public API — 개인 대시보드 레이아웃 조회/저장. | ||
| export type { DashboardLayoutState } from './model/dashboard-layout.types'; | ||
| export { getDashboardLayout } from './api/get-dashboard-layout'; | ||
| export { saveDashboardLayout } from './api/save-dashboard-layout'; |
7 changes: 7 additions & 0 deletions
7
src/entities/dashboard-layout/model/dashboard-layout.types.ts
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| // 대시보드 레이아웃 저장 상태 타입 — DB(WORKSPACE_LAYOUTS)의 layout jsonb 한 행에 직렬화된다. | ||
| // 화면에 배치된 위젯 = layout. 배치되지 않은 위젯은 카탈로그에서 "추가"로 꺼낸다(별도 hidden 개념 없음). | ||
| import type { Layout } from 'react-grid-layout'; | ||
|
|
||
| export interface DashboardLayoutState { | ||
| layout: Layout; | ||
| } |
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| // meeting-note 엔티티의 Public API (모델) | ||
| export { type MeetingNote } from './model/meeting-note.types'; | ||
| export { mockMeetingNotes } from './model/meeting-note.mock'; |
29 changes: 29 additions & 0 deletions
29
src/entities/side-project/meeting-note/model/meeting-note.mock.ts
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // 회의록 목데이터 | ||
| import type { MeetingNote } from './meeting-note.types'; | ||
|
|
||
| export const mockMeetingNotes: MeetingNote[] = [ | ||
| { | ||
| id: 'note-1', | ||
| title: 'Sprint 2 플래닝', | ||
| date: '2025-07-01', | ||
| summary: '스프린트 목표와 백로그 우선순위를 확정했습니다.', | ||
| }, | ||
| { | ||
| id: 'note-2', | ||
| title: 'Sprint 1 회고', | ||
| date: '2025-06-28', | ||
| summary: '지난 스프린트의 성과와 개선점을 논의했습니다.', | ||
| }, | ||
| { | ||
| id: 'note-3', | ||
| title: '디자인 시스템 논의', | ||
| date: '2025-06-24', | ||
| summary: '공통 컴포넌트와 디자인 토큰 구조를 정리했습니다.', | ||
| }, | ||
| { | ||
| id: 'note-4', | ||
| title: 'API 명세 리뷰', | ||
| date: '2025-06-20', | ||
| summary: '엔드포인트 규격과 에러 응답 형식을 검토했습니다.', | ||
| }, | ||
| ]; |
8 changes: 8 additions & 0 deletions
8
src/entities/side-project/meeting-note/model/meeting-note.types.ts
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| // 회의록(MeetingNote) 도메인 모델 | ||
| export interface MeetingNote { | ||
| id: string; | ||
| title: string; | ||
| date: string; | ||
| /** 본문 요약(미리보기) */ | ||
| summary: string; | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| // schedule-event 엔티티의 Public API (모델) | ||
| export { | ||
| SCHEDULE_TYPE_COLOR, | ||
| type ScheduleEvent, | ||
| type ScheduleEventType, | ||
| type CalendarMonth, | ||
| } from './model/schedule-event.types'; | ||
| export { mockTodaySchedule, mockCalendar } from './model/schedule-event.mock'; |
18 changes: 18 additions & 0 deletions
18
src/entities/side-project/schedule-event/model/schedule-event.mock.ts
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // 오늘 일정·월간 캘린더 목데이터 | ||
| import type { CalendarMonth, ScheduleEvent } from './schedule-event.types'; | ||
|
|
||
| export const mockTodaySchedule: ScheduleEvent[] = [ | ||
| { id: 'event-1', title: '디자인 리뷰 회의', time: '11:00', type: 'meeting' }, | ||
| { id: 'event-2', title: '팀 점심', time: '12:30', type: 'meeting' }, | ||
| { id: 'event-3', title: '스프린트 데일리', time: '14:00', type: 'meeting' }, | ||
| { id: 'event-4', title: '코드 리뷰', time: '15:00', type: 'meeting' }, | ||
| { id: 'event-5', title: 'API 명세 마감', time: '16:00', type: 'deadline' }, | ||
| { id: 'event-6', title: '회고 준비', time: '17:00', type: 'meeting' }, | ||
| ]; | ||
|
|
||
| export const mockCalendar: CalendarMonth = { | ||
| year: 2025, | ||
| month: 7, | ||
| today: 30, | ||
| eventDays: [2, 5, 8, 10, 14, 22, 28], | ||
| }; |
26 changes: 26 additions & 0 deletions
26
src/entities/side-project/schedule-event/model/schedule-event.types.ts
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| // 일정(ScheduleEvent)·캘린더 도메인 모델 + 유형 색상 | ||
| export type ScheduleEventType = 'meeting' | 'deadline'; | ||
|
|
||
| /** 일정 유형별 액센트 바 색상 (회의=보라 brand-end, 마감=빨강) */ | ||
| export const SCHEDULE_TYPE_COLOR: Record<ScheduleEventType, string> = { | ||
| meeting: '#8e51ff', | ||
| deadline: '#fb2c36', | ||
| }; | ||
|
|
||
| export interface ScheduleEvent { | ||
| id: string; | ||
| title: string; | ||
| time: string; | ||
| type: ScheduleEventType; | ||
| } | ||
|
|
||
| /** 월간 캘린더 데이터 */ | ||
| export interface CalendarMonth { | ||
| year: number; | ||
| /** 1-12 */ | ||
| month: number; | ||
| /** 오늘 날짜(일). 해당 월이 아니면 null */ | ||
| today: number | null; | ||
| /** 이벤트 점이 표시될 날짜(일) */ | ||
| eventDays: number[]; | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| // sprint 엔티티의 Public API — 스프린트 메타 + 벨로시티 | ||
| // 업무(Task)는 별도 슬라이스(@/entities/side-project/task)로 분리됨 | ||
| export { VELOCITY_MAX, type Sprint, type VelocityPoint } from './model/sprint.types'; | ||
| export { currentSprint, sprintVelocity, SIDE_PROJECT_WORKSPACE_ID } from './model/sprint.mock'; |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| // 스프린트 목데이터 — 현재 스프린트 메타 + 벨로시티 | ||
| // 업무(Task)는 여기서 소유하지 않는다 → task.mock.ts / task.selectors.ts 참고 | ||
| import type { Sprint, VelocityPoint } from './sprint.types'; | ||
|
|
||
| // 사이드 프로젝트 데모 워크스페이스 id — 스프린트·업무 목데이터가 공유하는 소유 워크스페이스 | ||
| export const SIDE_PROJECT_WORKSPACE_ID = 'ws-side-project'; | ||
|
|
||
| export const currentSprint: Sprint = { | ||
| id: 'sprint-2', | ||
| workspaceId: SIDE_PROJECT_WORKSPACE_ID, | ||
| name: 'Sprint 2', | ||
| startDate: '2025-07-01', | ||
| endDate: '2025-07-14', | ||
| daysLeft: 8, | ||
| totalPoints: 42, | ||
| completedPoints: 28, | ||
| }; | ||
|
|
||
| /** 스프린트별 계획/완료 포인트 추이 */ | ||
| export const sprintVelocity: VelocityPoint[] = [ | ||
| { sprint: 'S1', planned: 38, completed: 34 }, | ||
| { sprint: 'S2', planned: 42, completed: 28 }, | ||
| ]; |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| // 스프린트 도메인 모델 — 기간·포인트 메타만 가진다. | ||
| // 업무(Task)는 Sprint가 소유하지 않고, Task.sprintId로 이 스프린트를 참조한다. | ||
| // 스프린트 업무 조회는 getSprintTasks(sprintId), 백로그는 getBacklogTasks(workspaceId)를 쓴다. | ||
| export interface Sprint { | ||
| id: string; | ||
| /** 소유 워크스페이스 — 스프린트/백로그를 이 값으로 조회한다 */ | ||
| workspaceId: string; | ||
| name: string; | ||
| /** ISO 날짜 (YYYY-MM-DD) */ | ||
| startDate: string; | ||
| endDate: string; | ||
| daysLeft: number; | ||
| /** 스프린트 계획 포인트 총합 */ | ||
| totalPoints: number; | ||
| /** 완료 포인트 */ | ||
| completedPoints: number; | ||
| } | ||
|
|
||
| export interface VelocityPoint { | ||
| sprint: string; | ||
| planned: number; | ||
| completed: number; | ||
| } | ||
|
|
||
| /** 벨로시티 차트 Y축 최댓값 */ | ||
| export const VELOCITY_MAX = 60; |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| // 백로그(스프린트 미편입) 업무 조회 — Mock 구현. | ||
| // 백엔드 준비 시 supabase.from('tasks').select().eq('workspace_id', workspaceId).is('sprint_id', null) 로 교체한다. | ||
| // TODO(async): Supabase 전환 시 Promise 반환으로 바꾸고, 소비 위젯을 페칭 구조로 함께 옮긴다. | ||
| import type { Task } from '../model/task.types'; | ||
| import { mockTasks } from './task.mock'; | ||
|
|
||
| export function getBacklogTasks(workspaceId: string): Task[] { | ||
| return mockTasks.filter((task) => task.workspaceId === workspaceId && task.sprintId === null); | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| // 특정 스프린트에 편입된 업무 조회 — Mock 구현. | ||
| // 백엔드 준비 시 supabase.from('tasks').select().eq('sprint_id', sprintId) 로 교체한다. | ||
| // TODO(async): Supabase 전환 시 Promise 반환으로 바꾸고, 소비 위젯을 페칭 구조로 함께 옮긴다. | ||
| import type { Task } from '../model/task.types'; | ||
| import { mockTasks } from './task.mock'; | ||
|
|
||
| export function getSprintTasks(sprintId: string): Task[] { | ||
| return mockTasks.filter((task) => task.sprintId === sprintId); | ||
| } |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.