Skip to content

feat:매장 운영 업무 스케줄 위젯 추가(#28) - #28

Closed
seongjinss555 wants to merge 3 commits into
developfrom
feat/#25/dashboard-layout-store-schedule
Closed

feat:매장 운영 업무 스케줄 위젯 추가(#28)#28
seongjinss555 wants to merge 3 commits into
developfrom
feat/#25/dashboard-layout-store-schedule

Conversation

@seongjinss555

@seongjinss555 seongjinss555 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Pull Request

작업 내용

  • 매장 운영 대시보드에서 업무 스케줄 위젯을 추가할 수 있도록 구성했습니다.
  • 대시보드 위젯 렌더러에 workspaceId 컨텍스트를 전달해 위젯별 데이터 스코프를 맞췄습니다.
  • 최근 자료 위젯이 전체 목업 자료가 아니라 현재 워크스페이스 자료만 보여주도록 수정했습니다.
  • 레이아웃 추가/삭제 시 저장 서버 액션이 state updater 안에서 호출되지 않도록 저장 시점을 분리했습니다.

작업 결과

  • store-operation 대시보드 편집 모드의 위젯 추가 목록에 업무 스케줄이 표시됩니다.
  • 업무 스케줄 위젯은 현재 워크스페이스 멤버 기준 오늘 근무 인원과 근무 유형별 요약을 보여줍니다.
  • 자료 위젯은 workspaceId 기준으로 필터링되어 다른 워크스페이스 자료가 섞이지 않습니다.
  • 위젯 추가/삭제 중 React 렌더 단계에서 서버 액션이 호출되던 경고 원인을 제거했습니다.

변경 사항

Added

  • 매장 운영용 dashboard-work-schedule 위젯 추가
  • 위젯 렌더 컨텍스트에 workspaceId 추가

Changed

  • 대시보드 그리드가 각 위젯 렌더러에 워크스페이스 컨텍스트를 전달하도록 변경
  • store-operation 템플릿의 추가 가능 위젯 목록에 업무 스케줄 추가
  • 최근 자료 위젯이 워크스페이스 단위로 자료를 필터링하도록 변경

Fixed

  • 레이아웃 저장 서버 액션 호출을 useEffect로 이동해 state updater 내부 부수효과 제거

실행화면

  • 별도 캡처 미첨부

테스트

  • 로컬 실행 확인
  • 주요 시나리오 확인
  • 영향 범위 확인

검증 명령:

  • npm run lint
  • npm run typecheck
  • npm run build
  • git diff --check

리뷰 체크리스트

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

리뷰 요청사항

  • 대시보드 위젯 렌더 컨텍스트를 workspaceId로 확장한 방향이 이후 공지/자료/스케줄 DB 연동에도 적절한지 봐주세요.
  • 업무 스케줄 위젯의 정보 밀도가 기존 최근 공지/최근 자료 위젯과 어울리는지 봐주세요.

관련 이슈

Closes #28

Summary by CodeRabbit

  • New Features
    • 대시보드에 근무 스케줄 요약(Work Schedule) 위젯이 추가되고, 매장운영 템플릿에도 기본 포함되었습니다.
    • 위젯 크기별로 오늘 근무 요약/유형별 인원/향후 요일별 요약이 다르게 표시됩니다.
  • Improvements
    • 일부 위젯이 현재 워크스페이스 기준으로 데이터를 표시하도록 개선되었습니다(예: 최근 자료/근무 스케줄).
  • Bug Fixes
    • 대시보드 레이아웃 변경 사항이 더 안정적으로 저장되도록 동작이 개선되었습니다.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f065d169-9199-4fb7-9341-d5d31efe0bd0

📥 Commits

Reviewing files that changed from the base of the PR and between 9651e63 and 5e749e7.

📒 Files selected for processing (9)
  • src/features/dashboard/edit-layout/model/useDashboardLayout.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
  • src/widgets/store-operation/dashboard-recent-resources/ui/RecentResources.tsx
  • src/widgets/store-operation/dashboard-work-schedule/index.ts
  • src/widgets/store-operation/dashboard-work-schedule/ui/WorkScheduleSummary.tsx

📝 Walkthrough

Walkthrough

대시보드 레이아웃 저장이 useEffect 기반으로 바뀌었고, 위젯 렌더링에 workspaceId 컨텍스트가 추가됐다. RecentResources는 workspaceId로 필터링되며, work-schedule 템플릿 위젯과 WorkScheduleSummary가 새로 등록됐다.

Changes

대시보드 레이아웃 저장 및 위젯 컨텍스트 전달

Layer / File(s) Summary
레이아웃 저장 트리거 재구성
src/features/dashboard/edit-layout/model/useDashboardLayout.ts
핸들러 내부 저장 호출을 제거하고, layout 변경 시 didMountRef를 거쳐 saveDashboardLayout이 실행되도록 변경했다.
위젯 렌더 컨텍스트 전달
src/shared/dashboard/model/widget.types.ts, src/views/dashboard/ui/DashboardGrid.tsx, src/views/dashboard/ui/DashboardView.tsx, src/views/dashboard/config/widget-catalog.tsx, src/widgets/store-operation/dashboard-recent-resources/ui/RecentResources.tsx
WidgetDefinition.render가 workspaceId를 받도록 바뀌고, DashboardView/DashboardGrid가 이를 전달하며, recent-resources가 workspaceId 기준으로 목록을 구성하도록 수정됐다.

WorkScheduleSummary 위젯 추가

Layer / File(s) Summary
위젯 등록과 템플릿 반영
src/widgets/store-operation/dashboard-work-schedule/index.ts, src/views/dashboard/config/widget-catalog.tsx, src/views/dashboard/config/template-widgets.ts
WorkScheduleSummary를 public export에 추가하고, widget catalog와 store-operation 템플릿에 work-schedule 항목을 등록했다.
근무 요약 렌더링 구현
src/widgets/store-operation/dashboard-work-schedule/ui/WorkScheduleSummary.tsx
workspaceId로 멤버를 필터링해 오늘 근무, 요일별 근무, size별 표시 분기를 렌더링하는 새 위젯이 추가됐다.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DashboardView
  participant DashboardGrid
  participant WidgetCatalog
  participant RecentResources
  participant WorkScheduleSummary

  DashboardView->>DashboardGrid: workspaceId prop 전달
  DashboardGrid->>WidgetCatalog: widget.render(size, { workspaceId })
  WidgetCatalog->>RecentResources: workspaceId 전달
  WidgetCatalog->>WorkScheduleSummary: workspaceId 전달
Loading

Possibly related PRs

  • TeampleRun/syncly#12: WorkScheduleSummary가 사용하는 work-schedule 도메인 유틸과 목업 구성이 같은 영역에서 추가됐다.
  • TeampleRun/syncly#18: dashboard layout 저장 흐름과 위젯 렌더 컨텍스트 경로가 같은 코드 경로를 변경한다.

Suggested reviewers: wjswlgh96, JiWoongE, 0011810, Kwon812

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning 직접 이슈 #25는 캘린더 화면과 일정 추가 UI 구현인데, 이번 PR은 업무 스케줄 위젯과 대시보드 변경이라 요구사항을 충족하지 않습니다. 캘린더 메인 UI, 일정 추가 UI, /workspaces/[workspaceId]/calendar 연결, 월간 뷰와 일정 표시/추가 흐름을 구현해 #25 요구사항을 반영하세요.
Out of Scope Changes check ⚠️ Warning 캘린더 기능과 무관한 대시보드 위젯, 워크스페이스 컨텍스트, 레이아웃 저장 시점 변경이 이슈 #25 범위 밖으로 보입니다. 이 변경들은 별도 PR로 분리하거나, 현재 PR에 캘린더 기능 구현을 추가해 이슈 범위와 맞추세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed 제목은 매장 운영 업무 스케줄 위젯 추가라는 실제 변경 사항을 잘 요약합니다.
Description check ✅ Passed 필수 섹션들이 대부분 채워져 있고 작업 내용, 결과, 변경 사항, 테스트, 리뷰 요청사항이 포함되어 있습니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#25/dashboard-layout-store-schedule

Comment @coderabbitai help to get the list of available commands.

@seongjinss555
seongjinss555 force-pushed the feat/#25/dashboard-layout-store-schedule branch from 9651e63 to 5e749e7 Compare July 9, 2026 02:23
@seongjinss555
seongjinss555 deleted the feat/#25/dashboard-layout-store-schedule branch July 9, 2026 02:24
@seongjinss555 seongjinss555 changed the title feat:매장 운영 업무 스케줄 위젯 추가(#25) feat:매장 운영 업무 스케줄 위젯 추가(#28) Jul 9, 2026

@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: 3

🤖 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/features/dashboard/edit-layout/model/useDashboardLayout.ts`:
- Line 31: The layout-save path in useDashboardLayout currently calls
saveDashboardLayout on every layout change, which can trigger repeated saves
during drag/resize. Update the effect or change handler in useDashboardLayout to
debounce or batch these calls so saveDashboardLayout is invoked only after
changes settle, using the existing layout state and saveDashboardLayout symbol
to keep the behavior centralized.
- Line 38: The `useDashboardLayout` save path is discarding the
`saveDashboardLayout` promise without handling failures, so update the call site
to explicitly catch errors instead of relying on `void`. Use the
`saveDashboardLayout` invocation in `useDashboardLayout` to attach a rejection
handler that logs or otherwise handles the error, keeping the current
fire-and-forget behavior while preventing unhandled rejections when the real DB
implementation is added.

In
`@src/widgets/store-operation/dashboard-work-schedule/ui/WorkScheduleSummary.tsx`:
- Around line 69-86: The weekday summary in WorkScheduleSummary is aggregating
only the mock initial schedule, so it never reflects real day-to-day variation.
Update the logic around createInitialWorkSchedule, countSchedulesByWeekday, and
the workingShifts/primaryShift calculations to use actual schedule state or
injected data instead of the fixed mock defaultShift pattern; if this view is
meant to stay mock-only, replace this section with a simpler non-comparative
display that does not imply real weekday differences.
🪄 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: 33fbf92f-c6ee-4062-8bdf-afdcb7ce5abe

📥 Commits

Reviewing files that changed from the base of the PR and between 376f240 and 9651e63.

📒 Files selected for processing (9)
  • src/features/dashboard/edit-layout/model/useDashboardLayout.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
  • src/widgets/store-operation/dashboard-recent-resources/ui/RecentResources.tsx
  • src/widgets/store-operation/dashboard-work-schedule/index.ts
  • src/widgets/store-operation/dashboard-work-schedule/ui/WorkScheduleSummary.tsx

const [editMode, setEditMode] = useState(false);
const didMountRef = useRef(false);

// TODO: DB 연동 — 변경 저장 (드래그 중 잦은 호출은 debounce 예정)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

TODO: 드래그 중 저장 호출 debounce 필요

주석에 명시된 대로, layout이 변경될 때마다(드래그/리사이즈 stop 등) saveDashboardLayout이 호출되어 동일 세션에서 반복 호출이 발생할 수 있습니다. 실제 DB 연동 시 debounce나 트랜지션 배칭을 적용하는 것을 권장합니다. 원하시면 debounce 유틸리티 추가를 도와드릴까요?

🤖 Prompt for 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.

In `@src/features/dashboard/edit-layout/model/useDashboardLayout.ts` at line 31,
The layout-save path in useDashboardLayout currently calls saveDashboardLayout
on every layout change, which can trigger repeated saves during drag/resize.
Update the effect or change handler in useDashboardLayout to debounce or batch
these calls so saveDashboardLayout is invoked only after changes settle, using
the existing layout state and saveDashboardLayout symbol to keep the behavior
centralized.

return;
}

void saveDashboardLayout(workspaceId, pageType, { layout });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

saveDashboardLayout 프로미스 에러 처리 누락

void saveDashboardLayout(...)는 프로미스를 버릴 뿐 실패를 처리하지 않습니다. 현재는 no-op 스텁이라 문제가 없지만, TODO에 명시된 실제 DB 연동이 구현되면 예외 발생 시 unhandled rejection으로 조용히 실패합니다.

🛡️ 제안: catch로 에러 처리 추가
-    void saveDashboardLayout(workspaceId, pageType, { layout });
+    saveDashboardLayout(workspaceId, pageType, { layout }).catch((error) => {
+      console.error('Failed to save dashboard layout', error);
+    });
📝 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.

Suggested change
void saveDashboardLayout(workspaceId, pageType, { layout });
saveDashboardLayout(workspaceId, pageType, { layout }).catch((error) => {
console.error('Failed to save dashboard layout', error);
});
🤖 Prompt for 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.

In `@src/features/dashboard/edit-layout/model/useDashboardLayout.ts` at line 38,
The `useDashboardLayout` save path is discarding the `saveDashboardLayout`
promise without handling failures, so update the call site to explicitly catch
errors instead of relying on `void`. Use the `saveDashboardLayout` invocation in
`useDashboardLayout` to attach a rejection handler that logs or otherwise
handles the error, keeping the current fire-and-forget behavior while preventing
unhandled rejections when the real DB implementation is added.

Comment on lines +69 to +86
const members = mockWorkspaceMembers.filter((member) => member.workspaceId === workspaceId);
const schedule = createInitialWorkSchedule({
workspaceId,
members,
config: mockWorkScheduleConfig,
});
const today = getTodayWeekday();
const todayCounts = countSchedulesByWeekday({
schedule,
config: mockWorkScheduleConfig,
weekday: today,
});
const workingShifts = mockWorkScheduleConfig.shifts.filter((shift) => !shift.isOff);
const totalWorkingMembers = workingShifts.reduce(
(total, shift) => total + (todayCounts[shift.id] ?? 0),
0,
);
const primaryShift = workingShifts.find((shift) => (todayCounts[shift.id] ?? 0) > 0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# create-initial-work-schedule.ts의 실제 용도(placeholder 여부) 및 다른 소비처 확인
rg -n "createInitialWorkSchedule" -A5 -B5 --type=ts

Repository: TeampleRun/syncly

Length of output: 155


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg 'WorkScheduleSummary\.tsx|work-schedule|createInitialWorkSchedule|countSchedulesByWeekday|mockWorkScheduleConfig|mockWorkspaceMembers'

echo
echo "== usages =="
rg -n "createInitialWorkSchedule|countSchedulesByWeekday|mockWorkScheduleConfig|mockWorkspaceMembers|getTodayWeekday" src

echo
echo "== likely file outline =="
fd -a "WorkScheduleSummary.tsx|work-schedule.*ts" src

Repository: TeampleRun/syncly

Length of output: 5914


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== create-initial-work-schedule =="
cat -n src/entities/work-schedule/lib/create-initial-work-schedule.ts

echo
echo "== count-schedules-by-weekday =="
cat -n src/entities/work-schedule/lib/count-schedules-by-weekday.ts

echo
echo "== WorkScheduleSummary (relevant range) =="
sed -n '1,240p' src/widgets/store-operation/dashboard-work-schedule/ui/WorkScheduleSummary.tsx

echo
echo "== WorkScheduleView =="
cat -n src/views/store-operation/work-schedule/ui/WorkScheduleView.tsx

Repository: TeampleRun/syncly

Length of output: 9812


src/widgets/store-operation/dashboard-work-schedule/ui/WorkScheduleSummary.tsx:69-86, 158-182 — 요일별 근무 요약은 목업 초기 스케줄만 집계합니다. createInitialWorkSchedule가 모든 멤버에게 모든 요일의 같은 defaultShift.id를 넣어서, 이 그리드는 실제 요일별 차이 대신 항상 비슷한 값만 보여줍니다. 실제 주간 비교가 필요하면 스케줄 상태를 주입하거나, 목업이면 이 섹션을 다른 표현으로 바꾸는 편이 낫습니다.

🤖 Prompt for 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.

In
`@src/widgets/store-operation/dashboard-work-schedule/ui/WorkScheduleSummary.tsx`
around lines 69 - 86, The weekday summary in WorkScheduleSummary is aggregating
only the mock initial schedule, so it never reflects real day-to-day variation.
Update the logic around createInitialWorkSchedule, countSchedulesByWeekday, and
the workingShifts/primaryShift calculations to use actual schedule state or
injected data instead of the fixed mock defaultShift pattern; if this view is
meant to stay mock-only, replace this section with a simpler non-comparative
display that does not imply real weekday differences.

seongjinss555 added a commit that referenced this pull request Jul 9, 2026
feat:매장 운영 업무 스케줄 위젯 추가(#28)
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.

1 participant