Skip to content

[Fix] DateRangePicker 컴포넌트 커스텀화#198

Merged
chocoboy08 merged 5 commits intodevfrom
fix/change-date-range-picker
Dec 30, 2025
Merged

[Fix] DateRangePicker 컴포넌트 커스텀화#198
chocoboy08 merged 5 commits intodevfrom
fix/change-date-range-picker

Conversation

@chocoboy08
Copy link
Member

@chocoboy08 chocoboy08 commented Dec 30, 2025

Describe your changes

QA 내용
image

  • MUI 컴포넌트를 커스텀 DateRangePicker 컴포넌트로 교체했습니다.

To Reviewers

  • 시작일, 종료일 선택 방식이 기존의 흐름과 달라졌습니다. 사용성 피드백이 필요할 것 같습니다.

Summary by CodeRabbit

  • New Features

    • 이벤트 일정 등록 시 날짜 범위를 선택할 수 있는 새로운 날짜 범위 선택기 추가
    • 선택된 날짜 범위가 한국어 형식(YYYY.MM.DD. - YYYY.MM.DD.)으로 표시
  • Bug Fixes

    • 시작/종료 날짜가 각각 하루 전체를 포괄하도록 정상화하여 범위 처리 정확성 향상
    • 설명 입력이 없을 때 빈 문자열로 안전하게 처리
  • Chores

    • 날짜 처리와 UI용 라이브러리 의존성 추가 (date-fns, react-day-picker)

✏️ Tip: You can customize this high-level summary in your review settings.

@chocoboy08 chocoboy08 requested a review from a team as a code owner December 30, 2025 10:11
@coderabbitai
Copy link

coderabbitai bot commented Dec 30, 2025

Walkthrough

로컬 React DateRangePicker 컴포넌트와 관련 의존성(date-fns, react-day-picker)을 추가하고, 기존 EventInformation에서 MUI Pro 날짜 선택기를 로컬 DateRangePicker로 교체해 날짜 범위 선택 및 시작/종료일 정규화를 구현했습니다.

Changes

Cohort / File(s) 변경 사항
의존성 추가
package.json
date-fns ^4.1.0, react-day-picker ^9.12.0 추가
새 컴포넌트
src/components/EditEvent/DateRangePicker.tsx
읽기 전용 MUI TextField 클릭으로 Popover 내 react-day-picker 범위 선택 UI 표시하는 DateRangePicker 추가. 한국어 로케일 적용, 범위 선택 시 onChange 호출, 완전 범위 선택 시 자동 닫힘
컴포넌트 통합 및 정규화
src/components/EditEvent/EventInformation.tsx
기존 MUI Pro DateRangePicker 제거 후 로컬 DateRangePicker로 대체. 선택값을 startOfDay(시작) / endOfDay(종료)로 정규화하고 description ?? ""로 방어적 처리 적용

Sequence Diagram(s)

sequenceDiagram
  participant User as 사용자
  participant Input as TextField
  participant Pop as Popover
  participant Day as DayPicker
  participant Parent as EventInformation

  Note over Input,Day: 색상 `#DDEBF7` 배경 (변경/새로 추가된 흐름)
  사용자->>Input: 클릭 (날짜 필드)
  Input->>Pop: open(anchorEl)
  Pop->>Day: 렌더(범위 모드, locale=ko)
  사용자->>Day: 범위 선택 (from, to)
  Day-->>Input: 선택값 업데이트
  Input->>Parent: onChange({from, to})
  Parent->>Parent: startOfDay(from), endOfDay(to)
  Day->>Pop: 완전 범위 선택 시 close
  Pop->>Input: close()
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 달빛 아래 캘린더 살랑,
클릭 한 번에 팝오버 활짝,
시작은 새벽, 끝은 밤까지,
날짜들 모아 한 줄로 담아,
토끼가 기쁘게 깡총깡총!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed 제목은 DateRangePicker 컴포넌트 커스텀화라는 실제 변경사항을 명확하게 반영하고 있으며, 주요 변경사항을 간결하게 요약하고 있습니다.
Description check ✅ Passed PR 설명은 템플릿의 필수 섹션을 모두 포함하고 있으며, 변경사항과 리뷰어 참고사항이 명확하게 작성되어 있습니다.
✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

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)
package.json (1)

