From bfdb76cabe474705f9eb4fc0457623f4bc779616 Mon Sep 17 00:00:00 2001
From: itsscb <dev@itsscb.de>
Date: Wed, 5 Mar 2025 22:45:03 +0100
Subject: [PATCH] feat: enhance onboarding process with email handling and
 verification UI

---
 frontend/src/app/model/onboarding.ts          | 11 ++++
 .../notification/notification.component.css   |  4 ++
 .../notification/notification.component.ts    | 29 +++++++++-
 .../registration/registration.component.css   |  3 ++
 .../registration/registration.component.html  |  4 +-
 .../registration/registration.component.ts    | 47 +++++++++++++++-
 .../verification/verification.component.css   | 53 +++++++++++++++++++
 .../verification/verification.component.html  | 20 ++++++-
 .../verification/verification.component.ts    | 20 ++++---
 9 files changed, 178 insertions(+), 13 deletions(-)
 create mode 100644 frontend/src/app/model/onboarding.ts

diff --git a/frontend/src/app/model/onboarding.ts b/frontend/src/app/model/onboarding.ts
new file mode 100644
index 0000000..6433f4d
--- /dev/null
+++ b/frontend/src/app/model/onboarding.ts
@@ -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);
+}
diff --git a/frontend/src/app/page/onboarding/notification/notification.component.css b/frontend/src/app/page/onboarding/notification/notification.component.css
index 30abb2d..f684f54 100644
--- a/frontend/src/app/page/onboarding/notification/notification.component.css
+++ b/frontend/src/app/page/onboarding/notification/notification.component.css
@@ -14,6 +14,10 @@ img {
     padding: 0 1.5rem;
 }
 
+.content > p {
+    font-size: 1.3rem;
+}
+
 .button-container {
     display: flex;
     flex-direction: column;
diff --git a/frontend/src/app/page/onboarding/notification/notification.component.ts b/frontend/src/app/page/onboarding/notification/notification.component.ts
index 1362609..c2b60e3 100644
--- a/frontend/src/app/page/onboarding/notification/notification.component.ts
+++ b/frontend/src/app/page/onboarding/notification/notification.component.ts
@@ -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));
     }
 }
diff --git a/frontend/src/app/page/onboarding/registration/registration.component.css b/frontend/src/app/page/onboarding/registration/registration.component.css
index bfd8167..25e8009 100644
--- a/frontend/src/app/page/onboarding/registration/registration.component.css
+++ b/frontend/src/app/page/onboarding/registration/registration.component.css
@@ -6,6 +6,9 @@
     font-size: 1.5rem;
 }
 
+p {
+    font-size: 1.3rem;
+}
 
 .content {
     display: flex;
diff --git a/frontend/src/app/page/onboarding/registration/registration.component.html b/frontend/src/app/page/onboarding/registration/registration.component.html
index e789d4b..76a282e 100644
--- a/frontend/src/app/page/onboarding/registration/registration.component.html
+++ b/frontend/src/app/page/onboarding/registration/registration.component.html
@@ -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>
\ No newline at end of file
diff --git a/frontend/src/app/page/onboarding/registration/registration.component.ts b/frontend/src/app/page/onboarding/registration/registration.component.ts
index bf083ae..67b4a65 100644
--- a/frontend/src/app/page/onboarding/registration/registration.component.ts
+++ b/frontend/src/app/page/onboarding/registration/registration.component.ts
@@ -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(_ => {
+        });
+    }
 }
diff --git a/frontend/src/app/page/onboarding/verification/verification.component.css b/frontend/src/app/page/onboarding/verification/verification.component.css
index e69de29..2d57efe 100644
--- a/frontend/src/app/page/onboarding/verification/verification.component.css
+++ b/frontend/src/app/page/onboarding/verification/verification.component.css
@@ -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;
+}
\ No newline at end of file
diff --git a/frontend/src/app/page/onboarding/verification/verification.component.html b/frontend/src/app/page/onboarding/verification/verification.component.html
index f396b03..d5e2c32 100644
--- a/frontend/src/app/page/onboarding/verification/verification.component.html
+++ b/frontend/src/app/page/onboarding/verification/verification.component.html
@@ -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>
\ No newline at end of file
diff --git a/frontend/src/app/page/onboarding/verification/verification.component.ts b/frontend/src/app/page/onboarding/verification/verification.component.ts
index 11faa46..59d95b0 100644
--- a/frontend/src/app/page/onboarding/verification/verification.component.ts
+++ b/frontend/src/app/page/onboarding/verification/verification.component.ts
@@ -1,11 +1,19 @@
-import { Component } from '@angular/core';
+import {Component} from '@angular/core';
+import {TextLinkComponent} from "../../../atomic/text-link/text-link.component";
+import {RouterLink} from "@angular/router";
 
 @Component({
-  selector: 'app-verification',
-  imports: [],
-  templateUrl: './verification.component.html',
-  styleUrl: './verification.component.css'
+    selector: 'app-verification',
+    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');
+    }
 }