diff --git a/flightscore/src/api/api.ts b/flightscore/src/api/api.ts new file mode 100644 index 0000000..a4259ee --- /dev/null +++ b/flightscore/src/api/api.ts @@ -0,0 +1,54 @@ +export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'QUERY'; + +export interface ApiOptions extends RequestInit { + method?: HttpMethod; + body?: any; +} + +/** + * Zentraler API-Wrapper mit typisiertem Rückgabewert und Fehlerhandling. + * Beispiele: + * const tracks = await api('/api/tracks'); + * await api('/api/tracks/1', { method: 'DELETE' }); + */ +export async function api( + path: string, + options: ApiOptions = {} +): Promise { + const config: RequestInit = { + ...options, + headers: { + 'Content-Type': 'application/json', + ...(options.headers || {}), + }, + }; + + if (options.body && typeof options.body !== 'string') { + config.body = JSON.stringify(options.body); + } + + const response = await fetch(path, config); + + if (!response.ok) { + let msg = `HTTP Error ${response.status}`; + try { + const text = await response.text(); + msg += `: ${text}`; + } catch { } + throw new Error(msg); + } + + if (response.status === 204) return undefined as T; + + try { + return (await response.json()) as T; + } catch { + return undefined as T; + } +} + + +export const apiGet = (path: string) => api(path, { method: 'GET' }); +export const apiPost = (path: string, body: any) => api(path, { method: 'POST', body }); +export const apiPut = (path: string, body: any) => api(path, { method: 'PUT', body }); +export const apiDelete = (path: string) => api(path, { method: 'DELETE' }); \ No newline at end of file diff --git a/flightscore/src/app-root.ts b/flightscore/src/app-root.ts index f29a1e3..7dc042e 100644 --- a/flightscore/src/app-root.ts +++ b/flightscore/src/app-root.ts @@ -1,21 +1,46 @@ -import { LitElement, html } from 'lit'; +import { LitElement, html, css } from 'lit'; import { customElement } from 'lit/decorators.js'; import './pages/not-found-page'; import './components/nav-bar'; import './components/footer-bar'; import { Router } from './router/router'; import './pages/home-page'; +import './pages/competition-page'; +import './pages/auth/login-page'; +import './pages/auth/register-page'; @customElement('app-root') export class AppRoot extends LitElement { private router!: Router; + static styles = css` + :host { + display: flex; + flex-direction: column; + min-height: 100vh; + } + nav-bar { + flex: 0 0 auto; + } + + main { + flex: 1 0 auto; + display: flex; + flex-direction: column; + } + + footer-bar { + flex: 0 0 auto; + } +` + firstUpdated() { const outlet = this.shadowRoot?.getElementById('outlet') as HTMLElement; this.router = new Router(outlet, [ { path: '/', view: () => document.createElement('home-page') }, - { path: '/tracks', view: () => document.createElement('tracks-page') }, - { path: '/about', view: () => document.createElement('about-page') }, + { path: '/competitions', view: () => document.createElement('competition-page') }, + { path: '/login', view: () => document.createElement('login-page') }, + { path: '/register', view: () => document.createElement('register-page') }, ]); this.router.resolve(); this.addEventListener('nav', (e: any) => this.router.navigate(e.detail.path)); diff --git a/flightscore/src/components/footer-bar.css b/flightscore/src/components/footer-bar.css index fd4e595..c4bcb25 100644 --- a/flightscore/src/components/footer-bar.css +++ b/flightscore/src/components/footer-bar.css @@ -5,14 +5,12 @@ footer { display: flex; justify-content: space-around; align-items: center; - padding: 0.8rem 1.5rem; + padding: 0.8rem 0; font-size: 0.9rem; - margin-top: 3rem; flex-wrap: wrap; backdrop-filter: blur(10px); - position: fixed; - bottom: 0; - width: 100vw; + position: relative; + width: 100%; } a { diff --git a/flightscore/src/components/nav-bar.css b/flightscore/src/components/nav-bar.css index 228e068..bc9fb06 100644 --- a/flightscore/src/components/nav-bar.css +++ b/flightscore/src/components/nav-bar.css @@ -19,6 +19,8 @@ nav { display: flex; justify-content: center; align-items: center; + padding-right: 1rem; + } .brand img { diff --git a/flightscore/src/components/nav-bar.ts b/flightscore/src/components/nav-bar.ts index e2b6e5d..f2426d8 100644 --- a/flightscore/src/components/nav-bar.ts +++ b/flightscore/src/components/nav-bar.ts @@ -36,6 +36,7 @@ export class NavBar extends LitElement {