Added a Login and Register-Page

This commit is contained in:
CodingPhoenixx
2026-02-12 16:31:47 +01:00
parent 7a69e4a4ea
commit 61ebfec1c9
10 changed files with 311 additions and 15 deletions
+97
View File
@@ -0,0 +1,97 @@
import { LitElement, html, css } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { apiPost } from '../../api/api';
import '../../components/ui-link';
@customElement('login-page')
export class LoginPage extends LitElement {
static styles = css`
:host {
flex: 1;
background: linear-gradient(
135deg,
var(--color-accent),
color-mix(in srgb, var(--color-accent) 30%, black)
);
background-size: cover;
background-position: center;
display: flex;
justify-content: center;
align-items: center;
}
.form {
width: 100%;
max-width: 380px;
background: var(--color-bg-nav);
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 2rem;
display: flex;
flex-direction: column;
gap: 1rem;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.25);
}
input {
border: 1px solid var(--color-border);
border-radius: 6px;
padding: 0.6rem;
font-size: 1rem;
background: var(--color-bg);
color: var(--color-text);
}
ui-button {
align-self: flex-end;
}
.error {
color: crimson;
font-size: 0.9rem;
}
`;
@state() email = '';
@state() password = '';
@state() error: string | null = null;
@state() loading = false;
async handleLogin() {
this.error = null;
this.loading = true;
try {
const res = await apiPost<{ token: string }>('/api/auth/login', {
email: this.email,
password: this.password,
});
localStorage.setItem('token', res.token);
window.dispatchEvent(new CustomEvent('auth-changed')); // for later reactive flows
} catch (e: any) {
this.error = e.message || 'Login failed';
} finally {
this.loading = false;
}
}
render() {
return html`
<div class="form">
<h2>Login</h2>
<input type="email" placeholder="Email" .value=${this.email} @input=${(e: any)=> (this.email = e.target.value)}
/>
<input type="password" placeholder="Password" .value=${this.password} @input=${(e: any)=> (this.password =
e.target.value)}
/>
${this.error ? html`<div class="error">${this.error}</div>` : null}
<ui-button ?disabled=${this.loading} @click=${this.handleLogin}>${this.loading ? 'Loading...' : 'Login'}</ui-button>
<p>
No account?
<ui-link href="/register">Register</ui-link>
</p>
</div>
`;
}
}
+115
View File
@@ -0,0 +1,115 @@
import { LitElement, html, css } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { apiPost } from '../../api/api';
@customElement('register-page')
export class RegisterPage extends LitElement {
static styles = css`
:host {
flex: 1;
background: linear-gradient(
135deg,
var(--color-accent),
color-mix(in srgb, var(--color-accent) 30%, black)
);
background-size: cover;
background-position: center;
display: flex;
justify-content: center;
align-items: center;
}
.form {
width: 100%;
max-width: 380px;
background: var(--color-bg-nav);
border: 1px solid var(--color-border);
border-radius: 12px;
padding: 2rem;
display: flex;
flex-direction: column;
gap: 1rem;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.25);
}
input {
border: 1px solid var(--color-border);
border-radius: 6px;
padding: 0.6rem;
font-size: 1rem;
background: var(--color-bg);
color: var(--color-text);
}
.error {
color: crimson;
font-size: 0.9rem;
}
`;
@state() name = '';
@state() email = '';
@state() password = '';
@state() error: string | null = null;
@state() loading = false;
async handleRegister() {
this.error = null;
this.loading = true;
try {
const res = await apiPost<{ id: number; name: string; email: string }>(
'/api/auth/register',
{
name: this.name,
email: this.email,
password: this.password,
}
);
console.log('Registered user:', res);
window.dispatchEvent(
new CustomEvent('nav', {
detail: { path: '/login' },
bubbles: true,
composed: true,
})
);
} catch (e: any) {
this.error = e.message || 'Registration failed';
} finally {
this.loading = false;
}
}
render() {
return html`
<div class="form">
<h2>Register</h2>
<input
placeholder="Full name"
.value=${this.name}
@input=${(e: any) => (this.name = e.target.value)}
/>
<input
type="email"
placeholder="Email"
.value=${this.email}
@input=${(e: any) => (this.email = e.target.value)}
/>
<input
type="password"
placeholder="Password"
.value=${this.password}
@input=${(e: any) => (this.password = e.target.value)}
/>
${this.error ? html`<div class="error">${this.error}</div>` : null}
<ui-button
?disabled=${this.loading}
@click=${this.handleRegister}
>${this.loading ? 'Loading...' : 'Register'}</ui-button
>
</div>
`;
}
}
+11
View File
@@ -0,0 +1,11 @@
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
@customElement('competition-page')
export class CompetitionPage extends LitElement {
render() {
return html`
<h1>Welcome to the Competitions</h1>
`;
}
}