inital commit

This commit is contained in:
Torsten Schulz
2024-06-15 23:01:46 +02:00
parent 1b7fefe381
commit 61653ff407
105 changed files with 7805 additions and 524 deletions

View File

@@ -0,0 +1,138 @@
<template>
<div class="contact-person-form">
<h2>Kontaktperson Formular</h2>
<form @submit.prevent="saveContactPerson">
<label for="name">Name:</label>
<input type="text" id="name" v-model="localContactPerson.name" required>
<label for="phone">Telefon:</label>
<input type="text" id="phone" v-model="localContactPerson.phone">
<label for="street">Straße:</label>
<input type="text" id="street" v-model="localContactPerson.street">
<label for="zipcode">PLZ:</label>
<input type="text" id="zipcode" v-model="localContactPerson.zipcode">
<label for="city">Ort:</label>
<input type="text" id="city" v-model="localContactPerson.city">
<label for="email">Email:</label>
<input type="email" id="email" v-model="localContactPerson.email">
<label for="positions">Positionen:</label>
<multiselect
v-model="selectedPositions"
:options="positions"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:preserve-search="true"
placeholder="Wähle einige"
label="caption"
track-by="id"
:preselect-first="false"
></multiselect>
<button type="submit">Speichern</button>
<button type="button" @click="resetForm">Neue Kontaktperson</button>
</form>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect';
import axios from 'axios';
export default {
name: 'ContactPersonForm',
components: { Multiselect },
props: {
contactPerson: {
type: Object,
default: () => ({
name: '',
phone: '',
street: '',
zipcode: '',
city: '',
email: '',
positions: []
})
},
positions: {
type: Array,
required: true
}
},
data() {
return {
localContactPerson: { ...this.contactPerson },
selectedPositions: this.contactPerson.positions || []
};
},
watch: {
contactPerson: {
handler(newVal) {
this.localContactPerson = { ...newVal };
this.selectedPositions = newVal.positions || [];
},
deep: true,
immediate: true
},
selectedPositions(newVal) {
this.localContactPerson.positions = newVal;
}
},
methods: {
async saveContactPerson() {
try {
const positionIds = this.selectedPositions.map(position => position.id);
const payload = {
...this.localContactPerson,
positionIds: positionIds
};
if (this.localContactPerson.id) {
await axios.put(`http://localhost:3000/api/contact-persons/${this.localContactPerson.id}`, payload);
} else {
await axios.post('http://localhost:3000/api/contact-persons', payload);
}
this.$emit('contactPersonSaved');
} catch (error) {
console.error('Fehler beim Speichern der Kontaktperson:', error);
}
},
resetForm() {
this.localContactPerson = {
name: '',
phone: '',
street: '',
zipcode: '',
city: '',
email: '',
positions: []
};
this.selectedPositions = [];
}
}
};
</script>
<style scoped>
@import '~vue-multiselect/dist/vue-multiselect.css';
.contact-person-form {
max-width: 400px;
margin: auto;
}
form {
display: flex;
flex-direction: column;
}
label {
margin-top: 10px;
}
button {
margin-top: 20px;
}
</style>

View File

