Entfernt die myTischtennis-Integration aus dem Backend und Frontend. Löscht Controller, Routen und Service für myTischtennis. Aktualisiert die Datenmodelle, um die neue ExternalServiceAccount-Integration zu unterstützen. Ändert die API-Routen und Frontend-Komponenten, um die neuen Endpunkte zu verwenden.
This commit is contained in:
@@ -75,6 +75,10 @@
|
||||
<span class="nav-icon">🔗</span>
|
||||
myTischtennis-Account
|
||||
</a>
|
||||
<a href="/hettv-account" class="nav-link">
|
||||
<span class="nav-icon">🔗</span>
|
||||
HeTTV-Account
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
291
frontend/src/components/HettvDialog.vue
Normal file
291
frontend/src/components/HettvDialog.vue
Normal file
@@ -0,0 +1,291 @@
|
||||
<template>
|
||||
<div class="modal-overlay" @click.self="$emit('close')">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<h3>{{ account ? 'HeTTV-Account bearbeiten' : 'HeTTV-Account verknüpfen' }}</h3>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="hettv-email">HeTTV-E-Mail:</label>
|
||||
<input
|
||||
type="email"
|
||||
id="hettv-email"
|
||||
v-model="formData.email"
|
||||
placeholder="Ihre HeTTV-E-Mail-Adresse"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="hettv-password">HeTTV-Passwort:</label>
|
||||
<input
|
||||
type="password"
|
||||
id="hettv-password"
|
||||
v-model="formData.password"
|
||||
:placeholder="account && account.savePassword ? 'Leer lassen um beizubehalten' : 'Ihr HeTTV-Passwort'"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group checkbox-group">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="formData.savePassword"
|
||||
/>
|
||||
<span>HeTTV-Passwort speichern</span>
|
||||
</label>
|
||||
<p class="hint">
|
||||
Wenn aktiviert, wird Ihr HeTTV-Passwort verschlüsselt gespeichert,
|
||||
sodass automatische Synchronisationen möglich sind.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group" v-if="formData.password">
|
||||
<label for="app-password">Ihr App-Passwort zur Bestätigung:</label>
|
||||
<input
|
||||
type="password"
|
||||
id="app-password"
|
||||
v-model="formData.userPassword"
|
||||
placeholder="Ihr Passwort für diese App"
|
||||
required
|
||||
/>
|
||||
<p class="hint">
|
||||
Aus Sicherheitsgründen benötigen wir Ihr App-Passwort,
|
||||
um das HeTTV-Passwort zu speichern.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div v-if="error" class="error-message">
|
||||
{{ error }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class="btn-secondary" @click="$emit('close')" :disabled="saving">
|
||||
Abbrechen
|
||||
</button>
|
||||
<button class="btn-primary" @click="saveAccount" :disabled="!canSave || saving">
|
||||
{{ saving ? 'Speichere...' : 'Speichern' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import apiClient from '../apiClient.js';
|
||||
|
||||
export default {
|
||||
name: 'HettvDialog',
|
||||
props: {
|
||||
account: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formData: {
|
||||
email: this.account?.email || '',
|
||||
password: '',
|
||||
savePassword: this.account?.savePassword || false,
|
||||
userPassword: ''
|
||||
},
|
||||
saving: false,
|
||||
error: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
canSave() {
|
||||
if (!this.formData.email.trim()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.formData.password && !this.formData.userPassword) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async saveAccount() {
|
||||
if (!this.canSave) return;
|
||||
|
||||
this.error = null;
|
||||
this.saving = true;
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
email: this.formData.email,
|
||||
savePassword: this.formData.savePassword,
|
||||
service: 'hettv'
|
||||
};
|
||||
|
||||
if (this.formData.password) {
|
||||
payload.password = this.formData.password;
|
||||
payload.userPassword = this.formData.userPassword;
|
||||
}
|
||||
|
||||
await apiClient.post('/external-service/account', payload);
|
||||
this.$emit('saved');
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Speichern:', error);
|
||||
this.error = error.response?.data?.message || 'Fehler beim Speichern des Accounts';
|
||||
} finally {
|
||||
this.saving = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
||||
max-width: 600px;
|
||||
width: 90%;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 1.5rem;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.modal-header h3 {
|
||||
margin: 0;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 1.5rem;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 1rem 1.5rem;
|
||||
border-top: 1px solid #dee2e6;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.form-group input[type="text"],
|
||||
.form-group input[type="email"],
|
||||
.form-group input[type="password"] {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-group input[type="text"]:focus,
|
||||
.form-group input[type="email"]:focus,
|
||||
.form-group input[type="password"]:focus {
|
||||
outline: none;
|
||||
border-color: #007bff;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
}
|
||||
|
||||
.checkbox-group label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-weight: normal;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.checkbox-group input[type="checkbox"] {
|
||||
width: auto;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.hint {
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
color: #6c757d;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
padding: 0.75rem;
|
||||
background-color: #f8d7da;
|
||||
border: 1px solid #f5c6cb;
|
||||
border-radius: 4px;
|
||||
color: #721c24;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.btn-primary, .btn-secondary {
|
||||
padding: 0.75rem 1.5rem;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.btn-secondary:hover:not(:disabled) {
|
||||
background-color: #545b62;
|
||||
}
|
||||
|
||||
.btn-secondary:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -121,7 +121,8 @@ export default {
|
||||
try {
|
||||
const payload = {
|
||||
email: this.formData.email,
|
||||
savePassword: this.formData.savePassword
|
||||
savePassword: this.formData.savePassword,
|
||||
service: 'mytischtennis'
|
||||
};
|
||||
|
||||
// Nur password und userPassword hinzufügen, wenn ein Passwort eingegeben wurde
|
||||
@@ -130,7 +131,7 @@ export default {
|
||||
payload.userPassword = this.formData.userPassword;
|
||||
}
|
||||
|
||||
await apiClient.post('/mytischtennis/account', payload);
|
||||
await apiClient.post('/external-service/account', payload);
|
||||
this.$emit('saved');
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Speichern:', error);
|
||||
|
||||
@@ -14,6 +14,7 @@ import TrainingStatsView from './views/TrainingStatsView.vue';
|
||||
import PredefinedActivities from './views/PredefinedActivities.vue';
|
||||
import OfficialTournaments from './views/OfficialTournaments.vue';
|
||||
import MyTischtennisAccount from './views/MyTischtennisAccount.vue';
|
||||
import HettvAccount from './views/HettvAccount.vue';
|
||||
import Impressum from './views/Impressum.vue';
|
||||
import Datenschutz from './views/Datenschutz.vue';
|
||||
|
||||
@@ -33,6 +34,7 @@ const routes = [
|
||||
{ path: '/predefined-activities', component: PredefinedActivities },
|
||||
{ path: '/official-tournaments', component: OfficialTournaments },
|
||||
{ path: '/mytischtennis-account', component: MyTischtennisAccount },
|
||||
{ path: '/hettv-account', component: HettvAccount },
|
||||
{ path: '/impressum', component: Impressum },
|
||||
{ path: '/datenschutz', component: Datenschutz },
|
||||
];
|
||||
|
||||
314
frontend/src/views/HettvAccount.vue
Normal file
314
frontend/src/views/HettvAccount.vue
Normal file
@@ -0,0 +1,314 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<h1>HeTTV-Account</h1>
|
||||
|
||||
<div class="account-container">
|
||||
<div v-if="loading" class="loading">Lade...</div>
|
||||
|
||||
<div v-else-if="account" class="account-info">
|
||||
<div class="info-section">
|
||||
<h2>Verknüpfter Account</h2>
|
||||
|
||||
<div class="info-row">
|
||||
<label>E-Mail:</label>
|
||||
<span>{{ account.email }}</span>
|
||||
</div>
|
||||
|
||||
<div class="info-row">
|
||||
<label>Passwort gespeichert:</label>
|
||||
<span>{{ account.savePassword ? 'Ja' : 'Nein' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="info-row" v-if="account.lastLoginSuccess">
|
||||
<label>Letzter erfolgreicher Login:</label>
|
||||
<span>{{ formatDate(account.lastLoginSuccess) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="info-row" v-if="account.lastLoginAttempt">
|
||||
<label>Letzter Login-Versuch:</label>
|
||||
<span>{{ formatDate(account.lastLoginAttempt) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="button-group">
|
||||
<button class="btn-primary" @click="openEditDialog">Account bearbeiten</button>
|
||||
<button class="btn-secondary" @click="testConnection">Erneut einloggen</button>
|
||||
<button class="btn-danger" @click="deleteAccount">Account trennen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="no-account">
|
||||
<p>Kein HeTTV-Account verknüpft.</p>
|
||||
<button class="btn-primary" @click="openEditDialog">Account verknüpfen</button>
|
||||
</div>
|
||||
|
||||
<div class="info-box">
|
||||
<h3>Über HeTTV</h3>
|
||||
<p>Durch die Verknüpfung Ihres HeTTV-Accounts können Sie:</p>
|
||||
<ul>
|
||||
<li>Spielerdaten automatisch synchronisieren</li>
|
||||
<li>Ligainformationen abrufen</li>
|
||||
<li>Wettkampfdaten direkt importieren</li>
|
||||
</ul>
|
||||
<p><strong>Hinweis:</strong> Das Speichern des Passworts ist optional. Wenn Sie es nicht speichern, werden Sie bei jeder Synchronisation nach dem Passwort gefragt.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Dialog -->
|
||||
<HettvDialog
|
||||
v-if="showDialog"
|
||||
:account="account"
|
||||
@close="closeDialog"
|
||||
@saved="onAccountSaved"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import apiClient from '../apiClient.js';
|
||||
import HettvDialog from '../components/HettvDialog.vue';
|
||||
|
||||
export default {
|
||||
name: 'HettvAccount',
|
||||
components: {
|
||||
HettvDialog
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
account: null,
|
||||
showDialog: false
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.loadAccount();
|
||||
},
|
||||
methods: {
|
||||
async loadAccount() {
|
||||
try {
|
||||
this.loading = true;
|
||||
const response = await apiClient.get('/external-service/account', {
|
||||
params: { service: 'hettv' }
|
||||
});
|
||||
this.account = response.data.account;
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden des Accounts:', error);
|
||||
this.$store.dispatch('showMessage', {
|
||||
text: 'Fehler beim Laden des HeTTV-Accounts',
|
||||
type: 'error'
|
||||
});
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
openEditDialog() {
|
||||
this.showDialog = true;
|
||||
},
|
||||
|
||||
closeDialog() {
|
||||
this.showDialog = false;
|
||||
},
|
||||
|
||||
async onAccountSaved() {
|
||||
this.closeDialog();
|
||||
await this.loadAccount();
|
||||
this.$store.dispatch('showMessage', {
|
||||
text: 'HeTTV-Account erfolgreich gespeichert',
|
||||
type: 'success'
|
||||
});
|
||||
},
|
||||
|
||||
async testConnection() {
|
||||
try {
|
||||
await apiClient.post('/external-service/verify', {
|
||||
service: 'hettv'
|
||||
});
|
||||
this.$store.dispatch('showMessage', {
|
||||
text: 'Login erfolgreich! Verbindungsdaten aktualisiert.',
|
||||
type: 'success'
|
||||
});
|
||||
await this.loadAccount();
|
||||
} catch (error) {
|
||||
const message = error.response?.data?.message || 'Login fehlgeschlagen';
|
||||
|
||||
if (error.response?.status === 400 && message.includes('Kein Passwort gespeichert')) {
|
||||
this.showDialog = true;
|
||||
}
|
||||
|
||||
this.$store.dispatch('showMessage', {
|
||||
text: message,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async deleteAccount() {
|
||||
if (!confirm('Möchten Sie die Verknüpfung zum HeTTV-Account wirklich trennen?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await apiClient.delete('/external-service/account', {
|
||||
params: { service: 'hettv' }
|
||||
});
|
||||
this.account = null;
|
||||
this.$store.dispatch('showMessage', {
|
||||
text: 'HeTTV-Account erfolgreich getrennt',
|
||||
type: 'success'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Löschen des Accounts:', error);
|
||||
this.$store.dispatch('showMessage', {
|
||||
text: 'Fehler beim Trennen des Accounts',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
formatDate(dateString) {
|
||||
if (!dateString) return '-';
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleString('de-DE', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page-container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: var(--text-color, #333);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.account-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.account-info, .no-account {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 2rem;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.info-section h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1.5rem;
|
||||
color: var(--primary-color, #007bff);
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0.75rem 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.info-row:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.info-row label {
|
||||
font-weight: 600;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.info-row span {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.no-account {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-account p {
|
||||
margin-bottom: 1.5rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
background: #f8f9fa;
|
||||
border-left: 4px solid var(--primary-color, #007bff);
|
||||
padding: 1.5rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.info-box h3 {
|
||||
margin-top: 0;
|
||||
color: var(--primary-color, #007bff);
|
||||
}
|
||||
|
||||
.info-box ul {
|
||||
margin: 1rem 0;
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
.info-box li {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.btn-primary, .btn-secondary, .btn-danger {
|
||||
padding: 0.75rem 1.5rem;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: #6c757d;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: #545b62;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background-color: #dc3545;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-danger:hover {
|
||||
background-color: #c82333;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -387,10 +387,6 @@ export default {
|
||||
return '';
|
||||
},
|
||||
async updateRatingsFromMyTischtennis() {
|
||||
if (!confirm('TTR/QTTR-Werte von myTischtennis aktualisieren?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isUpdatingRatings = true;
|
||||
try {
|
||||
const response = await apiClient.post(`/clubmembers/update-ratings/${this.currentClub}`);
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2>Spielpläne</h2>
|
||||
<button @click="openImportModal">Spielplanimport</button>
|
||||
<div class="button-group">
|
||||
<button @click="openImportModal">Spielplanimport</button>
|
||||
<button @click="loadHettvData" :disabled="loadingHettv" class="hettv-button">
|
||||
{{ loadingHettv ? 'Lade HeTTV-Daten...' : 'HeTTV-Daten laden' }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="hoveredMatch && hoveredMatch.location" class="hover-info">
|
||||
<p><strong>{{ hoveredMatch.location.name || 'N/A' }}</strong></p>
|
||||
<p>{{ hoveredMatch.location.address || 'N/A' }}</p>
|
||||
@@ -79,6 +84,8 @@ export default {
|
||||
matches: [],
|
||||
selectedLeague: '',
|
||||
hoveredMatch: null,
|
||||
loadingHettv: false,
|
||||
hettvData: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -174,10 +181,15 @@ export default {
|
||||
async loadLeagues() {
|
||||
try {
|
||||
const clubId = this.currentClub;
|
||||
if (!clubId || clubId === 'null') {
|
||||
console.log('Kein Club ausgewählt, überspringe Liga-Laden');
|
||||
return;
|
||||
}
|
||||
const response = await apiClient.get(`/matches/leagues/current/${clubId}`);
|
||||
this.leagues = this.sortLeagues(response.data);
|
||||
} catch (error) {
|
||||
alert('Fehler beim Laden der Ligen');
|
||||
console.log('Fehler beim Laden der Ligen:', error.message);
|
||||
// Keine Alert mehr, da das normal ist wenn kein Club-Zugriff vorhanden
|
||||
}
|
||||
},
|
||||
async loadMatchesForLeague(leagueId, leagueName) {
|
||||
@@ -301,6 +313,39 @@ export default {
|
||||
|
||||
return ''; // Keine besondere Farbe
|
||||
},
|
||||
async loadHettvData() {
|
||||
this.loadingHettv = true;
|
||||
try {
|
||||
console.log('Lade HeTTV-Hauptseite...');
|
||||
const response = await apiClient.get('/external-service/hettv/main-page');
|
||||
|
||||
if (response.data.success) {
|
||||
this.hettvData = response.data.data;
|
||||
console.log('HeTTV-Daten geladen:', {
|
||||
downloadLinks: this.hettvData.downloadLinks,
|
||||
htmlLength: this.hettvData.htmlContent.length,
|
||||
trace: this.hettvData.trace,
|
||||
lastUrl: this.hettvData.lastUrl,
|
||||
lastStatus: this.hettvData.lastStatus,
|
||||
savedFile: this.hettvData.savedFile
|
||||
});
|
||||
|
||||
// Zeige gefundene Download-Links
|
||||
if (this.hettvData.downloadLinks.length > 0) {
|
||||
alert(`HeTTV-Daten erfolgreich geladen!\n\nGefundene Download-Links:\n${this.hettvData.downloadLinks.join('\n')}`);
|
||||
} else {
|
||||
alert('HeTTV-Hauptseite geladen, aber keine Download-Links gefunden.');
|
||||
}
|
||||
} else {
|
||||
alert('Fehler beim Laden der HeTTV-Daten: ' + response.data.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('HeTTV-Fehler:', error);
|
||||
alert('Fehler beim Laden der HeTTV-Daten: ' + (error.response?.data?.error || error.message));
|
||||
} finally {
|
||||
this.loadingHettv = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
await this.loadLeagues();
|
||||
@@ -451,4 +496,37 @@ li {
|
||||
.match-next-week:hover {
|
||||
background-color: #b8daff !important; /* Dunkleres Blau beim Hover */
|
||||
}
|
||||
|
||||
.button-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.button-group button {
|
||||
margin-right: 10px;
|
||||
padding: 8px 16px;
|
||||
border: 1px solid #ddd;
|
||||
background-color: #f8f9fa;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.button-group button:hover {
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.hettv-button {
|
||||
background-color: #007bff !important;
|
||||
color: white !important;
|
||||
border-color: #007bff !important;
|
||||
}
|
||||
|
||||
.hettv-button:hover {
|
||||
background-color: #0056b3 !important;
|
||||
}
|
||||
|
||||
.hettv-button:disabled {
|
||||
background-color: #6c757d !important;
|
||||
border-color: #6c757d !important;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user