Compare commits

...

2 commits

Author SHA1 Message Date
aee29f1ad5 fix(activities): favorites tab shows login toast instead of navigating when logged out
Tapping Favorites used to drop the user onto an empty page that
*then* fired the auth-prompt toast on mount — the navigation was
wasted motion. Mirror the Create tab pattern: onClick checks auth
first, fires the same toast (with Log in action) when unauthed,
and only router-pushes when authed.

`path` is kept on the tab so the active-highlight still works when
the user is actually on /activities/favorites after logging in
(BottomNav highlights via tab.path && isActive(tab.path)). The
mount-time toast on ActivitiesFavoritesPage stays as a defensive
fallback for direct URL access.
2026-05-25 11:56:27 +02:00
f92d4090dd fix(activities): buy-tickets login toast gets a Log in action button
Matches the pattern already used by BookmarkButton, RSVPButton, and
ActivitiesFavoritesPage — the auth-prompt toast carries an inline
"Log in" action that pushes /login. The buy-tickets toast was the
odd one out, leaving the buyer to find the login route themselves.

Also lifts the message + button label into i18n
(activities.detail.loginToBuyTickets, .logIn) so es/fr aren't
English-on-top.
2026-05-25 11:56:11 +02:00
6 changed files with 35 additions and 2 deletions

View file

@ -54,7 +54,27 @@ const tabs = computed<BottomTab[]>(() => [
disabled: !isAuthenticated.value, disabled: !isAuthenticated.value,
}, },
{ name: t('activities.nav.map'), icon: Map, path: '/activities/map' }, { name: t('activities.nav.map'), icon: Map, path: '/activities/map' },
{ name: t('activities.nav.favorites'), icon: Heart, path: '/activities/favorites' }, {
name: t('activities.nav.favorites'),
icon: Heart,
// path kept so the tab stays active-highlighted while the user is
// on /activities/favorites; onClick wins for the actual tap so we
// can gate on auth (mirrors the Create tab pattern above).
path: '/activities/favorites',
onClick: () => {
if (!isAuthenticated.value) {
toast.info(t('activities.favorites.loginPrompt'), {
action: {
label: t('activities.favorites.logIn'),
onClick: () => router.push('/login'),
},
})
return
}
router.push('/activities/favorites')
},
disabled: !isAuthenticated.value,
},
]) ])
// Feed tab is active for the bare /activities route AND all sub-paths that // Feed tab is active for the bare /activities route AND all sub-paths that

View file

@ -107,6 +107,8 @@ const messages: LocaleMessages = {
viewMyTickets: 'View in My Tickets', viewMyTickets: 'View in My Tickets',
soldOut: 'Sold Out', soldOut: 'Sold Out',
pastEvent: 'This event has already happened', pastEvent: 'This event has already happened',
loginToBuyTickets: 'Log in to buy tickets',
logIn: 'Log in',
free: 'Free', free: 'Free',
}, },
tickets: { tickets: {

View file

@ -107,6 +107,8 @@ const messages: LocaleMessages = {
viewMyTickets: 'Ver en Mis boletos', viewMyTickets: 'Ver en Mis boletos',
soldOut: 'Agotado', soldOut: 'Agotado',
pastEvent: 'Este evento ya pasó', pastEvent: 'Este evento ya pasó',
loginToBuyTickets: 'Inicia sesión para comprar boletos',
logIn: 'Iniciar sesión',
free: 'Gratis', free: 'Gratis',
}, },
tickets: { tickets: {

View file

@ -107,6 +107,8 @@ const messages: LocaleMessages = {
viewMyTickets: 'Voir dans Mes billets', viewMyTickets: 'Voir dans Mes billets',
soldOut: 'Épuisé', soldOut: 'Épuisé',
pastEvent: 'Cet événement est déjà passé', pastEvent: 'Cet événement est déjà passé',
loginToBuyTickets: 'Connectez-vous pour acheter des billets',
logIn: 'Connexion',
free: 'Gratuit', free: 'Gratuit',
}, },
tickets: { tickets: {

View file

@ -82,6 +82,8 @@ export interface LocaleMessages {
viewMyTickets: string viewMyTickets: string
soldOut: string soldOut: string
pastEvent: string pastEvent: string
loginToBuyTickets: string
logIn: string
free: string free: string
} }
tickets: { tickets: {

View file

@ -145,7 +145,12 @@ const showPurchaseDialog = ref(false)
function openPurchaseDialog() { function openPurchaseDialog() {
if (!isAuthenticated.value) { if (!isAuthenticated.value) {
toastService.info('Log in to buy tickets') toastService.info(t('activities.detail.loginToBuyTickets'), {
action: {
label: t('activities.detail.logIn'),
onClick: () => router.push('/login'),
},
})
return return
} }
showPurchaseDialog.value = true showPurchaseDialog.value = true