Songs & dates
This commit is contained in:
@@ -78,6 +78,23 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Worship Songs Section -->
|
||||
<section v-if="worshipSongs.length > 0" class="mb-8">
|
||||
<h2 class="text-2xl font-semibold text-gray-900 mb-4">Worship Songs</h2>
|
||||
<div class="bg-yellow-50 rounded-lg p-6">
|
||||
<ul class="space-y-3">
|
||||
<li
|
||||
v-for="(song, index) in worshipSongs"
|
||||
:key="index"
|
||||
:class="['text-gray-800', fontSizeClasses]"
|
||||
>
|
||||
<span class="font-semibold">{{ song.name }}</span>
|
||||
<span v-if="song.artist" class="text-gray-600"> - {{ song.artist }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Back Button -->
|
||||
<div class="border-t pt-6">
|
||||
<NuxtLink
|
||||
@@ -132,6 +149,15 @@ const bibleReferences = computed(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const worshipSongs = computed(() => {
|
||||
if (!sermon.value?.worship_songs) return []
|
||||
try {
|
||||
return JSON.parse(sermon.value.worship_songs)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
// Font size classes
|
||||
const fontSizeClasses = computed(() => {
|
||||
switch (fontSize.value) {
|
||||
|
||||
130
pages/admin.vue
130
pages/admin.vue
@@ -111,7 +111,7 @@
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<label for="date" class="block text-sm font-medium text-gray-700 mb-2">
|
||||
Sermon Date
|
||||
Primary Sermon Date
|
||||
</label>
|
||||
<input
|
||||
id="date"
|
||||
@@ -120,6 +120,37 @@
|
||||
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"
|
||||
/>
|
||||
<p class="text-xs text-gray-500 mt-1">This date will be used for the sermon URL and sorting</p>
|
||||
</div>
|
||||
|
||||
<!-- Additional Dates Section -->
|
||||
<div class="border-t pt-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-2">Additional Dates</h3>
|
||||
<p class="text-sm text-gray-600 mb-4">Add more dates if this sermon will be presented multiple times (e.g., Saturday and Sunday services)</p>
|
||||
<div class="space-y-3">
|
||||
<div v-for="(date, index) in sermonDates" :key="index" class="flex gap-3">
|
||||
<input
|
||||
v-model="sermonDates[index]"
|
||||
type="date"
|
||||
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="sermonDates.length > 1"
|
||||
type="button"
|
||||
@click="removeDate(index)"
|
||||
class="px-3 py-2 bg-red-100 text-red-700 rounded-md hover:bg-red-200"
|
||||
>
|
||||
−
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@click="addDate"
|
||||
class="px-4 py-2 bg-blue-100 text-blue-700 rounded-md hover:bg-blue-200 font-medium"
|
||||
>
|
||||
+ Add Date
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -231,6 +262,57 @@
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Worship Songs Section -->
|
||||
<div class="border-t pt-6">
|
||||
<h2 class="text-xl font-semibold text-gray-900 mb-4">Worship Songs</h2>
|
||||
<p class="text-sm text-gray-600 mb-4">Add songs that were sung during this service (optional)</p>
|
||||
<div class="space-y-4">
|
||||
<div v-for="(song, index) in worshipSongs" :key="index" class="border border-gray-200 rounded-lg p-4 space-y-3">
|
||||
<div class="flex flex-col md:flex-row gap-3">
|
||||
<div class="flex-1">
|
||||
<label :for="`song-name-${index}`" class="block text-sm font-medium text-gray-700 mb-1">
|
||||
Song Name
|
||||
</label>
|
||||
<input
|
||||
:id="`song-name-${index}`"
|
||||
v-model="song.name"
|
||||
type="text"
|
||||
placeholder="e.g., Amazing Grace"
|
||||
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 class="flex-1">
|
||||
<label :for="`song-artist-${index}`" class="block text-sm font-medium text-gray-700 mb-1">
|
||||
Artist/Composer
|
||||
</label>
|
||||
<input
|
||||
:id="`song-artist-${index}`"
|
||||
v-model="song.artist"
|
||||
type="text"
|
||||
placeholder="e.g., John Newton"
|
||||
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>
|
||||
<button
|
||||
v-if="worshipSongs.length > 1"
|
||||
type="button"
|
||||
@click="removeSong(index)"
|
||||
class="self-end px-3 py-2 bg-red-100 text-red-700 rounded-md hover:bg-red-200"
|
||||
>
|
||||
−
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@click="addSong"
|
||||
class="px-4 py-2 bg-blue-100 text-blue-700 rounded-md hover:bg-blue-200 font-medium"
|
||||
>
|
||||
+ Add Song
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Error/Success Messages -->
|
||||
<div v-if="error" class="text-red-600 text-sm">
|
||||
{{ error }}
|
||||
@@ -280,6 +362,8 @@ const archiveSuccess = ref('')
|
||||
// Create sermon form state
|
||||
const editingSermonId = ref<number | null>(null)
|
||||
const bibleReferences = ref([{ version: 'ESV', reference: '', text: '' }])
|
||||
const sermonDates = ref([''])
|
||||
const worshipSongs = ref([{ name: '', artist: '' }])
|
||||
const formData = ref({
|
||||
date: '',
|
||||
title: '',
|
||||
@@ -305,6 +389,22 @@ function removeReference(index: number) {
|
||||
bibleReferences.value.splice(index, 1)
|
||||
}
|
||||
|
||||
function addDate() {
|
||||
sermonDates.value.push('')
|
||||
}
|
||||
|
||||
function removeDate(index: number) {
|
||||
sermonDates.value.splice(index, 1)
|
||||
}
|
||||
|
||||
function addSong() {
|
||||
worshipSongs.value.push({ name: '', artist: '' })
|
||||
}
|
||||
|
||||
function removeSong(index: number) {
|
||||
worshipSongs.value.splice(index, 1)
|
||||
}
|
||||
|
||||
function formatDateToSlug(date: string) {
|
||||
// Convert YYYY-MM-DD to MMDDYYYY
|
||||
const [year, month, day] = date.split('-')
|
||||
@@ -324,13 +424,23 @@ async function handleSubmit() {
|
||||
)
|
||||
const bible_references = JSON.stringify(validReferences)
|
||||
|
||||
// Filter valid dates and serialize as JSON
|
||||
const validDates = sermonDates.value.filter(d => d)
|
||||
const dates = validDates.length > 0 ? JSON.stringify(validDates) : null
|
||||
|
||||
// Filter valid songs and serialize as JSON
|
||||
const validSongs = worshipSongs.value.filter(s => s.name)
|
||||
const worship_songs = validSongs.length > 0 ? JSON.stringify(validSongs) : null
|
||||
|
||||
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
|
||||
pastors_challenge: formData.value.pastors_challenge,
|
||||
dates,
|
||||
worship_songs
|
||||
}
|
||||
|
||||
if (editingSermonId.value) {
|
||||
@@ -382,6 +492,8 @@ function cancelEdit() {
|
||||
pastors_challenge: ''
|
||||
}
|
||||
bibleReferences.value = [{ version: 'ESV', reference: '', text: '' }]
|
||||
sermonDates.value = ['']
|
||||
worshipSongs.value = [{ name: '', artist: '' }]
|
||||
}
|
||||
|
||||
function handleEdit() {
|
||||
@@ -408,6 +520,20 @@ function handleEdit() {
|
||||
// Fallback for old format
|
||||
bibleReferences.value = [{ version: 'ESV', reference: sermon.bible_references, text: '' }]
|
||||
}
|
||||
|
||||
// Parse and load additional dates
|
||||
try {
|
||||
sermonDates.value = sermon.dates ? JSON.parse(sermon.dates) : ['']
|
||||
} catch {
|
||||
sermonDates.value = ['']
|
||||
}
|
||||
|
||||
// Parse and load worship songs
|
||||
try {
|
||||
worshipSongs.value = sermon.worship_songs ? JSON.parse(sermon.worship_songs) : [{ name: '', artist: '' }]
|
||||
} catch {
|
||||
worshipSongs.value = [{ name: '', artist: '' }]
|
||||
}
|
||||
|
||||
// Scroll to form (just below the management section)
|
||||
const formElement = document.querySelector('form')
|
||||
|
||||
@@ -123,9 +123,26 @@ const todaysSermon = computed(() => {
|
||||
today.setHours(0, 0, 0, 0)
|
||||
|
||||
return activeSermons.value.find((s: any) => {
|
||||
// Check primary date
|
||||
const sermonDate = new Date(s.date + 'T00:00:00')
|
||||
sermonDate.setHours(0, 0, 0, 0)
|
||||
return sermonDate.getTime() === today.getTime()
|
||||
if (sermonDate.getTime() === today.getTime()) return true
|
||||
|
||||
// Check additional dates if they exist
|
||||
if (s.dates) {
|
||||
try {
|
||||
const additionalDates = JSON.parse(s.dates)
|
||||
return additionalDates.some((dateStr: string) => {
|
||||
const additionalDate = new Date(dateStr + 'T00:00:00')
|
||||
additionalDate.setHours(0, 0, 0, 0)
|
||||
return additionalDate.getTime() === today.getTime()
|
||||
})
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}) || null
|
||||
})
|
||||
|
||||
@@ -137,9 +154,26 @@ const upcomingSermons = computed(() => {
|
||||
today.setHours(0, 0, 0, 0)
|
||||
|
||||
return activeSermons.value.filter((s: any) => {
|
||||
// Check primary date
|
||||
const sermonDate = new Date(s.date + 'T00:00:00')
|
||||
sermonDate.setHours(0, 0, 0, 0)
|
||||
return sermonDate.getTime() > today.getTime()
|
||||
if (sermonDate.getTime() > today.getTime()) return true
|
||||
|
||||
// Check additional dates if they exist
|
||||
if (s.dates) {
|
||||
try {
|
||||
const additionalDates = JSON.parse(s.dates)
|
||||
return additionalDates.some((dateStr: string) => {
|
||||
const additionalDate = new Date(dateStr + 'T00:00:00')
|
||||
additionalDate.setHours(0, 0, 0, 0)
|
||||
return additionalDate.getTime() > today.getTime()
|
||||
})
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ export default defineEventHandler(async (event) => {
|
||||
}
|
||||
|
||||
const body = await readBody(event)
|
||||
const { slug, title, date, bible_references, personal_appliance, pastors_challenge } = body
|
||||
const { slug, title, date, dates, bible_references, personal_appliance, pastors_challenge, worship_songs } = body
|
||||
|
||||
if (!slug || !title || !date || !bible_references || !personal_appliance || !pastors_challenge) {
|
||||
throw createError({
|
||||
@@ -25,9 +25,11 @@ export default defineEventHandler(async (event) => {
|
||||
slug,
|
||||
title,
|
||||
date,
|
||||
dates,
|
||||
bible_references,
|
||||
personal_appliance,
|
||||
pastors_challenge
|
||||
pastors_challenge,
|
||||
worship_songs
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
@@ -20,7 +20,7 @@ export default defineEventHandler(async (event) => {
|
||||
}
|
||||
|
||||
const body = await readBody(event)
|
||||
const { slug, title, date, bible_references, personal_appliance, pastors_challenge } = body
|
||||
const { slug, title, date, dates, bible_references, personal_appliance, pastors_challenge, worship_songs } = body
|
||||
|
||||
if (!slug || !title || !date || !bible_references || !personal_appliance || !pastors_challenge) {
|
||||
throw createError({
|
||||
@@ -33,10 +33,10 @@ export default defineEventHandler(async (event) => {
|
||||
const db = getDatabase()
|
||||
const result = db.prepare(`
|
||||
UPDATE sermons
|
||||
SET slug = ?, title = ?, date = ?, bible_references = ?,
|
||||
personal_appliance = ?, pastors_challenge = ?
|
||||
SET slug = ?, title = ?, date = ?, dates = ?, bible_references = ?,
|
||||
personal_appliance = ?, pastors_challenge = ?, worship_songs = ?
|
||||
WHERE id = ?
|
||||
`).run(slug, title, date, bible_references, personal_appliance, pastors_challenge, parseInt(id))
|
||||
`).run(slug, title, date, dates || null, bible_references, personal_appliance, pastors_challenge, worship_songs || null, parseInt(id))
|
||||
|
||||
if (result.changes === 0) {
|
||||
throw createError({
|
||||
|
||||
@@ -8,9 +8,11 @@ export interface Sermon {
|
||||
slug: string
|
||||
title: string
|
||||
date: string
|
||||
dates?: string
|
||||
bible_references: string
|
||||
personal_appliance: string
|
||||
pastors_challenge: string
|
||||
worship_songs?: string
|
||||
created_at?: string
|
||||
}
|
||||
|
||||
@@ -32,9 +34,11 @@ export function getDatabase() {
|
||||
slug TEXT UNIQUE NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
date TEXT NOT NULL,
|
||||
dates TEXT,
|
||||
bible_references TEXT NOT NULL,
|
||||
personal_appliance TEXT NOT NULL,
|
||||
pastors_challenge TEXT NOT NULL,
|
||||
worship_songs TEXT,
|
||||
archived INTEGER DEFAULT 0,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
@@ -87,16 +91,18 @@ export function getSermonBySlug(slug: string) {
|
||||
export function createSermon(sermon: Sermon) {
|
||||
const db = getDatabase()
|
||||
const stmt = db.prepare(`
|
||||
INSERT INTO sermons (slug, title, date, bible_references, personal_appliance, pastors_challenge)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
INSERT INTO sermons (slug, title, date, dates, bible_references, personal_appliance, pastors_challenge, worship_songs)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`)
|
||||
return stmt.run(
|
||||
sermon.slug,
|
||||
sermon.title,
|
||||
sermon.date,
|
||||
sermon.dates || null,
|
||||
sermon.bible_references,
|
||||
sermon.personal_appliance,
|
||||
sermon.pastors_challenge
|
||||
sermon.pastors_challenge,
|
||||
sermon.worship_songs || null
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user