Refactor memberController and memberService to include memberFormHandedOver field and improve parameter handling

Updated memberController to handle the showAll parameter more effectively and added memberFormHandedOver to the setClubMember method in memberService. Enhanced Member model to include memberFormHandedOver field with appropriate defaults. Updated MembersView to reflect changes in the UI, allowing for better member data management and visibility.
This commit is contained in:
Torsten Schulz (local)
2025-11-03 12:36:13 +01:00
parent 84ff4e126e
commit 76ee9ee742
4 changed files with 25 additions and 16 deletions

View File

@@ -4,10 +4,8 @@ import { devLog } from '../utils/logger.js';
const getClubMembers = async(req, res) => {
try {
const { authcode: userToken } = req.headers;
const { id: clubId, showAll } = req.params;
if (showAll === null) {
showAll = false;
}
const { id: clubId } = req.params;
const showAll = req.params.showAll ?? 'false';
res.status(200).json(await MemberService.getClubMembers(userToken, clubId, showAll));
} catch(error) {
res.status(500).json({ error: 'systemerror' });
@@ -27,12 +25,12 @@ const getWaitingApprovals = async(req, res) => {
const setClubMembers = async (req, res) => {
try {
const { id: memberId, firstname: firstName, lastname: lastName, street, city, birthdate, phone, email, active,
testMembership, picsInInternetAllowed, gender, ttr, qttr } = req.body;
const { id: memberId, firstname: firstName, lastname: lastName, street, city, birthdate, phone, email, active,
testMembership, picsInInternetAllowed, gender, ttr, qttr, memberFormHandedOver } = req.body;
const { id: clubId } = req.params;
const { authcode: userToken } = req.headers;
const addResult = await MemberService.setClubMember(userToken, clubId, memberId, firstName, lastName, street, city, birthdate,
phone, email, active, testMembership, picsInInternetAllowed, gender, ttr, qttr);
phone, email, active, testMembership, picsInInternetAllowed, gender, ttr, qttr, memberFormHandedOver);
res.status(addResult.status || 500).json(addResult.response);
} catch (error) {
console.error('[setClubMembers] - Error:', error);

View File

@@ -138,6 +138,13 @@ const Member = sequelize.define('Member', {
allowNull: true,
defaultValue: null
},
memberFormHandedOver: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
field: 'member_form_handed_over',
comment: 'Mitgliedsformular ausgehändigt'
},
myTischtennisPlayerId: {
type: DataTypes.STRING,
allowNull: true,
@@ -157,13 +164,7 @@ const Member = sequelize.define('Member', {
member.save();
},
}
},
{
underscored: true,
tableName: 'log',
timestamps: true
}
);
});
Member.belongsTo(Club, { as: 'club' });
Club.hasMany(Member, { as: 'members' });

View File

@@ -48,7 +48,7 @@ class MemberService {
}
async setClubMember(userToken, clubId, memberId, firstName, lastName, street, city, birthdate, phone, email, active = true, testMembership = false,
picsInInternetAllowed = false, gender = 'unknown', ttr = null, qttr = null) {
picsInInternetAllowed = false, gender = 'unknown', ttr = null, qttr = null, memberFormHandedOver = false) {
try {
await checkAccess(userToken, clubId);
let member = null;
@@ -69,6 +69,7 @@ class MemberService {
if (gender) member.gender = gender;
if (ttr !== undefined) member.ttr = ttr;
if (qttr !== undefined) member.qttr = qttr;
member.memberFormHandedOver = !!memberFormHandedOver;
await member.save();
} else {
await Member.create({
@@ -86,6 +87,7 @@ class MemberService {
gender: gender || 'unknown',
ttr: ttr,
qttr: qttr,
memberFormHandedOver: !!memberFormHandedOver,
});
}
return {

View File

@@ -56,6 +56,7 @@
<label class="checkbox-item"><span>Aktiv:</span> <input type="checkbox" v-model="newActive"></label>
<label class="checkbox-item"><span>Pics in Internet erlaubt:</span> <input type="checkbox" v-model="newPicsInInternetAllowed"></label>
<label class="checkbox-item"><span>Testmitgliedschaft:</span> <input type="checkbox" v-model="testMembership"></label>
<label class="checkbox-item"><span>Mitgliedsformular ausgehändigt:</span> <input type="checkbox" v-model="newMemberFormHandedOver"></label>
<label><span>Bild:</span> <input type="file" @change="onFileSelected"></label>
<div v-if="memberImagePreview">
<img :src="memberImagePreview" alt="Vorschau des Mitgliedsbildes"
@@ -113,6 +114,7 @@
<th>Name, Vorname</th>
<th>TTR / QTTR</th>
<th>Adresse</th>
<th>Mitgliedsformular</th>
<th>Geburtsdatum</th>
<th>Telefon-Nr.</th>
<th>Email-Adresse</th>
@@ -121,7 +123,7 @@
</thead>
<tbody>
<template v-for="member in filteredMembers" :key="member.id">
<tr v-if="member.active || showInactiveMembers" class="member-row" :class="{ 'row-inactive': !member.active, 'row-test': member.testMembership }" @click="editMember(member)">
<tr v-if="member.active || showInactiveMembers" class="member-row" :class="{ 'row-inactive': !member.active, 'row-test': member.testMembership && !member.memberFormHandedOver, 'row-test-form': member.testMembership && member.memberFormHandedOver }" @click="editMember(member)">
<td>
<img v-if="member.imageUrl" :src="member.imageUrl" alt="Mitgliedsbild"
style="max-width: 50px; max-height: 50px;"
@@ -145,6 +147,7 @@
<span v-else class="no-rating">-</span>
</td>
<td>{{ member.street }}, {{ member.city }}</td>
<td>{{ member.memberFormHandedOver ? '✓' : '' }}</td>
<td>{{ getFormattedBirthdate(member.birthDate) }}</td>
<td>{{ member.phone }}</td>
<td>{{ member.email }}</td>
@@ -336,6 +339,7 @@ export default {
testMembership: false,
showInactiveMembers: false,
newPicsInInternetAllowed: false,
newMemberFormHandedOver: false,
isUpdatingRatings: false,
showMemberInfo: false,
showActivitiesModal: false,
@@ -423,6 +427,7 @@ export default {
this.newGender = 'unknown';
this.memberImage = null;
this.memberImagePreview = null;
this.newMemberFormHandedOver = false;
},
onFileSelected(event) {
const file = event.target.files[0];
@@ -449,6 +454,7 @@ export default {
id: this.memberToEdit ? this.memberToEdit.id : null,
testMembership: this.testMembership,
picsInInternetAllowed: this.newPicsInInternetAllowed,
memberFormHandedOver: this.newMemberFormHandedOver,
};
let response;
@@ -493,6 +499,7 @@ export default {
this.newBirthdate = this.formatDateForInput(birthDate);
this.testMembership = member.testMembership;
this.newPicsInInternetAllowed = member.picsInInternetAllowed;
this.newMemberFormHandedOver = !!member.memberFormHandedOver;
try {
const response = await apiClient.get(`/clubmembers/image/${member.id}`, {
responseType: 'blob'
@@ -849,6 +856,7 @@ table td {
.is-inactive { text-decoration: line-through; }
.inactive-badge { margin-left: .5rem; font-size: .85em; color: #666; text-transform: lowercase; }
.row-test { background-color: #fff3cd; }
.row-test-form { background-color: #ffffcc; }
.rating-cell {
font-family: 'Courier New', monospace;