update mail verify screen
This commit is contained in:
parent
0f1efdab5d
commit
67b7ca3922
|
@ -1,20 +1,39 @@
|
|||
<div id="background">
|
||||
<div class="wrapper">
|
||||
<div class="content">
|
||||
@if (verifyStatus() === true) {
|
||||
@if (showRedirectMessage()) {
|
||||
<h1>Es geht gleich los!</h1>
|
||||
<h2>
|
||||
Danke für das bestätigen der E-Mail - Wir leiten dich zum Login
|
||||
weiter!
|
||||
</h2>
|
||||
<div class="bg-primary w-screen h-screen">
|
||||
<div class="modal modal-open">
|
||||
<div
|
||||
[ngStyle]="backgroundStyle"
|
||||
class="modal-box w-11/12 h-2/6 max-w-5xl flex">
|
||||
<div class="w-full flex flex-col justify-center items-center">
|
||||
@if (verifyStatus() === true) {
|
||||
@if (showRedirectMessage()) {
|
||||
<div class="text-center">
|
||||
<h1 class="font-bold text-3xl pt-5">Your email is verified!</h1>
|
||||
<p class="pt-3 pb-6">
|
||||
Your email {{ email() }} has been successfully verified. will
|
||||
<br />
|
||||
You be automatically redirected in to the login page to access
|
||||
the application shortly.
|
||||
</p>
|
||||
<button
|
||||
(click)="navigateToSignup()"
|
||||
class="btn btn-primary no-animation">
|
||||
Go to the App
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
} @else if (verifyStatus() === false) {
|
||||
<div class="text-center">
|
||||
<h1 class="font-bold text-3xl pt-5">
|
||||
Oops, something went wrong! :(
|
||||
</h1>
|
||||
<p class="pt-3">We couldn't verify your email.</p>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="text-center">
|
||||
<span class="loading loading-dots loading-lg"></span>
|
||||
</div>
|
||||
}
|
||||
} @else if (verifyStatus() === false) {
|
||||
<h1>Oops, da ist etwas schief gelaufen!</h1>
|
||||
<h2>Der Link ist nicht mehr gültig</h2>
|
||||
} @else {
|
||||
<h1>Verifizierung wird durchgeführt...</h1>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
#background {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
flex: 1;
|
||||
background-color: lightsalmon;
|
||||
display: flex;
|
||||
|
||||
.content{
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
h1 {
|
||||
font-size: 4rem;
|
||||
margin-left: 3rem;
|
||||
line-height: 1rem;
|
||||
}
|
||||
h2 {
|
||||
margin-left: 3rem;
|
||||
}
|
||||
p {
|
||||
margin-left: 3rem;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
import { CommonModule } from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
InputSignal,
|
||||
OnInit,
|
||||
WritableSignal,
|
||||
|
@ -12,11 +14,12 @@ import { Router } from '@angular/router';
|
|||
import { delay, filter, tap } from 'rxjs';
|
||||
|
||||
import { VerifyApiService } from '../../api';
|
||||
import { BackgroundPatternService } from '../../shared/service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-email-verify-root',
|
||||
standalone: true,
|
||||
imports: [],
|
||||
imports: [CommonModule],
|
||||
providers: [],
|
||||
templateUrl: './email-verify-root.component.html',
|
||||
styleUrl: './email-verify-root.component.scss',
|
||||
|
@ -24,6 +27,8 @@ import { VerifyApiService } from '../../api';
|
|||
})
|
||||
export class EmailVerifyRootComponent implements OnInit {
|
||||
public token: InputSignal<string> = input<string>('');
|
||||
public email: WritableSignal<string> = signal<string>('');
|
||||
public backgroundStyle: { 'background-image': string } | null = null;
|
||||
public verifyStatus: WritableSignal<boolean | null> = signal<boolean | null>(
|
||||
null
|
||||
);
|
||||
|
@ -31,19 +36,56 @@ export class EmailVerifyRootComponent implements OnInit {
|
|||
|
||||
public constructor(
|
||||
private readonly api: VerifyApiService,
|
||||
private readonly router: Router
|
||||
private readonly router: Router,
|
||||
private readonly el: ElementRef,
|
||||
private readonly backgroundPatternService: BackgroundPatternService
|
||||
) {}
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.verifyEmail();
|
||||
this.setBackground();
|
||||
}
|
||||
|
||||
public setBackground(): void {
|
||||
const color = getComputedStyle(this.el.nativeElement).getPropertyValue(
|
||||
'--p'
|
||||
);
|
||||
|
||||
const svgUrl = this.backgroundPatternService.getBubblesPattern(color, 0.1);
|
||||
|
||||
this.backgroundStyle = { 'background-image': `url("${svgUrl}")` };
|
||||
}
|
||||
|
||||
public navigateToSignup(): void {
|
||||
const email: string = this.extractEmail();
|
||||
|
||||
this.router.navigate(['/signup'], {
|
||||
queryParams: { verified: true, email: email },
|
||||
});
|
||||
}
|
||||
|
||||
private extractVerifyToken(): string {
|
||||
const [verifyToken]: string[] = this.token().split('|');
|
||||
|
||||
return verifyToken;
|
||||
}
|
||||
|
||||
private extractEmail(): string {
|
||||
const [, email]: string[] = this.token().split('|');
|
||||
|
||||
return email;
|
||||
}
|
||||
|
||||
private verifyEmail(): void {
|
||||
const [verifyToken, email]: string[] = this.token().split('|');
|
||||
const verifyToken: string = this.extractVerifyToken();
|
||||
const email: string = this.extractEmail();
|
||||
|
||||
this.email.set(decodeURIComponent(atob(email)));
|
||||
|
||||
this.api
|
||||
.verifyControllerVerifyEmail(verifyToken)
|
||||
.pipe(
|
||||
delay(1500),
|
||||
tap((isVerified: boolean) => {
|
||||
this.verifyStatus.set(isVerified);
|
||||
}),
|
||||
|
@ -51,12 +93,10 @@ export class EmailVerifyRootComponent implements OnInit {
|
|||
tap(() => {
|
||||
this.showRedirectMessage.set(true);
|
||||
}),
|
||||
delay(5000)
|
||||
delay(10000)
|
||||
)
|
||||
.subscribe(() => {
|
||||
this.router.navigate(['/signup'], {
|
||||
queryParams: { verified: true, email: email },
|
||||
});
|
||||
this.navigateToSignup();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -281,6 +281,7 @@
|
|||
<input
|
||||
formControlName="email"
|
||||
type="text"
|
||||
class="grow"
|
||||
placeholder="name@example.com" />
|
||||
</label>
|
||||
</div>
|
||||
|
@ -332,31 +333,30 @@
|
|||
<div class="modal modal-open" *ngIf="isDialogOpen()">
|
||||
<div
|
||||
[ngStyle]="backgroundStyle"
|
||||
class="modal-box w-11/12 h-3/6 max-w-5xl flex">
|
||||
class="modal-box w-11/12 h-2/6 max-w-5xl flex">
|
||||
<div class="w-full flex flex-col justify-center items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="2"
|
||||
stroke-width="1"
|
||||
stroke="currentColor"
|
||||
class="size-36">
|
||||
class="size-28 animate-jump animate-once animate-duration-[2000ms] animate-delay-500 animate-ease-in-out animate-normal">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M21.75 9v.906a2.25 2.25 0 0 1-1.183 1.981l-6.478 3.488M2.25 9v.906a2.25 2.25 0 0 0 1.183 1.981l6.478 3.488m8.839 2.51-4.66-2.51m0 0-1.023-.55a2.25 2.25 0 0 0-2.134 0l-1.022.55m0 0-4.661 2.51m16.5 1.615a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V8.844a2.25 2.25 0 0 1 1.183-1.981l7.5-4.039a2.25 2.25 0 0 1 2.134 0l7.5 4.039a2.25 2.25 0 0 1 1.183 1.98V19.5Z" />
|
||||
</svg>
|
||||
|
||||
<h1 class="font-bold text-6xl pt-5">Check your E-Mail</h1>
|
||||
<div class="flex flex-col items-center">
|
||||
<p class="pt-8 text-xl font-semibold">
|
||||
We sent an email link to complete your registration.
|
||||
<h1 class="font-bold text-3xl pt-5">Check your inbox, please!</h1>
|
||||
<div class="flex flex-col items-center text-center">
|
||||
<p class="pt-3">
|
||||
Hey, to start using [APP-NAME], we need to verify your email.
|
||||
</p>
|
||||
|
||||
<p class="text-xs pt-20 pb-2">
|
||||
<a class="cursor-pointer">
|
||||
Didn´t recieve the email? Click here to send it again.
|
||||
</a>
|
||||
<p class="pt-1">
|
||||
We´ve already sent out the verification link. Please check it and
|
||||
<br />
|
||||
confirm it´s really you.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -78,10 +78,6 @@ export class RegisterRootComponent implements OnInit {
|
|||
public form!: FormGroup;
|
||||
public isSigninSignal: WritableSignal<boolean> = signal(false);
|
||||
public isSignupSignal: WritableSignal<boolean> = signal(true);
|
||||
//public isDisplayButtons: WritableSignal<boolean> = signal(true);
|
||||
public emailInvalid: WritableSignal<string | null> = signal(null);
|
||||
public passwordInvalid: WritableSignal<string | null> = signal(null);
|
||||
public termsInvalid: WritableSignal<string | null> = signal(null);
|
||||
public userSignupSuccess: WritableSignal<boolean> = signal(false);
|
||||
public isDialogOpen: WritableSignal<boolean> = signal(false);
|
||||
private removeQueryParams: WritableSignal<boolean> = signal(false);
|
||||
|
@ -100,17 +96,6 @@ export class RegisterRootComponent implements OnInit {
|
|||
private readonly backgroundPatternService: BackgroundPatternService
|
||||
) {
|
||||
effect(() => {
|
||||
if (this.form) {
|
||||
if (this.isSigninSignal()) {
|
||||
this.form.addControl(
|
||||
'terms',
|
||||
new FormControl(false, Validators.requiredTrue)
|
||||
);
|
||||
} else {
|
||||
this.form.removeControl('terms');
|
||||
}
|
||||
}
|
||||
|
||||
if (this.removeQueryParams()) {
|
||||
this.clearRouteParams();
|
||||
}
|
||||
|
@ -134,7 +119,7 @@ export class RegisterRootComponent implements OnInit {
|
|||
'--p'
|
||||
);
|
||||
|
||||
const svgUrl = this.backgroundPatternService.getWigglePattern(color, 0.04);
|
||||
const svgUrl = this.backgroundPatternService.getWigglePattern(color, 0.1);
|
||||
|
||||
this.backgroundStyle = { 'background-image': `url("${svgUrl}")` };
|
||||
}
|
||||
|
@ -160,6 +145,8 @@ export class RegisterRootComponent implements OnInit {
|
|||
}
|
||||
|
||||
public toggleAction(action: AuthAction): void {
|
||||
this.resetFormValidation();
|
||||
|
||||
if (action === 'signin') {
|
||||
this.isSigninSignal.set(true);
|
||||
this.isSignupSignal.set(false);
|
||||
|
@ -167,11 +154,10 @@ export class RegisterRootComponent implements OnInit {
|
|||
this.isSigninSignal.set(false);
|
||||
this.isSignupSignal.set(true);
|
||||
}
|
||||
//this.isDisplayButtons.set(false);
|
||||
}
|
||||
|
||||
public onSubmit(): void {
|
||||
this.markControlsAsTouchedAndDirty(['email', 'password', 'terms']);
|
||||
this.markControlsAsTouchedAndDirty(['email', 'password']);
|
||||
|
||||
if (this.form?.valid) {
|
||||
if (this.isSigninSignal()) {
|
||||
|
@ -182,18 +168,6 @@ export class RegisterRootComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
public switchMask(): void {
|
||||
this.resetFormValidation();
|
||||
|
||||
if (this.isSignupSignal()) {
|
||||
this.isSignupSignal.set(false);
|
||||
this.isSigninSignal.set(true);
|
||||
} else if (this.isSigninSignal()) {
|
||||
this.isSignupSignal.set(true);
|
||||
this.isSigninSignal.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
private initializeForm(): void {
|
||||
this.form = this.formBuilder.group({
|
||||
email: new FormControl('', {
|
||||
|
@ -204,18 +178,14 @@ export class RegisterRootComponent implements OnInit {
|
|||
validators: [Validators.required, customPasswordValidator()],
|
||||
updateOn: 'change',
|
||||
}),
|
||||
terms: new FormControl(false, {
|
||||
validators: [Validators.requiredTrue],
|
||||
updateOn: 'change',
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
private handleRedirect(): void {
|
||||
if (this.verified()) {
|
||||
//this.isDisplayButtons.set(false);
|
||||
this.isSigninSignal.set(false);
|
||||
this.isSignupSignal.set(true);
|
||||
this.isSigninSignal.set(true);
|
||||
this.isSignupSignal.set(false);
|
||||
}
|
||||
if (this.email()) {
|
||||
this.form?.get('email')?.setValue(decodeURIComponent(atob(this.email())));
|
||||
|
@ -223,7 +193,6 @@ export class RegisterRootComponent implements OnInit {
|
|||
|
||||
if (this.login()) {
|
||||
this.isSignupSignal.set(true);
|
||||
//this.isDisplayButtons.set(false);
|
||||
this.isSigninSignal.set(false);
|
||||
}
|
||||
}
|
||||
|
@ -288,7 +257,7 @@ export class RegisterRootComponent implements OnInit {
|
|||
}
|
||||
|
||||
private resetFormValidation(): void {
|
||||
['email', 'password', 'terms'].forEach((controlName: string) => {
|
||||
['email', 'password'].forEach((controlName: string) => {
|
||||
this.resetControlValidation(controlName);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import chroma from 'chroma-js';
|
|||
providedIn: 'root',
|
||||
})
|
||||
export class BackgroundPatternService {
|
||||
public getWigglePattern(color: string, opacity: number = 0.08): string {
|
||||
public getWigglePattern(color: string, opacity: number): string {
|
||||
const colorHex = this.convertOklchStringToHex(color);
|
||||
const encodedHex = encodeURIComponent(colorHex);
|
||||
const pattern = `
|
||||
|
@ -22,6 +22,18 @@ export class BackgroundPatternService {
|
|||
return pattern.replace(/[\n\r]+|[\s]{2,}/g, ' ').trim();
|
||||
}
|
||||
|
||||
public getBubblesPattern(color: string, opacity: number): string {
|
||||
const colorHex = this.convertOklchStringToHex(color);
|
||||
const encodedHex = encodeURIComponent(colorHex);
|
||||
const pattern = `
|
||||
data:image/svg+xml,
|
||||
%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E
|
||||
%3Cpath d='M11 18c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm48 25c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm-43-7c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm63 31c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM34 90c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm56-76c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM12 86c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm28-65c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm23-11c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-6 60c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm29 22c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zM32 63c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm57-13c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-9-21c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM60 91c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM35 41c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM12 60c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2z' fill='${encodedHex}' fill-opacity='${opacity}' fill-rule='evenodd'/%3E
|
||||
%3C/svg%3E`;
|
||||
|
||||
return pattern.replace(/[\n\r]+|[\s]{2,}/g, ' ').trim();
|
||||
}
|
||||
|
||||
private convertOklchStringToHex(oklchString: string): string {
|
||||
const parts = oklchString.split(' ');
|
||||
const l = parseFloat(parts[0]);
|
||||
|
|
Loading…
Reference in New Issue