feat: enhance onboarding process with email handling and verification UI

This commit is contained in:
itsscb 2025-03-05 22:45:03 +01:00
parent aacbad3357
commit bfdb76cabe
9 changed files with 178 additions and 13 deletions

View File

@ -0,0 +1,11 @@
import {verify_email} from "./util";
export interface Onboarding {
notifications: boolean;
mail: string;
verified: boolean;
}
export function verify_onboarding(state: Onboarding): boolean {
return state.verified && verify_email(state.mail);
}

View File

@ -14,6 +14,10 @@ img {
padding: 0 1.5rem;
}
.content > p {
font-size: 1.3rem;
}
.button-container {
display: flex;
flex-direction: column;

View File

@ -2,6 +2,7 @@ import {Component} from '@angular/core';
import {RouterLink} from "@angular/router";
import {TextButtonComponent} from "../../../atomic/text-button/text-button.component";
import {TextLinkComponent} from "../../../atomic/text-link/text-link.component";
import {Onboarding} from "../../../model/onboarding";
@Component({
selector: 'app-notification',
@ -15,10 +16,34 @@ import {TextLinkComponent} from "../../../atomic/text-link/text-link.component";
})
export class NotificationComponent {
enable_notifications() {
localStorage.setItem('get_notifications', 'true');
let onboarding_raw = localStorage.getItem('onboarding');
let onboarding: Onboarding;
if (!onboarding_raw) {
onboarding = {
notifications: true,
mail: '',
verified: false
};
} else {
onboarding = JSON.parse(onboarding_raw);
onboarding.notifications = true;
}
localStorage.setItem('onboarding', JSON.stringify(onboarding));
}
disable_notifications() {
localStorage.setItem('get_notifications', 'false');
let onboarding_raw = localStorage.getItem('onboarding');
let onboarding: Onboarding;
if (!onboarding_raw) {
onboarding = {
notifications: false,
mail: '',
verified: false
};
} else {
onboarding = JSON.parse(onboarding_raw);
onboarding.notifications = false;
}
localStorage.setItem('onboarding', JSON.stringify(onboarding));
}
}

View File

@ -6,6 +6,9 @@
font-size: 1.5rem;
}
p {
font-size: 1.3rem;
}
.content {
display: flex;

View File

@ -9,8 +9,8 @@
<atomic-email-field [(value)]="mail"></atomic-email-field>
</div>
<div class="button-container">
<atomic-text-button [text]="'Weiter'"
[routerLink]="'/onboarding/verification'"></atomic-text-button>
<atomic-text-button (click)="set_mail()" [disabled]="!verify_mail()" [text]="'Weiter'">
</atomic-text-button>
<atomic-text-link [text]="'Stattdessen&nbsp;anmelden'" [routerLink]="'/login'"></atomic-text-link>
</div>
</div>

View File

@ -1,8 +1,10 @@
import {Component} from '@angular/core';
import {EmailFieldComponent} from "../../../atomic/input/email-field/email-field.component";
import {TextLinkComponent} from "../../../atomic/text-link/text-link.component";
import {RouterLink} from "@angular/router";
import {Router, RouterLink} from "@angular/router";
import {TextButtonComponent} from "../../../atomic/text-button/text-button.component";
import {Onboarding} from "../../../model/onboarding";
import {verify_email} from "../../../model/util";
@Component({
selector: 'app-registration',
@ -16,5 +18,46 @@ import {TextButtonComponent} from "../../../atomic/text-button/text-button.compo
styleUrl: './registration.component.css'
})
export class RegistrationComponent {
mail?: string;
mail: string = '';
constructor(private router: Router) {
}
ngOnInit() {
let onboarding_raw = localStorage.getItem('onboarding');
if (onboarding_raw) {
let onboarding: Onboarding = JSON.parse(onboarding_raw);
this.mail = onboarding.mail;
}
}
verify_mail() {
return verify_email(this.mail);
}
set_mail() {
if (!this.mail || !this.verify_mail()) {
return;
}
let onboarding_raw = localStorage.getItem('onboarding');
let onboarding: Onboarding;
if (!onboarding_raw) {
onboarding = {
notifications: false,
mail: this.mail,
verified: false
};
} else {
onboarding = JSON.parse(onboarding_raw);
if (onboarding.mail === this.mail) {
this.router.navigateByUrl('/onboarding/verification').then(_ => {
});
return;
}
onboarding.mail = this.mail;
}
localStorage.setItem('onboarding', JSON.stringify(onboarding));
this.router.navigateByUrl('/onboarding/verification').then(_ => {
});
}
}

View File

@ -0,0 +1,53 @@
.back-button-container {
margin-bottom: 2rem;
display: flex;
justify-content: flex-start;
width: 100%;
font-size: 1.5rem;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
justify-content: center;
justify-items: center;
height: 85vh;
row-gap: 1rem;
}
.form-container {
width: 100%;
max-width: 25rem;
text-align: start;
font-size: 1.3rem;
margin-left: 2rem;
}
.form-container > p {
line-height: 0.8rem;
}
.form-container > p:nth-last-child(2) {
margin-top: 3rem;
font-weight: bold;
font-size: 1.5rem;
}
.button-container {
display: flex;
flex-wrap: wrap;
column-gap: 1.3rem;
width: 100%;
max-width: 25rem;
}
atomic-text-button {
width: 100%;
}
.button-container > atomic-text-link {
font-size: 1.3rem;
}

View File

@ -1 +1,19 @@
<p>verification works!</p>
<div class="back-button-container">
<atomic-text-link [routerLink]="'/onboarding/registration'" [text]="'< Zurück'"
id="back-button"></atomic-text-link>
</div>
<div class="content">
<h1>Verifizieren</h1>
<div class="form-container">
<p>Wir haben dir eine E-Mail geschickt.</p>
<p>Bitte verifiziere deine E-Mail Adresse.</p>
<p>Dann geht es hier
<i>automatisch</i>
weiter.
</p>
<div class="button-container">
<p>Noch keine E-Mail erhalten? Auch im Spam Ordner nicht?</p>
<atomic-text-link (click)="tbd()" [text]="'Erneut&nbsp;senden'"></atomic-text-link>
</div>
</div>
</div>

View File

@ -1,11 +1,19 @@
import {Component} from '@angular/core';
import {TextLinkComponent} from "../../../atomic/text-link/text-link.component";
import {RouterLink} from "@angular/router";
@Component({
selector: 'app-verification',
imports: [],
imports: [
TextLinkComponent,
RouterLink
],
templateUrl: './verification.component.html',
styleUrl: './verification.component.css'
})
export class VerificationComponent {
// TODO: Implement the E-Mail verification re-send logic
tbd() {
alert('E-Mail sent message - TBD');
}
}