20-21: 사용하지 않는 의존성 정리 필요

@mui/x-date-pickers-pro는 코드베이스에서 전혀 사용되지 않고 있습니다. 커스텀 DateRangePicker가 react-day-picker를 기반으로 구현되어 있어 이 의존성을 제거할 수 있습니다.

또한 dayjsdate-fns가 혼재되어 있습니다. dayjs는 EventInformation.tsx와 RecruitmentRound 관련 모달에서 주로 날짜 관리에 사용되고, date-fns는 DateRangePicker.tsx에서 한국어 로케일 포맷팅에만 사용되고 있습니다. dayjs의 포맷팅 기능으로 통일하는 것을 검토하세요.

🧹 Nitpick comments (4)
src/components/EditEvent/DateRangePicker.tsx (3)

9-67: 디자인 토큰 사용을 고려하세요.

StyledDayPicker의 색상 값이 하드코딩되어 있습니다. wowds-tokenscolor 토큰을 사용하면 일관된 디자인 시스템을 유지할 수 있습니다.

또한 Lines 49-51에서 !important를 사용하고 있는데, 이는 스타일 우선순위 문제를 나타낼 수 있습니다. react-day-picker의 기본 스타일 오버라이드 방법을 확인해보세요.


98-110: 클릭 가능한 필드임을 시각적으로 표시하세요.

읽기 전용 TextField가 클릭 가능하지만, 사용자에게 이를 명확히 알려주는 시각적 단서(커서 모양, 아이콘 등)가 없습니다.

🔎 제안하는 개선 사항
       <TextField
         ref={inputRef}
         value={formatDateRange()}
         onClick={handleClick}
         label={"행사 신청 기간"}
         InputProps={{
           readOnly: true,
+          endAdornment: (
+            <InputAdornment position="end">
+              <CalendarTodayIcon />
+            </InputAdornment>
+          ),
         }}
-        style={{ backgroundColor: "white" }}
+        style={{ backgroundColor: "white", cursor: "pointer" }}
         variant="outlined"
         fullWidth
         size="small"
       />

추가로 import가 필요합니다:

import { InputAdornment } from "@mui/material";
import CalendarTodayIcon from "@mui/icons-material/CalendarToday";

98-110: 접근성 개선을 위한 ARIA 속성을 추가하세요.

스크린 리더 사용자를 위해 TextField에 적절한 ARIA 속성을 추가하면 접근성이 향상됩니다.

🔎 제안하는 개선 사항
       <TextField
         ref={inputRef}
         value={formatDateRange()}
         onClick={handleClick}
         label={"행사 신청 기간"}
         InputProps={{
           readOnly: true,
+          'aria-label': '행사 신청 기간 선택',
+          'aria-haspopup': 'dialog',
+          'aria-expanded': open,
         }}
         style={{ backgroundColor: "white" }}
         variant="outlined"
         fullWidth
         size="small"
       />
src/components/EditEvent/EventInformation.tsx (1)

1-24: 날짜 라이브러리 통합을 고려하세요.

현재 dayjsdate-fns 두 가지 날짜 라이브러리를 함께 사용하고 있습니다. 이는 번들 크기를 증가시키고 코드 일관성을 해칠 수 있습니다.

MUI의 DatePicker와 TimePicker가 여전히 dayjs를 사용하고 있으므로, 향후 모든 날짜 처리를 단일 라이브러리로 통합하는 것을 고려해보세요.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5f61c2e and d8ad851.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • package.json
  • src/components/EditEvent/DateRangePicker.tsx
  • src/components/EditEvent/EventInformation.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
src/components/EditEvent/EventInformation.tsx (1)
src/components/EditEvent/DateRangePicker.tsx (1)
  • DateRangePicker (74-129)
🔇 Additional comments (2)
src/components/EditEvent/EventInformation.tsx (1)

595-595: 좋은 방어적 코딩입니다!

