feat: Enhance club payment claims and task automation
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 1m0s

- Added `paid_amount_cents` column to `club_payment_claims` for better tracking of payments.
- Implemented compatibility checks for the new column in `clubPaymentClaimService` and `clubTaskAutomationService`.
- Updated various views to handle read-only states when editing is not allowed.
- Refactored forms in `ClubAccountsView`, `ClubInvoicesView`, `ClubTasksView`, and `ClubCommunicationView` to use factory functions for cleaner code.
- Introduced a new migration script to add the `paid_amount_cents` column if it doesn't exist and initialize it for existing paid claims.
- Created a detailed plan for enhancing club features and ensuring stability in existing modules.
This commit is contained in:
Torsten Schulz (local)
2026-07-13 17:01:13 +02:00
parent 90e6c2f9f6
commit ac97332e6f
17 changed files with 628 additions and 307 deletions

View File

@@ -166,6 +166,7 @@
<div class="section-header">
<h3>{{ form.id ? 'Konto bearbeiten' : 'Neues Konto' }}</h3>
</div>
<p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Konten können geprüft, aber nicht bearbeitet werden.</p>
<form class="account-form" @submit.prevent="submitAccount">
<label>
@@ -261,6 +262,7 @@
<div class="section-header">
<h3>{{ transactionForm.id ? 'Buchung bearbeiten' : 'Neue Buchung' }}</h3>
</div>
<p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Kontobewegungen bleiben sichtbar, neue Buchungen sind gesperrt.</p>
<form class="account-form" @submit.prevent="submitTransaction">
<div class="account-form-grid">
@@ -453,6 +455,25 @@ function createEmptyTransactionForm(accountId = '') {
};
}
function createEmptyAccountForm() {
return {
id: null,
name: '',
accountHolder: '',
bankName: '',
iban: '',
bic: '',
accountType: 'bank',
usageType: 'general',
currencyCode: 'EUR',
allowSepaCollections: false,
allowOutgoingPayments: true,
isDefault: false,
status: 'active',
notes: '',
};
}
export default {
name: 'ClubAccountsView',
components: {
@@ -475,22 +496,7 @@ export default {
accountType: '',
search: '',
},
form: {
id: null,
name: '',
accountHolder: '',
bankName: '',
iban: '',
bic: '',
accountType: 'bank',
usageType: 'general',
currencyCode: 'EUR',
allowSepaCollections: false,
allowOutgoingPayments: true,
isDefault: false,
status: 'active',
notes: '',
},
form: createEmptyAccountForm(),
transactionForm: createEmptyTransactionForm(),
infoDialog: {
isOpen: false,
@@ -553,13 +559,7 @@ export default {
immediate: true,
async handler(newClub) {
if (!newClub) {
this.accounts = [];
this.transactions = [];
this.selectedAccountId = null;
this.selectedTransactionId = null;
this.resetForm();
this.resetTransactionForm();
this.loadError = '';
this.clearAccountsState();
return;
}
await this.loadAccounts();
@@ -618,6 +618,16 @@ export default {
},
},
methods: {
clearAccountsState() {
this.accounts = [];
this.transactions = [];
this.paymentClaims = [];
this.selectedAccountId = null;
this.selectedTransactionId = null;
this.form = createEmptyAccountForm();
this.transactionForm = createEmptyTransactionForm();
this.loadError = '';
},
applyRouteQuery() {
const routeAccountId = this.$route?.query?.accountId;
const routeStatus = typeof this.$route?.query?.status === 'string' ? this.$route.query.status : '';
@@ -715,26 +725,12 @@ export default {
},
resetForm() {
this.selectedAccountId = null;
this.form = {
id: null,
name: '',
accountHolder: '',
bankName: '',
iban: '',
bic: '',
accountType: 'bank',
usageType: 'general',
currencyCode: 'EUR',
allowSepaCollections: false,
allowOutgoingPayments: true,
isDefault: false,
status: 'active',
notes: '',
};
this.form = createEmptyAccountForm();
this.resetTransactionForm('');
},
resetTransactionForm() {
resetTransactionForm(accountId = this.selectedAccountId || '') {
this.selectedTransactionId = null;
this.transactionForm = createEmptyTransactionForm(this.selectedAccountId || '');
this.transactionForm = createEmptyTransactionForm(accountId);
},
async loadPaymentClaims() {
if (!this.currentClub) {
@@ -760,13 +756,15 @@ export default {
await this.loadPaymentClaims();
this.applyRouteQuery();
if (this.selectedAccountId && !this.selectedAccount) {
this.selectedAccountId = null;
this.resetForm();
}
if (this.selectedTransactionId && !this.selectedTransaction) {
this.selectedTransactionId = null;
this.resetTransactionForm();
}
if (!this.selectedAccountId && this.accounts.length > 0) {
this.selectedAccountId = this.accounts[0].id;
} else if (this.accounts.length === 0) {
this.resetForm();
}
} catch (error) {
this.loadError = safeErrorMessage(error, 'Konten konnten nicht geladen werden.');
@@ -779,11 +777,15 @@ export default {
this.saving = true;
try {
const payload = { ...this.form };
let savedAccountId = this.form.id;
if (this.form.id) {
await apiClient.put(`/club-accounts/${this.currentClub}/${this.form.id}`, payload);
const response = await apiClient.put(`/club-accounts/${this.currentClub}/${this.form.id}`, payload);
savedAccountId = response.data?.account?.id || savedAccountId;
} else {
await apiClient.post(`/club-accounts/${this.currentClub}`, payload);
const response = await apiClient.post(`/club-accounts/${this.currentClub}`, payload);
savedAccountId = response.data?.account?.id || savedAccountId;
}
this.selectedAccountId = savedAccountId ? String(savedAccountId) : null;
await this.loadAccounts();
this.showInfo('Erfolg', 'Konto gespeichert.', '', 'success');
} catch (error) {
@@ -809,13 +811,16 @@ export default {
reference: this.transactionForm.reference,
notes: this.transactionForm.notes,
};
let savedTransactionId = this.transactionForm.id;
if (this.transactionForm.id) {
await apiClient.put(`/club-accounts/${this.currentClub}/transactions/${this.transactionForm.id}`, payload);
const response = await apiClient.put(`/club-accounts/${this.currentClub}/transactions/${this.transactionForm.id}`, payload);
savedTransactionId = response.data?.transaction?.id || savedTransactionId;
} else {
await apiClient.post(`/club-accounts/${this.currentClub}/transactions`, payload);
const response = await apiClient.post(`/club-accounts/${this.currentClub}/transactions`, payload);
savedTransactionId = response.data?.transaction?.id || savedTransactionId;
}
this.selectedTransactionId = savedTransactionId ? String(savedTransactionId) : null;
await this.loadAccounts();
this.resetTransactionForm();
} catch (error) {
this.showInfo('Fehler', safeErrorMessage(error, 'Kontobewegung konnte nicht gespeichert werden.'), '', 'error');
} finally {

View File

@@ -131,6 +131,7 @@
Neue Gruppe
</button>
</div>
<p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Verteilergruppen bleiben sichtbar, Änderungen sind hier gesperrt.</p>
<div class="groups-chip-list">
<button
@@ -209,6 +210,7 @@
<div class="section-header">
<h3>{{ threadForm.id ? 'Vorgang bearbeiten' : 'Neuer Vorgang' }}</h3>
</div>
<p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Vorgänge lassen sich prüfen, aber nicht ändern.</p>
<form class="thread-form" @submit.prevent="saveThread">
<div class="form-grid">
@@ -297,6 +299,7 @@
<div class="section-header">
<h3>Nachrichten</h3>
</div>
<p v-if="!canEdit && selectedThread" class="state-banner">Lesemodus aktiv. Verlauf und Versandstatus bleiben sichtbar, neue Einträge sind gesperrt.</p>
<p v-if="!selectedThread" class="state-banner">Wähle links einen Kommunikationsvorgang aus.</p>
<template v-else>
@@ -405,6 +408,7 @@
<div class="section-header">
<h3>Vorlagen & Antworten</h3>
</div>
<p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Vorlagen können eingesehen, aber nicht bearbeitet werden.</p>
<div class="groups-chip-list">
<button
@@ -749,19 +753,7 @@ export default {
immediate: true,
async handler(clubId) {
if (!clubId) {
this.threads = [];
this.groups = [];
this.members = [];
this.templates = [];
this.selectedThreadId = null;
this.selectedGroupId = null;
this.selectedTemplateId = null;
this.threadForm = createEmptyThreadForm();
this.groupForm = createEmptyGroupForm();
this.templateForm = createEmptyTemplateForm();
this.messageForm = createEmptyMessageForm();
this.messageTemplateId = '';
this.loadError = '';
this.clearCommunicationState();
return;
}
await this.loadCommunication();
@@ -810,6 +802,21 @@ export default {
},
},
methods: {
clearCommunicationState() {
this.threads = [];
this.groups = [];
this.members = [];
this.templates = [];
this.selectedThreadId = null;
this.selectedGroupId = null;
this.selectedTemplateId = null;
this.threadForm = createEmptyThreadForm();
this.groupForm = createEmptyGroupForm();
this.templateForm = createEmptyTemplateForm();
this.messageForm = createEmptyMessageForm();
this.messageTemplateId = '';
this.loadError = '';
},
showInfo(title, message, details = '', type = 'info') {
this.infoDialog = buildInfoConfig({ title, message, details, type });
},
@@ -938,6 +945,14 @@ export default {
}
if (!this.selectedThreadId && this.threads.length > 0) {
this.selectedThreadId = this.threads[0].id;
} else if (this.threads.length === 0) {
this.resetThreadForm();
}
if (this.groups.length === 0) {
this.resetGroupForm();
}
if (this.templates.length === 0) {
this.resetTemplateForm();
}
} catch (error) {
this.loadError = safeErrorMessage(error, 'Kommunikation konnte nicht geladen werden.');
@@ -1056,11 +1071,15 @@ export default {
scheduledAt: this.threadForm.scheduledAt || null,
recipientFilters: this.threadForm.threadType === 'direct' ? {} : this.threadForm.recipientFilters,
};
let savedThreadId = this.threadForm.id;
if (this.threadForm.id) {
await apiClient.put(`/club-communication/${this.currentClub}/threads/${this.threadForm.id}`, payload);
const response = await apiClient.put(`/club-communication/${this.currentClub}/threads/${this.threadForm.id}`, payload);
savedThreadId = response.data?.thread?.id || savedThreadId;
} else {
await apiClient.post(`/club-communication/${this.currentClub}/threads`, payload);
const response = await apiClient.post(`/club-communication/${this.currentClub}/threads`, payload);
savedThreadId = response.data?.thread?.id || savedThreadId;
}
this.selectedThreadId = savedThreadId ? Number(savedThreadId) : null;
await this.loadCommunication();
this.showInfo('Erfolg', 'Kommunikationsvorgang gespeichert.', '', 'success');
} catch (error) {
@@ -1119,11 +1138,15 @@ export default {
...this.groupForm,
filterDefinition: this.groupForm.filterDefinition,
};
let savedGroupId = this.groupForm.id;
if (this.groupForm.id) {
await apiClient.put(`/club-communication/${this.currentClub}/groups/${this.groupForm.id}`, payload);
const response = await apiClient.put(`/club-communication/${this.currentClub}/groups/${this.groupForm.id}`, payload);
savedGroupId = response.data?.group?.id || savedGroupId;
} else {
await apiClient.post(`/club-communication/${this.currentClub}/groups`, payload);
const response = await apiClient.post(`/club-communication/${this.currentClub}/groups`, payload);
savedGroupId = response.data?.group?.id || savedGroupId;
}
this.selectedGroupId = savedGroupId ? Number(savedGroupId) : null;
await this.loadCommunication();
this.showInfo('Erfolg', 'Verteilergruppe gespeichert.', '', 'success');
} catch (error) {
@@ -1154,11 +1177,15 @@ export default {
if (!this.currentClub || !this.canEdit) return;
this.templateSaving = true;
try {
let savedTemplateId = this.templateForm.id;
if (this.templateForm.id) {
await apiClient.put(`/club-communication/${this.currentClub}/templates/${this.templateForm.id}`, this.templateForm);
const response = await apiClient.put(`/club-communication/${this.currentClub}/templates/${this.templateForm.id}`, this.templateForm);
savedTemplateId = response.data?.template?.id || savedTemplateId;
} else {
await apiClient.post(`/club-communication/${this.currentClub}/templates`, this.templateForm);
const response = await apiClient.post(`/club-communication/${this.currentClub}/templates`, this.templateForm);
savedTemplateId = response.data?.template?.id || savedTemplateId;
}
this.selectedTemplateId = savedTemplateId ? Number(savedTemplateId) : null;
await this.loadCommunication();
this.showInfo('Erfolg', 'Vorlage gespeichert.', '', 'success');
} catch (error) {

View File

@@ -76,6 +76,7 @@
<h3>Rechnungsparteien</h3>
<button type="button" class="btn-secondary" :disabled="!canEdit" @click="startCreateParty">Neue Partei</button>
</div>
<p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Parteien können eingesehen, aber nicht bearbeitet werden.</p>
<div class="party-list">
<button
v-for="party in parties"
@@ -217,6 +218,7 @@
<div class="section-header">
<h3>{{ invoiceForm.id ? 'Rechnung bearbeiten' : 'Neue Rechnung' }}</h3>
</div>
<p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Rechnungen lassen sich prüfen, aber nicht ändern.</p>
<form class="invoice-form" @submit.prevent="submitInvoice">
<div class="invoice-form-grid">
<label>
@@ -458,6 +460,45 @@ function buildInvoiceNumber(prefix, nextNumber, referenceDate = new Date()) {
return normalizedPrefix ? `${normalizedPrefix}-${year}-${paddedCounter}` : `${year}-${paddedCounter}`;
}
function createEmptyInvoiceForm() {
const issuedOn = new Date().toISOString().slice(0, 10);
return {
id: null,
invoiceDirection: 'outgoing',
invoiceType: 'sponsoring',
status: 'draft',
invoiceNumber: '',
externalReference: '',
partyId: '',
accountId: '',
issuedOn,
dueOn: addDaysIso(issuedOn, 14),
paidOn: '',
currencyCode: 'EUR',
description: '',
items: [createEmptyInvoiceItem()],
};
}
function createEmptyPartyForm() {
return {
id: null,
name: '',
partyType: 'customer',
status: 'active',
contractReference: '',
validFrom: '',
validTo: '',
contactName: '',
email: '',
phone: '',
street: '',
postalCode: '',
city: '',
notes: '',
};
}
export default {
name: 'ClubInvoicesView',
components: {
@@ -486,37 +527,8 @@ export default {
status: '',
search: '',
},
invoiceForm: {
id: null,
invoiceDirection: 'outgoing',
invoiceType: 'sponsoring',
status: 'draft',
externalReference: '',
partyId: '',
accountId: '',
issuedOn: new Date().toISOString().slice(0, 10),
dueOn: addDaysIso(new Date(), 14),
paidOn: '',
currencyCode: 'EUR',
description: '',
items: [createEmptyInvoiceItem()],
},
partyForm: {
id: null,
name: '',
partyType: 'customer',
status: 'active',
contractReference: '',
validFrom: '',
validTo: '',
contactName: '',
email: '',
phone: '',
street: '',
postalCode: '',
city: '',
notes: '',
},
invoiceForm: createEmptyInvoiceForm(),
partyForm: createEmptyPartyForm(),
infoDialog: {
isOpen: false,
title: '',
@@ -604,19 +616,7 @@ export default {
immediate: true,
async handler(newClub) {
if (!newClub) {
this.invoices = [];
this.parties = [];
this.accounts = [];
this.invoiceSettings = {
outgoingInvoicePrefix: 'RE',
outgoingInvoiceNextNumber: 1,
incomingInvoicePrefix: 'EI',
incomingInvoiceNextNumber: 1,
};
this.selectedInvoiceId = null;
this.resetInvoiceForm();
this.resetPartyForm();
this.loadError = '';
this.clearInvoiceState();
return;
}
await this.loadInvoices();
@@ -681,6 +681,22 @@ export default {
},
},
methods: {
clearInvoiceState() {
this.invoices = [];
this.parties = [];
this.accounts = [];
this.invoiceSettings = {
outgoingInvoicePrefix: 'RE',
outgoingInvoiceNextNumber: 1,
incomingInvoicePrefix: 'EI',
incomingInvoiceNextNumber: 1,
};
this.selectedInvoiceId = null;
this.selectedPartyId = null;
this.invoiceForm = createEmptyInvoiceForm();
this.partyForm = createEmptyPartyForm();
this.loadError = '';
},
showInfo(title, message, details = '', type = 'info') {
this.infoDialog = buildInfoConfig({ title, message, details, type });
},
@@ -749,9 +765,23 @@ export default {
incomingInvoicePrefix: response.data?.settings?.incomingInvoicePrefix || 'EI',
incomingInvoiceNextNumber: Number(response.data?.settings?.incomingInvoiceNextNumber || 1) || 1,
};
if (this.selectedInvoiceId && !this.selectedInvoice) {
this.selectedInvoiceId = null;
this.resetInvoiceForm();
}
if (this.selectedPartyId && !this.selectedParty) {
this.selectedPartyId = null;
this.resetPartyForm();
}
if (!this.selectedInvoiceId && this.invoices.length > 0) {
this.selectedInvoiceId = this.invoices[0].id;
}
if (this.invoices.length === 0) {
this.resetInvoiceForm();
}
if (this.parties.length === 0) {
this.resetPartyForm();
}
this.applyWorkflowQueryPrefill();
} catch (error) {
this.loadError = safeErrorMessage(error, 'Rechnungen konnten nicht geladen werden.');
@@ -767,6 +797,7 @@ export default {
},
applyWorkflowQueryPrefill() {
if (!this.currentClub || !Array.isArray(this.parties)) return;
if (this.selectedInvoiceId || this.invoiceForm.id) return;
const partyId = String(this.$route?.query?.partyId || this.$route?.query?.selectedPartyId || '').trim();
if (!partyId) return;
const matchingParty = this.parties.find((party) => String(party.id) === partyId);
@@ -798,42 +829,11 @@ export default {
},
resetInvoiceForm() {
this.selectedInvoiceId = null;
const issuedOn = new Date().toISOString().slice(0, 10);
this.invoiceForm = {
id: null,
invoiceDirection: 'outgoing',
invoiceType: 'sponsoring',
status: 'draft',
invoiceNumber: '',
externalReference: '',
partyId: '',
accountId: '',
issuedOn,
dueOn: addDaysIso(issuedOn, 14),
paidOn: '',
currencyCode: 'EUR',
description: '',
items: [createEmptyInvoiceItem()],
};
this.invoiceForm = createEmptyInvoiceForm();
},
startCreateParty() {
this.selectedPartyId = null;
this.partyForm = {
id: null,
name: '',
partyType: 'customer',
status: 'active',
contractReference: '',
validFrom: '',
validTo: '',
contactName: '',
email: '',
phone: '',
street: '',
postalCode: '',
city: '',
notes: '',
};
this.partyForm = createEmptyPartyForm();
},
resetPartyForm() {
this.startCreateParty();
@@ -852,11 +852,15 @@ export default {
this.partySaving = true;
try {
const payload = { ...this.partyForm };
let savedPartyId = this.partyForm.id;
if (this.partyForm.id) {
await apiClient.put(`/club-invoices/${this.currentClub}/parties/${this.partyForm.id}`, payload);
const response = await apiClient.put(`/club-invoices/${this.currentClub}/parties/${this.partyForm.id}`, payload);
savedPartyId = response.data?.party?.id || savedPartyId;
} else {
await apiClient.post(`/club-invoices/${this.currentClub}/parties`, payload);
const response = await apiClient.post(`/club-invoices/${this.currentClub}/parties`, payload);
savedPartyId = response.data?.party?.id || savedPartyId;
}
this.selectedPartyId = savedPartyId ? String(savedPartyId) : null;
await this.loadInvoices();
this.showInfo('Erfolg', 'Rechnungspartei gespeichert.', '', 'success');
} catch (error) {
@@ -898,11 +902,15 @@ export default {
taxRate: item.taxRate,
})),
};
let savedInvoiceId = this.invoiceForm.id;
if (this.invoiceForm.id) {
await apiClient.put(`/club-invoices/${this.currentClub}/${this.invoiceForm.id}`, payload);
const response = await apiClient.put(`/club-invoices/${this.currentClub}/${this.invoiceForm.id}`, payload);
savedInvoiceId = response.data?.invoice?.id || savedInvoiceId;
} else {
await apiClient.post(`/club-invoices/${this.currentClub}`, payload);
const response = await apiClient.post(`/club-invoices/${this.currentClub}`, payload);
savedInvoiceId = response.data?.invoice?.id || savedInvoiceId;
}
this.selectedInvoiceId = savedInvoiceId ? String(savedInvoiceId) : null;
await this.loadInvoices();
this.showInfo('Erfolg', 'Rechnung gespeichert.', '', 'success');
} catch (error) {

View File

@@ -196,6 +196,7 @@
<div class="section-header">
<h3>{{ form.id ? 'Aufgabe bearbeiten' : 'Neue Aufgabe' }}</h3>
</div>
<p v-if="!canEdit" class="state-banner">Lesemodus aktiv. Aufgaben bleiben sichtbar, Änderungen am Formular sind gesperrt.</p>
<form class="task-form" @submit.prevent="submitTask">
<label>
<span>Titel</span>
@@ -420,6 +421,19 @@ function normalizeTask(payload = {}) {
};
}
function createEmptyTaskForm() {
return {
id: null,
title: '',
description: '',
status: 'open',
priority: 'normal',
dueAt: '',
remindAt: '',
assignedUserId: '',
};
}
export default {
name: 'ClubTasksView',
components: {
@@ -444,16 +458,7 @@ export default {
priority: '',
search: '',
},
form: {
id: null,
title: '',
description: '',
status: 'open',
priority: 'normal',
dueAt: '',
remindAt: '',
assignedUserId: '',
},
form: createEmptyTaskForm(),
infoDialog: {
isOpen: false,
title: '',
@@ -508,11 +513,7 @@ export default {
immediate: true,
async handler(newClub) {
if (!newClub) {
this.tasks = [];
this.workflowSources = [];
this.selectedTaskId = null;
this.resetForm();
this.loadError = '';
this.clearTaskState();
return;
}
await this.loadTasks();
@@ -542,6 +543,16 @@ export default {
},
},
methods: {
clearTaskState() {
this.tasks = [];
this.taskDefinitions = [];
this.taskSuggestions = [];
this.workflowSources = [];
this.assignableUsers = [];
this.selectedTaskId = null;
this.form = createEmptyTaskForm();
this.loadError = '';
},
normalizeAssignableUser(user = {}) {
const email = typeof user.email === 'string' ? user.email.trim() : '';
return {
@@ -632,16 +643,7 @@ export default {
},
resetForm() {
this.selectedTaskId = null;
this.form = {
id: null,
title: '',
description: '',
status: 'open',
priority: 'normal',
dueAt: '',
remindAt: '',
assignedUserId: '',
};
this.form = createEmptyTaskForm();
},
async loadTasks() {
if (!this.currentClub) return;
@@ -669,6 +671,8 @@ export default {
}
if (!this.selectedTaskId && this.tasks.length > 0) {
this.selectedTaskId = this.tasks[0].id;
} else if (this.tasks.length === 0) {
this.resetForm();
}
} catch (error) {
this.loadError = safeErrorMessage(error, 'Aufgaben konnten nicht geladen werden.');
@@ -690,14 +694,17 @@ export default {
assignedUserId: this.form.assignedUserId || null,
};
try {
let savedTaskId = this.form.id;
if (this.form.id) {
await apiClient.put(`/club-tasks/${this.currentClub}/${this.form.id}`, payload);
const response = await apiClient.put(`/club-tasks/${this.currentClub}/${this.form.id}`, payload);
savedTaskId = response.data?.task?.id || savedTaskId;
} else {
await apiClient.post(`/club-tasks/${this.currentClub}`, payload);
const response = await apiClient.post(`/club-tasks/${this.currentClub}`, payload);
savedTaskId = response.data?.task?.id || savedTaskId;
}
this.selectedTaskId = savedTaskId ? String(savedTaskId) : null;
await this.loadTasks();
this.showInfo('Erfolg', 'Aufgabe gespeichert.', '', 'success');
this.resetForm();
} catch (error) {
this.showInfo('Fehler', safeErrorMessage(error, 'Aufgabe konnte nicht gespeichert werden.'), '', 'error');
} finally {
@@ -746,6 +753,9 @@ export default {
await apiClient.patch(`/club-tasks/${this.currentClub}/${task.id}/status`, {
status: 'archived',
});
if (this.selectedTask?.id === task.id) {
this.resetForm();
}
await this.loadTasks();
this.showInfo('Erfolg', 'Aufgabe wurde archiviert.', '', 'success');
} catch (error) {

View File

@@ -2165,7 +2165,7 @@ export default {
};
const configureLeagueFromUrl = async () => {
if (!parsedMyTischtennisData.value || parsedMyTischtennisData.value.urlType !== 'table') {
if (!parsedMyTischtennisData.value || parsedMyTischtennisData.value.urlType !== 'table' || !selectedClub.value) {
return;
}
@@ -2176,6 +2176,7 @@ export default {
try {
const response = await apiClient.post('/mytischtennis/configure-league', {
url: myTischtennisUrl.value.trim(),
clubId: selectedClub.value,
createSeason: true
});