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
4 changed files with 197 additions and 141 deletions
Showing only changes of commit aca4e4b84a - Show all commits

View File

@ -14,7 +14,7 @@ import { Router } from '@angular/router';
import { delay, filter, tap } from 'rxjs';
import { VerifyApiService } from '../../api';
import { BackgroundPatternService } from '../../shared/service';
import { BackgroundPatternService, ThemeService } from '../../shared/service';
@Component({
selector: 'app-email-verify-root',
@ -38,7 +38,8 @@ export class EmailVerifyRootComponent implements OnInit {
private readonly api: VerifyApiService,
private readonly router: Router,
private readonly el: ElementRef,
private readonly backgroundPatternService: BackgroundPatternService
private readonly backgroundPatternService: BackgroundPatternService,
private readonly themeService: ThemeService
) {}
public ngOnInit(): void {
@ -47,11 +48,23 @@ export class EmailVerifyRootComponent implements OnInit {
}
public setBackground(): void {
const color = getComputedStyle(this.el.nativeElement).getPropertyValue(
'--p'
);
const theme = this.themeService.getTheme();
let opacity: number;
const svgUrl = this.backgroundPatternService.getBubblesPattern(color, 0.1);
if (theme === 'dark') {
opacity = 0.05;
} else {
opacity = 0.1;
}
const colorPrimary = getComputedStyle(
this.el.nativeElement
).getPropertyValue('--p');
const svgUrl = this.backgroundPatternService.getWigglePattern(
colorPrimary,
opacity
);
this.backgroundStyle = { 'background-image': `url("${svgUrl}")` };
}
@ -80,7 +93,9 @@ export class EmailVerifyRootComponent implements OnInit {
const verifyToken: string = this.extractVerifyToken();
const email: string = this.extractEmail();
if (verifyToken && email) {
this.email.set(decodeURIComponent(atob(email)));
}
this.api
.verifyControllerVerifyEmail(verifyToken)

View File

@ -1,117 +1,8 @@
<!-- <div id="background">
<div class="img-zone">
<div class="img-wrapper">
@if (userSignupSuccess()) {
<div class="success">
<h1>Danke für deine Registrierung!</h1>
<h2>
Wir haben dir eine Mail geschickt an
{{ form?.get('email')?.value }}. Bitte bestätige deine
E-Mail-Adresse um fortzufahren.
</h2>
<p>Du kannst diesen Tab nun schließen</p>
</div>
} @else {
<div class="headline">
<h1>Hi, Welcome to Ticket App.</h1>
</div>
}
</div>
</div>
@if (!userSignupSuccess()) {
<div class="content-zone">
<h1>
@if (isSignupSignal()) {
Anmelden
} @else if (isRegisterSignal()) {
Registrieren
} @else {
Erste Schritte
}
</h1>
@if (isDisplayButtons()) {
<div class="action">
<button
pButton
type="button"
label="Anmelden"
(click)="toggleAction('signup')"></button>
<button
pButton
type="button"
label="Registrieren"
(click)="toggleAction('register')"></button>
</div>
}
@if (isSignupSignal() || isRegisterSignal()) {
<div class="register-wrapper">
@if (form) {
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<div class="e-mail">
<div class="label">
<label for="email">E-Mail</label>
</div>
<input
pInputText
id="email"
formControlName="email"
aria-describedby="e-mail" />
</div>
<div class="password">
<div class="label">
<label for="password">Password</label>
</div>
<p-password
class="custom-p-password"
id="password"
formControlName="password"
aria-describedby="password"
[toggleMask]="true"></p-password>
</div>
@if (isRegisterSignal()) {
<div class="terms">
<p-checkbox
formControlName="terms"
label="Ich habe die AGB gelesen und stimme zu."
name="terms"
[binary]="true"></p-checkbox>
</div>
}
<div class="signup">
<button
pButton
type="submit"
[label]="
isSignupSignal()
? 'Anmelden'
: '✨ Jetzt KOSTENFREI loslegen ✨'
"></button>
</div>
<div class="change-mask">
<a
(click)="switchMask()"
(keyup.enter)="switchMask()"
tabindex="0">
@if (isSignupSignal()) {
Kein Account? Erstellen Sie jetzt KOSTENFREI einen!
} @else {
Schon einen Account? Hier einloggen
}
</a>
</div>
</form>
}
</div>
}
</div>
}
</div> -->
@if (!userSignupSuccess()) {
<div class="flex h-screen w-screen">
<div class="hidden md:flex md:flex-col md:w-1/2 bg-primary">
<div
[ngStyle]="leftBackgroundStyle"
class="hidden md:flex md:flex-col md:w-1/2 bg-primary">
<div class="flex-1 flex items-start pt-16 px-12">
<h1 class="text-3xl text-base-100">[LOGO] APP-NAME</h1>
</div>
@ -129,7 +20,7 @@
</div>
<!-- Rechter Bereich, immer sichtbar -->
<div class="flex flex-col w-full md:w-1/2">
<div [ngStyle]="rightBackgroundStyle" class="flex flex-col w-full md:w-1/2">
<div class="flex px-12 gap-3">
<div class="flex items-start justify-end pt-16">
<label class="swap swap-rotate">
@ -242,7 +133,7 @@
@if (isLoading()) {
<span class="loading loading-spinner"></span>
}
Sign In with Email
Sign Up with Email
</button>
<p class="text-xs w-full text-center">
By clicking continue, you agree to our
@ -319,6 +210,7 @@
<div class="flex items-center justify-between">
<label class="label cursor-pointer">
<input
[formControl]="rememberMe"
type="checkbox"
checked="checked"
class="checkbox checkbox-md checkbox-primary" />
@ -362,7 +254,7 @@
}
<div class="modal modal-open" *ngIf="isDialogOpen()">
<div
[ngStyle]="backgroundStyle"
[ngStyle]="dialogBackgroundStyle"
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

View File

@ -37,9 +37,9 @@ import { ApiConfiguration } from '../../config/api-configuration';
import {
AuthService,
BackgroundPatternService,
SessionStorageService,
ThemeService,
} from '../../shared/service';
import { LocalStorageService } from '../../shared/service/local-storage.service';
import {
customEmailValidator,
customPasswordValidator,
@ -72,11 +72,14 @@ type AuthAction = 'signin' | 'signup';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RegisterRootComponent implements OnInit {
public backgroundStyle: { 'background-image': string } | null = null;
public dialogBackgroundStyle: { 'background-image': string } | null = null;
public leftBackgroundStyle: { 'background-image': string } | null = null;
public rightBackgroundStyle: { 'background-image': string } | null = null;
public verified: InputSignal<boolean> = input<boolean>(false);
public login: InputSignal<boolean> = input<boolean>(false);
public email: InputSignal<string> = input<string>('');
public form!: FormGroup;
public rememberMe: FormControl = new FormControl(false);
public isSigninSignal: WritableSignal<boolean> = signal(false);
public isSignupSignal: WritableSignal<boolean> = signal(true);
public userSignupSuccess: WritableSignal<boolean> = signal(false);
@ -92,10 +95,10 @@ export class RegisterRootComponent implements OnInit {
private readonly formBuilder: FormBuilder,
private readonly authService: AuthService,
private readonly router: Router,
private readonly sessionStorageService: SessionStorageService,
private readonly themeService: ThemeService,
private readonly el: ElementRef,
private readonly backgroundPatternService: BackgroundPatternService
private readonly backgroundPatternService: BackgroundPatternService,
private readonly localStorageService: LocalStorageService
) {
effect(() => {
if (this.removeQueryParams()) {
@ -108,7 +111,6 @@ export class RegisterRootComponent implements OnInit {
this.setBackground();
this.initializeForm();
this.setupValueChanges();
this.preselectForm();
if ((this.email() && this.verified()) || this.login()) {
this.handleRedirect();
@ -117,13 +119,45 @@ export class RegisterRootComponent implements OnInit {
}
public setBackground(): void {
const color = getComputedStyle(this.el.nativeElement).getPropertyValue(
'--p'
const theme = this.themeService.getTheme();
let opacity: number;
if (theme === 'dark') {
opacity = 0.05;
} else {
opacity = 0.1;
}
const colorPrimary = getComputedStyle(
this.el.nativeElement
).getPropertyValue('--p');
const colorPrimaryC = getComputedStyle(
this.el.nativeElement
).getPropertyValue('--pc');
const svgUrlforDialog = this.backgroundPatternService.getWigglePattern(
colorPrimary,
opacity
);
const svgUrlForLeft = this.backgroundPatternService.getBankNotePattern(
colorPrimaryC,
opacity
);
const svgUrlForRight = this.backgroundPatternService.getHideoutPattern(
colorPrimary,
opacity
);
const svgUrl = this.backgroundPatternService.getWigglePattern(color, 0.1);
this.backgroundStyle = { 'background-image': `url("${svgUrl}")` };
this.dialogBackgroundStyle = {
'background-image': `url("${svgUrlforDialog}")`,
};
this.leftBackgroundStyle = {
'background-image': `url("${svgUrlForLeft}")`,
};
this.rightBackgroundStyle = {
'background-image': `url("${svgUrlForRight}")`,
};
}
public openModal(): void {
@ -136,20 +170,14 @@ export class RegisterRootComponent implements OnInit {
public toggleTheme(): void {
this.themeService.toggleTheme();
}
public preselectForm(): void {
if (!this.email() || !this.verified()) {
const email = this.sessionStorageService.getItem('email');
this.form?.get('email')?.setValue(email);
}
this.setBackground();
}
public toggleAction(action: AuthAction): void {
this.resetFormValidation();
if (action === 'signin') {
this.handlePreselect();
this.isSigninSignal.set(true);
this.isSignupSignal.set(false);
} else {
@ -170,9 +198,35 @@ export class RegisterRootComponent implements OnInit {
}
}
private handlePreselect(): void {
const rememberMe = this.localStorageService.getItem('remember-me');
const email = this.localStorageService.getItem('email');
if (rememberMe) {
this.isSigninSignal.set(true);
this.isSignupSignal.set(false);
}
if (email) {
this.form?.get('email')?.setValue(email);
}
this.rememberMe.setValue(rememberMe);
}
private initializeForm(): void {
const rememberMeValue = this.localStorageService.getItem('remember-me');
const email = this.localStorageService.getItem('email');
if (rememberMeValue) {
this.isSigninSignal.set(true);
this.isSignupSignal.set(false);
}
const emailValue = rememberMeValue && email ? email : '';
this.form = this.formBuilder.group({
email: new FormControl('', {
email: new FormControl(emailValue, {
validators: [Validators.required, customEmailValidator()],
updateOn: 'change',
}),
@ -181,6 +235,8 @@ export class RegisterRootComponent implements OnInit {
updateOn: 'change',
}),
});
this.rememberMe.setValue(rememberMeValue);
}
private handleRedirect(): void {
@ -275,6 +331,13 @@ export class RegisterRootComponent implements OnInit {
}
private signin(logiCredentials: UserCredentialsDtoApiModel): void {
const rememberMe = this.rememberMe.value;
if (rememberMe) {
this.localStorageService.setItem('email', logiCredentials.email);
this.localStorageService.setItem('remember-me', rememberMe);
}
this.authService
.signin(logiCredentials)
.pipe(

View File

@ -22,6 +22,19 @@ export class BackgroundPatternService {
return pattern.replace(/[\n\r]+|[\s]{2,}/g, ' ').trim();
}
public getTexturePattern(color: string, opacity: number): string {
const colorHex = this.convertOklchStringToHex(color);
const encodedHex = encodeURIComponent(colorHex);
const pattern = `
data:image/svg+xml,
%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3E
%3Cpath fill='${encodedHex}' fill-opacity='${opacity}' d='M1 3h1v1H1V3zm2-2h1v1H3V1z'%3E
%3C/path%3E
%3C/svg%3E`;
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);
@ -34,6 +47,79 @@ export class BackgroundPatternService {
return pattern.replace(/[\n\r]+|[\s]{2,}/g, ' ').trim();
}
public getBankNotePattern(color: string, opacity: number): string {
const colorHex = this.convertOklchStringToHex(color);
const encodedHex = encodeURIComponent(colorHex);
const pattern = `
data:image/svg+xml,
%3Csvg width='100' height='20' viewBox='0 0 100 20' xmlns='http://www.w3.org/2000/svg'%3E
%3Cpath d='M21.184 20c.357-.13.72-.264 1.088-.402l1.768-.661C33.64 15.347 39.647 14 50 14c10.271 0 15.362 1.222 24.629 4.928.955.383 1.869.74 2.75 1.072h6.225c-2.51-.73-5.139-1.691-8.233-2.928C65.888 13.278 60.562 12 50 12c-10.626 0-16.855 1.397-26.66 5.063l-1.767.662c-2.475.923-4.66 1.674-6.724 2.275h6.335zm0-20C13.258 2.892 8.077 4 0 4V2c5.744 0 9.951-.574 14.85-2h6.334zM77.38 0C85.239 2.966 90.502 4 100 4V2c-6.842 0-11.386-.542-16.396-2h-6.225zM0 14c8.44 0 13.718-1.21 22.272-4.402l1.768-.661C33.64 5.347 39.647 4 50 4c10.271 0 15.362 1.222 24.629 4.928C84.112 12.722 89.438 14 100 14v-2c-10.271 0-15.362-1.222-24.629-4.928C65.888 3.278 60.562 2 50 2 39.374 2 33.145 3.397 23.34 7.063l-1.767.662C13.223 10.84 8.163 12 0 12v2z' fill='${encodedHex}' fill-opacity='${opacity}' fill-rule='evenodd'/%3E
%3C/svg%3E`;
return pattern.replace(/[\n\r]+|[\s]{2,}/g, ' ').trim();
}
public getHideoutPattern(color: string, opacity: number): string {
const colorHex = this.convertOklchStringToHex(color);
const encodedHex = encodeURIComponent(colorHex);
const pattern = `
data:image/svg+xml,
%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E
%3Cg fill-rule='evenodd'%3E
%3Cg fill='${encodedHex}' fill-opacity='${opacity}'%3E
%3Cpath d='M0 38.59l2.83-2.83 1.41 1.41L1.41 40H0v-1.41zM0 1.4l2.83 2.83 1.41-1.41L1.41 0H0v1.41zM38.59 40l-2.83-2.83 1.41-1.41L40 38.59V40h-1.41zM40 1.41l-2.83 2.83-1.41-1.41L38.59 0H40v1.41zM20 18.6l2.83-2.83 1.41 1.41L21.41 20l2.83 2.83-1.41 1.41L20 21.41l-2.83 2.83-1.41-1.41L18.59 20l-2.83-2.83 1.41-1.41L20 18.59z'/%3E
%3C/g%3E
%3C/g%3E
%3C/svg%3E`;
return pattern.replace(/[\n\r]+|[\s]{2,}/g, ' ').trim();
}
public getFourPointsStarsPattern(color: string, opacity: number): string {
const colorHex = this.convertOklchStringToHex(color);
const encodedHex = encodeURIComponent(colorHex);
const pattern = `
data:image/svg+xml,
%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E
%3Cg fill='${encodedHex}' fill-opacity='${opacity}'%3E
%3Cpolygon fill-rule='evenodd' points='8 4 12 6 8 8 6 12 4 8 0 6 4 4 6 0 8 4'/%3E
%3C/g%3E
%3C/svg%3E`;
return pattern.replace(/[\n\r]+|[\s]{2,}/g, ' ').trim();
}
public getPlusPattern(color: string, opacity: number): string {
const colorHex = this.convertOklchStringToHex(color);
const encodedHex = encodeURIComponent(colorHex);
const pattern = `
data:image/svg+xml,
%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E
%3Cg fill='none' fill-rule='evenodd'%3E
%3Cg fill='${encodedHex}' fill-opacity='${opacity}'%3E
%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E
%3C/g%3E
%3C/g%3E
%3C/svg%3E`;
return pattern.replace(/[\n\r]+|[\s]{2,}/g, ' ').trim();
}
public getPolkaDotsPattern(color: string, opacity: number = 0.4): string {
const colorHex = this.convertOklchStringToHex(color);
const encodedHex = encodeURIComponent(colorHex);
const pattern = `
data:image/svg+xml,
%3Csvg width='20' height='20' viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg'%3E
%3Cg fill='${encodedHex}' fill-opacity='${opacity}' fill-rule='evenodd'%3E
%3Ccircle cx='3' cy='3' r='3'/%3E
%3Ccircle cx='13' cy='13' r='3'/%3E
%3C/g%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]);