fix(dayplan): per-day transport positions for multi-day reservations

Reordering places on one day of a multi-day reservation no longer
affects the order on other days. Transport positions are now stored
per-day in a new reservation_day_positions table instead of a single
global day_plan_position on the reservation.
This commit is contained in:
Maurice
2026-04-05 23:02:42 +02:00
parent a676dbe881
commit 03757ed0af
5 changed files with 89 additions and 18 deletions

View File

@@ -248,7 +248,7 @@ export const reservationsApi = {
create: (tripId: number | string, data: Record<string, unknown>) => apiClient.post(`/trips/${tripId}/reservations`, data).then(r => r.data),
update: (tripId: number | string, id: number, data: Record<string, unknown>) => apiClient.put(`/trips/${tripId}/reservations/${id}`, data).then(r => r.data),
delete: (tripId: number | string, id: number) => apiClient.delete(`/trips/${tripId}/reservations/${id}`).then(r => r.data),
updatePositions: (tripId: number | string, positions: { id: number; day_plan_position: number }[]) => apiClient.put(`/trips/${tripId}/reservations/positions`, { positions }).then(r => r.data),
updatePositions: (tripId: number | string, positions: { id: number; day_plan_position: number }[], dayId?: number) => apiClient.put(`/trips/${tripId}/reservations/positions`, { positions, day_id: dayId }).then(r => r.data),
}
export const weatherApi = {

View File

@@ -366,9 +366,12 @@ const DayPlanSidebar = React.memo(function DayPlanSidebar({
const timed = timedTransports[ti]
const minutes = timed.minutes
// Use persisted position if available
if (timed.data.day_plan_position != null) {
result.push({ type: timed.type, sortKey: timed.data.day_plan_position, data: timed.data })
// Use per-day position if available, fallback to global position
const dayObj = days.find(d => d.id === dayId)
const perDayPos = timed.data.day_positions?.[dayId] ?? timed.data.day_positions?.[String(dayId)]
const effectivePos = perDayPos ?? timed.data.day_plan_position
if (effectivePos != null) {
result.push({ type: timed.type, sortKey: effectivePos, data: timed.data })
continue
}
@@ -500,10 +503,15 @@ const DayPlanSidebar = React.memo(function DayPlanSidebar({
if (transportUpdates.length) {
for (const tu of transportUpdates) {
const res = reservations.find(r => r.id === tu.id)
if (res) res.day_plan_position = tu.day_plan_position
if (res) {
res.day_plan_position = tu.day_plan_position
// Update per-day position for multi-day reservations
if (!res.day_positions) res.day_positions = {}
res.day_positions[dayId] = tu.day_plan_position
}
}
setTransportPosVersion(v => v + 1)
await reservationsApi.updatePositions(tripId, transportUpdates)
await reservationsApi.updatePositions(tripId, transportUpdates, dayId)
}
if (prevAssignmentIds.length) {
const capturedDayId = dayId