diff --git a/flightscore/src/app-root.ts b/flightscore/src/app-root.ts
index 7dc042e..741b849 100644
--- a/flightscore/src/app-root.ts
+++ b/flightscore/src/app-root.ts
@@ -1,18 +1,22 @@
import { LitElement, html, css } from 'lit';
-import { customElement } from 'lit/decorators.js';
+import { customElement, state } from 'lit/decorators.js';
import './pages/not-found-page';
import './components/nav-bar';
+import './components/cc/cc-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';
+import './pages/cc/cc-home-page';
@customElement('app-root')
export class AppRoot extends LitElement {
private router!: Router;
+ @state() private isCompetitionCenter = false;
+
static styles = css`
:host {
display: flex;
@@ -41,14 +45,22 @@ export class AppRoot extends LitElement {
{ path: '/competitions', view: () => document.createElement('competition-page') },
{ path: '/login', view: () => document.createElement('login-page') },
{ path: '/register', view: () => document.createElement('register-page') },
+ { path: '/cc/', view: () => document.createElement('cc-home-page') },
]);
+
+ this.router.onRouteChange = (path: string) => {
+ this.isCompetitionCenter = path.startsWith('/cc');
+ };
+
this.router.resolve();
this.addEventListener('nav', (e: any) => this.router.navigate(e.detail.path));
}
render() {
return html`
-
+ ${this.isCompetitionCenter
+ ? html``
+ : html``}
`;
diff --git a/flightscore/src/components/cc/cc-nav-bar.css b/flightscore/src/components/cc/cc-nav-bar.css
new file mode 100644
index 0000000..bc9fb06
--- /dev/null
+++ b/flightscore/src/components/cc/cc-nav-bar.css
@@ -0,0 +1,76 @@
+nav {
+ backdrop-filter: blur(10px);
+ background: var(--color-bg-nav);
+ border-bottom: 1px solid var(--color-border);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0.75rem 1.5rem;
+ position: sticky;
+ top: 0;
+ z-index: 100;
+}
+
+.brand {
+ font-weight: 700;
+ font-size: 1.1rem;
+ user-select: none;
+ width: fit-content;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding-right: 1rem;
+
+}
+
+.brand img {
+ width: auto;
+ height: 2rem;
+ padding-right: 1rem;
+}
+
+.links {
+ display: flex;
+ gap: 1.25rem;
+ align-items: center;
+}
+
+.links a {
+ text-decoration: none;
+}
+
+a {
+ color: var(--color-text);
+ font-weight: 500;
+ position: relative;
+}
+
+a::after {
+ content: '';
+ position: absolute;
+ bottom: -6px;
+ left: 0;
+ width: 0%;
+ height: 2px;
+ background: var(--color-accent);
+ transition: 0.3s ease;
+}
+
+a:hover::after {
+ width: 100%;
+}
+
+button {
+ background: none;
+ border: 1px solid var(--color-border);
+ border-radius: 5px;
+ padding: 0.4rem 0.6rem;
+ color: var(--color-text);
+ cursor: pointer;
+ transition: all 0.3s ease;
+}
+
+button:hover {
+ border-color: var(--color-accent);
+ color: var(--color-accent);
+}
\ No newline at end of file
diff --git a/flightscore/src/components/cc/cc-nav-bar.ts b/flightscore/src/components/cc/cc-nav-bar.ts
new file mode 100644
index 0000000..6b4a0ff
--- /dev/null
+++ b/flightscore/src/components/cc/cc-nav-bar.ts
@@ -0,0 +1,49 @@
+import { LitElement, html, css, unsafeCSS } from 'lit';
+import { customElement, state } from 'lit/decorators.js';
+import styles from './cc-nav-bar.css?inline';
+import '../ui-link';
+
+@customElement('cc-nav-bar')
+export class CCNavBar extends LitElement {
+ static styles = css`${unsafeCSS(styles)}`;
+
+ @state() theme: 'light' | 'dark' =
+ (localStorage.getItem('theme') as 'light' | 'dark') ||
+ (window.matchMedia('(prefers-color-scheme: dark)').matches
+ ? 'dark'
+ : 'light');
+
+ firstUpdated() {
+ document.documentElement.setAttribute('data-theme', this.theme);
+ }
+
+ toggleTheme() {
+ this.theme = this.theme === 'light' ? 'dark' : 'light';
+ document.documentElement.setAttribute('data-theme', this.theme);
+ localStorage.setItem('theme', this.theme);
+ }
+
+ navigate(path: string) {
+ this.dispatchEvent(
+ new CustomEvent('nav', { detail: { path }, bubbles: true, composed: true })
+ );
+ }
+
+ render() {
+ return html`
+
+ `;
+ }
+}
\ No newline at end of file
diff --git a/flightscore/src/components/nav-bar.ts b/flightscore/src/components/nav-bar.ts
index f2426d8..ab4332b 100644
--- a/flightscore/src/components/nav-bar.ts
+++ b/flightscore/src/components/nav-bar.ts
@@ -38,6 +38,7 @@ export class NavBar extends LitElement {
Competitions
Login
+
diff --git a/flightscore/src/pages/auth/login-page.ts b/flightscore/src/pages/auth/login-page.ts
index 643d172..9e9ef01 100644
--- a/flightscore/src/pages/auth/login-page.ts
+++ b/flightscore/src/pages/auth/login-page.ts
@@ -68,7 +68,12 @@ export class LoginPage extends LitElement {
password: this.password,
});
localStorage.setItem('token', res.token);
- window.dispatchEvent(new CustomEvent('auth-changed')); // for later reactive flows
+ window.dispatchEvent(new CustomEvent('auth-changed'));
+ dispatchEvent(new CustomEvent('nav', {
+ detail: { path: "/cc/" },
+ bubbles: true,
+ composed: true,
+ }));
} catch (e: any) {
this.error = e.message || 'Login failed';
} finally {
diff --git a/flightscore/src/pages/cc/cc-home-page.ts b/flightscore/src/pages/cc/cc-home-page.ts
new file mode 100644
index 0000000..e4322ad
--- /dev/null
+++ b/flightscore/src/pages/cc/cc-home-page.ts
@@ -0,0 +1,12 @@
+import { LitElement, html } from 'lit';
+import { customElement } from 'lit/decorators.js';
+
+@customElement('cc-home-page')
+export class CCHomePage extends LitElement {
+ render() {
+ return html`
+
Welcome to the Competition Center Homepage
+ Analyze your tracks visually.
+ `;
+ }
+}
\ No newline at end of file
diff --git a/flightscore/src/pages/competition-page.ts b/flightscore/src/pages/competition-page.ts
index fd84c2d..e48e76a 100644
--- a/flightscore/src/pages/competition-page.ts
+++ b/flightscore/src/pages/competition-page.ts
@@ -6,6 +6,13 @@ export class CompetitionPage extends LitElement {
render() {
return html`
Welcome to the Competitions
+ Welcome to the Competitions
+ Welcome to the Competitions
+ Welcome to the Competitions
+ Welcome to the Competitions
+ Welcome to the Competitions
+ Welcome to the Competitions
+ Welcome to the Competitions
`;
}
}
\ No newline at end of file
diff --git a/flightscore/src/router/router.ts b/flightscore/src/router/router.ts
index 01a6f73..2df6b9a 100644
--- a/flightscore/src/router/router.ts
+++ b/flightscore/src/router/router.ts
@@ -7,6 +7,7 @@ export type Route = {
export class Router {
private routes: Route[];
private outlet: HTMLElement;
+ onRouteChange?: (path: string) => void;
constructor(outlet: HTMLElement, routes: Route[]) {
this.routes = routes;
@@ -26,5 +27,9 @@ export class Router {
this.outlet.append(
match ? match.view() : document.createElement('not-found-page')
);
+
+ if (this.onRouteChange) {
+ this.onRouteChange(path);
+ }
}
}
\ No newline at end of file