Add complete edit functionality for sermons with update API endpoint and enhanced Bible reference management
This commit is contained in:
114
pages/admin.vue
114
pages/admin.vue
@@ -20,13 +20,13 @@
|
||||
<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>
|
||||
<h2 class="text-2xl font-bold text-gray-900 mb-6">Select Sermon to Manage</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
|
||||
Choose a Sermon
|
||||
</label>
|
||||
<select
|
||||
id="sermon-select"
|
||||
@@ -39,13 +39,21 @@
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@click="handleEdit"
|
||||
:disabled="!selectedSermonId"
|
||||
class="px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed font-medium"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
<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' }}
|
||||
{{ deleting ? 'Deleting...' : 'Delete' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -62,9 +70,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Create New Sermon Form -->
|
||||
<!-- Create/Edit 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>
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-2xl font-bold text-gray-900">
|
||||
{{ editingSermonId ? 'Edit Sermon' : 'Create New Sermon' }}
|
||||
</h2>
|
||||
<button
|
||||
v-if="editingSermonId"
|
||||
type="button"
|
||||
@click="cancelEdit"
|
||||
class="text-sm text-gray-600 hover:text-gray-800"
|
||||
>
|
||||
Cancel Edit
|
||||
</button>
|
||||
</div>
|
||||
<!-- Basic Info -->
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
@@ -202,7 +222,7 @@
|
||||
: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' }}
|
||||
{{ loading ? (editingSermonId ? 'Updating...' : 'Creating...') : (editingSermonId ? 'Update Sermon' : 'Create Sermon') }}
|
||||
</button>
|
||||
<NuxtLink
|
||||
to="/"
|
||||
@@ -231,6 +251,7 @@ const deleteSuccess = ref('')
|
||||
const deleting = ref(false)
|
||||
|
||||
// Create sermon form state
|
||||
const editingSermonId = ref<number | null>(null)
|
||||
const bibleReferences = ref([{ version: 'ESV', reference: '', text: '' }])
|
||||
const formData = ref({
|
||||
date: '',
|
||||
@@ -269,21 +290,33 @@ async function handleSubmit() {
|
||||
)
|
||||
const bible_references = JSON.stringify(validReferences)
|
||||
|
||||
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
|
||||
}
|
||||
})
|
||||
const 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!'
|
||||
if (editingSermonId.value) {
|
||||
// Update existing sermon
|
||||
await $fetch(`/api/sermons/update/${editingSermonId.value}`, {
|
||||
method: 'PUT',
|
||||
body
|
||||
})
|
||||
success.value = 'Sermon updated successfully!'
|
||||
} else {
|
||||
// Create new sermon
|
||||
await $fetch('/api/sermons', {
|
||||
method: 'POST',
|
||||
body
|
||||
})
|
||||
success.value = 'Sermon created successfully!'
|
||||
}
|
||||
|
||||
// Reset form
|
||||
editingSermonId.value = null
|
||||
formData.value = {
|
||||
date: '',
|
||||
title: '',
|
||||
@@ -292,17 +325,60 @@ async function handleSubmit() {
|
||||
}
|
||||
bibleReferences.value = [{ version: 'ESV', reference: '', text: '' }]
|
||||
|
||||
// Refresh sermon list
|
||||
await refreshSermons()
|
||||
|
||||
// Redirect after 2 seconds
|
||||
setTimeout(() => {
|
||||
navigateTo('/')
|
||||
}, 2000)
|
||||
} catch (e: any) {
|
||||
error.value = e.data?.message || 'Failed to create sermon'
|
||||
error.value = e.data?.message || `Failed to ${editingSermonId.value ? 'update' : 'create'} sermon`
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function cancelEdit() {
|
||||
editingSermonId.value = null
|
||||
formData.value = {
|
||||
date: '',
|
||||
title: '',
|
||||
personal_appliance: '',
|
||||
pastors_challenge: ''
|
||||
}
|
||||
bibleReferences.value = [{ version: 'ESV', reference: '', text: '' }]
|
||||
}
|
||||
|
||||
function handleEdit() {
|
||||
if (!selectedSermonId.value) return
|
||||
|
||||
const sermon = allSermons.value?.find((s: any) => s.id === parseInt(selectedSermonId.value))
|
||||
if (!sermon) return
|
||||
|
||||
// Set editing mode
|
||||
editingSermonId.value = sermon.id
|
||||
|
||||
// Load sermon data into form
|
||||
formData.value = {
|
||||
date: sermon.date,
|
||||
title: sermon.title,
|
||||
personal_appliance: sermon.personal_appliance,
|
||||
pastors_challenge: sermon.pastors_challenge
|
||||
}
|
||||
|
||||
// Parse and load Bible references
|
||||
try {
|
||||
bibleReferences.value = JSON.parse(sermon.bible_references)
|
||||
} catch {
|
||||
// Fallback for old format
|
||||
bibleReferences.value = [{ version: 'ESV', reference: sermon.bible_references, text: '' }]
|
||||
}
|
||||
|
||||
// Scroll to form
|
||||
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' })
|
||||
}
|
||||
|
||||
async function handleDelete() {
|
||||
if (!selectedSermonId.value) return
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
to="/admin"
|
||||
class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 font-medium text-sm"
|
||||
>
|
||||
Create New Sermon
|
||||
Manage Sermons
|
||||
</NuxtLink>
|
||||
<button
|
||||
@click="handleLogout"
|
||||
|
||||
58
server/api/sermons/update/[id].put.ts
Normal file
58
server/api/sermons/update/[id].put.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { isAuthenticated } from '~/server/utils/auth'
|
||||
import { getDatabase } from '~/server/utils/database'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
// Check authentication
|
||||
if (!isAuthenticated(event)) {
|
||||
throw createError({
|
||||
statusCode: 401,
|
||||
message: 'Unauthorized'
|
||||
})
|
||||
}
|
||||
|
||||
const id = getRouterParam(event, 'id')
|
||||
|
||||
if (!id) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
message: 'Sermon ID is required'
|
||||
})
|
||||
}
|
||||
|
||||
const body = await readBody(event)
|
||||
const { slug, title, date, bible_references, personal_appliance, pastors_challenge } = body
|
||||
|
||||
if (!slug || !title || !date || !bible_references || !personal_appliance || !pastors_challenge) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
message: 'All fields are required'
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
const db = getDatabase()
|
||||
const result = db.prepare(`
|
||||
UPDATE sermons
|
||||
SET slug = ?, title = ?, date = ?, bible_references = ?,
|
||||
personal_appliance = ?, pastors_challenge = ?
|
||||
WHERE id = ?
|
||||
`).run(slug, title, date, bible_references, personal_appliance, pastors_challenge, parseInt(id))
|
||||
|
||||
if (result.changes === 0) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
message: 'Sermon not found'
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Sermon updated successfully'
|
||||
}
|
||||
} catch (error: any) {
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
message: error.message || 'Failed to update sermon'
|
||||
})
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user