Complete sermon management system with Nuxt 4, authentication, SQLite database, QR codes, and Docker deployment
This commit is contained in:
141
pages/index.vue
Normal file
141
pages/index.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<div class="min-h-screen bg-gray-50">
|
||||
<!-- Header -->
|
||||
<header class="bg-white shadow-sm border-b">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between items-center py-4">
|
||||
<!-- Logo -->
|
||||
<div class="flex items-center">
|
||||
<img src="/logos/logo.png" alt="New Life Christian Church" class="h-12 w-auto mr-3" />
|
||||
</div>
|
||||
|
||||
<!-- Welcome Message -->
|
||||
<div class="text-center flex-1">
|
||||
<h1 class="text-2xl font-bold text-gray-900">
|
||||
Welcome to New Life!
|
||||
</h1>
|
||||
<p class="text-gray-600 mt-1">
|
||||
Please choose the sermon you'd like to see.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Admin Login Button -->
|
||||
<div class="flex items-center space-x-4">
|
||||
<UButton
|
||||
v-if="!isLoggedIn"
|
||||
@click="showLoginModal = true"
|
||||
variant="outline"
|
||||
color="primary"
|
||||
>
|
||||
Admin Login
|
||||
</UButton>
|
||||
<UButton
|
||||
v-else
|
||||
@click="navigateTo('/admin')"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
>
|
||||
Create Sermon
|
||||
</UButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<!-- Time Filter -->
|
||||
<div class="mb-8 flex justify-center">
|
||||
<USelect
|
||||
v-model="timeFilter"
|
||||
:options="timeOptions"
|
||||
@update:model-value="loadSermons"
|
||||
class="w-48"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Loading State -->
|
||||
<div v-if="loading" class="flex justify-center py-12">
|
||||
<UIcon name="i-heroicons-arrow-path" class="animate-spin h-8 w-8 text-primary" />
|
||||
</div>
|
||||
|
||||
<!-- Sermons Grid -->
|
||||
<div v-else-if="sermons.length > 0" class="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||
<SermonCard
|
||||
v-for="sermon in sermons"
|
||||
:key="sermon.id"
|
||||
:sermon="sermon"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Empty State -->
|
||||
<div v-else class="text-center py-12">
|
||||
<UIcon name="i-heroicons-book-open" class="mx-auto h-12 w-12 text-gray-400" />
|
||||
<h3 class="mt-2 text-sm font-medium text-gray-900">No sermons found</h3>
|
||||
<p class="mt-1 text-sm text-gray-500">
|
||||
{{ timeFilter === '3months' ? 'No sermons in the last 3 months.' : 'No sermons found for the selected period.' }}
|
||||
</p>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Login Modal -->
|
||||
<LoginModal
|
||||
v-model="showLoginModal"
|
||||
@success="handleLoginSuccess"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { format, parseISO, isAfter, subMonths } from 'date-fns'
|
||||
|
||||
const timeFilter = ref('3months')
|
||||
const sermons = ref([])
|
||||
const loading = ref(true)
|
||||
const showLoginModal = ref(false)
|
||||
const isLoggedIn = ref(false)
|
||||
|
||||
const timeOptions = [
|
||||
{ label: 'Last 3 Months', value: '3months' },
|
||||
{ label: 'Last 6 Months', value: '6months' },
|
||||
{ label: 'Last Year', value: '1year' },
|
||||
{ label: 'All Sermons', value: 'all' }
|
||||
]
|
||||
|
||||
const loadSermons = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const { data } = await $fetch('/api/sermons', {
|
||||
query: { time: timeFilter.value }
|
||||
})
|
||||
sermons.value = data || []
|
||||
} catch (error) {
|
||||
console.error('Failed to load sermons:', error)
|
||||
sermons.value = []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// Check if user is logged in
|
||||
onMounted(async () => {
|
||||
// Check for existing auth token
|
||||
const token = useCookie('auth_token')
|
||||
if (token.value) {
|
||||
try {
|
||||
// Verify token with server
|
||||
await $fetch('/api/auth/verify')
|
||||
isLoggedIn.value = true
|
||||
} catch {
|
||||
isLoggedIn.value = false
|
||||
}
|
||||
}
|
||||
|
||||
await loadSermons()
|
||||
})
|
||||
|
||||
const handleLoginSuccess = () => {
|
||||
showLoginModal.value = false
|
||||
isLoggedIn.value = true
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user