From dd138e52938e7b0ad7df11e9663fdb1687f2b371 Mon Sep 17 00:00:00 2001 From: Konstantinos Thermos Date: Wed, 5 Aug 2026 19:04:40 +0300 Subject: [PATCH] fix(trips): default a new trip to the user's currency setting (#1790) The new-trip forms hard-coded EUR and ignored settings.default_currency, so creating a trip always opened on EUR even with USD set in Settings > General > Currency. Read default_currency (falling back to EUR when unset) in both the desktop TripFormModal and the mobile MNewTripSheet; edit mode still pre-fills the trip's own currency. Fixes #1784 --- .../src/components/Trips/TripFormModal.test.tsx | 15 +++++++++++++++ client/src/components/Trips/TripFormModal.tsx | 4 +++- .../mobile/screens/dashboard/MNewTripSheet.tsx | 4 +++- .../unit/mobile/dashboard/MNewTripSheet.test.tsx | 9 +++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/client/src/components/Trips/TripFormModal.test.tsx b/client/src/components/Trips/TripFormModal.test.tsx index 2b36e69ef..ad8346253 100644 --- a/client/src/components/Trips/TripFormModal.test.tsx +++ b/client/src/components/Trips/TripFormModal.test.tsx @@ -5,6 +5,7 @@ import userEvent from '@testing-library/user-event'; import { delay, http, HttpResponse } from 'msw'; import { useAuthStore } from '../../store/authStore'; import { useTripStore } from '../../store/tripStore'; +import { useSettingsStore } from '../../store/settingsStore'; import { usePermissionsStore } from '../../store/permissionsStore'; import { resetAllStores, seedStore } from '../../../tests/helpers/store'; import { buildUser, buildTrip } from '../../../tests/helpers/factories'; @@ -397,6 +398,20 @@ describe('TripFormModal', () => { expect(onSave).toHaveBeenCalledWith(expect.objectContaining({ currency: 'EUR' })); }); + it('FE-COMP-TRIPFORM-033b: a new trip defaults to the user\'s default_currency (#1784)', async () => { + seedStore(useSettingsStore, { settings: { ...useSettingsStore.getState().settings, default_currency: 'USD' } }); + const user = userEvent.setup(); + const onSave = vi.fn().mockResolvedValue({ trip: buildTrip({ id: 99 }) }); + render(); + + await user.type(screen.getByPlaceholderText(/Summer in Japan/i), 'New York 2026'); + const submitBtn = screen.getAllByText('Create New Trip').find(el => el.closest('button'))!; + await user.click(submitBtn.closest('button')!); + + await waitFor(() => expect(onSave).toHaveBeenCalled()); + expect(onSave).toHaveBeenCalledWith(expect.objectContaining({ currency: 'USD' })); + }); + // Changing the start of a dated trip must go through the date-shift choice step (#1288). const changeStartDate = async (user: ReturnType, iso: string) => { await user.click(screen.getAllByRole('button', { name: 'Enter date manually' })[0]); diff --git a/client/src/components/Trips/TripFormModal.tsx b/client/src/components/Trips/TripFormModal.tsx index fa28e3447..a49d4cc09 100644 --- a/client/src/components/Trips/TripFormModal.tsx +++ b/client/src/components/Trips/TripFormModal.tsx @@ -4,6 +4,7 @@ import { Calendar, Camera, Search, X, UserPlus, Bell } from 'lucide-react' import { tripsApi, authApi } from '../../api/client' import CustomSelect from '../shared/CustomSelect' import { useAuthStore } from '../../store/authStore' +import { useSettingsStore } from '../../store/settingsStore' import { useCanDo } from '../../store/permissionsStore' import { useToast } from '../shared/Toast' import { useTranslation } from '../../i18n' @@ -42,6 +43,7 @@ export default function TripFormModal({ isOpen, onClose, onSave, trip, onCoverUp const toast = useToast() const { t } = useTranslation() const currentUser = useAuthStore(s => s.user) + const defaultCurrency = useSettingsStore(s => s.settings.default_currency) || 'EUR' const tripRemindersEnabled = useAuthStore(s => s.tripRemindersEnabled) const setTripRemindersEnabled = useAuthStore(s => s.setTripRemindersEnabled) const can = useCanDo() @@ -93,7 +95,7 @@ export default function TripFormModal({ isOpen, onClose, onSave, trip, onCoverUp setCoverPreview(trip.cover_image || null) setCoverSearchQuery('') } else { - setFormData({ title: '', description: '', start_date: '', end_date: '', currency: 'EUR', reminder_days: tripRemindersEnabled ? 3 : 0, day_count: 7 }) + setFormData({ title: '', description: '', start_date: '', end_date: '', currency: defaultCurrency, reminder_days: tripRemindersEnabled ? 3 : 0, day_count: 7 }) setCustomReminder(false) setCoverPreview(null) setCoverSearchQuery('') diff --git a/client/src/mobile/screens/dashboard/MNewTripSheet.tsx b/client/src/mobile/screens/dashboard/MNewTripSheet.tsx index f1c297a64..654e054e0 100644 --- a/client/src/mobile/screens/dashboard/MNewTripSheet.tsx +++ b/client/src/mobile/screens/dashboard/MNewTripSheet.tsx @@ -3,6 +3,7 @@ import { Archive, ArchiveRestore, Camera, Search, X } from 'lucide-react' import { useTranslation } from '../../../i18n' import { tripsApi } from '../../../api/client' import { useCanDo } from '../../../store/permissionsStore' +import { useSettingsStore } from '../../../store/settingsStore' import { useToast } from '../../../components/shared/Toast' import { normalizeImageFile } from '../../../utils/convertHeic' import { getApiErrorMessage } from '../../../types' @@ -50,6 +51,7 @@ export default function MNewTripSheet({ open, trip, onClose, onSave, onCoverUpda const { t } = useTranslation() const toast = useToast() const can = useCanDo() + const defaultCurrency = useSettingsStore(s => s.settings.default_currency) || 'EUR' const fileRef = useRef(null) const coverSearchSeq = useRef(0) const canEditTrip = !isEditing || can('trip_edit', trip) @@ -77,7 +79,7 @@ export default function MNewTripSheet({ open, trip, onClose, onSave, onCoverUpda setDescription(trip?.description || '') setStartDate(trip?.start_date || '') setEndDate(trip?.end_date || '') - setCurrency(trip?.currency || 'EUR') + setCurrency(trip?.currency || defaultCurrency) setCoverPreview(trip?.cover_image || null) setPendingCoverFile(null) setPendingUnsplashUrl(null) diff --git a/client/tests/unit/mobile/dashboard/MNewTripSheet.test.tsx b/client/tests/unit/mobile/dashboard/MNewTripSheet.test.tsx index 5639d0421..c73f6c2f3 100644 --- a/client/tests/unit/mobile/dashboard/MNewTripSheet.test.tsx +++ b/client/tests/unit/mobile/dashboard/MNewTripSheet.test.tsx @@ -5,6 +5,7 @@ import MNewTripSheet from '../../../../src/mobile/screens/dashboard/MNewTripShee import { tripsApi } from '../../../../src/api/client'; import { useAuthStore } from '../../../../src/store/authStore'; import { usePermissionsStore } from '../../../../src/store/permissionsStore'; +import { useSettingsStore } from '../../../../src/store/settingsStore'; import { buildUser } from '../../../helpers/factories'; import type { DashboardTrip } from '../../../../src/pages/dashboard/dashboardModel'; import type { Trip, TripCreateRequest } from '@trek/shared'; @@ -75,6 +76,7 @@ beforeEach(() => { afterEach(() => { URL.createObjectURL = origCreateObjectURL; delete window.__addToast; + useSettingsStore.setState(s => ({ settings: { ...s.settings, default_currency: '' } })); vi.restoreAllMocks(); }); @@ -88,6 +90,13 @@ describe('MNewTripSheet', () => { expect(screen.getByText('Add cover image')).toBeInTheDocument(); }); + it('FE-MOB-NTSH-001b: create mode defaults the currency to the user\'s default_currency (#1784)', () => { + useSettingsStore.setState(s => ({ settings: { ...s.settings, default_currency: 'USD' } })); + render( {}} onSave={() => {}} />); + + expect(screen.getByLabelText('currency')).toHaveValue('USD'); + }); + it('FE-MOB-NTSH-002: edit mode preloads the trip and hides the no-date hint', () => { render( {}} onSave={() => {}} />);