Files
mareike/app/Domains/Event/Views/Partials/CommonSettings.vue
T

337 lines
12 KiB
Vue

<script setup>
import {onMounted, reactive, ref} from "vue";
import ErrorText from "../../../../Views/Components/ErrorText.vue";
import AmountInput from "../../../../Views/Components/AmountInput.vue";
import TextEditor from "../../../../Views/Components/TextEditor.vue";
import {request} from "../../../../../resources/js/components/HttpClient.js";
import {toast} from "vue3-toastify";
const emit = defineEmits(['close'])
const props = defineProps({
event: Object,
})
const dynmicProps = reactive({
localGroups: [],
eatingHabits:[],
paymentMethods: []
});
const contributingLocalGroups = ref([])
const eatingHabits = ref([]);
const paymentMethods = ref([]);
// pro-Event-Config je Zahlungsmethode: { slug: { option: value } }
const paymentMethodConfigurations = reactive({});
const errors = reactive({})
const formData = reactive({
contributingLocalGroups: contributingLocalGroups.value,
eventName: props.event.name,
eventLocation: props.event.location,
postalCode: props.event.postalCode,
email: props.event.email,
earlyBirdEnd: props.event.earlyBirdEnd.internal,
registrationFinalEnd: props.event.registrationFinalEnd.internal,
alcoholicsAge: props.event.alcoholicsAge,
eatingHabits: eatingHabits.value,
sendWeeklyReports: props.event.sendWeeklyReports,
registrationAllowed: props.event.registrationAllowed,
flatSupport: props.event.flatSupportEdit,
supportPerson: props.event.supportPersonIndex,
})
onMounted(async () => {
const response = await fetch('/api/v1/core/retrieve-event-setting-data');
const data = await response.json();
Object.assign(dynmicProps, data);
contributingLocalGroups.value = props.event.contributingLocalGroups?.map(t => t.id) ?? []
eatingHabits.value = props.event.eatingHabits?.map(t => t.id) ?? []
paymentMethods.value = props.event.paymentMethods?.map(t => t.slug) ?? []
// Pro-Event-Config vorbelegen: bereits gespeicherte Pivot-Config des Events hat Vorrang,
// sonst der Tenant-Standard (Snapshot-Quelle für neu zugewiesene Methoden).
const eventConfigBySlug = {}
for (const pm of props.event.paymentMethods ?? []) {
eventConfigBySlug[pm.slug] = pm.configuration ?? {}
}
for (const method of dynmicProps.paymentMethods ?? []) {
const source = eventConfigBySlug[method.slug] ?? method.configuration ?? {}
const config = {}
for (const option of method.optionsSchema ?? []) {
config[option.name] = source[option.name] ?? ''
}
paymentMethodConfigurations[method.slug] = config
}
});
async function save() {
if (paymentMethods.value.length === 0) {
toast.error('Mindestens eine Zahlungsmöglichkeit muss ausgewählt sein.')
return
} else if(paymentMethods.value.length > 1) {
toast.error('Aktuell wird nur exakt eine Zahlungseinstellung unterstützt.')
return
}
const response = await request('/api/v1/event/details/' + props.event.id + '/common-settings', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: {
eventName: formData.eventName,
eventLocation: formData.eventLocation,
postalCode: formData.postalCode,
email: formData.email,
earlyBirdEnd: formData.earlyBirdEnd,
registrationFinalEnd: formData.registrationFinalEnd,
alcoholicsAge: formData.alcoholicsAge,
sendWeeklyReports: formData.sendWeeklyReports,
registrationAllowed: formData.registrationAllowed,
flatSupport: formData.flatSupport,
supportPerson: formData.supportPerson,
contributingLocalGroups: contributingLocalGroups.value,
eatingHabits: eatingHabits.value,
paymentMethods: paymentMethods.value,
paymentMethodConfigurations: paymentMethodConfigurations,
}
})
if (response.status === 'success') {
toast.success('Einstellungen wurden erfolgreich gespeichert.')
emit('close')
} else {
toast.error(response.message ?? 'Beim Speichern ist ein Fehler aufgetreten.')
}
}
</script>
<template>
<h2>Einstellungen</h2>
<div class="container">
<div class="row top">
<div class="left">
<table class="event-settings-table" style="width: 80%;">
<tr>
<th>Veranstaltungsname</th>
<td>
<input type="text" v-model="formData.eventName" class="width-full" /><br />
<ErrorText :message="errors.eventName" />
</td>
</tr>
<tr>
<th>Veranstaltungsort</th>
<td>
<input type="text" v-model="formData.eventLocation" class="width-full" /><br />
<ErrorText :message="errors.eventLocation" />
</td>
</tr>
<tr>
<th>Postleitzahl des Veranstaltungsorts</th>
<td>
<input type="text" v-model="formData.postalCode" class="width-full" /><br />
<ErrorText :message="errors.eventPostalCode" />
</td>
</tr>
<tr>
<th>E-Mail-Adresse der Veranstaltungsleitung</th>
<td>
<input type="text" v-model="formData.email" class="width-full" /><br />
<ErrorText :message="errors.eventEmail" />
</td>
</tr>
<tr>
<th>Ende der EarlyBird-Phase</th>
<td>
<input type="date" v-model="formData.earlyBirdEnd" class="width-full" /><br />
<ErrorText :message="errors.earlyBirdEnd" />
</td>
</tr>
<tr>
<th>Finaler Anmeldeschluss</th>
<td>
<input type="date" v-model="formData.registrationFinalEnd" class="width-full" /><br />
<ErrorText :message="errors.registrationFinalEnd" />
</td>
</tr>
<tr>
<th>Fördermittel</th>
<td>
<amountInput v-model="formData.supportPerson" clasS="width-small" /> Euro p.P. / Tag
</td>
</tr>
<tr>
<th>Zuschüsse</th>
<td>
<amountInput v-model="formData.flatSupport" clasS="width-small" /> Euro pauschal
</td>
</tr>
<tr>
<th>Mindestalter für Alkoholkonsum</th>
<td>
<input type="number" v-model="formData.alcoholicsAge" class="width-tiny" /><br />
<ErrorText :message="errors.alcoholicsAge" />
</td>
</tr>
<tr>
<td colspan="2" style="height: 25px !important;">
<input type="checkbox" v-model="formData.sendWeeklyReports" id="sendWeeklyReports" />
<label for="sendWeeklyReports">Wöchentliche Zusammenfassung per E-Mail an Stämme schicken</label>
</td>
</tr>
<tr>
<td colspan="2">
<input type="checkbox" v-model="formData.registrationAllowed" id="registrationAllowed" />
<label for="registrationAllowed">Veranstaltung ist für Anmeldungen geöffnet</label>
</td>
</tr>
</table>
</div>
<div class="right">
<table>
<tr>
<th>Teilnehmende Stämme</th>
</tr>
<tr v-for="localGroup in dynmicProps.localGroups">
<td>
<input type="checkbox" :id="'localgroup_' + localGroup.id" :value="localGroup.id" v-model="contributingLocalGroups" />
<label style="padding-left: 5px;" :for="'localgroup_' + localGroup.id">{{localGroup.name}}</label>
</td>
</tr>
<tr>
<th style="padding-top: 40px !important;">Angebotene Ernährung</th>
</tr>
<tr v-for="eatingHabit in dynmicProps.eatingHabits">
<td>
<input type="checkbox" :id="'eatinghabit' + eatingHabit.id" :value="eatingHabit.id" v-model="eatingHabits" />
<label style="padding-left: 5px;" :for="'eatinghabit' + eatingHabit.id">{{eatingHabit.name}}</label>
</td>
</tr>
<tr>
<th style="padding-top: 40px !important;">Zahlungsmöglichkeiten</th>
</tr>
<tr v-for="paymentMethod in dynmicProps.paymentMethods">
<td>
<input type="checkbox" :id="'paymentmethod' + paymentMethod.id" :value="paymentMethod.slug" v-model="paymentMethods" />
<label style="padding-left: 5px;" :for="'paymentmethod' + paymentMethod.id">{{paymentMethod.name}}</label>
<div
v-if="paymentMethods.includes(paymentMethod.slug) && (paymentMethod.optionsSchema?.length ?? 0) > 0"
class="payment-method-config"
>
<div v-for="option in paymentMethod.optionsSchema" :key="option.name" class="payment-method-config-row">
<label>{{ option.label }}<span v-if="option.required" class="required-marker">*</span></label>
<TextEditor v-if="option.type === 'richtext'"
v-model="paymentMethodConfigurations[paymentMethod.slug][option.name]"/>
<input v-else type="text"
v-model="paymentMethodConfigurations[paymentMethod.slug][option.name]"
class="width-full"/>
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="row bott">
<input type="button" value="Speichern" @click="save" />
</div>
</div>
</template>
<style scoped>
.container {
display: flex;
flex-direction: column;
gap: 10px; /* Abstand zwischen den Zeilen */
width: 95%;
margin: auto;
}
.row {
display: flex;
gap: 10px; /* Abstand zwischen den Spalten */
}
.row.top .left {
flex: 0 0 70%; /* feste Breite von 80% */
padding: 10px;
}
.row.top .right {
flex: 0 0 30%; /* feste Breite von 20% */
padding: 10px;
}
.row.bottom {
padding: 10px;
}
.event-settings-table {
}
.event-settings-table tr {
vertical-align: top;
}
.event-settings-table td {
height: 50px;
}
.event-settings-table th {
vertical-align: top;
width: 250px;
}
.payment-method-config {
margin: 6px 0 12px 24px;
padding-left: 10px;
border-left: 2px solid #d1d5db;
}
.payment-method-config-row {
margin-bottom: 6px;
}
.payment-method-config-row label {
display: block;
font-size: 0.85rem;
color: #374151;
margin-bottom: 2px;
}
.required-marker {
color: #ef4444;
margin-left: 2px;
}
</style>