Fix blank page issue on module route refresh
- Pre-register all module routes automatically from module definitions in router configuration - Add useModuleReady composable for clean reactive loading states during module initialization - Update ChatPage and EventsPage with proper loading/error states and computed service access - Remove duplicate route registration from plugin manager install phase - Maintain modular architecture while ensuring routes are available immediately on app startup Resolves blank pages and Vue Router warnings when refreshing on /chat, /events, /my-tickets routes. Users now see proper loading indicators instead of blank screens during module initialization. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
85635cfc96
commit
7145af3f83
5 changed files with 140 additions and 15 deletions
|
|
@ -1,9 +1,36 @@
|
|||
<template>
|
||||
<div class="h-[calc(100vh-3.5rem)] lg:h-[calc(100vh-4rem)] xl:h-[calc(100vh-5rem)] w-full">
|
||||
<!-- Loading State -->
|
||||
<div v-if="isLoading" class="flex flex-col items-center justify-center min-h-screen">
|
||||
<div class="flex flex-col items-center space-y-4">
|
||||
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-primary"></div>
|
||||
<div class="text-center space-y-2">
|
||||
<h2 class="text-xl font-semibold">Loading Chat...</h2>
|
||||
<p class="text-sm text-muted-foreground">Setting up encrypted messaging and connecting to Nostr relays...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Error State -->
|
||||
<div v-else-if="error" class="flex flex-col items-center justify-center min-h-screen">
|
||||
<div class="text-center space-y-4">
|
||||
<h2 class="text-xl font-semibold text-red-600">Failed to load chat</h2>
|
||||
<p class="text-muted-foreground">{{ error }}</p>
|
||||
<button @click="location.reload()" class="px-4 py-2 bg-primary text-primary-foreground rounded">
|
||||
Retry
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Chat Content - Only render when module is ready -->
|
||||
<div v-else class="h-[calc(100vh-3.5rem)] lg:h-[calc(100vh-4rem)] xl:h-[calc(100vh-5rem)] w-full">
|
||||
<ChatComponent />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useModuleReady } from '@/composables/useModuleReady'
|
||||
import ChatComponent from '../components/ChatComponent.vue'
|
||||
|
||||
// Simple reactive module loading - no complex logic needed
|
||||
const { isReady, isLoading, error } = useModuleReady('chat')
|
||||
</script>
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
<!-- eslint-disable vue/multi-word-component-names -->
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useModuleReady } from '@/composables/useModuleReady'
|
||||
import { useEvents } from '../composables/useEvents'
|
||||
import { useAuth } from '@/composables/useAuth'
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
|
|
@ -13,8 +14,21 @@ import PurchaseTicketDialog from '../components/PurchaseTicketDialog.vue'
|
|||
import { RefreshCw, User, LogIn } from 'lucide-vue-next'
|
||||
import { formatEventPrice } from '@/lib/utils/formatting'
|
||||
|
||||
const { upcomingEvents, pastEvents, isLoading, error, refresh } = useEvents()
|
||||
const { isAuthenticated, userDisplay } = useAuth()
|
||||
// Simple reactive module loading
|
||||
const { isReady: moduleReady, isLoading: moduleLoading, error: moduleError } = useModuleReady('events')
|
||||
|
||||
// Only call services when module is ready - prevents service injection errors
|
||||
const eventsData = computed(() => moduleReady.value ? useEvents() : null)
|
||||
const authData = computed(() => moduleReady.value ? useAuth() : null)
|
||||
|
||||
// Reactive service data
|
||||
const upcomingEvents = computed(() => eventsData.value?.upcomingEvents.value ?? [])
|
||||
const pastEvents = computed(() => eventsData.value?.pastEvents.value ?? [])
|
||||
const isLoading = computed(() => eventsData.value?.isLoading.value ?? false)
|
||||
const error = computed(() => eventsData.value?.error.value ?? null)
|
||||
const refresh = () => eventsData.value?.refresh()
|
||||
const isAuthenticated = computed(() => authData.value?.isAuthenticated.value ?? false)
|
||||
const userDisplay = computed(() => authData.value?.userDisplay.value ?? null)
|
||||
const showPurchaseDialog = ref(false)
|
||||
const selectedEvent = ref<{
|
||||
id: string
|
||||
|
|
@ -24,7 +38,15 @@ const selectedEvent = ref<{
|
|||
} | null>(null)
|
||||
|
||||
function formatDate(dateStr: string) {
|
||||
return format(new Date(dateStr), 'PPP')
|
||||
if (!dateStr) return 'Date not available'
|
||||
|
||||
const date = new Date(dateStr)
|
||||
if (isNaN(date.getTime())) {
|
||||
return 'Invalid date'
|
||||
}
|
||||
|
||||
// Format like "October 5th, 2025" to match the clean UI
|
||||
return format(date, 'MMMM do, yyyy')
|
||||
}
|
||||
|
||||
function handlePurchaseClick(event: {
|
||||
|
|
@ -45,7 +67,30 @@ function handlePurchaseClick(event: {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container mx-auto py-8 px-4">
|
||||
<!-- Module Loading State -->
|
||||
<div v-if="moduleLoading" class="flex flex-col items-center justify-center min-h-screen">
|
||||
<div class="flex flex-col items-center space-y-4">
|
||||
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-primary"></div>
|
||||
<div class="text-center space-y-2">
|
||||
<h2 class="text-xl font-semibold">Loading Events...</h2>
|
||||
<p class="text-sm text-muted-foreground">Loading event management and ticketing system...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Module Error State -->
|
||||
<div v-else-if="moduleError" class="flex flex-col items-center justify-center min-h-screen">
|
||||
<div class="text-center space-y-4">
|
||||
<h2 class="text-xl font-semibold text-red-600">Failed to load events</h2>
|
||||
<p class="text-muted-foreground">{{ moduleError }}</p>
|
||||
<button @click="location.reload()" class="px-4 py-2 bg-primary text-primary-foreground rounded">
|
||||
Retry
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Events Content - Only render when module is ready -->
|
||||
<div v-else class="container mx-auto py-8 px-4">
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<div class="space-y-1">
|
||||
<h1 class="text-3xl font-bold text-foreground">Events</h1>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue