feat(tournament): enhance external participant management with email and address fields
- Added email and address fields to the external participant model, allowing for more comprehensive participant information. - Updated the tournament service and controller to handle the new fields when adding external participants. - Modified frontend components to include input fields for email and address, improving user experience and data collection. - Updated localization strings to support the new fields, ensuring clarity in the user interface.
This commit is contained in:
@@ -545,9 +545,9 @@ export const setMatchActive = async (req, res) => {
|
||||
// Externe Teilnehmer hinzufügen
|
||||
export const addExternalParticipant = async (req, res) => {
|
||||
const { authcode: token } = req.headers;
|
||||
const { clubId, tournamentId, classId, firstName, lastName, club, birthDate, gender } = req.body;
|
||||
const { clubId, tournamentId, classId, firstName, lastName, club, birthDate, gender, email, address } = req.body;
|
||||
try {
|
||||
await tournamentService.addExternalParticipant(token, clubId, classId, firstName, lastName, club, birthDate, gender);
|
||||
await tournamentService.addExternalParticipant(token, clubId, classId, firstName, lastName, club, birthDate, gender, email, address);
|
||||
emitTournamentChanged(clubId, tournamentId);
|
||||
res.status(200).json({ message: 'Externer Teilnehmer hinzugefügt' });
|
||||
} catch (error) {
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
-- E-Mail und Adresse für externe Teilnehmer (für Weitermeldung)
|
||||
-- Die Felder werden verschlüsselt gespeichert (siehe Model)
|
||||
|
||||
ALTER TABLE `external_tournament_participant`
|
||||
ADD COLUMN `email` VARCHAR(500) NULL AFTER `club`,
|
||||
ADD COLUMN `address` TEXT NULL AFTER `email`;
|
||||
@@ -53,6 +53,40 @@ const ExternalTournamentParticipant = sequelize.define('ExternalTournamentPartic
|
||||
return decryptData(encryptedValue);
|
||||
}
|
||||
},
|
||||
email: {
|
||||
type: DataTypes.STRING(500),
|
||||
allowNull: true,
|
||||
set(value) {
|
||||
if (!value) {
|
||||
this.setDataValue('email', null);
|
||||
return;
|
||||
}
|
||||
const encryptedValue = encryptData(value);
|
||||
this.setDataValue('email', encryptedValue);
|
||||
},
|
||||
get() {
|
||||
const encryptedValue = this.getDataValue('email');
|
||||
if (!encryptedValue) return null;
|
||||
return decryptData(encryptedValue);
|
||||
}
|
||||
},
|
||||
address: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
set(value) {
|
||||
if (!value) {
|
||||
this.setDataValue('address', null);
|
||||
return;
|
||||
}
|
||||
const encryptedValue = encryptData(value);
|
||||
this.setDataValue('address', encryptedValue);
|
||||
},
|
||||
get() {
|
||||
const encryptedValue = this.getDataValue('address');
|
||||
if (!encryptedValue) return null;
|
||||
return decryptData(encryptedValue);
|
||||
}
|
||||
},
|
||||
birthDate: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
|
||||
@@ -3369,7 +3369,7 @@ Ve // 2. Neues Turnier anlegen
|
||||
}
|
||||
|
||||
// Externe Teilnehmer hinzufügen
|
||||
async addExternalParticipant(userToken, clubId, classId, firstName, lastName, club, birthDate, gender) {
|
||||
async addExternalParticipant(userToken, clubId, classId, firstName, lastName, club, birthDate, gender, email = null, address = null) {
|
||||
await checkAccess(userToken, clubId);
|
||||
if (!classId) {
|
||||
throw new Error('Klasse ist erforderlich');
|
||||
@@ -3432,6 +3432,8 @@ Ve // 2. Neues Turnier anlegen
|
||||
firstName,
|
||||
lastName,
|
||||
club: club || null,
|
||||
email: email || null,
|
||||
address: address || null,
|
||||
birthDate: birthDate || null,
|
||||
gender: participantGender,
|
||||
groupId: null
|
||||
|
||||
@@ -172,9 +172,9 @@ export default {
|
||||
this.playerData = {
|
||||
name: `${externalParticipant.firstName || ''} ${externalParticipant.lastName || ''}`.trim(),
|
||||
birthDate: externalParticipant.birthDate || null,
|
||||
address: null, // Externe Teilnehmer haben keine Adresse
|
||||
address: externalParticipant.address || null,
|
||||
gender: externalParticipant.gender || null,
|
||||
email: null, // Externe Teilnehmer haben keine E-Mail
|
||||
email: externalParticipant.email || null,
|
||||
phone: null // Externe Teilnehmer haben keine Telefonnummer
|
||||
};
|
||||
} else {
|
||||
|
||||
@@ -77,6 +77,22 @@
|
||||
{{ $t('tournaments.add') }}
|
||||
</button>
|
||||
</div>
|
||||
<div class="add-participant-row add-participant-row-contact">
|
||||
<input
|
||||
type="email"
|
||||
:value="newExternalParticipant.email"
|
||||
@input="$emit('update:newExternalParticipant', { ...newExternalParticipant, email: $event.target.value })"
|
||||
:placeholder="$t('tournaments.email') + ' (' + $t('tournaments.optional') + ', ' + $t('tournaments.forForwarding') + ')'"
|
||||
class="external-input external-input-email"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
:value="newExternalParticipant.address"
|
||||
@input="$emit('update:newExternalParticipant', { ...newExternalParticipant, address: $event.target.value })"
|
||||
:placeholder="$t('tournaments.address') + ' (' + $t('tournaments.optional') + ', ' + $t('tournaments.forForwarding') + ')'"
|
||||
class="external-input external-input-address"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="participants-table-container">
|
||||
@@ -97,6 +113,8 @@
|
||||
<th class="participant-name">{{ $t('tournaments.name') }}</th>
|
||||
<th v-if="allowsExternal" class="participant-gender-cell">{{ $t('members.gender') }}</th>
|
||||
<th v-if="allowsExternal" class="participant-club-cell">{{ $t('tournaments.club') }}</th>
|
||||
<th v-if="allowsExternal" class="participant-email-cell">{{ $t('tournaments.email') }}</th>
|
||||
<th v-if="allowsExternal" class="participant-address-cell">{{ $t('tournaments.address') }}</th>
|
||||
<th v-if="isGroupTournament" class="participant-group-cell">{{ $t('tournaments.group') }}</th>
|
||||
<th class="participant-action-cell">{{ $t('tournaments.action') }}</th>
|
||||
</tr>
|
||||
@@ -146,6 +164,14 @@
|
||||
{{ participant.club || '–' }}
|
||||
</template>
|
||||
</td>
|
||||
<td v-if="allowsExternal" class="participant-email-cell">
|
||||
<template v-if="participant.member">–</template>
|
||||
<template v-else>{{ participant.email || '–' }}</template>
|
||||
</td>
|
||||
<td v-if="allowsExternal" class="participant-address-cell">
|
||||
<template v-if="participant.member">–</template>
|
||||
<template v-else>{{ participant.address || '–' }}</template>
|
||||
</td>
|
||||
<td v-if="isGroupTournament" class="participant-group-cell">
|
||||
<select
|
||||
:value="participant.groupNumber"
|
||||
@@ -178,6 +204,8 @@
|
||||
<th class="participant-name">{{ $t('tournaments.name') }}</th>
|
||||
<th v-if="allowsExternal" class="participant-gender-cell">{{ $t('members.gender') }}</th>
|
||||
<th v-if="allowsExternal" class="participant-club-cell">{{ $t('tournaments.club') }}</th>
|
||||
<th v-if="allowsExternal" class="participant-email-cell">{{ $t('tournaments.email') }}</th>
|
||||
<th v-if="allowsExternal" class="participant-address-cell">{{ $t('tournaments.address') }}</th>
|
||||
<th class="participant-class-cell">{{ $t('tournaments.class') }}</th>
|
||||
<th v-if="isGroupTournament" class="participant-group-cell">{{ $t('tournaments.group') }}</th>
|
||||
<th class="participant-action-cell">{{ $t('tournaments.action') }}</th>
|
||||
@@ -228,6 +256,14 @@
|
||||
{{ participant.club || '–' }}
|
||||
</template>
|
||||
</td>
|
||||
<td v-if="allowsExternal" class="participant-email-cell">
|
||||
<template v-if="participant.member">–</template>
|
||||
<template v-else>{{ participant.email || '–' }}</template>
|
||||
</td>
|
||||
<td v-if="allowsExternal" class="participant-address-cell">
|
||||
<template v-if="participant.member">–</template>
|
||||
<template v-else>{{ participant.address || '–' }}</template>
|
||||
</td>
|
||||
<td class="participant-class-cell">
|
||||
<select
|
||||
:value="participant.classId"
|
||||
@@ -571,6 +607,32 @@ export default {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.add-participant-row-contact {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.external-input-email {
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
.external-input-address {
|
||||
min-width: 220px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.participants-table-header .participant-email-cell,
|
||||
.participants-table-body .participant-email-cell {
|
||||
min-width: 140px;
|
||||
}
|
||||
|
||||
.participants-table-header .participant-address-cell,
|
||||
.participants-table-body .participant-address-cell {
|
||||
min-width: 160px;
|
||||
max-width: 220px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.participants-layout {
|
||||
flex-direction: column;
|
||||
|
||||
@@ -659,6 +659,8 @@
|
||||
"startKORound": "K.o.-Runde starten",
|
||||
"deleteKORound": "K.o.-Runde",
|
||||
"address": "Adresse",
|
||||
"email": "E-Mail",
|
||||
"forForwarding": "für Weitermeldung",
|
||||
"showPlayerDetails": "Spielerdetails anzeigen",
|
||||
"noPlayerDataAvailable": "Keine Spielerdaten verfügbar",
|
||||
"koRound": "K.-o.-Runde",
|
||||
|
||||
@@ -377,6 +377,8 @@ export default {
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
club: '',
|
||||
email: '',
|
||||
address: '',
|
||||
birthDate: null,
|
||||
gender: 'unknown'
|
||||
},
|
||||
@@ -2839,18 +2841,23 @@ export default {
|
||||
try {
|
||||
await apiClient.post('/tournament/external-participant', {
|
||||
clubId: this.currentClub,
|
||||
tournamentId: this.selectedDate,
|
||||
classId: classId,
|
||||
firstName: this.newExternalParticipant.firstName,
|
||||
lastName: this.newExternalParticipant.lastName,
|
||||
club: this.newExternalParticipant.club || null,
|
||||
birthDate: this.newExternalParticipant.birthDate || null,
|
||||
gender: this.newExternalParticipant.gender || 'unknown'
|
||||
gender: this.newExternalParticipant.gender || 'unknown',
|
||||
email: this.newExternalParticipant.email || null,
|
||||
address: this.newExternalParticipant.address || null
|
||||
});
|
||||
// Leere Eingabefelder
|
||||
this.newExternalParticipant = {
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
club: '',
|
||||
email: '',
|
||||
address: '',
|
||||
birthDate: null,
|
||||
gender: 'unknown'
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user