description ?? ""를 사용하여 undefined 값을 방지한 것은 제어 컴포넌트의 좋은 사례입니다.

package.json (1)

25-25: 패키지 버전 및 보안 상태 확인됨date-fns@4.1.0react-day-picker@9.12.0은 모두 npm 레지스트리에 존재하는 유효한 버전이며, 알려진 보안 취약점이 없습니다.

  • date-fns@4.1.0: 현재 최신 버전, 보안 취약점 없음
  • react-day-picker@9.12.0: 최신 버전 9.13.0 사용 가능하지만, 현재 버전도 안전함

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/components/EditEvent/DateRangePicker.tsx (1)

47-52: !important 사용을 최소화하는 것을 권장합니다.

CSS 우선순위를 강제하기 위해 !important를 사용하고 있습니다. 라이브러리 기본 스타일을 덮어쓰기 위해 필요할 수 있지만, 더 구체적인 선택자나 스타일 우선순위를 활용하는 방식이 유지보수에 더 유리합니다.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d8ad851 and c40a185.

📒 Files selected for processing (2)
  • src/components/EditEvent/DateRangePicker.tsx
  • src/components/EditEvent/EventInformation.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/EditEvent/EventInformation.tsx
🔇 Additional comments (6)
src/components/EditEvent/DateRangePicker.tsx (6)

69-72: 타입 정의가 명확합니다.

인터페이스가 react-day-picker의 range 모드 API와 잘 맞춰져 있으며, 선택적 속성과 콜백 시그니처가 적절하게 정의되어 있습니다.


74-86: Popover 상태 관리가 올바릅니다.

MUI Popover의 표준 패턴을 정확하게 따르고 있으며, anchor element 관리와 open/close 핸들러가 적절하게 구현되어 있습니다.


88-94: 날짜 형식화 로직이 정확합니다.

모든 케이스(선택 없음, 시작일만, 범위)를 올바르게 처리하고 있으며, 한국어 로케일을 일관되게 사용하고 있습니다.


96-110: TextField 구성이 적절합니다.

읽기 전용 입력 필드로 설정되어 있어 사용자가 picker를 통해서만 날짜를 선택할 수 있도록 강제하고 있으며, 스타일과 속성이 적절하게 설정되어 있습니다.


140-142: 이전 리뷰 피드백이 반영되었습니다.

날짜 범위가 완전히 선택되면 Popover가 자동으로 닫히도록 구현되어 있습니다. 사용성이 개선되었습니다.


1-7: 외부 라이브러리 버전 및 호환성 검증 완료

date-fns 4.1.0과 react-day-picker 9.12.0은 모두 최신 버전이며 호환성이 검증되었습니다. date-fns 4.1.0은 알려진 보안 취약점이 없고, react-day-picker 9.12.0은 date-fns ^4.x에 대한 의존성을 가지고 있어 현재 프로젝트의 버전 구성이 최적으로 구성되어 있습니다.

Comment on lines +128 to +143
onSelect={range => {
// 기간이 선택되어있을 때 새로운 날짜 클릭 시 시작일부터 다시 선택하도록
if (value?.from && value?.to && range?.from) {
const clickedDate =
range.from.getTime() !== value.from.getTime() ? range.from : range.to;

onChange({ from: clickedDate, to: undefined });
return;
}

onChange(range);

if (range?.from && range?.to) {
handleClose();
}
}}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -name "DateRangePicker.tsx" -type f

Repository: gdg-hongik-univ/gdsc-admin

Length of output: 116


🏁 Script executed:

cat -n ./src/components/EditEvent/DateRangePicker.tsx

Repository: gdg-hongik-univ/gdsc-admin

Length of output: 4779


🏁 Script executed:

cd . && find . -name "package.json" -type f | head -5 | xargs grep -l "react-day-picker"

Repository: gdg-hongik-univ/gdsc-admin

Length of output: 84


🏁 Script executed:

cat ./package.json | grep -A 2 -B 2 "react-day-picker"

Repository: gdg-hongik-univ/gdsc-admin

Length of output: 221


