Add member transfer functionality to memberController and update routes and UI
Implemented a new transferMembers function in memberController to handle member transfers, including validation for transfer endpoint and template. Updated memberRoutes to include a new route for member transfers. Enhanced MembersView with a button to open a transfer dialog and integrated a MemberTransferDialog component for user interaction during the transfer process.
This commit is contained in:
528
frontend/src/components/MemberTransferDialog.vue
Normal file
528
frontend/src/components/MemberTransferDialog.vue
Normal file
@@ -0,0 +1,528 @@
|
||||
<template>
|
||||
<BaseDialog
|
||||
:model-value="modelValue"
|
||||
@update:model-value="$emit('update:modelValue', $event)"
|
||||
title="Mitglieder übertragen"
|
||||
size="large"
|
||||
:close-on-overlay="false"
|
||||
@close="handleClose"
|
||||
>
|
||||
<div class="transfer-form">
|
||||
<div class="form-section">
|
||||
<h4>Login-Konfiguration</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="loginEndpoint">Login-Endpoint URL:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="loginEndpoint"
|
||||
v-model="config.loginEndpoint"
|
||||
placeholder="https://example.com/api/login"
|
||||
class="form-input"
|
||||
/>
|
||||
<span class="hint">Optional: Falls für die Übertragung ein Login erforderlich ist</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="loginFormat">Login-Format:</label>
|
||||
<select id="loginFormat" v-model="config.loginFormat" class="form-select">
|
||||
<option value="json">JSON</option>
|
||||
<option value="form-data">Form Data</option>
|
||||
<option value="x-www-form-urlencoded">URL Encoded</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Login-Daten:</label>
|
||||
<div class="credentials-group">
|
||||
<div class="credential-row">
|
||||
<input
|
||||
type="text"
|
||||
v-model="loginCredentials.username"
|
||||
placeholder="Benutzername / Email"
|
||||
class="form-input"
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
v-model="loginCredentials.password"
|
||||
placeholder="Passwort"
|
||||
class="form-input"
|
||||
/>
|
||||
</div>
|
||||
<div class="credential-row">
|
||||
<input
|
||||
type="text"
|
||||
v-model="loginCredentials.additionalField1"
|
||||
:placeholder="additionalField1Placeholder"
|
||||
class="form-input"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
v-model="loginCredentials.additionalField2"
|
||||
:placeholder="additionalField2Placeholder"
|
||||
class="form-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span class="hint">Zusätzliche Felder werden nur verwendet, wenn sie ausgefüllt sind</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<h4>Übertragungs-Konfiguration</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="transferEndpoint">Übertragungs-Endpoint URL: <span class="required">*</span></label>
|
||||
<input
|
||||
type="text"
|
||||
id="transferEndpoint"
|
||||
v-model="config.transferEndpoint"
|
||||
placeholder="https://example.com/api/members"
|
||||
class="form-input"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="transferMethod">HTTP-Methode:</label>
|
||||
<select id="transferMethod" v-model="config.transferMethod" class="form-select">
|
||||
<option value="POST">POST</option>
|
||||
<option value="PUT">PUT</option>
|
||||
<option value="GET">GET</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="transferFormat">Übertragungs-Format:</label>
|
||||
<select id="transferFormat" v-model="config.transferFormat" class="form-select">
|
||||
<option value="json">JSON</option>
|
||||
<option value="xml">XML</option>
|
||||
<option value="form-data">Form Data</option>
|
||||
<option value="x-www-form-urlencoded">URL Encoded</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="checkbox-item">
|
||||
<input type="checkbox" v-model="config.useBulkMode" />
|
||||
<span>Bulk-Import-Modus (alle Mitglieder auf einmal übertragen)</span>
|
||||
</label>
|
||||
<span class="hint">Wenn aktiviert, werden alle Mitglieder in einem Request als Array übertragen. Das Template definiert das Format für ein einzelnes Mitglied.</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="transferTemplate">Übertragungs-Template: <span class="required">*</span></label>
|
||||
<textarea
|
||||
id="transferTemplate"
|
||||
v-model="config.transferTemplate"
|
||||
rows="8"
|
||||
class="form-textarea"
|
||||
placeholder='{"name": "{{firstName}} {{lastName}}", "email": "{{email}}", "phone": "{{phone}}"}'
|
||||
required
|
||||
></textarea>
|
||||
<div class="template-help">
|
||||
<strong>Verfügbare Platzhalter:</strong>
|
||||
<ul>
|
||||
<li><code>{{firstName}}</code> - Vorname</li>
|
||||
<li><code>{{lastName}}</code> - Nachname</li>
|
||||
<li><code>{{fullName}}</code> - Vollständiger Name</li>
|
||||
<li><code>{{email}}</code> - E-Mail-Adresse</li>
|
||||
<li><code>{{phone}}</code> - Telefonnummer</li>
|
||||
<li><code>{{street}}</code> - Straße</li>
|
||||
<li><code>{{city}}</code> - Ort</li>
|
||||
<li><code>{{birthDate}}</code> - Geburtsdatum (YYYY-MM-DD)</li>
|
||||
<li><code>{{geburtsdatum}}</code> - Geburtsdatum (YYYY-MM-DD, alternativ)</li>
|
||||
<li><code>{{address}}</code> - Kombinierte Adresse (Straße, Ort)</li>
|
||||
<li><code>{{ttr}}</code> - TTR-Wert</li>
|
||||
<li><code>{{qttr}}</code> - QTTR-Wert</li>
|
||||
<li><code>{{gender}}</code> - Geschlecht</li>
|
||||
</ul>
|
||||
<p><strong>Beispiel JSON (für einzelnes Mitglied):</strong></p>
|
||||
<pre>{{ jsonExample }}</pre>
|
||||
<p v-if="config.useBulkMode" class="bulk-hint">
|
||||
<strong>Bulk-Modus aktiv:</strong> Das Template wird für jedes Mitglied angewendet und automatisch in <code>{"members": [...]}</code> gewrappt.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<button class="btn-secondary" @click="handleClose">Abbrechen</button>
|
||||
<button
|
||||
class="btn-primary"
|
||||
@click="handleTransfer"
|
||||
:disabled="!isValid || isTransferring"
|
||||
>
|
||||
{{ isTransferring ? 'Übertrage...' : 'Übertragen' }}
|
||||
</button>
|
||||
</template>
|
||||
</BaseDialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseDialog from './BaseDialog.vue';
|
||||
import apiClient from '../apiClient.js';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'MemberTransferDialog',
|
||||
components: {
|
||||
BaseDialog
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['currentClub']),
|
||||
|
||||
isValid() {
|
||||
return !!(this.config.transferEndpoint && this.config.transferTemplate);
|
||||
},
|
||||
|
||||
additionalField1Placeholder() {
|
||||
if (this.config.loginFormat === 'form-data' || this.config.loginFormat === 'x-www-form-urlencoded') {
|
||||
return 'Feldname: Wert (z.B. client_id: abc123)';
|
||||
}
|
||||
return 'Zusätzliches Feld (z.B. client_id)';
|
||||
},
|
||||
|
||||
additionalField2Placeholder() {
|
||||
if (this.config.loginFormat === 'form-data' || this.config.loginFormat === 'x-www-form-urlencoded') {
|
||||
return 'Feldname: Wert (z.B. client_secret: xyz789)';
|
||||
}
|
||||
return 'Zusätzliches Feld (z.B. client_secret)';
|
||||
},
|
||||
|
||||
jsonExample() {
|
||||
return JSON.stringify({
|
||||
firstName: "{{firstName}}",
|
||||
lastName: "{{lastName}}",
|
||||
geburtsdatum: "{{geburtsdatum}}",
|
||||
email: "{{email}}",
|
||||
phone: "{{phone}}",
|
||||
address: "{{address}}"
|
||||
}, null, 2);
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
config: {
|
||||
loginEndpoint: '',
|
||||
loginFormat: 'json',
|
||||
transferEndpoint: '',
|
||||
transferMethod: 'POST',
|
||||
transferFormat: 'json',
|
||||
transferTemplate: '',
|
||||
useBulkMode: false
|
||||
},
|
||||
loginCredentials: {
|
||||
username: '',
|
||||
password: '',
|
||||
additionalField1: '',
|
||||
additionalField2: ''
|
||||
},
|
||||
isTransferring: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleClose() {
|
||||
this.$emit('update:modelValue', false);
|
||||
this.resetForm();
|
||||
},
|
||||
|
||||
resetForm() {
|
||||
this.config = {
|
||||
loginEndpoint: '',
|
||||
loginFormat: 'json',
|
||||
transferEndpoint: '',
|
||||
transferMethod: 'POST',
|
||||
transferFormat: 'json',
|
||||
transferTemplate: '',
|
||||
useBulkMode: false
|
||||
};
|
||||
this.loginCredentials = {
|
||||
username: '',
|
||||
password: '',
|
||||
additionalField1: '',
|
||||
additionalField2: ''
|
||||
};
|
||||
this.isTransferring = false;
|
||||
},
|
||||
|
||||
async handleTransfer() {
|
||||
if (!this.isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isTransferring = true;
|
||||
|
||||
try {
|
||||
// Login-Credentials zusammenstellen
|
||||
const loginCredentials = {};
|
||||
if (this.loginCredentials.username) {
|
||||
loginCredentials.username = this.loginCredentials.username;
|
||||
}
|
||||
if (this.loginCredentials.password) {
|
||||
loginCredentials.password = this.loginCredentials.password;
|
||||
}
|
||||
|
||||
// Zusätzliche Felder verarbeiten
|
||||
if (this.loginCredentials.additionalField1) {
|
||||
const parts1 = this.loginCredentials.additionalField1.split(':').map(s => s.trim());
|
||||
if (parts1.length === 2) {
|
||||
loginCredentials[parts1[0]] = parts1[1];
|
||||
} else {
|
||||
loginCredentials[parts1[0]] = parts1[0];
|
||||
}
|
||||
}
|
||||
if (this.loginCredentials.additionalField2) {
|
||||
const parts2 = this.loginCredentials.additionalField2.split(':').map(s => s.trim());
|
||||
if (parts2.length === 2) {
|
||||
loginCredentials[parts2[0]] = parts2[1];
|
||||
} else {
|
||||
loginCredentials[parts2[0]] = parts2[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Konfiguration zusammenstellen
|
||||
const transferConfig = {
|
||||
transferEndpoint: this.config.transferEndpoint,
|
||||
transferMethod: this.config.transferMethod,
|
||||
transferFormat: this.config.transferFormat,
|
||||
transferTemplate: this.config.transferTemplate
|
||||
};
|
||||
|
||||
// Login-Konfiguration nur hinzufügen, wenn Endpoint vorhanden
|
||||
if (this.config.loginEndpoint) {
|
||||
transferConfig.loginEndpoint = this.config.loginEndpoint;
|
||||
transferConfig.loginFormat = this.config.loginFormat;
|
||||
transferConfig.loginCredentials = loginCredentials;
|
||||
}
|
||||
|
||||
const response = await apiClient.post(
|
||||
`/clubmembers/transfer/${this.currentClub}`,
|
||||
transferConfig
|
||||
);
|
||||
|
||||
if (response.data.success) {
|
||||
const message = response.data.message ||
|
||||
`${response.data.transferred} von ${response.data.total} Mitglieder(n) erfolgreich übertragen.`;
|
||||
|
||||
let details = '';
|
||||
if (response.data.errors && response.data.errors.length > 0) {
|
||||
details = 'Fehler:\n' + response.data.errors.map(e =>
|
||||
`${e.member}: ${e.error}`
|
||||
).join('\n');
|
||||
}
|
||||
|
||||
this.$emit('success', {
|
||||
message: message,
|
||||
details: details,
|
||||
results: response.data
|
||||
});
|
||||
|
||||
this.handleClose();
|
||||
} else {
|
||||
this.$emit('error', {
|
||||
message: response.data.message || 'Übertragung fehlgeschlagen',
|
||||
error: response.data.error
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Transfer error:', error);
|
||||
const errorMessage = error.response?.data?.error ||
|
||||
error.response?.data?.message ||
|
||||
error.message ||
|
||||
'Fehler bei der Übertragung';
|
||||
|
||||
this.$emit('error', {
|
||||
message: 'Fehler bei der Übertragung',
|
||||
error: errorMessage
|
||||
});
|
||||
} finally {
|
||||
this.isTransferring = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.transfer-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 6px;
|
||||
padding: 1.5rem;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.form-section h4 {
|
||||
margin: 0 0 1rem 0;
|
||||
color: #333;
|
||||
font-size: 1.1em;
|
||||
border-bottom: 2px solid #007bff;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-group .required {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.form-input,
|
||||
.form-select,
|
||||
.form-textarea {
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 4px;
|
||||
font-size: 0.9em;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
font-family: 'Courier New', monospace;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.credentials-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.credential-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.hint {
|
||||
display: block;
|
||||
margin-top: 0.25rem;
|
||||
font-size: 0.85em;
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.template-help {
|
||||
margin-top: 0.75rem;
|
||||
padding: 1rem;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #e9ecef;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
.template-help strong {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.template-help ul {
|
||||
margin: 0.5rem 0;
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.template-help li {
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
|
||||
.template-help code {
|
||||
background-color: #e9ecef;
|
||||
padding: 0.2rem 0.4rem;
|
||||
border-radius: 3px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.template-help pre {
|
||||
background-color: #282c34;
|
||||
color: #abb2bf;
|
||||
padding: 0.75rem;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
.bulk-hint {
|
||||
margin-top: 0.75rem;
|
||||
padding: 0.75rem;
|
||||
background-color: #e7f3ff;
|
||||
border-left: 4px solid #007bff;
|
||||
border-radius: 4px;
|
||||
color: #004085;
|
||||
}
|
||||
|
||||
.bulk-hint code {
|
||||
background-color: #cce5ff;
|
||||
padding: 0.2rem 0.4rem;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.5rem 1.5rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.btn-primary:disabled {
|
||||
background-color: #6c757d;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: #6c757d;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.5rem 1.5rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: #5a6268;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
<button @click="updateRatingsFromMyTischtennis" class="btn-update-ratings" :disabled="isUpdatingRatings">
|
||||
{{ isUpdatingRatings ? 'Aktualisiere...' : 'TTR/QTTR von myTischtennis aktualisieren' }}
|
||||
</button>
|
||||
<button @click="openTransferDialog" class="btn-transfer">
|
||||
Mitglieder übertragen
|
||||
</button>
|
||||
</div>
|
||||
<div class="newmember">
|
||||
<div class="toggle-new-member">
|
||||
@@ -156,35 +159,7 @@
|
||||
<button @click.stop="openActivitiesModal(member)" class="btn-activities">Übungen</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!-- Info Dialog -->
|
||||
<InfoDialog
|
||||
v-model="infoDialog.isOpen"
|
||||
:title="infoDialog.title"
|
||||
:message="infoDialog.message"
|
||||
:details="infoDialog.details"
|
||||
:type="infoDialog.type"
|
||||
/>
|
||||
|
||||
<!-- Confirm Dialog -->
|
||||
<ConfirmDialog
|
||||
v-model="confirmDialog.isOpen"
|
||||
:title="confirmDialog.title"
|
||||
:message="confirmDialog.message"
|
||||
:details="confirmDialog.details"
|
||||
:type="confirmDialog.type"
|
||||
@confirm="handleConfirmResult(true)"
|
||||
@cancel="handleConfirmResult(false)"
|
||||
/>
|
||||
|
||||
<!-- Member Activities Dialog -->
|
||||
<MemberActivitiesDialog
|
||||
v-model="showActivitiesModal"
|
||||
:member="selectedMemberForActivities"
|
||||
:club-id="currentClub"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -212,28 +187,41 @@
|
||||
@delete-note="deleteNote"
|
||||
@close="closeNotesModal"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Info Dialog -->
|
||||
<InfoDialog
|
||||
v-model="infoDialog.isOpen"
|
||||
:title="infoDialog.title"
|
||||
:message="infoDialog.message"
|
||||
:details="infoDialog.details"
|
||||
:type="infoDialog.type"
|
||||
/>
|
||||
|
||||
<!-- Confirm Dialog -->
|
||||
<ConfirmDialog
|
||||
v-model="confirmDialog.isOpen"
|
||||
:title="confirmDialog.title"
|
||||
:message="confirmDialog.message"
|
||||
:details="confirmDialog.details"
|
||||
:type="confirmDialog.type"
|
||||
@confirm="handleConfirmResult(true)"
|
||||
@cancel="handleConfirmResult(false)"
|
||||
/>
|
||||
<!-- Info Dialog -->
|
||||
<InfoDialog
|
||||
v-model="infoDialog.isOpen"
|
||||
:title="infoDialog.title"
|
||||
:message="infoDialog.message"
|
||||
:details="infoDialog.details"
|
||||
:type="infoDialog.type"
|
||||
/>
|
||||
|
||||
<!-- Confirm Dialog -->
|
||||
<ConfirmDialog
|
||||
v-model="confirmDialog.isOpen"
|
||||
:title="confirmDialog.title"
|
||||
:message="confirmDialog.message"
|
||||
:details="confirmDialog.details"
|
||||
:type="confirmDialog.type"
|
||||
@confirm="handleConfirmResult(true)"
|
||||
@cancel="handleConfirmResult(false)"
|
||||
/>
|
||||
|
||||
<!-- Member Activities Dialog -->
|
||||
<MemberActivitiesDialog
|
||||
v-model="showActivitiesModal"
|
||||
:member="selectedMemberForActivities"
|
||||
:club-id="currentClub"
|
||||
/>
|
||||
|
||||
<!-- Member Transfer Dialog -->
|
||||
<MemberTransferDialog
|
||||
v-model="showTransferDialog"
|
||||
@success="handleTransferSuccess"
|
||||
@error="handleTransferError"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -247,6 +235,7 @@ import ImageViewerDialog from '../components/ImageViewerDialog.vue';
|
||||
import BaseDialog from '../components/BaseDialog.vue';
|
||||
import MemberNotesDialog from '../components/MemberNotesDialog.vue';
|
||||
import MemberActivitiesDialog from '../components/MemberActivitiesDialog.vue';
|
||||
import MemberTransferDialog from '../components/MemberTransferDialog.vue';
|
||||
export default {
|
||||
name: 'MembersView',
|
||||
components: {
|
||||
@@ -255,7 +244,8 @@ export default {
|
||||
ImageViewerDialog,
|
||||
BaseDialog,
|
||||
MemberNotesDialog,
|
||||
MemberActivitiesDialog
|
||||
MemberActivitiesDialog,
|
||||
MemberTransferDialog
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['isAuthenticated', 'currentClub']),
|
||||
@@ -345,7 +335,8 @@ export default {
|
||||
showActivitiesModal: false,
|
||||
selectedMemberForActivities: null,
|
||||
selectedAgeGroup: '',
|
||||
selectedGender: ''
|
||||
selectedGender: '',
|
||||
showTransferDialog: false
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
@@ -737,6 +728,30 @@ export default {
|
||||
this.selectedAgeGroup = '';
|
||||
this.selectedGender = '';
|
||||
this.showInactiveMembers = false;
|
||||
},
|
||||
|
||||
openTransferDialog() {
|
||||
this.showTransferDialog = true;
|
||||
},
|
||||
|
||||
handleTransferSuccess(event) {
|
||||
const { message, details, results } = event;
|
||||
this.showInfo(
|
||||
'Übertragung erfolgreich',
|
||||
message,
|
||||
details,
|
||||
'success'
|
||||
);
|
||||
},
|
||||
|
||||
handleTransferError(event) {
|
||||
const { message, error } = event;
|
||||
this.showInfo(
|
||||
'Fehler bei der Übertragung',
|
||||
message,
|
||||
error,
|
||||
'error'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1142,4 +1157,19 @@ table td {
|
||||
.btn-clear-filters:hover {
|
||||
background-color: #5a6268;
|
||||
}
|
||||
|
||||
.btn-transfer {
|
||||
background-color: #17a2b8;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9em;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-transfer:hover {
|
||||
background-color: #138496;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user