feature/init-tailwind-daisyui #13

Merged
igorpropisnov merged 10 commits from feature/init-tailwind-daisyui into main 2024-06-26 19:22:33 +02:00
6 changed files with 114 additions and 102 deletions
Showing only changes of commit 67b7ca3922 - Show all commits

View File

@ -1,20 +1,39 @@
<div id="background">
<div class="wrapper">
<div class="content">
<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()) {
<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="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) {
<h1>Oops, da ist etwas schief gelaufen!</h1>
<h2>Der Link ist nicht mehr gültig</h2>
<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 {
<h1>Verifizierung wird durchgeführt...</h1>
<div class="text-center">
<span class="loading loading-dots loading-lg"></span>
</div>
}
</div>
</div>
</div>
</div>

View File

@ -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;
}
}
}

View File

@ -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();
});
}
}

View File

@ -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>

View File

@ -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);
});
}

View File

@ -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]);