Bugs in settings fixed, profile added
This commit is contained in:
110
frontend/src/dialogues/admin/AnswerContact.vue
Normal file
110
frontend/src/dialogues/admin/AnswerContact.vue
Normal file
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<DialogWidget ref="dialog" :title="$t('admin.editcontactrequest.title')" :show-close="true" :buttons="buttons"
|
||||
@close="closeDialog" name="AnswerContact" :modal="true" :isTitleTranslated="true">
|
||||
<div class="contact-details">
|
||||
<h3>Von: {{ contact.email }}</h3>
|
||||
<p>{{ contact.message }}</p>
|
||||
</div>
|
||||
<div class="editor-container">
|
||||
<Editor v-model="answer" :init="tinymceInitOptions" :api-key="apiKey" />
|
||||
</div>
|
||||
</DialogWidget>
|
||||
|
||||
<DialogWidget ref="errorDialog" :title="$t('error.title')" :show-close="true" :buttons="errorButtons"
|
||||
@close="closeErrorDialog" name="ErrorDialog" :modal="true" :isTitleTranslated="false">
|
||||
<div>
|
||||
<p>{{ errorMessage }}</p>
|
||||
</div>
|
||||
</DialogWidget>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, onBeforeUnmount } from 'vue'
|
||||
import Editor from '@tinymce/tinymce-vue'
|
||||
import apiClient from '@/utils/axios.js'
|
||||
import DialogWidget from '@/components/DialogWidget.vue'
|
||||
|
||||
export default {
|
||||
name: 'AnswerContact',
|
||||
components: {
|
||||
DialogWidget,
|
||||
Editor,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
apiKey: import.meta.env.VITE_TINYMCE_API_KEY,
|
||||
dialog: null,
|
||||
errorDialog: null,
|
||||
contact: null,
|
||||
answer: '',
|
||||
errorMessage: '',
|
||||
tinymceInitOptions: {
|
||||
height: 300,
|
||||
menubar: false,
|
||||
plugins: [
|
||||
'advlist autolink lists link image charmap print preview anchor',
|
||||
'searchreplace visualblocks code fullscreen',
|
||||
'insertdatetime media table paste code help wordcount'
|
||||
],
|
||||
toolbar:
|
||||
'undo redo cut copy paste | bold italic forecolor fontfamily fontsize | \
|
||||
alignleft aligncenter alignright alignjustify | \
|
||||
bullist numlist outdent indent | removeformat | help'
|
||||
},
|
||||
buttons: [
|
||||
{ text: 'OK', action: this.sendAnswer },
|
||||
{ text: 'Cancel', action: this.closeDialog }
|
||||
],
|
||||
errorButtons: [
|
||||
{ text: 'OK', action: this.closeErrorDialog }
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open(contactData) {
|
||||
this.contact = contactData;
|
||||
this.dialog.open();
|
||||
this.answer = '';
|
||||
},
|
||||
closeDialog() {
|
||||
this.dialog.close();
|
||||
this.answer = '';
|
||||
},
|
||||
closeErrorDialog() {
|
||||
this.errorDialog.close();
|
||||
},
|
||||
async sendAnswer() {
|
||||
try {
|
||||
await apiClient.post('/api/admin/contacts/answer', {
|
||||
id: this.contact.id,
|
||||
answer: this.answer,
|
||||
});
|
||||
this.dialog.close();
|
||||
this.$emit('refresh');
|
||||
this.answer = '';
|
||||
} catch (error) {
|
||||
const errorText = error.response?.data?.error || 'An unexpected error occurred.';
|
||||
this.errorMessage = errorText;
|
||||
this.errorDialog.open();
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.dialog = this.$refs.dialog;
|
||||
this.errorDialog = this.$refs.errorDialog;
|
||||
},
|
||||
beforeUnmount() {
|
||||
// Aufräumarbeiten falls nötig
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.contact-details {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
149
frontend/src/dialogues/socialnetwork/UserProfileDialog.vue
Normal file
149
frontend/src/dialogues/socialnetwork/UserProfileDialog.vue
Normal file
@@ -0,0 +1,149 @@
|
||||
<template>
|
||||
<DialogWidget ref="dialog" :title="$t('socialnetwork.profile.pretitle')" :isTitleTranslated="isTitleTranslated"
|
||||
:show-close="true" :buttons="[{ text: 'Ok', action: 'close' }]" :modal="false" @close="closeDialog">
|
||||
<div class="dialog-body">
|
||||
<div>
|
||||
<ul class="tab-list">
|
||||
<li v-for="tab in tabs" :key="tab.name" :class="{ active: activeTab === tab.name }"
|
||||
@click="selectTab(tab.name)">
|
||||
{{ tab.label }}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content" v-if="activeTab === 'general'">
|
||||
<table>
|
||||
<tr v-for="(value, key) in userProfile.params" :key="key">
|
||||
<td>{{ $t(`socialnetwork.profile.${key}`) }}</td>
|
||||
<td>{{ generateValue(key, value) }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DialogWidget>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DialogWidget from '@/components/DialogWidget.vue';
|
||||
import apiClient from '@/utils/axios.js';
|
||||
|
||||
export default {
|
||||
name: 'UserProfileDialog',
|
||||
components: {
|
||||
DialogWidget
|
||||
},
|
||||
props: {
|
||||
userId: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isTitleTranslated: true,
|
||||
userProfile: {},
|
||||
activeTab: 'general',
|
||||
userId: '',
|
||||
tabs: [
|
||||
{ name: 'general', label: this.$t('socialnetwork.profile.tab.general') },
|
||||
{ name: 'images', label: this.$t('socialnetwork.profile.tab.images') },
|
||||
{ name: 'guestbook', label: this.$t('socialnetwork.profile.tab.guestbook') }
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.dialog.open();
|
||||
this.loadUserProfile();
|
||||
},
|
||||
async loadUserProfile() {
|
||||
try {
|
||||
const response = await apiClient.get(`/api/socialnetwork/profile/${this.userId}`);
|
||||
this.userProfile = response.data;
|
||||
const newTitle = this.$t('socialnetwork.profile.title').replace('<username>', this.userProfile.username);
|
||||
this.$refs.dialog.updateTitle(newTitle, false);
|
||||
} catch (error) {
|
||||
this.$refs.dialog.updateTitle('socialnetwork.profile.error_title', true);
|
||||
console.error('Fehler beim Laden des Benutzerprofils:', error);
|
||||
}
|
||||
},
|
||||
closeDialog() {
|
||||
this.$refs.dialog.close();
|
||||
},
|
||||
selectTab(tabName) {
|
||||
this.activeTab = tabName;
|
||||
},
|
||||
generateValue(key, value) {
|
||||
if (Array.isArray(value.value)) {
|
||||
const strings = [];
|
||||
for (const val of value.value) {
|
||||
strings.push(this.generateValue(key, {type: value.type, value: val}));
|
||||
}
|
||||
return strings.join(', ');
|
||||
}
|
||||
switch (value.type) {
|
||||
case 'bool':
|
||||
return this.$t(`socialnetwork.profile.values.bool.${value.value}`);
|
||||
case 'multiselect':
|
||||
case 'singleselect':
|
||||
return this.$t(`socialnetwork.profile.values.${key}.${value.value}`);
|
||||
case 'date':
|
||||
const date = new Date(value.value);
|
||||
return date.toLocaleDateString();
|
||||
case 'string':
|
||||
case 'int':
|
||||
return value.value;
|
||||
case 'float':
|
||||
return new Intl.NumberFormat(navigator.language, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
}).format(parseFloat(value.value));
|
||||
default:
|
||||
return value.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tab-list {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 2px solid #ccc;
|
||||
}
|
||||
|
||||
.tab-list li {
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
margin-right: 5px;
|
||||
border: 1px solid #ccc;
|
||||
border-bottom: none;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.tab-list li.active {
|
||||
background: #ffffff;
|
||||
border-bottom: 2px solid #ffffff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
padding: 20px;
|
||||
border: 1px solid #ccc;
|
||||
background: #ffffff;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.dialog-body,
|
||||
.dialog-body > div {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dialog-body > div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user