Add Rideshare functionality to NostrFeed module

- Introduced a new RideshareComposer component for creating rideshare posts, allowing users to specify ride details such as type, locations, date, time, and contact methods.
- Enhanced NostrFeed.vue to display rideshare badges for relevant posts, improving visibility and categorization of rideshare content.
- Updated Home.vue to integrate the RideshareComposer, providing users with an option to compose rideshare requests or offers alongside regular notes.

These changes enhance the user experience by facilitating rideshare interactions within the NostrFeed module, promoting community engagement.
This commit is contained in:
padreug 2025-09-17 02:21:42 +02:00
parent 667a7c2d89
commit dfd3ddd112
3 changed files with 564 additions and 10 deletions

View file

@ -36,15 +36,24 @@
<!-- Main Feed Area - Takes remaining height -->
<div class="flex-1 overflow-hidden">
<!-- Collapsible Note Composer -->
<!-- Collapsible Composer -->
<div v-if="showComposer || replyTo" class="border-b bg-background">
<div class="px-4 py-3 sm:px-6">
<!-- Regular Note Composer -->
<NoteComposer
v-if="composerType === 'note' || replyTo"
:reply-to="replyTo"
@note-published="onNotePublished"
@clear-reply="onClearReply"
@close="onCloseComposer"
/>
<!-- Rideshare Composer -->
<RideshareComposer
v-else-if="composerType === 'rideshare'"
@rideshare-published="onRidesharePublished"
@close="onCloseComposer"
/>
</div>
</div>
@ -61,15 +70,44 @@
</div>
</div>
<!-- Floating Action Button for Compose -->
<!-- Floating Action Buttons for Compose -->
<div v-if="!showComposer && !replyTo" class="fixed bottom-6 right-6 z-50">
<Button
@click="showComposer = true"
size="lg"
class="h-14 w-14 rounded-full shadow-lg hover:shadow-xl transition-all bg-primary hover:bg-primary/90 border-2 border-primary-foreground/20 flex items-center justify-center p-0"
>
<Plus class="h-6 w-6 stroke-[2.5]" />
</Button>
<!-- Main compose button -->
<div class="flex flex-col items-end gap-3">
<!-- Secondary buttons (when expanded) -->
<div v-if="showComposerOptions" class="flex flex-col gap-2">
<Button
@click="openComposer('note')"
size="lg"
variant="secondary"
class="h-12 px-4 rounded-full shadow-md hover:shadow-lg transition-all gap-2"
>
<MessageSquare class="h-4 w-4" />
<span class="text-sm">Note</span>
</Button>
<Button
@click="openComposer('rideshare')"
size="lg"
variant="secondary"
class="h-12 px-4 rounded-full shadow-md hover:shadow-lg transition-all gap-2"
>
<Car class="h-4 w-4" />
<span class="text-sm">Rideshare</span>
</Button>
</div>
<!-- Main FAB -->
<Button
@click="toggleComposerOptions"
size="lg"
class="h-14 w-14 rounded-full shadow-lg hover:shadow-xl transition-all bg-primary hover:bg-primary/90 border-2 border-primary-foreground/20 flex items-center justify-center p-0"
>
<Plus
class="h-6 w-6 stroke-[2.5] transition-transform duration-200"
:class="{ 'rotate-45': showComposerOptions }"
/>
</Button>
</div>
</div>
<!-- Quick Filters Bar (Mobile) -->
@ -97,10 +135,11 @@
// import NotificationPermission from '@/components/notifications/NotificationPermission.vue'
import { ref, computed, watch } from 'vue'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Filter, Plus } from 'lucide-vue-next'
import { Filter, Plus, MessageSquare, Car } from 'lucide-vue-next'
import PWAInstallPrompt from '@/components/pwa/PWAInstallPrompt.vue'
import FeedFilters from '@/modules/nostr-feed/components/FeedFilters.vue'
import NoteComposer from '@/modules/nostr-feed/components/NoteComposer.vue'
import RideshareComposer from '@/modules/nostr-feed/components/RideshareComposer.vue'
import NostrFeed from '@/modules/nostr-feed/components/NostrFeed.vue'
import { FILTER_PRESETS } from '@/modules/nostr-feed/config/content-filters'
import appConfig from '@/app.config'
@ -113,6 +152,8 @@ const adminPubkeys = appConfig.modules['nostr-feed']?.config?.adminPubkeys || []
// UI state
const showFilters = ref(false)
const showComposer = ref(false)
const showComposerOptions = ref(false)
const composerType = ref<'note' | 'rideshare'>('note')
// Feed configuration
const selectedFilters = ref<ContentFilter[]>(FILTER_PRESETS.all)
@ -191,6 +232,27 @@ const onReplyToNote = (note: ReplyToNote) => {
const onCloseComposer = () => {
showComposer.value = false
showComposerOptions.value = false
replyTo.value = undefined
}
// New composer methods
const toggleComposerOptions = () => {
showComposerOptions.value = !showComposerOptions.value
}
const openComposer = (type: 'note' | 'rideshare') => {
composerType.value = type
showComposer.value = true
showComposerOptions.value = false
}
const onRidesharePublished = (noteId: string) => {
console.log('Rideshare post published:', noteId)
// Refresh the feed to show the new rideshare post
feedKey.value++
// Hide composer
showComposer.value = false
showComposerOptions.value = false
}
</script>