diff --git a/client/src/components/Planner/BookingCostsSection.tsx b/client/src/components/Planner/BookingCostsSection.tsx
index 1683b895..2938b178 100644
--- a/client/src/components/Planner/BookingCostsSection.tsx
+++ b/client/src/components/Planner/BookingCostsSection.tsx
@@ -12,8 +12,10 @@ import type { BudgetItem } from '../../types'
* button (the modal saves the booking first, then opens the full Costs editor);
* once linked it shows the expense with edit / remove actions.
*/
-export function BookingCostsSection({ reservationId, onCreate, onEdit, onRemove }: {
+export function BookingCostsSection({ reservationId, pendingExpense, onCreate, onEdit, onRemove }: {
reservationId: number | null
+ /** A cost parsed from an import that will be linked on save — previewed before the booking exists. */
+ pendingExpense?: { total_price: number; currency?: string | null; category: string } | null
onCreate: () => void
onEdit: (item: BudgetItem) => void
onRemove: (item: BudgetItem) => void
@@ -27,6 +29,25 @@ export function BookingCostsSection({ reservationId, onCreate, onEdit, onRemove
const labelCls = 'block text-[11px] font-semibold uppercase tracking-[0.08em] text-content-faint mb-[6px]'
+ // Import review (booking not saved yet): preview the parsed cost that will be linked on save.
+ if (!linked && pendingExpense && pendingExpense.total_price > 0) {
+ const meta = catMeta(pendingExpense.category)
+ const Icon = meta.Icon
+ return (
+
+
+
+
+
+
{t(meta.labelKey)}
+
{t('reservations.createExpenseHint')}
+
+
{formatMoney(pendingExpense.total_price, pendingExpense.currency || base, locale)}
+
+
+ )
+ }
+
if (linked) {
const meta = catMeta(linked.category)
const Icon = meta.Icon
diff --git a/client/src/components/Planner/ReservationModal.tsx b/client/src/components/Planner/ReservationModal.tsx
index 2518f2dd..c5bae7b1 100644
--- a/client/src/components/Planner/ReservationModal.tsx
+++ b/client/src/components/Planner/ReservationModal.tsx
@@ -299,6 +299,13 @@ export function ReservationModal({ isOpen, onClose, onSave, reservation, days, p
try { await deleteBudgetItem(Number(tripId), item.id) } catch { toast.error(t('common.unknownError')) }
}
+ // On an import review (not yet saved), preview the parsed price as the cost that will be linked.
+ const prefillMeta = prefill?.metadata && typeof prefill.metadata === 'object' ? (prefill.metadata as Record) : null
+ const prefillPrice = Number(prefillMeta?.price)
+ const pendingExpense = !reservation && Number.isFinite(prefillPrice) && prefillPrice > 0
+ ? { total_price: prefillPrice, currency: (prefillMeta?.priceCurrency as string | null) ?? null, category: typeToCostCategory(form.type) }
+ : null
+
const handleFileChange = async (e) => {
const file = (e.target as HTMLInputElement).files?.[0]
if (!file) return
@@ -685,6 +692,7 @@ export function ReservationModal({ isOpen, onClose, onSave, reservation, days, p
{isBudgetEnabled && (
) : null
+ const prefillPrice = Number(prefillMeta?.price)
+ const pendingExpense = !reservation && Number.isFinite(prefillPrice) && prefillPrice > 0
+ ? { total_price: prefillPrice, currency: (prefillMeta?.priceCurrency as string | null) ?? null, category: typeToCostCategory(form.type) }
+ : null
+
const handleFileChange = async (e: React.ChangeEvent) => {
const file = e.target.files?.[0]
if (!file) return
@@ -740,6 +747,7 @@ export function TransportModal({ isOpen, onClose, onSave, reservation, days, sel
{isBudgetEnabled && (