feature/ui-redesign #8

Merged
thoenykaroli merged 3 commits from feature/ui-redesign into main 2026-06-01 09:42:42 +02:00
4 changed files with 78 additions and 25 deletions
Showing only changes of commit fdffc08417 - Show all commits

View File

@ -1,19 +1,32 @@
/**
* ticketmaster.js Schnittstelle zum Backend-Proxy für die Ticketmaster Discovery API.
* Der direkte API-Aufruf läuft über den eigenen Backend-Server, um den API-Key
* nicht im Frontend zu exponieren (OWASP: Sensitive Data Exposure vermeiden).
*/
/**
* Lädt Events für eine Stadt über den Backend-Proxy.
* @param {string} city - Stadtname für die Suche
* @returns {Promise<Array>} Array von rohen Ticketmaster-Event-Objekten
*/
export async function fetchEvents(city) { export async function fetchEvents(city) {
const url = `http://localhost:3000/api/events?city=${city}`; const url = `http://localhost:3000/api/events?city=${encodeURIComponent(city)}`;
try { try {
const response = await fetch(url); const response = await fetch(url);
if (!response.ok) { if (!response.ok) {
throw new Error("API request failed"); throw new Error(`Backend antwortete mit Status ${response.status}`);
} }
const data = await response.json(); const data = await response.json();
// Ticketmaster gibt Events unter _embedded.events zurück; leeres Array als Fallback
return data._embedded?.events || []; return data._embedded?.events || [];
} catch (error) { } catch (error) {
console.error("Error fetching events:", error); console.error("Fehler beim Laden der Events:", error);
return []; // Fehler nach oben weitergeben, damit app.js ihn dem Nutzer anzeigen kann
throw error;
} }
} }

View File

@ -1,20 +1,38 @@
/**
* auth.js Kommunikation mit dem Backend für Registrierung und Login.
* Nutzt die Fetch-API mit einfachem Header-basiertem Authentifizierungsschema.
*
* Sicherheitshinweis: Passwörter werden unverschlüsselt als HTTP-Header übertragen.
* Dies ist bewusst vereinfacht (kein TLS/HTTPS in der lokalen Entwicklungsumgebung).
* In einer Produktionsumgebung müssten JWT-Tokens oder Sessions eingesetzt werden.
*/
const BASE_URL = "http://localhost:3000/api"; const BASE_URL = "http://localhost:3000/api";
/**
* Registriert einen neuen Benutzer beim Backend.
* Das Backend vergibt ein Standard-Passwort ("1234").
* @param {string} username - Gewünschter Benutzername
* @returns {Promise<Object>} Objekt mit name und password
*/
export async function register(username) { export async function register(username) {
const res = await fetch(`${BASE_URL}/user`, { const res = await fetch(`${BASE_URL}/user`, {
method: "POST", method: "POST",
headers: { headers: { "Content-Type": "application/json" },
"Content-Type": "application/json"
},
body: JSON.stringify({ username }) body: JSON.stringify({ username })
}); });
return res.json(); return res.json();
} }
/**
* Meldet einen Benutzer an.
* Credentials werden als HTTP-Header übermittelt (X-Username, X-Password).
* @param {string} username
* @param {string} password
* @returns {Promise<boolean>} true bei Erfolg (HTTP 200), false bei falschen Credentials
*/
export async function login(username, password) { export async function login(username, password) {
const res = await fetch(`${BASE_URL}/user`, { const res = await fetch(`${BASE_URL}/user`, {
method: "GET", method: "GET",
headers: { headers: {
@ -23,5 +41,6 @@ export async function login(username, password) {
} }
}); });
return res.status === 201; // HTTP 200 = Anmeldung erfolgreich, 401 = ungültige Credentials
return res.status === 200;
} }

View File

@ -1,14 +1,26 @@
/**
* eventService.js Transformiert rohe Ticketmaster-API-Daten in ein vereinfachtes Event-Objekt.
* Kapselt die Datenstruktur der externen API, sodass der Rest der App davon unabhängig bleibt.
*/
import { fetchEvents } from "../api/ticketmaster.js"; import { fetchEvents } from "../api/ticketmaster.js";
/**
* Lädt und transformiert Events für eine gegebene Stadt.
* @param {string} city - Stadtname
* @returns {Promise<Array<{id, name, date, time, venue, category}>>}
*/
export async function getEvents(city) { export async function getEvents(city) {
const events = await fetchEvents(city); const events = await fetchEvents(city);
// Rohe API-Daten auf ein einheitliches, einfaches Format abbilden
return events.map(event => ({ return events.map(event => ({
id: event.id, id: event.id,
name: event.name, name: event.name,
date: event.dates?.start?.localDate || null, date: event.dates?.start?.localDate || null,
time: event.dates?.start?.localTime || null, time: event.dates?.start?.localTime || null,
venue: event._embedded?.venues?.[0]?.name || "Unknown venue", venue: event._embedded?.venues?.[0]?.name || "Unbekannter Ort",
// Kategorie aus dem ersten Klassifizierungs-Segment extrahieren (z.B. "Music", "Sports")
category: event.classifications?.[0]?.segment?.name category: event.classifications?.[0]?.segment?.name
? event.classifications[0].segment.name.toLowerCase() ? event.classifications[0].segment.name.toLowerCase()
: null : null

View File

@ -1,3 +1,12 @@
/**
* filters.js Liest die aktuellen Filterwerte aus den Formularfeldern.
* Gibt ein einheitliches Filter-Objekt zurück, das von app.js ausgewertet wird.
*/
/**
* Liest Stadtname, Datumsbereich und Kategorie aus den Eingabefeldern.
* @returns {{ city: string, dateFrom: string, dateTo: string, category: string }}
*/
export function getFilters() { export function getFilters() {
const city = document.querySelector("#city-input").value.trim(); const city = document.querySelector("#city-input").value.trim();
const dateFrom = document.querySelector("#date-from").value; const dateFrom = document.querySelector("#date-from").value;
@ -5,4 +14,4 @@ export function getFilters() {
const category = document.querySelector("#category-input").value; const category = document.querySelector("#category-input").value;
return { city, dateFrom, dateTo, category }; return { city, dateFrom, dateTo, category };
} }