Show toast with login link instead of redirecting for bookmark/RSVP

Both BookmarkButton and RSVPButton now show a toast notification
with a "Log in" action button when tapped by unauthenticated users.
RSVP buttons are now always visible (not hidden behind v-if).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-04-20 12:35:37 +02:00
commit e0dde90adc
2 changed files with 20 additions and 5 deletions

View file

@ -3,16 +3,14 @@ import { computed } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Heart } from 'lucide-vue-next' import { Heart } from 'lucide-vue-next'
import { toast } from 'vue-sonner'
import { useAuth } from '@/composables/useAuthService' import { useAuth } from '@/composables/useAuthService'
import { useBookmarks } from '../composables/useBookmarks' import { useBookmarks } from '../composables/useBookmarks'
import { NIP52_KINDS } from '../types/nip52' import { NIP52_KINDS } from '../types/nip52'
const props = defineProps<{ const props = defineProps<{
/** Activity organizer pubkey */
pubkey: string pubkey: string
/** Activity d-tag */
dTag: string dTag: string
/** Activity kind (default: 31923) */
kind?: number kind?: number
}>() }>()
@ -25,7 +23,12 @@ const bookmarked = computed(() => isBookmarked(activityKind.value, props.pubkey,
function handleToggle() { function handleToggle() {
if (!isAuthenticated.value) { if (!isAuthenticated.value) {
router.push('/login') toast.info('Log in to save favorites', {
action: {
label: 'Log in',
onClick: () => router.push('/login'),
},
})
return return
} }
toggleBookmark(activityKind.value, props.pubkey, props.dTag) toggleBookmark(activityKind.value, props.pubkey, props.dTag)

View file

@ -1,8 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import { useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Check, HelpCircle, X } from 'lucide-vue-next' import { Check, HelpCircle, X } from 'lucide-vue-next'
import { toast } from 'vue-sonner'
import { useAuth } from '@/composables/useAuthService' import { useAuth } from '@/composables/useAuthService'
import { useRSVP } from '../composables/useRSVP' import { useRSVP } from '../composables/useRSVP'
import { NIP52_KINDS, type RSVPStatus } from '../types/nip52' import { NIP52_KINDS, type RSVPStatus } from '../types/nip52'
@ -13,6 +15,7 @@ const props = defineProps<{
kind?: number kind?: number
}>() }>()
const router = useRouter()
const { t } = useI18n() const { t } = useI18n()
const { isAuthenticated } = useAuth() const { isAuthenticated } = useAuth()
const { getMyRSVP, getRSVPCount, setRSVP } = useRSVP() const { getMyRSVP, getRSVPCount, setRSVP } = useRSVP()
@ -28,12 +31,21 @@ const buttons: { status: RSVPStatus; labelKey: string; icon: any }[] = [
] ]
function handleClick(status: RSVPStatus) { function handleClick(status: RSVPStatus) {
if (!isAuthenticated.value) {
toast.info('Log in to RSVP', {
action: {
label: 'Log in',
onClick: () => router.push('/login'),
},
})
return
}
setRSVP(activityKind.value, props.pubkey, props.dTag, status) setRSVP(activityKind.value, props.pubkey, props.dTag, status)
} }
</script> </script>
<template> <template>
<div v-if="isAuthenticated" class="space-y-2"> <div class="space-y-2">
<div class="flex gap-2"> <div class="flex gap-2">
<Button <Button
v-for="btn in buttons" v-for="btn in buttons"