[#243][fe][schedule]feat: 일정 삭제 화면#245
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Walkthrough
Sequence Diagram(s)sequenceDiagram
autonumber
actor User as 사용자
participant MV as ModifyScheduleView
participant SF as ScheduleForm (mode="edit")
participant DM as DeleteScheduleModal
participant USF as useScheduleForm
participant SS as scheduleService
participant API as schedule/api.js
participant BE as Backend
User->>SF: "삭제" 버튼 클릭
SF->>DM: v-model=true (모달 열기)
alt 해당 일정만 삭제
User->>DM: "해당 일정만 삭제"
DM-->>SF: emit deleteOne
SF-->>MV: emit deleteOne(formData)
MV->>USF: onDeleteOne(payload)
USF->>SS: deleteSchedule({scheduleId, instanceDate, startAt, endAt})
SS->>API: deleteSchedule(payload)
API->>BE: DELETE /v1/schedules (body=payload)
alt 성공
BE-->>API: 200
API-->>SS: resolve
SS-->>USF: resolve
USF->>USF: 날짜 갱신/재조회
USF-->>MV: onSuccess 콜백
MV-->>User: 화면 이동/알림
else 실패
BE-->>API: 4xx/5xx
API-->>SS: error
SS-->>USF: error
USF-->>MV: onError 콜백
MV-->>User: 에러 표시
end
DM-->>SF: emit update:modelValue(false)
else 이후 일정 모두 삭제
User->>DM: "이후 일정 모두 삭제"
DM-->>SF: emit deleteAll
SF-->>MV: emit deleteAll(formData)
MV->>USF: onDeleteAll({scheduleId, fromAt})
USF->>SS: deleteSchedulesStartingFrom({scheduleId, fromAt})
SS->>API: deleteSchedulesStartingFrom(payload)
API->>BE: DELETE /v1/schedules/from (body=payload)
alt 성공
BE-->>API: 200
API-->>SS: resolve
SS-->>USF: resolve
USF->>USF: 날짜 갱신/재조회
USF-->>MV: onSuccess 콜백
MV-->>User: 화면 이동/알림
else 실패
BE-->>API: 4xx/5xx
API-->>SS: error
SS-->>USF: error
USF-->>MV: onError 콜백
MV-->>User: 에러 표시
end
DM-->>SF: emit update:modelValue(false)
end
sequenceDiagram
autonumber
participant RU as rruleUtils.expandRecurringSchedule
participant OV as scheduleOverrides
RU->>RU: 초기 인스턴스 계산
RU->>OV: override 목록 필터링(overrideDate 존재 ∧ type≠CANCELLED)
loop 반복 확장
RU->>RU: 다음 발생일 계산
alt until 경계 존재
RU->>RU: nextDate > until 이면 중단
end
RU->>RU: CANCELLED 오버라이드 스킵
RU->>RU: 유효 오버라이드 적용
end
RU-->>RU: 결과 반환
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
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: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (8)
front/src/features/schedule/api.js(1 hunks)front/src/features/schedule/components/DeleteScheduleModal.vue(1 hunks)front/src/features/schedule/components/ScheduleForm.vue(2 hunks)front/src/features/schedule/scheduleService.js(2 hunks)front/src/features/schedule/useScheduleForm.js(7 hunks)front/src/features/schedule/views/CreateScheduleView.vue(1 hunks)front/src/features/schedule/views/ModifyScheduleView.vue(3 hunks)front/src/shared/utils/rruleUtils.js(5 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-07-22T08:47:21.989Z
Learnt from: HanaHww2
PR: HI-dle/rouby#183
File: front/src/shared/utils/rruleUtils.js:144-144
Timestamp: 2025-07-22T08:47:21.989Z
Learning: front/src/shared/utils/rruleUtils.js에서 schedule 인스턴스는 의도적으로 `id`와 `originId` 두 속성을 모두 가집니다. override인 경우 `id`가 달라지므로 `originId`로 원본 스케줄을 추적하고, 인스턴스 키는 `instance.id`(override의 경우 override ID)를 사용합니다.
Applied to files:
front/src/shared/utils/rruleUtils.js
📚 Learning: 2025-07-09T16:16:59.462Z
Learnt from: HanaHww2
PR: HI-dle/rouby#113
File: front/src/features/schedule/validations.js:3-28
Timestamp: 2025-07-09T16:16:59.462Z
Learning: In front/src/features/schedule/useScheduleForm.js, errors are cleared reactively when form input values change rather than clearing all errors at the start of validation. This provides better UX as users see errors disappear immediately when they start fixing the specific fields that caused them.
Applied to files:
front/src/features/schedule/useScheduleForm.js
🧬 Code graph analysis (3)
front/src/features/schedule/api.js (1)
front/src/features/schedule/scheduleService.js (4)
deleteSchedule(30-32)deleteSchedule(30-32)deleteSchedulesStartingFrom(34-36)deleteSchedulesStartingFrom(34-36)
front/src/features/schedule/scheduleService.js (2)
front/src/features/schedule/api.js (4)
deleteSchedule(26-32)deleteSchedule(26-32)deleteSchedulesStartingFrom(34-40)deleteSchedulesStartingFrom(34-40)front/src/shared/utils/errorUtils.js (1)
wrapApi(33-41)
front/src/features/schedule/useScheduleForm.js (3)
front/src/shared/utils/dateTimeUtils.js (2)
formatDateTime(5-23)formatDateTime(5-23)front/src/features/schedule/validations.js (2)
validateForm(3-28)validateForm(3-28)front/src/features/schedule/scheduleService.js (8)
createSchedule(7-12)createSchedule(7-12)updateSchedule(22-28)updateSchedule(22-28)deleteSchedule(30-32)deleteSchedule(30-32)deleteSchedulesStartingFrom(34-36)deleteSchedulesStartingFrom(34-36)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
| default: 'create', // 'create' | 'edit' | ||
| }, | ||
| }) | ||
| const emit = defineEmits(['submit', 'cancel', 'inputDatetime', 'autoResize']) |
There was a problem hiding this comment.
새로 추가한 삭제 이벤트를 defineEmits에 선언해야 합니다.
emit('deleteOne', ...), emit('deleteAll', ...)를 호출하지만 defineEmits 배열에 포함되어 있지 않아 런타임 경고와 타입 추론 오류가 발생합니다. 아래처럼 이벤트 목록을 업데이트해주세요.
-const emit = defineEmits(['submit', 'cancel', 'inputDatetime', 'autoResize'])
+const emit = defineEmits([
+ 'submit',
+ 'cancel',
+ 'inputDatetime',
+ 'autoResize',
+ 'deleteOne',
+ 'deleteAll',
+])📝 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.
| const emit = defineEmits(['submit', 'cancel', 'inputDatetime', 'autoResize']) | |
| const emit = defineEmits([ | |
| 'submit', | |
| 'cancel', | |
| 'inputDatetime', | |
| 'autoResize', | |
| 'deleteOne', | |
| 'deleteAll', | |
| ]) |
🤖 Prompt for AI Agents
In front/src/features/schedule/components/ScheduleForm.vue around line 24, the
component calls emit('deleteOne', ...) and emit('deleteAll', ...) but those
events are not declared in the defineEmits array, causing runtime warnings and
broken type inference; update the defineEmits call to include 'deleteOne' and
'deleteAll' (and any relevant payload typings if using TypeScript) so the
emitted events are declared and properly typed.
| initValues.allDay ? subDays(initValues.end, 1) : initValues.end, | ||
| ) |
There was a problem hiding this comment.
하루종일 일정 초기화 시 subDays에 문자열을 직접 전달하면 TypeError가 발생합니다.
API에서 내려오는 initValues.end는 문자열인데, 현재 코드에서는 그대로 subDays에 넘겨 즉시 예외가 발생합니다. 날짜 객체로 변환한 뒤 하루를 빼도록 수정해주세요.
- initValues.allDay ? subDays(initValues.end, 1) : initValues.end,
+ initValues.allDay
+ ? subDays(new Date(initValues.end), 1)
+ : initValues.end,🤖 Prompt for AI Agents
In front/src/features/schedule/useScheduleForm.js around lines 40-41,
initValues.end is a string from the API and is passed directly to subDays
causing a TypeError; convert the string to a Date object before calling subDays
(e.g., use new Date(initValues.end) or parseISO/init parsing used in the
codebase) and guard against null/undefined so you call subDays only with a valid
Date.
| const handleDeleteOne = async (schedule) => { | ||
| const instanceDate = route.params.date | ||
| console.log(schedule) | ||
| await onDeleteOne( | ||
| { scheduleId: schedule.id, instanceDate: instanceDate, startAt: schedule.start, endAt: schedule.end }, | ||
| () => { | ||
| router.push('/schedule/daily/list') | ||
| }, | ||
| (msg) => { | ||
| errorModal.msg = msg | ||
| errorModal.show = true | ||
| }, | ||
| ) | ||
| } | ||
|
|
||
| const handleDeleteAll = async (schedule) => { | ||
| await onDeleteAll( | ||
| { scheduleId: schedule.id, fromAt: schedule.start }, | ||
| () => { | ||
| router.push('/schedule/daily/list') | ||
| }, | ||
| (msg) => { | ||
| errorModal.msg = msg | ||
| errorModal.show = true | ||
| }, | ||
| ) | ||
| } |
There was a problem hiding this comment.
삭제 요청에 필요한 필드가 잘못 전달되어 런타임 예외와 잘못된 API 호출이 발생합니다.
현재 핸들러는 이벤트 인자로 넘어오는 schedule을 기대하지만, DeleteScheduleModal→ScheduleForm 연쇄에서 payload가 없는 경우 schedule이 undefined가 되어 즉시 TypeError가 발생합니다. 또한 스토어에서 가져온 인스턴스는 startAt/endAt 속성을 사용하기 때문에 schedule.start/schedule.end로 보내면 값이 undefined가 되어 서버가 일정을 식별하지 못합니다. 상위 스코프의 schedule을 직접 사용하고 올바른 필드명을 전달하도록 수정해주세요.
-const handleDeleteOne = async (schedule) => {
- const instanceDate = route.params.date
- console.log(schedule)
- await onDeleteOne(
- { scheduleId: schedule.id, instanceDate: instanceDate, startAt: schedule.start, endAt: schedule.end },
+const handleDeleteOne = async () => {
+ if (!schedule) return
+ const instanceDate = route.params.date
+ await onDeleteOne(
+ {
+ scheduleId: schedule.id,
+ instanceDate,
+ startAt: schedule.startAt,
+ endAt: schedule.endAt,
+ },
@@
-const handleDeleteAll = async (schedule) => {
- await onDeleteAll(
- { scheduleId: schedule.id, fromAt: schedule.start },
+const handleDeleteAll = async () => {
+ if (!schedule) return
+ await onDeleteAll(
+ {
+ scheduleId: schedule.id,
+ fromAt: schedule.startAt,
+ },📝 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.
| const handleDeleteOne = async (schedule) => { | |
| const instanceDate = route.params.date | |
| console.log(schedule) | |
| await onDeleteOne( | |
| { scheduleId: schedule.id, instanceDate: instanceDate, startAt: schedule.start, endAt: schedule.end }, | |
| () => { | |
| router.push('/schedule/daily/list') | |
| }, | |
| (msg) => { | |
| errorModal.msg = msg | |
| errorModal.show = true | |
| }, | |
| ) | |
| } | |
| const handleDeleteAll = async (schedule) => { | |
| await onDeleteAll( | |
| { scheduleId: schedule.id, fromAt: schedule.start }, | |
| () => { | |
| router.push('/schedule/daily/list') | |
| }, | |
| (msg) => { | |
| errorModal.msg = msg | |
| errorModal.show = true | |
| }, | |
| ) | |
| } | |
| const handleDeleteOne = async () => { | |
| if (!schedule) return | |
| const instanceDate = route.params.date | |
| await onDeleteOne( | |
| { | |
| scheduleId: schedule.id, | |
| instanceDate, | |
| startAt: schedule.startAt, | |
| endAt: schedule.endAt, | |
| }, | |
| () => { | |
| router.push('/schedule/daily/list') | |
| }, | |
| (msg) => { | |
| errorModal.msg = msg | |
| errorModal.show = true | |
| }, | |
| ) | |
| } | |
| const handleDeleteAll = async () => { | |
| if (!schedule) return | |
| await onDeleteAll( | |
| { | |
| scheduleId: schedule.id, | |
| fromAt: schedule.startAt, | |
| }, | |
| () => { | |
| router.push('/schedule/daily/list') | |
| }, | |
| (msg) => { | |
| errorModal.msg = msg | |
| errorModal.show = true | |
| }, | |
| ) | |
| } |
🤖 Prompt for AI Agents
In front/src/features/schedule/views/ModifyScheduleView.vue around lines 67 to
93, the handlers read an event arg `schedule` which can be undefined and they
send wrong property names (using schedule.start/schedule.end) to the API;
instead reference the component's outer-scope `schedule` variable (not the event
arg) and send the correct fields: use schedule.id and schedule.startAt /
schedule.endAt (keep instanceDate from route.params.date), and add a simple
guard to return early if the outer-scope schedule is falsy before calling
onDeleteOne/onDeleteAll so no TypeError occurs.
| console.log(rruleStr) | ||
| const vevent = new ICAL.Component('vevent') |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
디버그용 console.log를 제거해주세요.
공용 util에서 남아 있는 console.log는 운영 환경에서 불필요한 노이즈이자 민감한 데이터가 노출될 가능성이 있습니다. 로그 대신 디버깅 도구나 명시적인 로거를 사용해주세요.
- console.log(rruleStr)
@@
- console.log(recurrence)
@@
- console.log("언틸" + recurrence.until)Also applies to: 64-65, 98-101
🤖 Prompt for AI Agents
In front/src/shared/utils/rruleUtils.js around lines 23-24 (and also at 64-65
and 98-101), there are leftover console.log debug statements that should be
removed; delete those console.log calls and, if runtime visibility is required,
replace them with calls to the project's logger (e.g., import and use the
existing logger or a debug utility) or wrap them behind a debug flag so no
sensitive data is printed in production. Ensure no other console.* calls remain
in this util and run a quick search to confirm removal.
|
|
||
| const handleDeleteOne = async (schedule) => { | ||
| const instanceDate = route.params.date | ||
| console.log(schedule) |
| format(parseISO(o.overrideDate), 'yyyy-MM-dd'), | ||
| ), | ||
| (schedule.scheduleOverrides || []) | ||
| .filter(o => o.overrideDate && o.overrideType?.toUpperCase() !== 'CANCELLED') |
There was a problem hiding this comment.
여기서 필터링하면 이후 로직에서 오버라이드 되었던 일자에도 일정을 생성하게 됩니다.
아래 오버라이드 일정 만드는 부분에서 조건절로 취소인 경우는 제외하기만 하면 될 거 같아요.
| ) | ||
| } | ||
|
|
||
| // ---------- overridesType이 cancelled면 필터링하자 |
There was a problem hiding this comment.
불필요한 주석이나 콘솔로그는 제거 부탁드릴게요~
|
|
||
| console.log("언틸" + recurrence.until) | ||
| // 반복 종료 체크: recurrence.until 또는 untilAt 반영 | ||
| if (recurrence.until && nextDate > parseISO(recurrence.until)) break |
There was a problem hiding this comment.
until 은 createIcalComponent 메소드에서 리커런스룰을 통해서 반영되어 일정 목록을 생성해주는지 확인 부탁드릴게요.
| } | ||
| // 단일 일정 삭제 | ||
| return axios.patch('/v1/schedules', payload, { | ||
| headers: { 'Content-Type': 'application/json' }, |
There was a problem hiding this comment.
이걸 제거하면 안되더라구요
| const { rangeStart, rangeEnd } = getMonthRange(monthKey) | ||
|
|
||
| // 반복이 없는 경우 | ||
| console.log(recurrence) |
#️⃣연관된 이슈
변경 타입
변경 내용
as-is
to-be(변경 후 설명을 여기에 작성)
체크리스트
코멘트
Summary by CodeRabbit
신기능
버그 수정