Conversation
chore: develop을 main 머지 커밋과 동기화
* feat(api): serve swagger docs * fix(api): address swagger docs review * fix(api): document error response examples * test(api): assert openapi response refs resolve
* docs(api): 확정 스케줄 조회 계약 정리 * feat(api): 보관함 API 구현 * feat(api): 대시보드 API 구현 * feat(web): 확정 스케줄 API 연결 함수 추가 * feat(web): 대시보드 API 연결 * feat(web): 보관함 API 연결 * feat(web): 보관함 CSV 근무표 형식 적용 * fix: 보관함·대시보드 리뷰 반영 * docs(api): 보관함·대시보드 OpenAPI 추가 * refactor(web): 스케줄 시간 표시 util 분리
* feat(web): 가능 시간 관리 UI 개선 * feat(web): 가능 시간 드래그 선택 개선 * fix(web): 가능 시간 UI 리뷰 반영
* feat(web): improve schedule calendar and time inputs * fix: address schedule review feedback * fix: address remaining schedule review comments
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Walkthrough대시보드/스케줄 히스토리 조회, CSV 내보내기 API 및 OpenAPI/Swagger 문서화가 백엔드에 추가되고, 웹에서는 대시보드·스케줄 히스토리 페이지가 새 API/React Query와 연동됩니다. 또한 가용성 달력(드래그 다중 선택), 조직 폼 운영시간 Select, 스케줄 페이지의 그룹형 표시가 함께 변경됩니다. Changes대시보드/스케줄 히스토리 백엔드 API 및 문서화
웹 대시보드/스케줄 히스토리 프론트엔드
가용성 달력, 조직 폼, 스케줄 페이지 UX 개선
Estimated code review effort: 4 (Complex) | ~75 minutes Related issues: 명시된 관련 이슈 정보 없음. Related PRs: 명시된 관련 PR 정보 없음. Suggested labels: backend, frontend, api, documentation Suggested reviewers: 프로젝트 컨벤션과 스펙 정합성 검토를 위해 백엔드/프론트엔드 양쪽에 익숙한 리뷰어를 지정하는 것을 권장합니다.
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 15
🤖 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 `@apps/api/package.json`:
- Line 13: Update the api package’s typecheck script so it does not run against
missing or stale declarations from `@fragment/shared` and `@fragment/database`. In
the package.json script that defines typecheck, add the required workspace build
step(s) before tsc --noEmit, or otherwise ensure those dependencies are resolved
from source rather than dist/index.d.ts. Use the typecheck script and the
referenced workspace packages as the main anchors when making the change.
In `@apps/api/test/schedule-history.routes.test.ts`:
- Around line 405-406: The export CSV test in schedule-history.routes.test.ts
only checks that the content-type contains text/csv, so it can miss a regression
where the charset is dropped. Update the assertion in the GET
/schedule-history/:scheduleId/export.csv test to verify the full response header
contract, including charset=utf-8, using the response.headers["content-type"]
check alongside the existing BOM validation.
- Around line 121-136: Add a regression test in schedule-history.routes.test.ts
for the Schedule History route that sends only month without year and expects a
400 VALIDATION_ERROR response. Extend the existing rejects invalid history query
coverage in the schedule history route tests so the contract enforced by the
handler/createDateRangeFilter path is exercised when month is present alone. Use
the same test setup patterns already used in the schedule history route spec
(createFakePrisma, createApp, request, authHeader) to locate and add the new
case.
In `@apps/web/src/features/availability/components/mvp-availability-page.tsx`:
- Around line 1091-1094: Replace the inline gridTemplateColumns style in
mvp-availability-page.tsx with a Tailwind-based layout approach. Update the
component that renders the timetable grid so it uses utility classes and/or a
flex/table structure instead of injecting dynamic px values via the style prop,
keeping the same TIMETABLE_TIME_COLUMN_WIDTH and
visibleTimetableDates.length-driven layout behavior. Locate the grid container
in the availability page component and refactor that section to remove the
inline style attribute entirely.
- Around line 421-424: The availability flow is treating any existing
activePlanningPeriod as if it matches the currently selected
workStartDate/workEndDate, which can enable fetch/save for a different range.
Update the logic around hasSavedPlanningPeriod, canFetchAvailability, and the
save button gating in mvp-availability-page.tsx to also verify the selected
dates are exactly the same as the stored planning period before considering it
saved. Make the same equality check consistent in the related availability query
and save paths referenced by the comment so only an unchanged planning period is
reused.
In `@apps/web/src/features/dashboard/api/dashboard-api.ts`:
- Line 1: The DashboardResponse import in dashboard-api should follow the
project’s API type path rule instead of importing from the shared package root.
Update the import in the dashboard-api module to use the API types location
under packages/shared/src/types/api/, keeping the existing DashboardResponse
symbol but changing only the source path to match the repository’s API
request/response type convention.
In `@apps/web/src/features/dashboard/components/mvp-dashboard-page.tsx`:
- Around line 49-64: `formatAssignmentTime` and
`scheduleAssignmentToCalendarItem` are formatting ISO date-times by slicing
strings, which loses timezone-aware time and breaks next-day detection. Replace
the `slice(11, 16)`/`slice(0, 10) > workDate` logic with proper `Date`-based or
formatter-based calculation so `startsAt` and `endsAt` are rendered correctly
for `ConfirmedScheduleCalendarItem`, including midnight crossings and any `+1`
day display. If there is an existing shared schedule display utility, use that
instead to keep date and date-time handling consistent with the guidelines.
In `@apps/web/src/features/organization/components/organization-form.tsx`:
- Around line 34-48: The TIME_OPTIONS select in organization-form.tsx is
incorrectly narrowing time-of-day values to 30-minute slots, so existing
server-provided HH:MM values like 09:15 cannot be represented or reselected in
the edit form. Update the organization form time inputs to support the full
HH:MM contract used by the API and shared schema, and only keep a 30-minute
restriction if you also align the shared schema, server validation, and API docs
accordingly. Check the TIME_OPTIONS constant and the related time field handling
in the organization form so existing organization times remain faithfully
editable.
In
`@apps/web/src/features/schedule-history/components/mvp-schedule-history-page.tsx`:
- Around line 133-140: `mvp-schedule-history-page` is forcing a month selection,
which prevents year-only history lookup. Update the `effectiveSelectedMonth`
logic so an empty month remains valid instead of defaulting to the first item,
and add an explicit “전체 월” (or equivalent) option in the month Select that maps
to the empty month state. Make sure `historyItems` and any related filtering
paths continue to use `selectedYearItems` when no month is chosen, preserving
the `year`-only query flow in `isHistoryInMonth` and the UI state handling.
In `@apps/web/src/features/schedules/components/mvp-schedules-page.tsx`:
- Around line 428-475: The new utility logic in groupUnfilledConditionsByDate,
getShortageCount, getUnfilledConditionLabel, and getUnfilledConditionPreview has
branching behavior and should be covered by tests. Add focused unit tests for
these helpers to verify date grouping/sorting, shortage count clamping, and
preview truncation with hidden-count formatting, using the existing
mvp-schedules-page.tsx utility symbols as the entry point. Keep the tests
minimal but include at least one or two representative cases for each branch so
regressions are caught.
- Around line 72-78: The time-grouping logic is duplicated here and in
confirmed-schedule-calendar.tsx, and the ScheduleTimeGroup shape differs between
files, which will cause maintenance drift. Move the shared
grouping/label/preview behavior into the common schedule-display utility and
have mvp-schedules-page.tsx reuse it instead of defining its own
ScheduleTimeGroup, getTimeRangeLabel, getWorkerNamesPreview, and
groupSchedulesByTime. Keep the returned group shape consistent across both
components by aligning the local types with the shared helper’s symbols.
- Around line 1035-1044: The calendar cell rendering in the schedule page is
recalculating groupSchedulesByTime for each date inside calendarDates.map,
causing repeated work on every render. Move the per-date grouping logic out of
the cell loop in mvp-schedules-page.tsx by precomputing schedules by date and
caching the grouped result with useMemo, then read the memoized groups when
deriving visibleScheduleGroups and hiddenScheduleGroupCount.
In `@apps/web/src/lib/schedule-display.ts`:
- Around line 3-9: `formatScheduleAssignmentTimeRange` is calculating the “익일”
prefix by comparing `endsAt` only against `startsAt`, which breaks cases where
both times are on the next day relative to `workDate`. Update this function to
use `assignment.workDate` as the reference date and compare both `startsAt` and
`endsAt` against it when deciding whether to add the 익일 prefix. Keep the time
formatting logic in `formatScheduleAssignmentTimeRange` but make the
day-boundary check explicit for start/end based on `workDate`.
In `@docs/openapi.yaml`:
- Around line 1522-1569: CreateMinimumStaffingRuleRequest and
UpdateMinimumStaffingRuleRequest currently allow arbitrary extra fields because
they do not close the object schema. Add additionalProperties: false to both
request schemas in openapi.yaml, keeping minProperties: 1 only on
UpdateMinimumStaffingRuleRequest for partial updates. Make sure the change is
applied to the named schemas so generated clients and validation stay aligned
with the server contract.
- Around line 755-811: The ScheduleHistory 404 contract is too generic in the
OpenAPI spec and should be fixed to match the API docs by returning
SCHEDULE_NOT_FOUND for both getScheduleHistoryDetail and
exportScheduleHistoryCsv. Update the responses for
/schedule-history/{scheduleId} and /schedule-history/{scheduleId}/export.csv to
reference or define a dedicated 404 response tied to SCHEDULE_NOT_FOUND instead
of the shared NotFound response, so the operationId-defined endpoints only
advertise the confirmed-schedule-missing case.
🪄 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: 12e8358c-cb73-4010-9822-c89eda127d63
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (38)
.env.exampleapps/api/package.jsonapps/api/src/app.tsapps/api/src/modules/dashboard/dashboard.handlers.tsapps/api/src/modules/dashboard/dashboard.service.tsapps/api/src/modules/organization/organization.service.tsapps/api/src/modules/schedule-history/schedule-history.handlers.tsapps/api/src/modules/schedule-history/schedule-history.service.tsapps/api/src/openapi.tsapps/api/src/routes/dashboard.routes.tsapps/api/src/routes/index.tsapps/api/src/routes/schedule-history.routes.tsapps/api/test/dashboard.routes.test.tsapps/api/test/docs.routes.test.tsapps/api/test/helpers/fake-prisma.tsapps/api/test/organization.routes.test.tsapps/api/test/schedule-history.routes.test.tsapps/web/src/features/availability/components/mvp-availability-page.tsxapps/web/src/features/dashboard/api/dashboard-api.tsapps/web/src/features/dashboard/components/mvp-dashboard-page.tsxapps/web/src/features/dashboard/queries/dashboard-queries.tsapps/web/src/features/dashboard/queries/dashboard-query-keys.tsapps/web/src/features/organization/components/mvp-organization-edit-page.tsxapps/web/src/features/organization/components/organization-form.tsxapps/web/src/features/schedule-history/api/schedule-history-api.tsapps/web/src/features/schedule-history/components/mvp-schedule-history-page.tsxapps/web/src/features/schedule-history/queries/schedule-history-queries.tsapps/web/src/features/schedule-history/queries/schedule-history-query-keys.tsapps/web/src/features/schedules/components/confirmed-schedule-calendar.tsxapps/web/src/features/schedules/components/mvp-schedules-page.tsxapps/web/src/lib/api-client.tsapps/web/src/lib/schedule-display.tsdocs/API.mddocs/SWAGGER.mddocs/openapi.yamlpackage.jsonpackages/shared/src/schemas/dashboard.tspackages/shared/src/schemas/schedule-history.ts
| className="grid gap-1" | ||
| style={{ | ||
| gridTemplateColumns: `${TIMETABLE_TIME_COLUMN_WIDTH}px repeat(${visibleTimetableDates.length}, ${TIMETABLE_DATE_COLUMN_WIDTH}px)`, | ||
| }} |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
인라인 스타일을 Tailwind 기반 레이아웃으로 대체하세요.
style로 동적 px 기반 grid template을 주입하고 있어 프로젝트 스타일링 규칙을 벗어납니다. 테이블/행 flex 구조 또는 토큰화된 utility class로 동일한 레이아웃을 구성해 주세요. As per coding guidelines, apps/web/src/**/*.{css,ts,tsx}: Use Tailwind CSS utility classes only; avoid inline style attributes.
🤖 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 `@apps/web/src/features/availability/components/mvp-availability-page.tsx`
around lines 1091 - 1094, Replace the inline gridTemplateColumns style in
mvp-availability-page.tsx with a Tailwind-based layout approach. Update the
component that renders the timetable grid so it uses utility classes and/or a
flex/table structure instead of injecting dynamic px values via the style prop,
keeping the same TIMETABLE_TIME_COLUMN_WIDTH and
visibleTimetableDates.length-driven layout behavior. Locate the grid container
in the availability page component and refactor that section to remove the
inline style attribute entirely.
Source: Coding guidelines
| function groupUnfilledConditionsByDate(conditions: UnfilledCondition[]): UnfilledConditionGroup[] { | ||
| const groupsByDate = new Map<string, UnfilledConditionGroup>(); | ||
|
|
||
| conditions.forEach((condition) => { | ||
| const group = groupsByDate.get(condition.date); | ||
|
|
||
| if (group) { | ||
| group.conditions.push(condition); | ||
| return; | ||
| } | ||
|
|
||
| groupsByDate.set(condition.date, { | ||
| conditions: [condition], | ||
| date: condition.date, | ||
| dayLabel: condition.dayLabel, | ||
| }); | ||
| }); | ||
|
|
||
| return [...groupsByDate.values()] | ||
| .map((group) => ({ | ||
| ...group, | ||
| conditions: [...group.conditions].sort((left, right) => | ||
| left.timeRange.localeCompare(right.timeRange), | ||
| ), | ||
| })) | ||
| .sort((left, right) => left.date.localeCompare(right.date)); | ||
| } | ||
|
|
||
| function getShortageCount(condition: UnfilledCondition) { | ||
| return Math.max(condition.requiredWorkers - condition.assignedWorkers, 0); | ||
| } | ||
|
|
||
| function getUnfilledConditionLabel(condition: UnfilledCondition) { | ||
| return `${condition.timeRange} ${getShortageCount(condition)}명 부족`; | ||
| } | ||
|
|
||
| function getUnfilledConditionPreview(conditions: UnfilledCondition[]) { | ||
| const visibleConditions = conditions.slice(0, MAX_PREVIEW_UNFILLED_CONDITIONS); | ||
| const hiddenConditionCount = conditions.length - visibleConditions.length; | ||
| const visibleLabel = visibleConditions.map(getUnfilledConditionLabel).join(" · "); | ||
|
|
||
| if (hiddenConditionCount <= 0) { | ||
| return visibleLabel; | ||
| } | ||
|
|
||
| return `${visibleLabel} · +${hiddenConditionCount}개`; | ||
| } | ||
|
|
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
신규 그룹핑/미리보기 유틸에 대한 테스트가 없음
groupUnfilledConditionsByDate, getShortageCount, getUnfilledConditionPreview는 날짜별 정렬, 부족 인원 계산, 숨김 개수 처리 등 분기 로직이 있는 유틸입니다. CLAUDE.md에 따르면 "복잡한 유틸 또는 hook을 추가할 때만 테스트를 작성"하도록 되어 있는데, 이번 변경에는 대응하는 테스트 파일이 보이지 않습니다. 최소한 그룹핑 순서와 부족 인원 계산 케이스 1~2개는 단위 테스트로 검증해두면 이후 회귀를 막기 좋습니다.
As per path instructions, "Web은 기본적으로 typecheck/lint를 우선하고, 복잡한 유틸 또는 hook을 추가할 때만 테스트를 작성한다."
🤖 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 `@apps/web/src/features/schedules/components/mvp-schedules-page.tsx` around
lines 428 - 475, The new utility logic in groupUnfilledConditionsByDate,
getShortageCount, getUnfilledConditionLabel, and getUnfilledConditionPreview has
branching behavior and should be covered by tests. Add focused unit tests for
these helpers to verify date grouping/sorting, shortage count clamping, and
preview truncation with hidden-count formatting, using the existing
mvp-schedules-page.tsx utility symbols as the entry point. Keep the tests
minimal but include at least one or two representative cases for each branch so
regressions are caught.
Source: Path instructions
|
리뷰 반영 커밋을 푸시했습니다. 반영한 내용은 다음과 같습니다.
로컬 검증도 완료했습니다.
|
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/src/features/availability/components/mvp-availability-page.tsx (1)
505-512: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win저장 전 근무자/기간 전환 시 draft가 조용히 사라집니다.
hasUnsavedChanges가 있어도 근무자 또는 기간을 바꿀 수 있고, 이후 새 조회 결과가 Line 505-512에서draftAvailability를 서버값으로 덮어써 사용자가 드래그로 입력한 변경분이 유실됩니다. 전환 전에 저장/취소를 요구해 주세요.수정 예시
function selectWorkDate(date: string) { if (isPageLoading) { return; } + + if (hasUnsavedChanges) { + setSaveMessage("가능 시간을 저장하거나 변경 취소한 뒤 근무 기간을 변경해 주세요."); + return; + } if (!workStartDate || (workStartDate && workEndDate) || date < workStartDate) {onClick={() => { + if (worker.id === selectedWorkerId) { + return; + } + + if (hasUnsavedChanges) { + setSaveMessage("가능 시간을 저장하거나 변경 취소한 뒤 다른 근무자를 선택해 주세요."); + return; + } + setSelectedWorkerId(worker.id); setSelectedAvailabilityDate(""); setSaveMessage(""); }}Also applies to: 755-772, 1011-1015
🤖 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 `@apps/web/src/features/availability/components/mvp-availability-page.tsx` around lines 505 - 512, The availability page is overwriting in-progress edits when worker or period changes, causing unsaved draft changes to disappear. Update the selection/change flow in mvp-availability-page.tsx so that the handlers around hasUnsavedChanges block switching or first prompt the user to save or discard before updating the active worker/date range. Also make sure the availabilityResult.data useEffect that resets savedAvailability/draftAvailability only runs when it is safe to replace the draft, and apply the same guard to the related worker/period transition logic in the other affected sections.
🤖 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 `@apps/web/src/features/schedules/components/mvp-schedules-page.test.ts`:
- Around line 1-65: The issue is that this test is colocated with the wrong
feature component path even though it only verifies the helpers in
unfilled-conditions. Move the test to sit alongside the target module by
renaming/replacing mvp-schedules-page.test.ts with unfilled-conditions.test.ts
in the utils area, and keep the existing assertions for
groupUnfilledConditionsByDate, getShortageCount, and getUnfilledConditionPreview
unchanged.
In `@apps/web/src/features/schedules/components/mvp-schedules-page.tsx`:
- Around line 197-199: `dateTimeToTime()` currently returns only the clock time,
so schedule ranges from `assignmentToScheduleItem` and
`candidateToScheduleCandidateItem` can hide next-day ավարտs; update the
rendering path to incorporate `dayOffset` when building the displayed time
range. Reuse the same next-day formatting behavior as
`formatScheduleAssignmentTimeRange()` in `schedule-display.ts`, and make sure
the start/end labels can show the `익일` or `+1` indicator when `endsAt` crosses
midnight.
---
Outside diff comments:
In `@apps/web/src/features/availability/components/mvp-availability-page.tsx`:
- Around line 505-512: The availability page is overwriting in-progress edits
when worker or period changes, causing unsaved draft changes to disappear.
Update the selection/change flow in mvp-availability-page.tsx so that the
handlers around hasUnsavedChanges block switching or first prompt the user to
save or discard before updating the active worker/date range. Also make sure the
availabilityResult.data useEffect that resets
savedAvailability/draftAvailability only runs when it is safe to replace the
draft, and apply the same guard to the related worker/period transition logic in
the other affected sections.
🪄 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: b160b507-7098-40aa-b652-bab1dbd79194
📒 Files selected for processing (12)
apps/api/package.jsonapps/api/test/schedule-history.routes.test.tsapps/web/src/features/availability/components/mvp-availability-page.tsxapps/web/src/features/dashboard/components/mvp-dashboard-page.tsxapps/web/src/features/schedule-history/components/mvp-schedule-history-page.tsxapps/web/src/features/schedules/components/confirmed-schedule-calendar.tsxapps/web/src/features/schedules/components/mvp-schedules-page.test.tsapps/web/src/features/schedules/components/mvp-schedules-page.tsxapps/web/src/features/schedules/utils/unfilled-conditions.tsapps/web/src/lib/schedule-display.test.tsapps/web/src/lib/schedule-display.tsdocs/openapi.yaml
|
추가 리뷰 3건을 반영했습니다.
로컬 검증:
|
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/src/features/availability/components/mvp-availability-page.tsx (1)
981-1076: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win근무 기간 저장 실패 메시지가 숨겨집니다.
새 기간 선택 직후에는
hasMatchingPlanningPeriod가false라서 Line 981 이하 섹션이 렌더링되지 않습니다. 이 상태에서savePlanningPeriod()가 실패해saveMessage가 설정되어도 Line 1073의 메시지 영역이 숨겨져 사용자가 실패 원인을 볼 수 없습니다.수정 예시
- {hasMatchingPlanningPeriod ? ( + {saveMessage ? ( + <div className="rounded-lg border border-border bg-surface-secondary px-6 py-3 text-sm text-muted-foreground"> + {saveMessage} + </div> + ) : null} + + {hasMatchingPlanningPeriod ? ( <section className="min-w-0 overflow-hidden rounded-xl border border-border bg-card shadow-card"> ... - {saveMessage ? ( - <div className="border-b border-border bg-surface-secondary px-6 py-3 text-sm text-muted-foreground"> - {saveMessage} - </div> - ) : null} -🤖 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 `@apps/web/src/features/availability/components/mvp-availability-page.tsx` around lines 981 - 1076, The planning-period save error state is being hidden because the section gated by hasMatchingPlanningPeriod disappears before saveMessage can render. Update mvp-availability-page so savePlanningPeriod failures can still surface the message even when the newly selected period is not yet matching, by moving the saveMessage display outside the hasMatchingPlanningPeriod-only block or rendering a separate always-visible status area tied to savePlanningPeriod and saveMessage. Make sure the failure feedback remains visible immediately after a failed save and still clears correctly when the user retries or changes selection.
🤖 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 `@apps/web/src/features/availability/components/mvp-availability-page.tsx`:
- Line 408: The synchronization logic in mvp-availability-page.tsx is reapplying
activePlanningPeriod even when the user edits workStartDate or workEndDate,
which causes the newly selected period to snap back. Update the effect around
activePlanningPeriod so it only syncs when the server-side planning period truly
changes, and exclude normal local date edits from retriggering the reset. Use
the existing symbols activePlanningPeriod, workStartDate, workEndDate, and
hasUnsavedChangesRef to keep the user’s in-progress selection intact.
---
Outside diff comments:
In `@apps/web/src/features/availability/components/mvp-availability-page.tsx`:
- Around line 981-1076: The planning-period save error state is being hidden
because the section gated by hasMatchingPlanningPeriod disappears before
saveMessage can render. Update mvp-availability-page so savePlanningPeriod
failures can still surface the message even when the newly selected period is
not yet matching, by moving the saveMessage display outside the
hasMatchingPlanningPeriod-only block or rendering a separate always-visible
status area tied to savePlanningPeriod and saveMessage. Make sure the failure
feedback remains visible immediately after a failed save and still clears
correctly when the user retries or changes selection.
🪄 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: 539eaf38-953a-44b7-b833-56f5f60fe080
📒 Files selected for processing (5)
apps/web/src/features/availability/components/mvp-availability-page.tsxapps/web/src/features/schedules/components/mvp-schedules-page.tsxapps/web/src/features/schedules/utils/unfilled-conditions.test.tsapps/web/src/lib/schedule-display.test.tsapps/web/src/lib/schedule-display.ts
| visitedKeys: Set<string>; | ||
| } | null>(null); | ||
| const suppressNextCellClickRef = useRef(false); | ||
| const hasUnsavedChangesRef = useRef(false); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
기존 근무 기간이 있으면 새 기간 선택이 즉시 되돌아갑니다.
Line 497에서 activePlanningPeriod를 무조건 다시 주입하는데, 이 effect가 workStartDate/workEndDate 변경에도 실행됩니다. 사용자가 새 시작일을 고르면 Line 497-498이 기존 저장 기간으로 되돌려 종료일 선택을 완료할 수 없습니다. 서버 planning period가 실제로 바뀐 경우에만 동기화하세요.
수정 예시
const suppressNextCellClickRef = useRef(false);
const hasUnsavedChangesRef = useRef(false);
+ const lastSyncedPlanningPeriodKeyRef = useRef<string | null>(null);
useEffect(() => {
if (!planningPeriodQuery.data) {
return;
}
if (!activePlanningPeriod) {
+ if (hasUnsavedChangesRef.current) {
+ setSaveMessage("가능 시간을 저장하거나 변경 취소한 뒤 근무 기간 변경을 반영해 주세요.");
+ return;
+ }
+
+ lastSyncedPlanningPeriodKeyRef.current = null;
setWorkStartDate("");
setWorkEndDate("");
return;
}
+ const planningPeriodKey = `${activePlanningPeriod.startDate}:${activePlanningPeriod.endDate}`;
+
+ if (lastSyncedPlanningPeriodKeyRef.current === planningPeriodKey) {
+ return;
+ }
+
if (
hasUnsavedChangesRef.current &&
(activePlanningPeriod.startDate !== workStartDate ||
activePlanningPeriod.endDate !== workEndDate)
) {
setSaveMessage("가능 시간을 저장하거나 변경 취소한 뒤 근무 기간 변경을 반영해 주세요.");
return;
}
+ lastSyncedPlanningPeriodKeyRef.current = planningPeriodKey;
setWorkStartDate(activePlanningPeriod.startDate);
setWorkEndDate(activePlanningPeriod.endDate);
setCalendarMonthDate(getMonthStartDate(activePlanningPeriod.startDate));Also applies to: 488-500
🤖 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 `@apps/web/src/features/availability/components/mvp-availability-page.tsx` at
line 408, The synchronization logic in mvp-availability-page.tsx is reapplying
activePlanningPeriod even when the user edits workStartDate or workEndDate,
which causes the newly selected period to snap back. Update the effect around
activePlanningPeriod so it only syncs when the server-side planning period truly
changes, and exclude normal local date edits from retriggering the reset. Use
the existing symbols activePlanningPeriod, workStartDate, workEndDate, and
hasUnsavedChangesRef to keep the user’s in-progress selection intact.
개요
develop 브랜치에 쌓인 대시보드, 보관함, 스케줄 추천/확정, Swagger 문서 개선 사항을 main 브랜치에 반영합니다.
관련 이슈 없음
변경 사항
변경 유형
feat— 새로운 기능fix— 버그 수정refactor— 리팩터링 (기능 변경 없음)test— 테스트 코드perf— 성능 개선docs— 문서 수정chore— 빌드·설정 변경영향 범위
web—apps/webapi—apps/apidb—packages/databaseshared—packages/sharedrepo— 루트 설정·CI/CD·문서테스트 방법
corepack pnpm format:checkcorepack pnpm --filter @fragment/web lintcorepack pnpm --filter @fragment/web typecheckcorepack pnpm --filter @fragment/web exec vitest run src/lib/schedule-display.test.ts src/features/schedules/components/mvp-schedules-page.test.tscorepack pnpm --filter @fragment/api lintcorepack pnpm --filter @fragment/api typecheckcorepack pnpm --filter @fragment/api test -- schedule-history.routes.test.ts체크리스트
packages/shared) 업데이트 (타입 변경 시)스크린샷 / 영상
첨부하지 않았습니다.
리뷰 포인트
workDate기준 익일 표시를 올바르게 처리하는지 확인해 주세요.Summary by CodeRabbit
New Features
Bug Fixes