feat(MemberTtrHistory): implement TTR history management and UI enhancements

- Added new endpoints in the member controller for retrieving and refreshing TTR history.
- Integrated TTR history functionality into the member service, allowing for seamless data retrieval and updates.
- Updated the member model to include a field for TTR history player ID, enhancing data tracking.
- Enhanced the MembersView to display TTR history with a dedicated dialog for better user interaction.
- Improved the MyTischtennisClient to support fetching historical player IDs, enriching the data provided to users.
- Refactored various components to ensure consistent styling and functionality across the application.
This commit is contained in:
Torsten Schulz (local)
2026-03-18 15:34:10 +01:00
parent 79adad9564
commit 563a7e8dde
16 changed files with 1471 additions and 108 deletions

View File

@@ -166,6 +166,12 @@ const Member = sequelize.define('Member', {
allowNull: true,
comment: 'Player ID from myTischtennis (e.g. NU2705037)',
field: 'my_tischtennis_player_id'
},
myTischtennisHistoryPlayerId: {
type: DataTypes.STRING,
allowNull: true,
comment: 'TTR history player ID from myTischtennis (e.g. P14EC4981D)',
field: 'my_tischtennis_history_player_id'
}
}, {
underscored: true,

View File

@@ -0,0 +1,79 @@
import { DataTypes } from 'sequelize';
import sequelize from '../database.js';
const MemberTtrHistory = sequelize.define('MemberTtrHistory', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
memberId: {
type: DataTypes.INTEGER,
allowNull: false,
field: 'member_id'
},
clubId: {
type: DataTypes.INTEGER,
allowNull: false,
field: 'club_id'
},
playerId: {
type: DataTypes.STRING,
allowNull: true,
field: 'player_id'
},
sourceDate: {
type: DataTypes.DATEONLY,
allowNull: false,
field: 'source_date'
},
ttr: {
type: DataTypes.INTEGER,
allowNull: true
},
qttr: {
type: DataTypes.INTEGER,
allowNull: true
},
label: {
type: DataTypes.STRING,
allowNull: true
},
sourceType: {
type: DataTypes.STRING,
allowNull: true,
field: 'source_type'
},
fetchedAt: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
field: 'fetched_at'
},
rawPayload: {
type: DataTypes.JSON,
allowNull: true,
field: 'raw_payload'
}
}, {
underscored: true,
tableName: 'member_ttr_history',
timestamps: true,
indexes: [
{
fields: ['member_id']
},
{
fields: ['club_id']
},
{
fields: ['player_id']
},
{
fields: ['source_date']
}
]
});
export default MemberTtrHistory;

View File

@@ -48,6 +48,7 @@ import ApiLog from './ApiLog.js';
import MemberTransferConfig from './MemberTransferConfig.js';
import MemberContact from './MemberContact.js';
import MemberImage from './MemberImage.js';
import MemberTtrHistory from './MemberTtrHistory.js';
import TrainingGroup from './TrainingGroup.js';
import MemberTrainingGroup from './MemberTrainingGroup.js';
import ClubDisabledPresetGroup from './ClubDisabledPresetGroup.js';
@@ -90,6 +91,9 @@ DiaryNote.belongsTo(Member, { foreignKey: 'memberId' });
Member.hasMany(MemberNote, { as: 'memberNotes', foreignKey: 'memberId' });
MemberNote.belongsTo(Member, { foreignKey: 'memberId' });
Member.hasMany(MemberTtrHistory, { as: 'ttrHistoryEntries', foreignKey: 'memberId' });
MemberTtrHistory.belongsTo(Member, { as: 'member', foreignKey: 'memberId' });
DiaryDate.hasMany(DiaryNote, { as: 'diaryNotes', foreignKey: 'diaryDateId' });
DiaryNote.belongsTo(DiaryDate, { foreignKey: 'diaryDateId' });
@@ -417,6 +421,7 @@ export {
MemberTransferConfig,
MemberContact,
MemberImage,
MemberTtrHistory,
TrainingGroup,
MemberTrainingGroup,
ClubDisabledPresetGroup,