292 lines
8.0 KiB
Vue
292 lines
8.0 KiB
Vue
<template>
|
|
<div class="event-management">
|
|
<h2>Veranstaltungen</h2>
|
|
<button v-if="hasNewsletterPreview" @click="goBackToNewsletterImport">Zurück zum Gemeindebrief-Import</button>
|
|
<button @click="createEvent">Neue Veranstaltung</button>
|
|
<EventForm v-if="showForm"
|
|
ref="eventForm"
|
|
:event="selectedEvent"
|
|
:institutions="institutions"
|
|
:eventPlaces="eventPlaces"
|
|
:contactPersons="contactPersons"
|
|
@saved="handleEventSaved"
|
|
@cancelled="handleEventCancelled" />
|
|
|
|
<div class="filter-section">
|
|
<input
|
|
v-model="searchQuery"
|
|
type="text"
|
|
placeholder="Suche nach Name, Typ, Beschreibung..."
|
|
class="search-input"
|
|
/>
|
|
<label class="checkbox-label">
|
|
<input
|
|
v-model="showPastEvents"
|
|
type="checkbox"
|
|
/>
|
|
Vergangene Events anzeigen
|
|
</label>
|
|
</div>
|
|
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Typ</th>
|
|
<th>Datum</th>
|
|
<th>Uhrzeit</th>
|
|
<th>Wochentag</th>
|
|
<th>Beschreibung</th>
|
|
<th>Aktionen</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="event in filteredEvents" :key="event.id">
|
|
<td>{{ event.name }}</td>
|
|
<td>{{ getEventTypeCaption(event.eventTypeId) }}</td>
|
|
<td>{{ event.date }}</td>
|
|
<td>{{ formatTime(event.time) }}<span v-if="event.endTime"> - {{ formatTime(event.endTime) }}</span></td>
|
|
<td>{{ getWeekdayName(event.dayOfWeek) }}</td>
|
|
<td>{{ event.description }}</td>
|
|
<td>
|
|
<button @click="editEvent(event)">Bearbeiten</button>
|
|
<button @click="deleteEvent(event.id)">Löschen</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import axios from 'axios';
|
|
import EventForm from '@/components/EventForm.vue';
|
|
import { formatTime } from '../../utils/strings';
|
|
|
|
export default {
|
|
components: { EventForm },
|
|
data() {
|
|
return {
|
|
events: [],
|
|
institutions: [],
|
|
eventPlaces: [],
|
|
contactPersons: [],
|
|
eventTypes: [],
|
|
selectedEvent: null,
|
|
showForm: false,
|
|
searchQuery: '',
|
|
showPastEvents: false,
|
|
hasNewsletterPreview: false,
|
|
};
|
|
},
|
|
computed: {
|
|
filteredEvents() {
|
|
let filtered = this.events;
|
|
|
|
// Filter vergangene Events aus
|
|
if (!this.showPastEvents) {
|
|
const today = new Date();
|
|
today.setHours(0, 0, 0, 0);
|
|
|
|
filtered = filtered.filter(event => {
|
|
// Events mit Wochentag (ohne festes Datum) immer anzeigen
|
|
if (event.dayOfWeek !== null && event.dayOfWeek !== undefined && !event.date) {
|
|
return true;
|
|
}
|
|
// Events mit Datum: nur zukünftige oder heutige anzeigen
|
|
if (event.date) {
|
|
const eventDate = new Date(event.date);
|
|
eventDate.setHours(0, 0, 0, 0);
|
|
return eventDate >= today;
|
|
}
|
|
// Events ohne Datum und ohne Wochentag anzeigen
|
|
return true;
|
|
});
|
|
}
|
|
|
|
// Suchfilter anwenden
|
|
if (this.searchQuery.trim()) {
|
|
const query = this.searchQuery.toLowerCase();
|
|
filtered = filtered.filter(event => {
|
|
const name = event.name ? event.name.toLowerCase() : '';
|
|
const description = event.description ? event.description.toLowerCase() : '';
|
|
const eventType = this.getEventTypeCaption(event.eventTypeId).toLowerCase();
|
|
|
|
return name.includes(query) ||
|
|
description.includes(query) ||
|
|
eventType.includes(query);
|
|
});
|
|
}
|
|
|
|
return filtered;
|
|
}
|
|
},
|
|
async created() {
|
|
await this.fetchData();
|
|
this.hasNewsletterPreview = !!localStorage.getItem('newsletter_import_last_result');
|
|
this.applyNewsletterDraft();
|
|
},
|
|
methods: {
|
|
formatTime,
|
|
async fetchData() {
|
|
try {
|
|
const [eventResponse, institutionResponse, eventPlaceResponse, contactPersonResponse, eventTypeResponse] = await Promise.all([
|
|
axios.get('/events'),
|
|
axios.get('/institutions'),
|
|
axios.get('/event-places'),
|
|
axios.get('/contact-persons'),
|
|
axios.get('/event-types')
|
|
]);
|
|
|
|
this.events = eventResponse.data;
|
|
this.institutions = institutionResponse.data;
|
|
this.eventPlaces = eventPlaceResponse.data;
|
|
this.contactPersons = contactPersonResponse.data;
|
|
this.eventTypes = eventTypeResponse.data;
|
|
} catch (error) {
|
|
console.error('Fehler beim Abrufen der Daten:', error);
|
|
}
|
|
},
|
|
createEvent() {
|
|
this.selectedEvent = {};
|
|
this.showForm = true;
|
|
this.scrollToFormAndFocus();
|
|
},
|
|
goBackToNewsletterImport() {
|
|
this.$router.push('/admin/newsletter-import');
|
|
},
|
|
applyNewsletterDraft() {
|
|
const raw = localStorage.getItem('newsletter_import_event_draft');
|
|
if (!raw) return;
|
|
localStorage.removeItem('newsletter_import_event_draft');
|
|
try {
|
|
const draft = JSON.parse(raw);
|
|
const resolvedEventPlace =
|
|
this.eventPlaces.find((place) => place.id === draft?.event_place_id) ||
|
|
this.eventPlaces.find((place) =>
|
|
draft?.event_place_name &&
|
|
String(place?.name || '').toLowerCase().includes(String(draft.event_place_name).toLowerCase())
|
|
) ||
|
|
null;
|
|
this.selectedEvent = {
|
|
name: draft?.name || '',
|
|
description: '',
|
|
date: draft?.date || '',
|
|
time: draft?.time || '',
|
|
eventTypeId: draft?.eventTypeId ?? null,
|
|
event_place_id: resolvedEventPlace?.id ?? draft?.event_place_id ?? null,
|
|
eventPlace: resolvedEventPlace,
|
|
__newsletterDateMode: draft?.dateMode || null,
|
|
__newsletterBulkDates: draft?.bulkDates || '',
|
|
};
|
|
this.showForm = true;
|
|
this.scrollToFormAndFocus();
|
|
} catch (error) {
|
|
console.error('Fehler beim Übernehmen des Gemeindebrief-Entwurfs (Event):', error);
|
|
}
|
|
},
|
|
editEvent(event) {
|
|
this.selectedEvent = { ...event };
|
|
this.showForm = true;
|
|
this.scrollToFormAndFocus();
|
|
},
|
|
scrollToFormAndFocus() {
|
|
// Wartet auf das Rendern des Formulars und scrollt dann nach oben
|
|
this.$nextTick(() => {
|
|
// Nach oben scrollen
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
|
|
// Das erste Feld fokussieren
|
|
if (this.$refs.eventForm) {
|
|
this.$refs.eventForm.focusFirstField();
|
|
}
|
|
});
|
|
},
|
|
async deleteEvent(id) {
|
|
try {
|
|
await axios.delete(`/events/${id}`);
|
|
this.fetchData();
|
|
} catch (error) {
|
|
console.error('Fehler beim Löschen der Veranstaltung:', error);
|
|
}
|
|
},
|
|
handleEventSaved() {
|
|
this.showForm = false;
|
|
this.fetchData();
|
|
},
|
|
handleEventCancelled() {
|
|
this.showForm = false;
|
|
},
|
|
getEventTypeCaption(eventTypeId) {
|
|
const eventType = this.eventTypes.find(type => type.id === eventTypeId);
|
|
return eventType ? eventType.caption : 'Unbekannt';
|
|
},
|
|
getWeekdayName(dayOfWeek) {
|
|
const weekdays = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'];
|
|
return weekdays[dayOfWeek];
|
|
},
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.event-management {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.filter-section {
|
|
margin: 20px 0;
|
|
display: flex;
|
|
gap: 20px;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.search-input {
|
|
flex: 1;
|
|
min-width: 250px;
|
|
padding: 8px 12px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.search-input:focus {
|
|
outline: none;
|
|
border-color: #4CAF50;
|
|
}
|
|
|
|
.checkbox-label {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
cursor: pointer;
|
|
user-select: none;
|
|
}
|
|
|
|
.checkbox-label input[type="checkbox"] {
|
|
cursor: pointer;
|
|
}
|
|
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
th,
|
|
td {
|
|
border: 1px solid #ddd;
|
|
padding: 8px;
|
|
}
|
|
|
|
th {
|
|
background-color: #f2f2f2;
|
|
}
|
|
|
|
button {
|
|
margin: 5px;
|
|
}
|
|
</style>
|