Files
nlcc-itinerary/pages/admin.vue

302 lines
9.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="min-h-screen bg-gray-50">
<header class="bg-white shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-4">
<img src="/logos/logo.png" alt="New Life Christian Church" class="h-16 w-auto" />
<h1 class="text-2xl font-bold text-gray-900">Create New Sermon</h1>
</div>
<button
@click="handleLogout"
class="text-sm font-medium text-red-600 hover:text-red-700"
>
Logout
</button>
</div>
</div>
</header>
<main class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<!-- Manage Existing Sermons Section -->
<div class="bg-white shadow-lg rounded-lg p-8 mb-8">
<h2 class="text-2xl font-bold text-gray-900 mb-6">Manage Existing Sermons</h2>
<div v-if="allSermons && allSermons.length > 0" class="space-y-4">
<div class="flex gap-4 items-end">
<div class="flex-1">
<label for="sermon-select" class="block text-sm font-medium text-gray-700 mb-2">
Select Sermon to Delete
</label>
<select
id="sermon-select"
v-model="selectedSermonId"
class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
>
<option value="">-- Choose a sermon --</option>
<option v-for="sermon in allSermons" :key="sermon.id" :value="sermon.id">
{{ sermon.title }} ({{ formatDate(sermon.date) }})
</option>
</select>
</div>
<button
type="button"
@click="handleDelete"
:disabled="!selectedSermonId || deleting"
class="px-6 py-2 bg-red-600 text-white rounded-md hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 disabled:opacity-50 disabled:cursor-not-allowed font-medium"
>
{{ deleting ? 'Deleting...' : 'Delete Sermon' }}
</button>
</div>
<div v-if="deleteError" class="text-red-600 text-sm">
{{ deleteError }}
</div>
<div v-if="deleteSuccess" class="text-green-600 text-sm">
{{ deleteSuccess }}
</div>
</div>
<div v-else class="text-gray-500 text-sm">
No sermons available to manage.
</div>
</div>
<!-- Create New Sermon Form -->
<form @submit.prevent="handleSubmit" class="bg-white shadow-lg rounded-lg p-8 space-y-8">
<h2 class="text-2xl font-bold text-gray-900">Create New Sermon</h2>
<!-- Basic Info -->
<div class="space-y-6">
<div>
<label for="date" class="block text-sm font-medium text-gray-700 mb-2">
Sermon Date
</label>
<input
id="date"
v-model="formData.date"
type="date"
required
class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
/>
</div>
<div>
<label for="title" class="block text-sm font-medium text-gray-700 mb-2">
Sermon Title
</label>
<input
id="title"
v-model="formData.title"
type="text"
required
placeholder="Enter sermon title"
class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
/>
</div>
</div>
<!-- Section 1: Bible References -->
<div class="border-t pt-6">
<h2 class="text-xl font-semibold text-gray-900 mb-4">Section 1: Bible References</h2>
<div class="space-y-3">
<div v-for="(ref, index) in bibleReferences" :key="index" class="flex gap-2">
<input
v-model="bibleReferences[index]"
type="text"
placeholder="e.g., John 3:16"
class="flex-1 px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
/>
<button
v-if="bibleReferences.length > 1"
type="button"
@click="removeReference(index)"
class="px-3 py-2 bg-red-100 text-red-700 rounded-md hover:bg-red-200"
>
</button>
</div>
<button
type="button"
@click="addReference"
class="px-4 py-2 bg-blue-100 text-blue-700 rounded-md hover:bg-blue-200 font-medium"
>
+ Add Reference
</button>
</div>
</div>
<!-- Section 2: Personal Appliance -->
<div class="border-t pt-6">
<h2 class="text-xl font-semibold text-gray-900 mb-4">Section 2: Personal Appliance</h2>
<textarea
v-model="formData.personal_appliance"
rows="6"
required
placeholder="Enter personal appliance content..."
class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
></textarea>
</div>
<!-- Section 3: Pastor's Challenge -->
<div class="border-t pt-6">
<h2 class="text-xl font-semibold text-gray-900 mb-4">Section 3: Pastor's Challenge</h2>
<textarea
v-model="formData.pastors_challenge"
rows="6"
required
placeholder="Enter pastor's challenge content..."
class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
></textarea>
</div>
<!-- Error/Success Messages -->
<div v-if="error" class="text-red-600 text-sm">
{{ error }}
</div>
<div v-if="success" class="text-green-600 text-sm">
{{ success }}
</div>
<!-- Submit Button -->
<div class="flex gap-4">
<button
type="submit"
:disabled="loading"
class="flex-1 py-3 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50"
>
{{ loading ? 'Creating...' : 'Create Sermon' }}
</button>
<NuxtLink
to="/"
class="px-6 py-3 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50"
>
Cancel
</NuxtLink>
</div>
</form>
</main>
</div>
</template>
<script setup lang="ts">
definePageMeta({
middleware: 'auth'
})
// Fetch all sermons for management
const { data: allSermons, refresh: refreshSermons } = await useFetch('/api/sermons')
// Sermon management state
const selectedSermonId = ref('')
const deleteError = ref('')
const deleteSuccess = ref('')
const deleting = ref(false)
// Create sermon form state
const bibleReferences = ref([''])
const formData = ref({
date: '',
title: '',
personal_appliance: '',
pastors_challenge: ''
})
const error = ref('')
const success = ref('')
const loading = ref(false)
function addReference() {
bibleReferences.value.push('')
}
function removeReference(index: number) {
bibleReferences.value.splice(index, 1)
}
function formatDateToSlug(date: string) {
// Convert YYYY-MM-DD to MMDDYYYY
const [year, month, day] = date.split('-')
return `sermon-${month}${day}${year}`
}
async function handleSubmit() {
error.value = ''
success.value = ''
loading.value = true
try {
const slug = formatDateToSlug(formData.value.date)
const bible_references = bibleReferences.value.filter(ref => ref.trim()).join('\n')
await $fetch('/api/sermons', {
method: 'POST',
body: {
slug,
title: formData.value.title,
date: formData.value.date,
bible_references,
personal_appliance: formData.value.personal_appliance,
pastors_challenge: formData.value.pastors_challenge
}
})
success.value = 'Sermon created successfully!'
// Reset form
formData.value = {
date: '',
title: '',
personal_appliance: '',
pastors_challenge: ''
}
bibleReferences.value = ['']
// Redirect after 2 seconds
setTimeout(() => {
navigateTo('/')
}, 2000)
} catch (e: any) {
error.value = e.data?.message || 'Failed to create sermon'
} finally {
loading.value = false
}
}
async function handleDelete() {
if (!selectedSermonId.value) return
deleteError.value = ''
deleteSuccess.value = ''
deleting.value = true
try {
await $fetch(`/api/sermons/${selectedSermonId.value}`, {
method: 'DELETE'
})
deleteSuccess.value = 'Sermon deleted successfully!'
selectedSermonId.value = ''
// Refresh the sermon list
await refreshSermons()
} catch (e: any) {
deleteError.value = e.data?.message || 'Failed to delete sermon'
} finally {
deleting.value = false
}
}
function formatDate(dateString: string) {
const date = new Date(dateString)
return date.toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})
}
async function handleLogout() {
await $fetch('/api/auth/logout', { method: 'POST' })
await navigateTo('/login')
}
</script>