From bf4db389ff991536a7c005d20f1f50c6186e884c Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Wed, 20 May 2026 17:38:17 +0200 Subject: [PATCH] feat(api): add endpoint for team table data by season --- server/api/spielplan/table.get.js | 137 ++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 server/api/spielplan/table.get.js diff --git a/server/api/spielplan/table.get.js b/server/api/spielplan/table.get.js new file mode 100644 index 0000000..6547bc8 --- /dev/null +++ b/server/api/spielplan/table.get.js @@ -0,0 +1,137 @@ +import { promises as fs } from 'fs' +import path from 'path' +import { getCurrentSeasonSlug, validateSeasonSlug } from '../../utils/spielplan-data.js' +import { getServerDataPath } from '../../utils/paths.js' +import { error as loggerError } from '../../utils/logger.js' + +const TABLES_FILE_PATTERN = /^tables_(\d{2}--\d{2})\.json$/ + +function normalizeTeamName(value) { + return String(value || '').trim().toLowerCase().replace(/\s+/g, ' ') +} + +async function listTableSeasons() { + const importDir = getServerDataPath('spielplan-import') + + try { + const files = await fs.readdir(importDir) + return files + .map((file) => { + const match = file.match(TABLES_FILE_PATTERN) + return match ? match[1] : null + }) + .filter(Boolean) + .sort() + .reverse() + } catch (error) { + if (error?.code !== 'ENOENT') { + loggerError('Fehler beim Lesen der Tabellen-Saisons', { error }) + } + return [] + } +} + +async function readTablesBySeason(season) { + const filePath = getServerDataPath('spielplan-import', `tables_${season}.json`) + const content = await fs.readFile(filePath, 'utf8') + const parsed = JSON.parse(content) + return { filePath, parsed } +} + +function findTeamTable(tables, teamQuery) { + const normalizedQuery = normalizeTeamName(teamQuery) + + const exact = tables.find((entry) => normalizeTeamName(entry?.teamName) === normalizedQuery) + if (exact) return exact + + return tables.find((entry) => normalizeTeamName(entry?.teamName).includes(normalizedQuery)) || null +} + +export default defineEventHandler(async (event) => { + try { + const query = getQuery(event) + const team = String(query.team || query.mannschaft || '').trim() + + if (!team) { + return { + success: false, + message: 'Query-Parameter team (oder mannschaft) fehlt', + team: null, + table: null + } + } + + const requestedSeason = query.season ? String(query.season).trim() : null + if (requestedSeason && !validateSeasonSlug(requestedSeason)) { + return { + success: false, + message: 'Ungueltiger Saison-Slug', + team, + table: null, + season: requestedSeason + } + } + + const availableSeasons = await listTableSeasons() + const defaultSeason = getCurrentSeasonSlug() + const season = requestedSeason || defaultSeason + + let loaded = null + try { + loaded = await readTablesBySeason(season) + } catch (error) { + if (error?.code === 'ENOENT' && !requestedSeason && availableSeasons.length > 0) { + loaded = await readTablesBySeason(availableSeasons[0]) + } else { + throw error + } + } + + if (!loaded) { + return { + success: false, + message: 'Keine Tabellen-Daten gefunden', + team, + table: null, + season, + availableSeasons + } + } + + const payload = loaded.parsed || {} + const tables = Array.isArray(payload.tables) ? payload.tables : [] + const found = findTeamTable(tables, team) + const effectiveSeason = payload?.source?.season?.seasonSlug || season + + if (!found) { + return { + success: false, + message: 'Keine Tabellen-Daten fuer die Mannschaft gefunden', + team, + table: null, + season: effectiveSeason, + filePath: loaded.filePath, + availableTeams: tables.map((entry) => entry?.teamName).filter(Boolean) + } + } + + return { + success: true, + message: 'Tabellen-Daten erfolgreich geladen', + team, + table: found, + season: effectiveSeason, + filePath: loaded.filePath, + importedAt: payload.importedAt || null, + availableSeasons + } + } catch (error) { + loggerError('Fehler beim Laden der Tabellen-Daten:', { error }) + return { + success: false, + message: 'Fehler beim Laden der Tabellen-Daten', + team: null, + table: null + } + } +}) \ No newline at end of file