Feature: Added Login / Register Feature #3
|
@ -1,15 +1,15 @@
|
||||||
<div id="background">
|
<div id="background">
|
||||||
<div class="img-zone">
|
<div class="img-zone">
|
||||||
<div class="img-wrapper">
|
<div class="img-wrapper">
|
||||||
<h1>Hi, Welcome to Ticket App.</h1>
|
<h1 (click)="DEBUG_restSignal()">Hi, Welcome to Ticket App.</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-zone">
|
<div class="content-zone">
|
||||||
<h1>
|
<h1>
|
||||||
@if (this.isSignupSignal()) {
|
@if (this.isSignupSignal()) {
|
||||||
Registrieren
|
|
||||||
} @else if (this.isRegisterSignal()) {
|
|
||||||
Anmelden
|
Anmelden
|
||||||
|
} @else if (this.isRegisterSignal()) {
|
||||||
|
Registrieren
|
||||||
} @else {
|
} @else {
|
||||||
Erste Schritte
|
Erste Schritte
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,45 @@
|
||||||
pButton
|
pButton
|
||||||
type="button"
|
type="button"
|
||||||
label="Anmelden"
|
label="Anmelden"
|
||||||
(click)="toggleAction('register')"></button>
|
(click)="toggleAction('signup')"></button>
|
||||||
<button
|
<button
|
||||||
pButton
|
pButton
|
||||||
type="button"
|
type="button"
|
||||||
label="Registrieren"
|
label="Registrieren"
|
||||||
(click)="toggleAction('signup')"></button>
|
(click)="toggleAction('register')"></button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (this.isSignupSignal()) {
|
||||||
|
<div class="register-wrapper">
|
||||||
|
<form [formGroup]="form" *ngIf="form" (ngSubmit)="onSubmit()">
|
||||||
|
<div class="e-mail">
|
||||||
|
<div class="label">
|
||||||
|
<label for="email">E-Mail</label>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
pInputText
|
||||||
|
id="email"
|
||||||
|
formControlName="email"
|
||||||
|
[ngClass]="{ 'ng-invalid ng-dirty': emailInvalid() }"
|
||||||
|
aria-describedby="e-mail" />
|
||||||
|
</div>
|
||||||
|
<div class="password">
|
||||||
|
<div class="label">
|
||||||
|
<label for="password">Password</label>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
pInputText
|
||||||
|
id="password"
|
||||||
|
formControlName="password"
|
||||||
|
aria-describedby="password"
|
||||||
|
[ngClass]="{ 'ng-invalid ng-dirty': passwordInvalid() }"
|
||||||
|
type="password" />
|
||||||
|
</div>
|
||||||
|
<div class="signup">
|
||||||
|
<button pButton type="submit" label="Anmelden"></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +74,7 @@
|
||||||
pInputText
|
pInputText
|
||||||
id="email"
|
id="email"
|
||||||
formControlName="email"
|
formControlName="email"
|
||||||
|
[ngClass]="{ 'ng-invalid ng-dirty': emailInvalid() }"
|
||||||
aria-describedby="e-mail" />
|
aria-describedby="e-mail" />
|
||||||
</div>
|
</div>
|
||||||
<div class="password">
|
<div class="password">
|
||||||
|
@ -52,10 +86,22 @@
|
||||||
id="password"
|
id="password"
|
||||||
formControlName="password"
|
formControlName="password"
|
||||||
aria-describedby="password"
|
aria-describedby="password"
|
||||||
|
[ngClass]="{ 'ng-invalid ng-dirty': passwordInvalid() }"
|
||||||
type="password" />
|
type="password" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="terms">
|
||||||
|
<p-checkbox
|
||||||
|
formControlName="terms"
|
||||||
|
label="Ich habe die AGB gelesen und stimme zu."
|
||||||
|
name="terms"
|
||||||
|
[ngClass]="{ 'ng-invalid ng-dirty': termsInvalid() }"
|
||||||
|
[binary]="true" />
|
||||||
|
</div>
|
||||||
<div class="signup">
|
<div class="signup">
|
||||||
<button pButton type="submit" label="Anmelden"></button>
|
<button
|
||||||
|
pButton
|
||||||
|
type="submit"
|
||||||
|
label="✨ Jetzt KOSTENFREI registrieren ✨"></button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -53,9 +53,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.e-mail,
|
.e-mail,
|
||||||
.password {
|
.password,
|
||||||
|
.terms {
|
||||||
.label {
|
.label {
|
||||||
font-size: 1.5em;
|
font-size: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
|
@ -63,8 +64,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.terms {
|
||||||
|
padding-top: 1.33em;
|
||||||
|
}
|
||||||
|
|
||||||
.password {
|
.password {
|
||||||
padding-top: 3em;
|
padding-top: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.signup {
|
.signup {
|
||||||
|
@ -76,3 +81,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// .ng-invalid.ng-dirty {
|
||||||
|
// border: 1px solid red;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .error {
|
||||||
|
// color: red;
|
||||||
|
// font-size: 12px;
|
||||||
|
// }
|
||||||
|
|
|
@ -5,16 +5,22 @@ import {
|
||||||
OnInit,
|
OnInit,
|
||||||
WritableSignal,
|
WritableSignal,
|
||||||
signal,
|
signal,
|
||||||
|
effect,
|
||||||
|
DestroyRef,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { InputTextModule } from 'primeng/inputtext';
|
import { InputTextModule } from 'primeng/inputtext';
|
||||||
import {
|
import {
|
||||||
FormBuilder,
|
FormBuilder,
|
||||||
|
FormControl,
|
||||||
FormGroup,
|
FormGroup,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
Validators,
|
Validators,
|
||||||
} from '@angular/forms';
|
} from '@angular/forms';
|
||||||
import { ButtonModule } from 'primeng/button';
|
import { ButtonModule } from 'primeng/button';
|
||||||
|
import { CheckboxModule } from 'primeng/checkbox';
|
||||||
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
|
import { debounceTime } from 'rxjs/operators';
|
||||||
|
|
||||||
type AuthAction = 'register' | 'signup';
|
type AuthAction = 'register' | 'signup';
|
||||||
|
|
||||||
|
@ -27,6 +33,7 @@ type AuthAction = 'register' | 'signup';
|
||||||
InputTextModule,
|
InputTextModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
ButtonModule,
|
ButtonModule,
|
||||||
|
CheckboxModule,
|
||||||
],
|
],
|
||||||
templateUrl: './register-root.component.html',
|
templateUrl: './register-root.component.html',
|
||||||
styleUrl: './register-root.component.scss',
|
styleUrl: './register-root.component.scss',
|
||||||
|
@ -34,27 +41,91 @@ type AuthAction = 'register' | 'signup';
|
||||||
})
|
})
|
||||||
export class RegisterRootComponent implements OnInit {
|
export class RegisterRootComponent implements OnInit {
|
||||||
public form: FormGroup | undefined;
|
public form: FormGroup | undefined;
|
||||||
|
|
||||||
public isRegisterSignal: WritableSignal<boolean> = signal(false);
|
public isRegisterSignal: WritableSignal<boolean> = signal(false);
|
||||||
public isSignupSignal: WritableSignal<boolean> = signal(false);
|
public isSignupSignal: WritableSignal<boolean> = signal(false);
|
||||||
public isDisplayButtons: WritableSignal<boolean> = signal(true);
|
public isDisplayButtons: WritableSignal<boolean> = signal(true);
|
||||||
|
|
||||||
constructor(private readonly formBuilder: FormBuilder) {}
|
public emailInvalid: WritableSignal<boolean | null> = signal(true);
|
||||||
|
public passwordInvalid: WritableSignal<boolean | null> = signal(null);
|
||||||
|
public termsInvalid: WritableSignal<boolean | null> = signal(null);
|
||||||
|
|
||||||
ngOnInit() {
|
constructor(
|
||||||
this.form = this.formBuilder.group({
|
private readonly formBuilder: FormBuilder,
|
||||||
email: ['', [Validators.required, Validators.email]],
|
private readonly destroyRef: DestroyRef
|
||||||
password: ['', [Validators.required, Validators.minLength(6)]],
|
) {
|
||||||
|
effect(() => {
|
||||||
|
if (this.form) {
|
||||||
|
if (this.isRegisterSignal()) {
|
||||||
|
this.form.addControl(
|
||||||
|
'terms',
|
||||||
|
new FormControl(false, Validators.requiredTrue)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.form.removeControl('terms');
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggleAction(action: AuthAction) {
|
public ngOnInit(): void {
|
||||||
const isRegister = action === 'register';
|
this.form = this.formBuilder.group({
|
||||||
this.isRegisterSignal.set(isRegister);
|
email: ['', [Validators.required, Validators.email]],
|
||||||
this.isSignupSignal.set(!isRegister);
|
password: ['', [Validators.required, Validators.minLength(6)]],
|
||||||
|
terms: [false, [Validators.requiredTrue]],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.form.statusChanges
|
||||||
|
.pipe(debounceTime(500), takeUntilDestroyed(this.destroyRef))
|
||||||
|
.subscribe(() => {
|
||||||
|
this.updateFieldInvalidity();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleAction(action: AuthAction): void {
|
||||||
|
if (action === 'register') {
|
||||||
|
this.isRegisterSignal.set(true);
|
||||||
|
this.isSignupSignal.set(false);
|
||||||
|
} else {
|
||||||
|
this.isRegisterSignal.set(false);
|
||||||
|
this.isSignupSignal.set(true);
|
||||||
|
}
|
||||||
this.isDisplayButtons.set(false);
|
this.isDisplayButtons.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onSubmit() {
|
public onSubmit(): void {
|
||||||
console.log('signup');
|
this.form?.markAllAsTouched();
|
||||||
|
this.updateFieldInvalidity();
|
||||||
|
|
||||||
|
if (this.isSignupSignal() && this.form?.valid) {
|
||||||
|
this.signin();
|
||||||
|
} else if (this.isRegisterSignal() && this.form?.valid) {
|
||||||
|
this.register();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DEBUG_restSignal(): void {
|
||||||
|
this.isRegisterSignal.set(false);
|
||||||
|
this.isSignupSignal.set(false);
|
||||||
|
this.isDisplayButtons.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateFieldInvalidity(): void {
|
||||||
|
this.emailInvalid.set(this.isFieldInvalid('email'));
|
||||||
|
this.passwordInvalid.set(this.isFieldInvalid('password'));
|
||||||
|
this.termsInvalid.set(this.isFieldInvalid('terms'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private isFieldInvalid(field: string): boolean {
|
||||||
|
const formField = this.form?.get(field);
|
||||||
|
return !!formField && !formField.valid && formField.touched;
|
||||||
|
}
|
||||||
|
|
||||||
|
private signin(): void {
|
||||||
|
console.log('Signin...');
|
||||||
|
}
|
||||||
|
|
||||||
|
private register(): void {
|
||||||
|
console.log('Register...');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
@import 'primeng/resources/themes/lara-light-blue/theme.css';
|
@import 'primeng/resources/themes/lara-light-blue/theme.css';
|
||||||
@import 'primeng/resources/primeng.css';
|
@import 'primeng/resources/primeng.css';
|
||||||
|
|
||||||
|
// PrimeNG icons
|
||||||
|
@import 'primeicons/primeicons.css';
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
Loading…
Reference in New Issue