Add WYSIWYG text editor for Satzung content management
This commit introduces a new WYSIWYG text editor for editing the Satzung text directly within the CMS. It includes functionality for saving the edited content and displays a success or error message based on the save operation's outcome. Additionally, the layout has been updated to improve the presentation of the PDF upload section and current PDF information.
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<!-- 1. PDF-Upload -->
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 mb-6">
|
||||
<h2 class="text-xl font-semibold mb-4">
|
||||
PDF-Upload
|
||||
@@ -68,14 +69,15 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- 2. Aktuelle PDF-Information -->
|
||||
<div
|
||||
v-if="currentPdfUrl"
|
||||
class="bg-white rounded-xl shadow-sm border border-gray-200 p-6"
|
||||
class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 mb-6"
|
||||
>
|
||||
<h2 class="text-xl font-semibold mb-4">
|
||||
Aktuelle Satzung
|
||||
Aktuelle Satzung (PDF)
|
||||
</h2>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
|
||||
<div>
|
||||
<p class="text-gray-600">
|
||||
PDF-Datei verfügbar
|
||||
@@ -94,6 +96,52 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. Textfassung (WYSIWYG) -->
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 mb-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h2 class="text-xl font-semibold">
|
||||
Textfassung für die Website
|
||||
</h2>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex items-center px-4 py-2 rounded-lg bg-primary-600 text-white hover:bg-primary-700 disabled:opacity-50 disabled:cursor-not-allowed text-sm"
|
||||
:disabled="savingText"
|
||||
@click="saveText"
|
||||
>
|
||||
<svg
|
||||
v-if="savingText"
|
||||
class="animate-spin -ml-1 mr-2 h-4 w-4 text-white"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle
|
||||
class="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
stroke-width="4"
|
||||
/>
|
||||
<path
|
||||
class="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
{{ savingText ? 'Speichert...' : 'Text speichern' }}
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-sm text-gray-500 mb-4">
|
||||
Diese HTML-Fassung wird auf der Seite „Verein → Satzung“ angezeigt. Die PDF-Version bleibt die rechtlich verbindliche Fassung.
|
||||
</p>
|
||||
|
||||
<RichTextEditor
|
||||
v-model="satzungContent"
|
||||
label="Satzung (HTML-Version)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="message"
|
||||
class="mt-4 p-4 rounded-lg"
|
||||
@@ -107,6 +155,7 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import RichTextEditor from '~/components/RichTextEditor.vue'
|
||||
|
||||
definePageMeta({
|
||||
middleware: 'auth',
|
||||
@@ -121,6 +170,8 @@ const currentPdfUrl = ref('')
|
||||
const lastUpdated = ref('')
|
||||
const message = ref('')
|
||||
const messageType = ref('')
|
||||
const satzungContent = ref('')
|
||||
const savingText = ref(false)
|
||||
|
||||
async function loadCurrentSatzung() {
|
||||
try {
|
||||
@@ -131,6 +182,11 @@ async function loadCurrentSatzung() {
|
||||
// Einfache Zeitstempel-Simulation
|
||||
lastUpdated.value = new Date().toLocaleDateString('de-DE')
|
||||
}
|
||||
if (satzung?.content) {
|
||||
satzungContent.value = satzung.content
|
||||
} else {
|
||||
satzungContent.value = ''
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Fehler beim Laden der aktuellen Satzung:', e)
|
||||
}
|
||||
@@ -187,5 +243,51 @@ async function uploadPdf() {
|
||||
}
|
||||
}
|
||||
|
||||
async function saveText() {
|
||||
savingText.value = true
|
||||
message.value = ''
|
||||
try {
|
||||
const current = await $fetch('/api/config')
|
||||
const currentSeiten = current.seiten || {}
|
||||
const currentSatzung = currentSeiten.satzung || {}
|
||||
|
||||
const updated = {
|
||||
...current,
|
||||
seiten: {
|
||||
...currentSeiten,
|
||||
satzung: {
|
||||
...currentSatzung,
|
||||
content: satzungContent.value || ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await $fetch('/api/config', {
|
||||
method: 'PUT',
|
||||
body: updated
|
||||
})
|
||||
|
||||
message.value = 'Satzungstext erfolgreich gespeichert'
|
||||
messageType.value = 'success'
|
||||
|
||||
try {
|
||||
window.showSuccessModal && window.showSuccessModal('Erfolg', 'Satzungstext erfolgreich gespeichert.')
|
||||
} catch {
|
||||
// Modal optional
|
||||
}
|
||||
} catch (error) {
|
||||
const errMsg = error?.data?.message || 'Fehler beim Speichern des Satzungstextes'
|
||||
message.value = errMsg
|
||||
messageType.value = 'error'
|
||||
try {
|
||||
window.showErrorModal && window.showErrorModal('Fehler', errMsg)
|
||||
} catch {
|
||||
// optional
|
||||
}
|
||||
} finally {
|
||||
savingText.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(loadCurrentSatzung)
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user