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:
@@ -869,7 +869,8 @@ class MyTischtennisClient {
|
||||
* @param {string} fedNickname - Federation nickname (e.g., "HeTTV")
|
||||
* @returns {Promise<Object>} Rankings with player entries (all pages)
|
||||
*/
|
||||
async getClubRankings(cookie, clubId, fedNickname, currentRanking = 'yes') {
|
||||
async getClubRankings(cookie, clubId, fedNickname, currentRanking = 'yes', options = {}) {
|
||||
const { includeHistoryPlayerIds = false } = options;
|
||||
const allEntries = [];
|
||||
let currentPage = 0;
|
||||
let hasMorePages = true;
|
||||
@@ -877,8 +878,6 @@ class MyTischtennisClient {
|
||||
|
||||
while (hasMorePages) {
|
||||
const endpoint = `/rankings/andro-rangliste?all-players=on&clubnr=${clubId}&fednickname=${fedNickname}¤t-ranking=${currentRanking}&results-per-page=100&page=${currentPage}&_data=routes%2F%24`;
|
||||
|
||||
|
||||
const result = await this.authenticatedRequest(endpoint, cookie, {
|
||||
method: 'GET'
|
||||
});
|
||||
@@ -917,15 +916,39 @@ class MyTischtennisClient {
|
||||
error: 'Keine entries in blockLoaderData gefunden'
|
||||
};
|
||||
}
|
||||
|
||||
let historyPlayerIdsByName = null;
|
||||
if (includeHistoryPlayerIds) {
|
||||
const htmlEndpoint = `/rankings/andro-rangliste?clubnr=${clubId}&fednickname=${fedNickname}&all-players=on&continent=all&country=all¤t-ranking=${currentRanking}&results-per-page=100&page=${currentPage + 1}`;
|
||||
const htmlResult = await this.authenticatedRequest(htmlEndpoint, cookie, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'text/html,application/xhtml+xml'
|
||||
}
|
||||
});
|
||||
historyPlayerIdsByName = htmlResult.success
|
||||
? this.extractHistoryPlayerIdsFromAndroRankingHtml(htmlResult.data)
|
||||
: new Map();
|
||||
}
|
||||
|
||||
const enrichedEntries = entries.map((entry) => {
|
||||
const nameKey = this._buildRankingNameKey(entry?.firstname, entry?.lastname);
|
||||
const historyPlayerId = historyPlayerIdsByName?.get(nameKey) || null;
|
||||
return {
|
||||
...entry,
|
||||
historyPlayerId,
|
||||
myTischtennisHistoryPlayerId: historyPlayerId
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
// Füge Entries hinzu
|
||||
allEntries.push(...entries);
|
||||
allEntries.push(...enrichedEntries);
|
||||
|
||||
// Prüfe ob es weitere Seiten gibt
|
||||
// Wenn die aktuelle Seite weniger Einträge hat als das Limit, sind wir am Ende
|
||||
// Oder wenn wir alle erwarteten Einträge haben
|
||||
if (entries.length === 0) {
|
||||
if (enrichedEntries.length === 0) {
|
||||
hasMorePages = false;
|
||||
} else if (rankingData.numberOfPages && currentPage >= rankingData.numberOfPages - 1) {
|
||||
hasMorePages = false;
|
||||
@@ -946,6 +969,45 @@ class MyTischtennisClient {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
extractHistoryPlayerIdsFromAndroRankingHtml(html) {
|
||||
const result = new Map();
|
||||
const source = typeof html === 'string' ? html : String(html || '');
|
||||
const anchorPattern = /href="\/community\/external-profile\?player-id=(P[A-Z0-9]+)"[^>]*>([^<]+)<\/a>/gi;
|
||||
|
||||
let match = null;
|
||||
while ((match = anchorPattern.exec(source)) !== null) {
|
||||
const playerId = match[1];
|
||||
const fullName = this._decodeHtmlEntities(match[2] || '');
|
||||
const key = this._buildRankingFullNameKey(fullName);
|
||||
if (key && playerId && !result.has(key)) {
|
||||
result.set(key, playerId);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
_buildRankingNameKey(firstname, lastname) {
|
||||
return this._buildRankingFullNameKey(`${firstname || ''} ${lastname || ''}`);
|
||||
}
|
||||
|
||||
_buildRankingFullNameKey(name) {
|
||||
return String(name || '')
|
||||
.normalize('NFKC')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
_decodeHtmlEntities(value) {
|
||||
return String(value || '')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, "'")
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
}
|
||||
}
|
||||
|
||||
export default new MyTischtennisClient();
|
||||
|
||||
Reference in New Issue
Block a user