Repository navigation
fix(plan): 일정 드래그를 낙관적 갱신으로 바꿔 놓자마자 새 자리에 보이도록 수정 - #263
Open
KangShinGyu98 wants to merge 28 commits into
Open
KangShinGyu98 wants to merge 28 commits into
KangShinGyu98 wants to merge 28 commits into
Conversation
- 일차 목록 queryFn이 캐시만 읽던 것을 서버(GET …/items)에서 받도록 변경. 지도 등 같은 키를 읽는 곳도 같은 조회 옵션을 써서 무효화하면 항상 서버에서 받음 - STOMP 이벤트는 목록을 직접 받아 쓰지 않고 무효화. 같은 일차를 받는 중이면 TanStack이 옛 조회를 취소하고 그 응답을 버림 - 일정 전체 응답은 요청을 보낸 뒤 바뀐 일차 목록을 덮지 않음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 장소 추가·시간·메모·이동수단·삭제·순서 변경은 응답을 setQueryData로 반영하고 onSettled에서 그 일차를 무효화 - 장소 추가는 mutationFn에서 요청만 하고 캐시 반영은 onSuccess로 옮김 - 본인 시간·메모 변경의 STOMP 반향(UPDATED)은 진행 중인 조회에 합류하고, 다른 사람 변경이 섞이면 새로 받음 - 손으로 넣었던 분기 삭제: 쓸 때마다 일정 전체 재조회, 못 찾으면 무효화, 실패 시 직접 GET Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 이동수단 선택: 서버 값을 useState로 복사·되돌리던 것을, 저장 중에는 고른 수단(variables), 끝나면 서버 값을 보여 주도록 변경 - 모바일 편집 목록의 순서 변경·일차 이동: pending useState 대신 variables·isPending으로 새 자리를 그림 - 순서 변경의 연쇄 PATCH 대기 useState 삭제. onSuccess가 끝날 때까지 isPending이 이어짐 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 늦게 온 옛 조회 응답, 다시 받는 중 본인 삭제, 일정 전체 응답이 더 새 일차 목록을 덮는지 확인 - 바뀐 함수 모양(공용 조회 옵션, 장소 추가 응답, 모바일 드래그 표시)에 맞춰 기존 테스트 수정 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 경로 key를 (방, 일차, 출발 항목, 도착 장소, 이동수단)으로 바꾼다 — 목록·지도·batch 시딩이 다음 장소의 googlePlaceId를 넘긴다 - 순서가 바뀐 구간은 key가 달라져 옛 도착지의 거리·선을 보여 주지 않는다 - 도착 장소가 없는 구간은 조회하지 않는다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 순서 변경·장소 추가·삭제·일차 간 이동·이동수단 변경(본인·STOMP)과 일정 전체 재조회 뒤의 구간 경로 무효화를 지운다 — 바뀐 구간은 새 key로 받는다 - 구간 계산·무효화 모듈(scheduleStompRouteScope.ts)과 STOMP 경로 무효화 디바운스 삭제 - 장소 삭제는 응답으로 일차 목록에서 그 장소만 빼고, 일차 삭제 뒤의 경로 무효화도 지운다 - 지도 에폭 증가 호출 삭제 (지도 key 정리는 다음 커밋) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 지도 선 key는 (방, 일차, 출발 항목, 출발·도착 장소, 이동수단)만 쓴다 — 도착 장소가 바뀌면 key가 달라져 새 선을 그린다 - 에폭 스토어(plan-map-directions-epoch-store) 삭제 - 선의 React key도 에폭 대신 도착 장소로 구분한다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- batch가 받아 둔 구간 경로를 목록 칸(다음 장소 googlePlaceId)과 지도(지도 구간 계산)가 단건 요청 없이 쓰는지 본다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 서버가 그 순간의 순서로 다음 항목을 고르던 단건 GET에 destinationItemId를 보낸다 — 요청한 구간과 응답 구간이 항상 같다 - 경로 key·지도 선 key·sessionStorage key의 도착 값을 다음 장소의 itemId로 바꾼다 - 서버에 이 파라미터가 배포되기 전에는 서버가 무시하고 지금처럼 다음 항목으로 계산한다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- batch 응답의 toItemId(서버가 계산한 구간의 도착 항목)로 경로 key를 만든다 — 요청 때 목록에서 짐작하지 않는다 - 응답을 기다리는 사이 순서가 바뀌면 결과를 통째로 버리던 일정 지문 비교를 지운다 - 마지막 항목·항목 없음 답은 도착 항목이 없어 저장하지 않고, 그 칸이 도착 항목을 지정한 단건 조회로 받는다 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- useRooms.ts: useReorderScheduleItem은 #250 구조(useMutation + onSettled 무효화)를 남기고 dev의 isReorderSettling 파사드를 버림, JSDoc의 연쇄 PATCH 문구 삭제 - scheduleItemPlaces.ts: #249대로 순서 변경 뒤 시작 시각 연쇄 PATCH 삭제, 쓰지 않게 된 toast·scheduleTime·roomSchedulesQueryKey import 정리 - PlanTravelTime.tsx: #250의 variables 기반 selectedMode를 null 허용 serverMode 위에 둠(dev의 useState 동기화 제거) - scheduleItemPlaces.create.test.ts: #250 테스트 유지, dev의 시간 보존 테스트 2개는 updateScheduleItem 미호출만 확인하도록 맞춤 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- scheduleItemRoutePersistedQuery.ts·useRooms.ts: 도착 항목(destinationItemId: number | null)과 null 이동수단을 함께 받고, null 수단이면 key·조회를 끔 - schedule-bulk-hydration.ts: scheduleSegmentRoutesCached를 도착 항목 기준으로 두고 미설정 수단 구간은 건너뜀, DRIVING 기본값·경로 무효화 import 삭제 - scheduleItemPlaces.ts: syncPlanPlacesAfterReorderSuccess는 #258 시그니처(경로 무효화 없음), #249대로 시작 시각 연쇄 PATCH 삭제 - PlanTravelTime.test.tsx: dev의 DOM 렌더 테스트에 destinationItemId prop과 단건 경로 인자를 더함 - PlanTravelTime.summary.test.tsx·scheduleItemPlaces.create.test.ts: 자동 병합된 테스트를 #258 시그니처에 맞춤 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 같은 일차 순서 변경(movePlanPlaceWithinDay), 일차 간 이동(removePlanPlace·insertPlanPlace) - 일차 순서 변경은 dayNumber·date를 새 자리대로 다시 매김(moveRoomScheduleToDay) - 위치는 서버 순서 API와 같은 뜻(옮긴 뒤 목록에서의 자리), 대상 일차에 이미 있으면 두 번 넣지 않음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- useReorderScheduleItem·useMoveScheduleItemToSchedule: onMutate에서 cancelQueries → 이전 값 저장 → setQueryData, onError에서 이전 값으로 되돌림, onSettled에서 그 일차(들)를 다시 받음 - 순서 응답은 캐시에 쓰지 않음 — 이미 새 순서로 그렸고, 연달아 놓으면 앞 응답이 뒤 저장 전 순서를 다시 그림(syncPlanPlacesAfterReorderSuccess·mergeOrRefetchSchedulePlanPlacesFromItems 삭제) - 두 mutation에 같은 mutationKey를 두고, 같은 일차를 바꾸는 저장이 마지막일 때만 다시 받음(isMutating, TanStack 동시 낙관적 갱신) - 일차 간 이동은 옮길 장소를 출발 일차 캐시에서 꺼내고, 두 일차 무효화를 onSuccess에서 onSettled로 옮김(가계부 무효화는 onSuccess 유지) - 테스트: 응답 전 새 순서·실패 되돌림·진행 중 조회 취소·재조회 실패에도 저장 유지·연달아 저장해도 마지막 순서만 그리고 한 번만 다시 받음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- resolvePlanItemDrop: 놓은 결과({ itemId, from, to })를 보낼 mutation 변수로 바꿈 — 같은 일차는 순서 변경(newOrderIndex), 다른 일차는 일차 간 이동(넣을 자리를 대상 일차 길이로 맞춤), 제자리면 null
- usePlanItemDropCommit: 고른 mutation을 mutateAsync로 보내고 실패하면 토스트, 끝나면 onSettled(잠금이 없어 저장마다 promise를 따로 받음)
- reorder_itinerary는 useReorderScheduleItem onSuccess에서 보냄(쓰기 분석 이벤트는 mutation 훅에), PC·모바일 호출부의 전송 삭제
- 저장 중·연결 끊김·다른 사람의 변경 중에도 막지 않음 — 어긋나도 onSettled 재조회가 서버 상태로 맞춤
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- usePlanItemDragController: 드래그 상태 한 벌(무엇을·어디로·헤더 강조), 행 위치 측정, 미리보기를 갖고 놓으면 usePlanItemDropCommit에 넘김 - 놓은 뒤 캐시(onMutate)가 그 일차 목록을 바꿀 때까지 놓은 모양을 유지해 옛 순서가 한 프레임 보이지 않게 함 - 다른 일차로 놓아도 출발 일차 dragend가 미리보기를 풀지 않음(저장이 끝날 때 품, 그사이 시작한 새 드래그는 풀지 않음) - 손잡이·놓을 영역을 잠그지 않음 — 저장 중·재동기화 중·장소 추가 중·일차 추가·삭제 중에도 끌고 놓을 수 있고 onSettled 재조회가 맞춤 - PlanItinerary·PlanScheduleDayBlock은 컨트롤러가 준 props만 붙이고(PlanScheduleDayBlock의 interactionLocked prop 삭제), PlanDaySection은 헤더 강조를 props(crossDayDrop)로 받음(스토어 구독 제거) - ExpenseProvider 테스트: usePlanItemDropCommit mock 추가 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 캐시는 저장 응답 전에 새 순서지만 서버는 옛 순서라, 단건 경로가 옛 이웃까지 계산돼 새 구간 key에 남을 수 있음(destinationItemId를 무시하는 백엔드) - 저장 중인 일차를 useScheduleItemMoveSavingDays(장소 이동 mutationKey의 useMutationState)로 읽음 - PC 목록·모바일 목록의 routeQueryEnabled와 지도 구간 선 조회를 그 일차만 끔(다른 일차는 그대로) - 저장 중 새 구간은 이동 시간 자리에 Spinner, 지도는 새 구간 선 없이 핀만 새 순서 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- useMobilePlanDragController: mutation·pending 계산 대신 usePlanItemDropCommit 사용, 손잡이를 잠그지 않음(저장 중에도 다음 카드를 끌 수 있음, 끄는 중 다른 손가락만 무시) - 놓은 뒤 캐시(onMutate)가 출발·대상 일차 목록을 바꿀 때까지 놓은 모양을 유지(rowStyle이 그 일차 캐시 목록을 받음) - MobilePlanItinerary는 캐시 목록을 그대로 그림(applyPendingPlanMove 삭제), move mutation의 place 변수 삭제 - context 값을 메모하고 dragDisabled 필드 삭제 - 테스트: pending 테스트를 컨트롤러 놓기·저장 중 유지·저장 중 다음 드래그 테스트로 바꿈, 경로 보기 테스트의 drag 값 모양 맞춤 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- useMoveRoomSchedule: onMutate에서 room-schedules를 옮기고 dayNumber·date를 자리대로 다시 매김, 실패하면 되돌림 - 일정 다시 받기를 onSuccess(refreshRoomSchedules)에서 onSettled(room-schedules 무효화)로 옮기고, 연달아 옮기면 마지막 저장이 끝날 때만 받음(mutationKey + isMutating). 가계부 무효화는 onSuccess 유지 - usePlanScheduleDayReorder: 놓은 뒤 캐시가 일정 목록을 바꿀 때까지 놓은 모양을 유지, drop 뒤 dragend가 풀지 않음(반환 모양은 그대로) - 테스트: 응답 전 새 순서·날짜, 실패 되돌림, 놓은 모양 유지, onSettled 무효화, 연달아 옮기면 한 번만 다시 받음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 삭제: plan-item-cross-day-drag-store, usePlanDaySectionCrossDayDrop, usePlanItineraryReorder(와 분석 테스트 — 놓기 결정·PC 컨트롤러 테스트로 옮김) - planItemReorder.ts: executePlanItemCrossDayMove와 dataTransfer에서 일차·장소·자리를 읽던 함수 삭제, beginPlanItemDrag는 끌기 이미지와 Firefox용 setData만 남김 - scheduleItemPlaces.ts: 쓰는 곳이 없어진 newOrderIndexAfterMove 삭제(놓기 결정이 놓은 자리를 그대로 씀) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 끊긴 동안·놓친 변경을 다시 받는 동안·앞선 일차 저장 중·일차 추가·삭제 중에도 일차를 끌고 놓을 수 있음 — 조금 틀어져도 onSettled 재조회가 서버 상태로 맞춤 - 앞선 저장이 끝나도 그사이 시작한 새 드래그는 풀지 않음(놓기마다 다른 값으로 비교) - usePlanScheduleDayReorder의 interactionLocked 인자 삭제, 일차가 1개일 때만 비활성 - 장소 드래그(PC·모바일)는 처음부터 잠금을 두지 않았으므로 쓰는 곳이 없어진 useScheduleResyncPending·PLAN_ORDER_RESYNCING_MESSAGE 삭제 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 서버에 닿지 못하면 fetch가 TypeError("Failed to fetch")를 던져 그 문구가 토스트에 그대로 보였음(dev부터 있던 동작)
- messageForSaveError(errors.ts): 서버가 준 문구가 있으면 그 문구, 네트워크 오류면 fallback
- 일차 간 이동("다른 일차로 옮기지 못했어요.")·일차 순서 변경("일차 순서를 바꾸지 못했어요.")에 적용
- 테스트: 네트워크 오류일 때 두 문구
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- onSettled가 다시 받기(invalidate) promise를 돌려주면 그 GET이 끝날 때까지 mutateAsync가 reject되지 않아, 화면은 바로 되돌아가는데 토스트만 늦게 떴음 - 순서 변경·일차 간 이동·일차 순서 변경의 onSettled에서 다시 받기를 기다리지 않음(같은 대상의 마지막 저장일 때만 받는 것은 그대로) - 테스트: 다시 받기가 끝나지 않아도 실패를 바로 알림 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- dev의 #250(#258·#260 포함 스쿼시)과 이 브랜치의 로컬 병합본이 겹쳐 12개 파일 충돌 - 이 브랜치만 바꾼 파일(모바일 드래그·테스트, 지도 경로, 가계부 무효화 테스트, useRooms 테스트, usePlanItineraryReorder 삭제)은 이 브랜치 그대로 - dev만 바꾼 schedules-dispatch.ts·두 테스트(탭 ID 반향)는 dev 그대로 - useRooms.ts: dev의 순서 변경 JSDoc 대신 이 브랜치 주석 유지 - scheduleItemPlaces.ts: dev의 invalidateSchedulePlanPlaces joinInFlight 삭제를 얹고, 이 브랜치가 지운 순서 응답 반영 함수는 지운 채로 - scheduleItemPlaces.create.test.ts: 지운 순서 응답 테스트는 지운 채로, dev가 강화한 일차 간 이동 테스트를 받음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This branch was successfully deployed
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.


노션
변경 내용
usePlanItemDragController)가 맡고, PC·모바일이 같은 놓기 결정(resolvePlanItemDrop·usePlanItemDropCommit)을 씀. 놓은 뒤 캐시가 바뀔 때까지 놓은 모양을 유지해 원래 자리로 튀지 않음destinationItemId를 아직 무시해 옛 이웃 경로가 새 key에 남는 문제)Failed to fetch대신 한국어 문구.reorder_itinerary는 순서 변경 mutation onSuccess에서 보냄변경 이유
테스트
npm run lintnpm testnpm run build🤖 Generated with Claude Code