mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
fix(tours): simplify post-save confirmation
This commit is contained in:
@@ -146,16 +146,18 @@ describe('TourPlannerToursRail', () => {
|
||||
expect(controller.openTour).toHaveBeenCalledWith(tour)
|
||||
})
|
||||
|
||||
it('TOUR-PLANNER-RAIL-003: assigns the saved tour immediately when a day is picked', async () => {
|
||||
it('keeps the post-save confirmation compact and assigns through the saved TOUR-PLANNER row action', async () => {
|
||||
const controller = planner({ saveOutcome: tour, editingPlaceId: tour.place_id })
|
||||
const onAssignToDay = vi.fn().mockResolvedValue(undefined)
|
||||
render(<TourPlannerToursRail planner={controller} tours={[tour]} {...railProps} onAssignToDay={onAssignToDay} />)
|
||||
|
||||
expect(screen.getByRole('status')).toHaveTextContent('Tour saved')
|
||||
expect(screen.queryByRole('button', { name: 'Assign to a day' })).not.toBeInTheDocument()
|
||||
expect(onAssignToDay).not.toHaveBeenCalled()
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Plan another' }))
|
||||
expect(controller.startNewTour).toHaveBeenCalledOnce()
|
||||
expect(controller.discard).not.toHaveBeenCalled()
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Assign to a day' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Add to day: Saved ridge walk' }))
|
||||
const dayOption = screen.getByRole('button', { name: /Summit day/ })
|
||||
expect(dayOption).toHaveTextContent(/Day 1/i)
|
||||
expect(dayOption).toHaveTextContent(/May 15/i)
|
||||
@@ -164,16 +166,17 @@ describe('TourPlannerToursRail', () => {
|
||||
await waitFor(() => expect(onAssignToDay).toHaveBeenCalledWith(42, 7))
|
||||
})
|
||||
|
||||
it('keeps the saved outcome and its day action when assignment fails', async () => {
|
||||
it('keeps the save confirmation and row assignment action available when row assignment fails', async () => {
|
||||
const controller = planner({ saveOutcome: tour, editingPlaceId: tour.place_id })
|
||||
const onAssignToDay = vi.fn().mockResolvedValue(false)
|
||||
render(<TourPlannerToursRail planner={controller} tours={[tour]} {...railProps} onAssignToDay={onAssignToDay} />)
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Assign to a day' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Add to day: Saved ridge walk' }))
|
||||
fireEvent.click(screen.getByRole('button', { name: /Summit day/ }))
|
||||
|
||||
await waitFor(() => expect(onAssignToDay).toHaveBeenCalledWith(42, 7))
|
||||
expect(screen.getByRole('status')).toHaveTextContent('Tour saved')
|
||||
expect(screen.getByRole('button', { name: 'Assign to a day' })).toBeEnabled()
|
||||
expect(screen.queryByRole('button', { name: 'Assign to a day' })).not.toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: 'Add to day: Saved ridge walk' })).toBeEnabled()
|
||||
})
|
||||
|
||||
it('TOUR-PLANNER-RAIL-004: protects a dirty draft before selecting a GPX Tour', () => {
|
||||
|
||||
@@ -398,7 +398,6 @@ export function TourPlannerToursRail({ planner, tours, days, loading, onAssignTo
|
||||
const toast = useToast()
|
||||
const distanceUnit = useSettingsStore(state => state.settings.distance_unit)
|
||||
const [pendingTour, setPendingTour] = useState<TourListItem | null>(null)
|
||||
const [assigning, setAssigning] = useState(false)
|
||||
const isSaving = planner.isSaving
|
||||
const hasRoute = (planner.mode.type === 'new-draft' || planner.mode.type === 'edit-saved') && planner.route !== null
|
||||
const routeAnalysis = planner.routeAnalysis
|
||||
@@ -422,17 +421,6 @@ export function TourPlannerToursRail({ planner, tours, days, loading, onAssignTo
|
||||
selectTour(tour)
|
||||
}
|
||||
|
||||
const assignSavedTour = async (dayId: number) => {
|
||||
const savedTour = planner.saveOutcome
|
||||
if (!canAssign || !savedTour) return
|
||||
setAssigning(true)
|
||||
try {
|
||||
await onAssignToDay(savedTour.place_id, dayId)
|
||||
} finally {
|
||||
setAssigning(false)
|
||||
}
|
||||
}
|
||||
|
||||
const walkingTime = { label: t('tours.planner.inspector.duration'), value: t('tours.durationMinutes', { count: Math.max(1, Math.round((planner.durationSeconds ?? 0) / 60)) }) }
|
||||
|
||||
return (
|
||||
@@ -464,20 +452,9 @@ export function TourPlannerToursRail({ planner, tours, days, loading, onAssignTo
|
||||
<CheckCircle2 size={16} strokeWidth={2} className="flex-none text-success" />
|
||||
{t('tours.planner.saved')}
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<DialogButton onClick={() => { if (canEdit && !isSaving) planner.startNewTour() }} disabled={!canEdit || isSaving}>
|
||||
{t('tours.planner.planAnother')}
|
||||
</DialogButton>
|
||||
<TourDayMenu
|
||||
variant="button"
|
||||
primary
|
||||
days={days}
|
||||
placeId={planner.saveOutcome.place_id}
|
||||
label={t('tours.planner.assignToDay')}
|
||||
disabled={!canAssign || assigning}
|
||||
onPick={day => { void assignSavedTour(day.id) }}
|
||||
/>
|
||||
</div>
|
||||
<DialogButton onClick={() => { if (canEdit && !isSaving) planner.startNewTour() }} disabled={!canEdit || isSaving}>
|
||||
{t('tours.planner.planAnother')}
|
||||
</DialogButton>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1101,4 +1101,27 @@ describe('useTourPlanner', () => {
|
||||
await act(async () => { expect(await result.current.save()).toBeNull() })
|
||||
expect(updateTour).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('keeps the existing save-failure notice and draft when a Tour update fails', async () => {
|
||||
detailTour.mockResolvedValue({
|
||||
tour: savedTour,
|
||||
waypoints: [
|
||||
{ lat: 48, lng: 11, role: 'start', sequence: 0 },
|
||||
{ lat: 48.01, lng: 11.02, role: 'end', sequence: 1 },
|
||||
],
|
||||
})
|
||||
updateTour.mockRejectedValue(new Error('Tour update failed'))
|
||||
const { result } = renderHook(() => useTourPlanner({ tripId: 29 }))
|
||||
await act(async () => { expect(await result.current.openTour(savedTour)).toBe(true) })
|
||||
act(() => result.current.setName('Keep this draft'))
|
||||
await act(async () => { await vi.advanceTimersByTimeAsync(450) })
|
||||
const view = render(<TourPlannerRail planner={result.current} />)
|
||||
|
||||
await act(async () => { expect(await result.current.save()).toBeNull() })
|
||||
view.rerender(<TourPlannerRail planner={result.current} />)
|
||||
|
||||
expect(result.current.editingPlaceId).toBe(savedTour.place_id)
|
||||
expect(result.current.name).toBe('Keep this draft')
|
||||
expect(screen.getByText('Tour could not be saved. Your draft is still here.')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user