@@ -0,0 +1,250 @@
<template>
<div class="event-form">
<h2>Veranstaltung Formular</h2>
<form @submit.prevent="saveEvent">
<table>
<tr>
<td><label for="name">Name:</label></td>
<td><input type="text" id="name" v-model="eventData.name" required></td>
</tr>
<tr>
<td><label for="eventType">Typ:</label></td>
<td>
<multiselect
v-model="selectedEventType"
:options="eventTypes"
label="caption"
track-by="id"
placeholder="Typ wählen"
></multiselect>
</td>
</tr>
<tr>
<td><label for="dateMode">Datum-Modus:</label></td>
<td>
<select v-model="dateMode">
<option value="date">Datum</option>
<option value="weekday">Wochentag</option>
<option value="interval">Intervall</option>
</select>
</td>
</tr>
<tr v-if="dateMode === 'date' || dateMode === 'interval'">
<td><label for="date">Datum:</label></td>
<td><input type="date" id="date" v-model="eventData.date"></td>
</tr>
<tr v-if="dateMode === 'weekday' || dateMode === 'interval'">
<td><label for="dayOfWeek">Wochentag:</label></td>
<td>
<multiselect
v-model="eventData.dayOfWeek"
:options="weekdays"
label="name"
track-by="value"
placeholder="Wochentag wählen"
></multiselect>
</td>
</tr>
<tr>
<td><label for="time">Uhrzeit:</label></td>
<td><input type="time" id="time" v-model="eventData.time"></td>
</tr>
<tr>
<td><label for="endTime">Ende-Uhrzeit:</label></td>
<td><input type="time" id="endTime" v-model="eventData.endTime"></td>
</tr>
<tr>
<td><label for="description">Beschreibung:</label></td>
<td><textarea id="description" v-model="eventData.description" class="descriptionedit"></textarea></td>
</tr>
<tr>
<td><label for="institution">Institution:</label></td>
<td>
<multiselect
v-model="selectedInstitution"
:options="localInstitutions"
label="name"
track-by="id"
placeholder="Institution wählen"
></multiselect>
</td>
</tr>
<tr>
<td><label for="eventPlace">Veranstaltungsort:</label></td>
<td>
<multiselect
v-model="selectedEventPlace"
:options="localEventPlaces"
label="name"
track-by="id"
placeholder="Veranstaltungsort wählen"
></multiselect>
</td>
</tr>
<tr>
<td><label for="contactPersons">Kontaktpersonen:</label></td>
<td>
<multiselect
v-model="selectedContactPersons"
:options="localContactPersons"
:multiple="true"
label="name"
track-by="id"
placeholder="Kontaktpersonen wählen"
></multiselect>
</td>
</tr>
<tr>
<td colspan="2"><button type="submit">Speichern</button></td>
</tr>
</table>
</form>
</div>
</template>
<script>
import axios from 'axios';
import Multiselect from 'vue-multiselect';
export default {
name: 'EventForm',
components: { Multiselect },
props: {
event: {
type: Object,
required: true,
default: () => ({})
},
institutions: {
type: Array,
required: true,
default: () => []
},
eventPlaces: {
type: Array,
required: true,
default: () => []
},
contactPersons: {
type: Array,
required: true,
default: () => []
}
},
data() {
return {
eventData: { ...this.event },
selectedEventType: null,
selectedInstitution: this.event.institution || null,
selectedEventPlace: this.event.eventPlace || null,
selectedContactPersons: this.event.contactPersons || [],
eventTypes: [],
dateMode: 'date',
weekdays: [
{ name: 'Montag', value: 1 },
{ name: 'Dienstag', value: 2 },
{ name: 'Mittwoch', value: 3 },
{ name: 'Donnerstag', value: 4 },
{ name: 'Freitag', value: 5 },
{ name: 'Samstag', value: 6 },
{ name: 'Sonntag', value: 7 },
],
localInstitutions: [...this.institutions],
localEventPlaces: [...this.eventPlaces],
localContactPersons: [...this.contactPersons]
};
},
watch: {
event(newVal) {
this.eventData = { ...newVal };
this.selectedEventType = this.eventTypes.find(type => type.id === newVal.eventTypeId) || null;
this.selectedInstitution = newVal.institution || null;
this.selectedEventPlace = newVal.eventPlace || null;
this.selectedContactPersons = newVal.contactPersons || [];
this.determineDateMode();
},
institutions(newVal) {
this.localInstitutions = [...newVal];
},
eventPlaces(newVal) {
this.localEventPlaces = [...newVal];
},
contactPersons(newVal) {
this.localContactPersons = [...newVal];
}
},
async created() {
try {
const eventTypeResponse = await axios.get('http://localhost:3000/api/event-types');
this.eventTypes = eventTypeResponse.data;
this.selectedEventType = this.eventTypes.find(type => type.id === this.event.eventTypeId) || null;
} catch (error) {
console.error('Failed to fetch event types:', error);
}
this.determineDateMode();
},
methods: {
async saveEvent() {
try {
const payload = {
...this.eventData,
eventTypeId: this.selectedEventType ? this.selectedEventType.id : null,
institution_id: this.selectedInstitution ? this.selectedInstitution.id : null,
event_place_id: this.selectedEventPlace ? this.selectedEventPlace.id : null,
contactPersonIds: this.selectedContactPersons.map(person => person.id)
};
payload.dayOfWeek = payload.dayOfWeek.value;
let response;
if (this.eventData.id) {
response = await axios.put(`http://localhost:3000/api/events/${this.eventData.id}`, payload);
} else {
response = await axios.post('http://localhost:3000/api/events', payload);
}
this.$emit('saved', response.data);
} catch (error) {
console.error('Failed to save event:', error);
}
},
determineDateMode() {
if (this.eventData.date && this.eventData.dayOfWeek) {
this.dateMode = 'interval';
} else if (this.eventData.date) {
this.dateMode = 'date';
} else if (this.eventData.dayOfWeek) {
this.dateMode = 'weekday';
} else {
this.dateMode = 'date';
}
}
}
};
</script>
<style scoped>
@import 'vue-multiselect/dist/vue-multiselect.css';
.event-form {
max-width: 600px;
margin: 0 auto;
display: flex;
flex-direction: column;
}
table {
width: 100%;
border-collapse: collapse;
}
td {
padding: 8px;
vertical-align: top;
}
label {
display: block;
}
button {
margin-top: 20px;
}
.descriptionedit {
width: 100%;
height: 10em;
}
</style>