🌐 Web query:

react-day-picker v9 range mode onSelect behavior when clicking date after range selected

💡 Result:

Short answer: in v9 DayPicker's range mode keeps internal state, so after a completed range is selected a subsequent click typically adjusts the existing range (moves start or end) instead of automatically clearing it — you can still implement "reset on click" in onSelect when controlled, but you'll see a small flicker because the internal state updates first then the controlled prop overrides it. [1][2][3]

What to do

  • Docs: range mode is intended to be controlled via selected + onSelect. [2]
  • Behavior & bug: the internal-state + controlled-state interaction (and the resulting flicker) is described in issue #2362. [1]
  • Workarounds:
    • Implement reset in onSelect: if selected.from && selected.to then set selected = { from: clickedDate, to: undefined }. This works functionally but may flicker. [1][2]
    • To avoid visual flicker, force a remount when you reset (e.g. change a key on the DayPicker) so the component's internal state is cleared immediately. (Common React workaround; used for similar date-picker issues). [4]
  • Related notes: v9 changed some range semantics vs v8 (e.g. clicking the same day twice behavior). See related issue. [3]

Sources

  • Range internal-state / controlled interaction (issue #2362). [1]
  • Range mode docs (props: selected, onSelect, min/max, required). [2]
  • Change in v9 range click semantics (issue #2302). [3]
  • Remount/key workaround pattern (StackOverflow example). [4]

range.to가 undefined일 수 있어 런타임 오류 발생 가능합니다.

Line 130의 조건 (value?.from && value?.to && range?.from)을 통과하더라도, react-day-picker v9의 범위 모드에서 사용자가 완료된 범위 이후 새로운 날짜를 클릭하면 range{ from: clickedDate, to: undefined }를 전달합니다.

이 경우 Line 132의 삼항 연산자는 range.to를 평가하게 되어 clickedDate가 undefined가 되고, Line 134에서 onChange({ from: undefined, to: undefined })를 호출하게 됩니다.

Line 132를 다음과 같이 수정하여 안전성을 확보하세요:

- const clickedDate =
-   range.from.getTime() !== value.from.getTime() ? range.from : range.to;
+ const clickedDate =
+   range.from.getTime() !== value.from.getTime() ? range.from : (range.to || range.from);

또는 더 간단하게, 완료된 범위 상태에서 새 클릭 시 항상 새 범위의 from을 시작점으로 설정하는 방식으로 전체 조건을 제거할 수도 있습니다.

📝 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
onSelect={range => {
// 기간이 선택되어있을 때 새로운 날짜 클릭 시 시작일부터 다시 선택하도록
if (value?.from && value?.to && range?.from) {
const clickedDate =
range.from.getTime() !== value.from.getTime() ? range.from : range.to;
onChange({ from: clickedDate, to: undefined });
return;
}
onChange(range);
if (range?.from && range?.to) {
handleClose();
}
}}
onSelect={range => {
// 기간이 선택되어있을 때 새로운 날짜 클릭 시 시작일부터 다시 선택하도록
if (value?.from && value?.to && range?.from) {
const clickedDate =
range.from.getTime() !== value.from.getTime() ? range.from : (range.to || range.from);
onChange({ from: clickedDate, to: undefined });
return;
}
onChange(range);
if (range?.from && range?.to) {
handleClose();
}
}}
🤖 Prompt for AI Agents
In src/components/EditEvent/DateRangePicker.tsx around lines 128-143, the
current onSelect handler can read range.to when it may be undefined; change the
logic so clickedDate is never undefined — either (A) replace the ternary with a
safe expression that falls back when range.to is missing (e.g. prefer range.from
and only use range.to if present), or (B) simplify by always using range.from as
the new start when a completed range is clicked (remove the complex condition
and set onChange({ from: range.from, to: undefined }) ), and ensure you only
access range.from/to after checking range is defined.

@chocoboy08 chocoboy08 merged commit 5b2cc4b into dev Dec 30, 2025
2 checks passed
@chocoboy08 chocoboy08 deleted the fix/change-date-range-picker branch December 30, 2025 14:57
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