mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 13:36:48 +00:00
refactor(planner): share the trip sheet wiring between desktop and phone
The phone trip sheet host wrote out by hand three pieces of planner wiring the desktop planner already had. useBookingExpenseEditor now holds the expense editor both planners open over the trip: the booking request state, the receipt fallback, the base currency, the current user and the save that reloads the budget. TripPlannerPage and MTripSheets both read it. applyTripCoverUpdate patches a new trip cover into the store for the trip form on both sides. The transport editor and the transit route change moved into openTransportEditorWith and changeTransitRouteWith, which take the planner's setters. usePlannerDialogs builds openTransportEditor and changeTransitRoute on them, and the phone sheet calls the same helpers on the planner it receives. There are no differences between the two views to keep as options.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import TransitJourneyModal from '../../../../components/Planner/TransitJourneyModal'
|
||||
import BookingImportModal from '../../../../components/Planner/BookingImportModal'
|
||||
@@ -6,11 +6,9 @@ import AirTrailImportModal from '../../../../components/Planner/AirTrailImportMo
|
||||
import TripFormModal from '../../../../components/Trips/TripFormModal'
|
||||
import TripMembersModal from '../../../../components/Trips/TripMembersModal'
|
||||
import TourDetailDialog from '../../../../components/Tours/TourDetailDialog'
|
||||
import type { ExpensePrefill } from '../../../../components/Budget/CostsPanel'
|
||||
import { expenseEditorFor } from '../../../../components/Budget/CostsPanel.helpers'
|
||||
import { useAuthStore } from '../../../../store/authStore'
|
||||
import { useSettingsStore } from '../../../../store/settingsStore'
|
||||
import { useTripStore } from '../../../../store/tripStore'
|
||||
import { useBookingExpenseEditor } from '../../../../pages/tripPlanner/useBookingExpenseEditor'
|
||||
import { applyTripCoverUpdate } from '../../../../pages/tripPlanner/tripCover'
|
||||
import { latestReservation } from '../../../../pages/tripPlanner/transportEditorOpeners'
|
||||
import MConfirmSheet from '../../settings/MConfirmSheet'
|
||||
import MDayImpactList from '../../../components/MDayImpactList'
|
||||
import MDaySheet from './MDaySheet'
|
||||
@@ -34,8 +32,6 @@ import MRtKindSheet from '../roadtrip/MRtKindSheet'
|
||||
import MRtInfoSheet from '../roadtrip/MRtInfoSheet'
|
||||
import MRtCorridorSheet from '../roadtrip/MRtCorridorSheet'
|
||||
import MRtDraftSheet from '../roadtrip/MRtDraftSheet'
|
||||
import type { BookingExpenseRequest } from '../../../../components/Planner/BookingCostsSection.types'
|
||||
import type { BudgetItem } from '../../../../types'
|
||||
import type { MTripSheetsProps } from '../MTripShell'
|
||||
import { lockBodyScroll } from '../../../../utils/bodyScrollLock'
|
||||
import { focusDialog, trapTab } from '../../../../components/shared/dialogFocus'
|
||||
@@ -110,16 +106,9 @@ export default function MTripSheets({ planner, shell }: MTripSheetsProps) {
|
||||
|
||||
// Booking-linked expense editor (save-then-open from the booking modals) —
|
||||
// same page-level wiring as the desktop planner.
|
||||
const meId = useAuthStore(s => s.user?.id ?? -1)
|
||||
const displayCurrency = useSettingsStore(s => s.settings.default_currency)
|
||||
const loadBudgetItems = useTripStore(s => s.loadBudgetItems)
|
||||
const [bookingExpense, setBookingExpense] = useState<{ editing: BudgetItem | null; prefill?: ExpensePrefill } | null>(null)
|
||||
const openBookingExpense = (req: BookingExpenseRequest) => {
|
||||
if (req.editItem) setBookingExpense({ editing: req.editItem })
|
||||
else if (req.prefill) setBookingExpense({ editing: null, prefill: req.prefill })
|
||||
}
|
||||
const costsBase = (displayCurrency || trip?.currency || 'EUR').toUpperCase()
|
||||
const expenseEditor = expenseEditorFor(bookingExpense, () => setBookingExpense(null), planner.receiptExpense, planner.clearReceiptExpense)
|
||||
const { meId, costsBase, openBookingExpense, expenseEditor, onExpenseSaved } = useBookingExpenseEditor({
|
||||
tripId, tripCurrency: trip?.currency, receiptExpense: planner.receiptExpense, clearReceiptExpense: planner.clearReceiptExpense,
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -180,34 +169,12 @@ export default function MTripSheets({ planner, shell }: MTripSheetsProps) {
|
||||
await planner.handleDeleteReservation(planner.transitJourney!.id)
|
||||
planner.setTransitJourney(null)
|
||||
}}
|
||||
onChangeRoute={() => {
|
||||
// Re-enter the transit search seeded with this journey's route; the
|
||||
// existing reservation is replaced on save.
|
||||
const journey = planner.transitJourney!
|
||||
const eps = journey.endpoints || []
|
||||
const from = eps.find(e => e.role === 'from')
|
||||
const to = eps.find(e => e.role === 'to')
|
||||
planner.setTransitPrefill({
|
||||
from: from ? { name: from.name, lat: from.lat, lng: from.lng } : null,
|
||||
to: to ? { name: to.name, lat: to.lat, lng: to.lng } : null,
|
||||
})
|
||||
planner.setEditingTransport(journey)
|
||||
planner.setTransportModalDayId(journey.day_id ?? null)
|
||||
planner.setTransportModalAutomated(true)
|
||||
planner.setTransitJourney(null)
|
||||
planner.setShowTransportModal(true)
|
||||
}}
|
||||
onEditDetails={() => {
|
||||
// Hand off to the full transport editor for the booking fields —
|
||||
// same target as the transports tab's pencil (#2148).
|
||||
const journey = planner.reservations.find(r => r.id === planner.transitJourney!.id) ?? planner.transitJourney!
|
||||
planner.setEditingTransport(journey)
|
||||
planner.setTransportModalDayId(journey.day_id ?? null)
|
||||
planner.setTransportModalAutomated(false)
|
||||
planner.setTransitPrefill(null)
|
||||
planner.setTransitJourney(null)
|
||||
planner.setShowTransportModal(true)
|
||||
}}
|
||||
// Re-enter the transit search seeded with this journey's route; the
|
||||
// existing reservation is replaced on save.
|
||||
onChangeRoute={() => planner.changeTransitRoute(planner.transitJourney!)}
|
||||
// Hand off to the full transport editor for the booking fields, the same
|
||||
// target as the transports tab's pencil (#2148). The store copy may be newer.
|
||||
onEditDetails={() => planner.openTransportEditor(latestReservation(planner.reservations, planner.transitJourney!))}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -221,7 +188,7 @@ export default function MTripSheets({ planner, shell }: MTripSheetsProps) {
|
||||
editing={expenseEditor.editing}
|
||||
prefill={expenseEditor.prefill}
|
||||
onClose={expenseEditor.close}
|
||||
onSaved={() => { expenseEditor.close(); loadBudgetItems(tripId) }}
|
||||
onSaved={onExpenseSaved}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -237,9 +204,7 @@ export default function MTripSheets({ planner, shell }: MTripSheetsProps) {
|
||||
toast.success(t('trip.toast.tripUpdated'))
|
||||
}}
|
||||
trip={trip}
|
||||
onCoverUpdate={(_, coverUrl) => useTripStore.setState(state => ({
|
||||
trip: state.trip ? { ...state.trip, cover_image: coverUrl } : state.trip,
|
||||
}))}
|
||||
onCoverUpdate={applyTripCoverUpdate}
|
||||
/>
|
||||
<TripMembersModal
|
||||
isOpen={sheet?.id === 'members'}
|
||||
|
||||
Reference in New Issue
Block a user