View File

@@ -1,58 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@@ -0,0 +1,124 @@
<template>
<div class="institution-form">
<h2>{{ institution && institution.id ? 'Institution bearbeiten' : 'Institution erstellen' }}</h2>
<form @submit.prevent="saveInstitution">
<label for="name">Name:</label>
<input type="text" id="name" v-model="localInstitution.name" required>
<label for="street">Straße:</label>
<input type="text" id="street" v-model="localInstitution.street">
<label for="zipcode">PLZ:</label>
<input type="text" id="zipcode" v-model="localInstitution.zipcode">
<label for="city">Ort:</label>
<input type="text" id="city" v-model="localInstitution.city">
<label for="phone">Telefon:</label>
<input type="text" id="phone" v-model="localInstitution.phone">
<label for="fax">Fax:</label>
<input type="text" id="fax" v-model="localInstitution.fax">
<label for="email">E-Mail:</label>
<input type="email" id="email" v-model="localInstitution.email">
<label for="contactPersons">Kontaktpersonen:</label>
<multiselect
v-model="selectedContactPersons"
:options="contactPersons"
:multiple="true"
placeholder="Kontaktpersonen auswählen"
label="name"
track-by="id"
></multiselect>
<button type="submit">Speichern</button>
<button type="button" @click="$emit('cancelled')">Abbrechen</button>
</form>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect';
import axios from 'axios';
export default {
name: 'InstitutionForm',
components: { Multiselect },
props: {
institution: {
type: Object,
default: () => null
},
contactPersons: {
type: Array,
required: true
}
},
data() {
return {
localInstitution: {
name: '',
street: '',
zipcode: '',
city: '',
phone: '',
fax: '',
email: '',
contactPersons: []
},
selectedContactPersons: []
};
},
watch: {
institution: {
immediate: true,
handler(newVal) {
if (newVal) {
this.localInstitution = { ...newVal };
this.selectedContactPersons = newVal.contactPersons || [];
}
}
},
selectedContactPersons(newVal) {
this.localInstitution.contactPersons = newVal;
}
},
methods: {
async saveInstitution() {
try {
if (this.localInstitution.id) {
await axios.put(`http://localhost:3000/api/institutions/${this.localInstitution.id}`, this.localInstitution);
} else {
await axios.post('http://localhost:3000/api/institutions', this.localInstitution);
}
this.$emit('saved');
this.$emit('cancelled');
} catch (error) {
console.error('Fehler beim Speichern der Institution:', error);
}
}
}
};
</script>
<style scoped>
@import '~vue-multiselect/dist/vue-multiselect.css';
.institution-form {
max-width: 400px;
margin: auto;
}
form {
display: flex;
flex-direction: column;
}
label {
margin-top: 10px;
}
button {
margin-top: 20px;
}
</style>

View File

@@ -0,0 +1,68 @@
<template>
<div>
<multiselect
v-model="selectedPositions"
:options="options"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:preserve-search="true"
placeholder="Positionen auswählen"
label="caption"
track-by="id"
></multiselect>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect';
import axios from 'axios';
export default {
name: 'PositionSelect',
components: { Multiselect },
props: {
value: {
type: Array,
default: () => []
},
options: {
type: Array,
default: () => []
}
},
data() {
return {
selectedPositions: this.value
};
},
watch: {
value(newVal) {
this.selectedPositions = newVal;
console.log('PositionSelect - value watch - newVal:', newVal);
},
selectedPositions(newVal) {
console.log('PositionSelect - selectedPositions watch - newVal:', newVal);
this.$emit('input', newVal);
}
},
created() {
this.fetchPositions();
},
methods: {
async fetchPositions() {
try {
const response = await axios.get('http://localhost:3000/api/positions');
console.log('PositionSelect - fetchPositions - response.data:', response.data);
this.$emit('update:options', response.data);
} catch (error) {
console.error('Fehler beim Abrufen der Positionen:', error);
}
}
}
};
</script>
<style scoped>
@import '~vue-multiselect/dist/vue-multiselect.css';
</style>