155 lines
4.5 KiB
Vue
155 lines
4.5 KiB
Vue
<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">
|
|
<div class="flex items-center">
|
|
<img src="/logos/logo.png" alt="New Life Christian Church" class="logo-image" />
|
|
<UButton
|
|
@click="navigateTo('/')"
|
|
variant="ghost"
|
|
color="gray"
|
|
icon="i-heroicons-arrow-left"
|
|
>
|
|
Back to Sermons
|
|
</UButton>
|
|
</div>
|
|
<div>
|
|
<QRCodeButton :url="currentUrl" :title="sermon?.title" @click="showQRModal = $event" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<main class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
<!-- 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>
|
|
|
|
<!-- Sermon Content -->
|
|
<div v-else-if="sermon">
|
|
<UCard>
|
|
<template #header>
|
|
<div class="text-center">
|
|
<h1 class="text-3xl font-bold text-gray-900">{{ sermon.title }}</h1>
|
|
<p class="text-lg text-gray-600 mt-2">
|
|
{{ formatDate(sermon.date) }}
|
|
</p>
|
|
</div>
|
|
</template>
|
|
|
|
<div class="space-y-8">
|
|
<!-- Bible References -->
|
|
<div v-if="sermon.bibleReferences && sermon.bibleReferences.length > 0">
|
|
<h2 class="text-2xl font-semibold text-gray-900 mb-4">Bible References</h2>
|
|
<div class="grid gap-3 md:grid-cols-2">
|
|
<div
|
|
v-for="reference in sermon.bibleReferences"
|
|
:key="reference"
|
|
class="bg-red-50 border border-red-200 rounded-lg p-4"
|
|
>
|
|
<p class="text-red-800 font-medium">{{ reference }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Personal Application -->
|
|
<div v-if="sermon.personalApplication">
|
|
<h2 class="text-2xl font-semibold text-gray-900 mb-4">Personal Application</h2>
|
|
<UCard class="bg-blue-50 border-blue-200">
|
|
<p class="text-blue-900 whitespace-pre-wrap">{{ sermon.personalApplication }}</p>
|
|
</UCard>
|
|
</div>
|
|
|
|
<!-- Pastor's Challenge -->
|
|
<div v-if="sermon.pastorChallenge">
|
|
<h2 class="text-2xl font-semibold text-gray-900 mb-4">Pastor's Challenge</h2>
|
|
<UCard class="bg-green-50 border-green-200">
|
|
<p class="text-green-900 whitespace-pre-wrap">{{ sermon.pastorChallenge }}</p>
|
|
</UCard>
|
|
</div>
|
|
</div>
|
|
</UCard>
|
|
</div>
|
|
|
|
<!-- Not Found -->
|
|
<div v-else class="text-center py-12">
|
|
<UIcon name="i-heroicons-exclamation-triangle" class="mx-auto h-12 w-12 text-gray-400" />
|
|
<h3 class="mt-2 text-sm font-medium text-gray-900">Sermon not found</h3>
|
|
<p class="mt-1 text-sm text-gray-500">
|
|
The sermon you're looking for doesn't exist.
|
|
</p>
|
|
<div class="mt-6">
|
|
<UButton @click="navigateTo('/')">
|
|
Back to Sermons
|
|
</UButton>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- QR Code Modal -->
|
|
<QRCodeModal
|
|
v-model="showQRModal"
|
|
:url="currentUrl"
|
|
:title="sermon?.title"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { format, parseISO } from 'date-fns'
|
|
|
|
interface Sermon {
|
|
id: number
|
|
title: string
|
|
date: string
|
|
slug: string
|
|
bibleReferences?: string[]
|
|
personalApplication?: string
|
|
pastorChallenge?: string
|
|
}
|
|
|
|
const route = useRoute()
|
|
const slug = route.params.slug as string
|
|
|
|
const sermon = ref<Sermon | null>(null)
|
|
const loading = ref(true)
|
|
const showQRModal = ref(false)
|
|
|
|
const currentUrl = computed(() => {
|
|
if (process.client) {
|
|
return window.location.pathname
|
|
}
|
|
return `/${slug}`
|
|
})
|
|
|
|
const formatDate = (dateString: string) => {
|
|
try {
|
|
return format(parseISO(dateString), 'MMMM d, yyyy')
|
|
} catch {
|
|
return dateString
|
|
}
|
|
}
|
|
|
|
const loadSermon = async () => {
|
|
loading.value = true
|
|
try {
|
|
const data = await $fetch(`/api/sermons/${slug}`)
|
|
sermon.value = data
|
|
} catch (error) {
|
|
console.error('Failed to load sermon:', error)
|
|
sermon.value = null
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (slug) {
|
|
loadSermon()
|
|
}
|
|
})
|
|
</script>
|