diff --git a/frontend/package.json b/frontend/package.json
index 773b7d7..c4c71fe 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -29,6 +29,7 @@
"@angular/platform-browser-dynamic": "^17.3.0",
"@angular/router": "^17.3.0",
"@types/dompurify": "^3.0.5",
+ "chroma-js": "^2.4.2",
"crypto-js": "^4.2.0",
"dompurify": "^3.1.3",
"primeicons": "^7.0.0",
@@ -46,6 +47,7 @@
"@angular-eslint/template-parser": "17.2.1",
"@angular/cli": "^17.3.0",
"@angular/compiler-cli": "^17.3.0",
+ "@types/chroma-js": "^2.4.4",
"@types/crypto-js": "^4.2.2",
"@types/jest": "^29.5.12",
"@typescript-eslint/eslint-plugin": "6.19.0",
@@ -64,6 +66,7 @@
"postcss": "^8.4.38",
"prettier": "3.2.5",
"tailwindcss": "^3.4.4",
+ "tailwindcss-animated": "^1.1.2",
"typescript": "~5.4.2",
"wait-on": "^7.2.0"
},
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index e92a955..0c54529 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -32,6 +32,9 @@ dependencies:
'@types/dompurify':
specifier: ^3.0.5
version: 3.0.5
+ chroma-js:
+ specifier: ^2.4.2
+ version: 2.4.2
crypto-js:
specifier: ^4.2.0
version: 4.2.0
@@ -79,6 +82,9 @@ devDependencies:
'@angular/compiler-cli':
specifier: ^17.3.0
version: 17.3.0(@angular/compiler@17.3.0)(typescript@5.4.2)
+ '@types/chroma-js':
+ specifier: ^2.4.4
+ version: 2.4.4
'@types/crypto-js':
specifier: ^4.2.2
version: 4.2.2
@@ -133,6 +139,9 @@ devDependencies:
tailwindcss:
specifier: ^3.4.4
version: 3.4.4
+ tailwindcss-animated:
+ specifier: ^1.1.2
+ version: 1.1.2(tailwindcss@3.4.4)
typescript:
specifier: ~5.4.2
version: 5.4.2
@@ -3155,6 +3164,10 @@ packages:
'@types/node': 20.11.27
dev: true
+ /@types/chroma-js@2.4.4:
+ resolution: {integrity: sha512-/DTccpHTaKomqussrn+ciEvfW4k6NAHzNzs/sts1TCqg333qNxOhy8TNIoQCmbGG3Tl8KdEhkGAssb1n3mTXiQ==}
+ dev: true
+
/@types/connect-history-api-fallback@1.5.4:
resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==}
dependencies:
@@ -4352,6 +4365,10 @@ packages:
engines: {node: '>=10'}
dev: true
+ /chroma-js@2.4.2:
+ resolution: {integrity: sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A==}
+ dev: false
+
/chrome-trace-event@1.0.3:
resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==}
engines: {node: '>=6.0'}
@@ -9543,6 +9560,14 @@ packages:
tslib: 2.6.2
dev: true
+ /tailwindcss-animated@1.1.2(tailwindcss@3.4.4):
+ resolution: {integrity: sha512-SI4owS5ojserhgEYIZA/uFVdNjU2GMB2P3sjtjmFA52VxoUi+Hht6oR5+RdT+CxrX9cNNYEa+vbTWHvN9zbj3w==}
+ peerDependencies:
+ tailwindcss: '>=3.1.0'
+ dependencies:
+ tailwindcss: 3.4.4
+ dev: true
+
/tailwindcss@3.4.4:
resolution: {integrity: sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==}
engines: {node: '>=14.0.0'}
diff --git a/frontend/src/app/pages/register-root/register-root.component.html b/frontend/src/app/pages/register-root/register-root.component.html
index 1915a6a..e2695f8 100644
--- a/frontend/src/app/pages/register-root/register-root.component.html
+++ b/frontend/src/app/pages/register-root/register-root.component.html
@@ -108,89 +108,257 @@
}
-->
-
-
-
-
[LOGO] APP-NAME
+
+@if (!userSignupSuccess()) {
+
+
+
+
[LOGO] APP-NAME
+
+
+
+
+ “This library has saved me countless hours of work and helped me
+ deliver stunning designs to my clients faster than ever before.”
+
+
+ — Sofia Davis
+
+
+
-
-
-
- “This library has saved me countless hours of work and helped me
- deliver stunning designs to my clients faster than ever before.”
-
-
- — Sofia Davis
-
-
+
+
+
+
+
+
+ @if (isSignupSignal()) {
+
+ }
+ @if (isSigninSignal()) {
+
+ }
+
+
+ @if (isSignupSignal()) {
+
+
Create an Account
+
+ Enter your email below to create your Account
+
+
+
+ }
+ @if (isSigninSignal()) {
+
+ }
+
+
+
+} @else {
+
+}
+
+
+
+
-
-
-
-
-
-
Create an Account
-
Enter your email below to create your Account
-
diff --git a/frontend/src/app/pages/register-root/register-root.component.ts b/frontend/src/app/pages/register-root/register-root.component.ts
index 7569c2b..653ffb1 100644
--- a/frontend/src/app/pages/register-root/register-root.component.ts
+++ b/frontend/src/app/pages/register-root/register-root.component.ts
@@ -9,6 +9,7 @@ import {
effect,
InputSignal,
input,
+ ElementRef,
} from '@angular/core';
import {
FormBuilder,
@@ -34,6 +35,7 @@ import {
import { ApiConfiguration } from '../../config/api-configuration';
import {
AuthService,
+ BackgroundPatternService,
SessionStorageService,
ThemeService,
} from '../../shared/service';
@@ -42,7 +44,7 @@ import {
customPasswordValidator,
} from '../../shared/validator';
-type AuthAction = 'register' | 'signup';
+type AuthAction = 'signin' | 'signup';
@Component({
selector: 'app-register-root',
@@ -69,17 +71,19 @@ type AuthAction = 'register' | 'signup';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RegisterRootComponent implements OnInit {
+ public backgroundStyle: { 'background-image': string } | null = null;
public verified: InputSignal
= input(false);
public login: InputSignal = input(false);
public email: InputSignal = input('');
- public form: FormGroup | undefined;
- public isRegisterSignal: WritableSignal = signal(false);
- public isSignupSignal: WritableSignal = signal(false);
- public isDisplayButtons: WritableSignal = signal(true);
+ public form!: FormGroup;
+ public isSigninSignal: WritableSignal = signal(false);
+ public isSignupSignal: WritableSignal = signal(true);
+ //public isDisplayButtons: WritableSignal = signal(true);
public emailInvalid: WritableSignal = signal(null);
public passwordInvalid: WritableSignal = signal(null);
public termsInvalid: WritableSignal = signal(null);
public userSignupSuccess: WritableSignal = signal(false);
+ public isDialogOpen: WritableSignal = signal(false);
private removeQueryParams: WritableSignal = signal(false);
public get isDarkMode(): boolean {
@@ -91,11 +95,13 @@ export class RegisterRootComponent implements OnInit {
private readonly authService: AuthService,
private readonly router: Router,
private readonly sessionStorageService: SessionStorageService,
- private readonly themeService: ThemeService
+ private readonly themeService: ThemeService,
+ private readonly el: ElementRef,
+ private readonly backgroundPatternService: BackgroundPatternService
) {
effect(() => {
if (this.form) {
- if (this.isRegisterSignal()) {
+ if (this.isSigninSignal()) {
this.form.addControl(
'terms',
new FormControl(false, Validators.requiredTrue)
@@ -112,6 +118,7 @@ export class RegisterRootComponent implements OnInit {
}
public ngOnInit(): void {
+ this.setBackground();
this.initializeForm();
this.setupValueChanges();
this.preselectForm();
@@ -122,6 +129,24 @@ export class RegisterRootComponent implements OnInit {
}
}
+ public setBackground(): void {
+ const color = getComputedStyle(this.el.nativeElement).getPropertyValue(
+ '--p'
+ );
+
+ const svgUrl = this.backgroundPatternService.getWigglePattern(color, 0.04);
+
+ this.backgroundStyle = { 'background-image': `url("${svgUrl}")` };
+ }
+
+ public openModal(): void {
+ this.isDialogOpen.set(true);
+ }
+
+ public closeModal(): void {
+ this.isDialogOpen.set(false);
+ }
+
public toggleTheme(): void {
this.themeService.toggleTheme();
}
@@ -135,24 +160,24 @@ export class RegisterRootComponent implements OnInit {
}
public toggleAction(action: AuthAction): void {
- if (action === 'register') {
- this.isRegisterSignal.set(true);
+ if (action === 'signin') {
+ this.isSigninSignal.set(true);
this.isSignupSignal.set(false);
} else {
- this.isRegisterSignal.set(false);
+ this.isSigninSignal.set(false);
this.isSignupSignal.set(true);
}
- this.isDisplayButtons.set(false);
+ //this.isDisplayButtons.set(false);
}
public onSubmit(): void {
this.markControlsAsTouchedAndDirty(['email', 'password', 'terms']);
if (this.form?.valid) {
- if (this.isRegisterSignal()) {
- this.signup(this.form.value);
- } else {
+ if (this.isSigninSignal()) {
this.signin(this.form.value);
+ } else {
+ this.signup(this.form.value);
}
}
}
@@ -162,10 +187,10 @@ export class RegisterRootComponent implements OnInit {
if (this.isSignupSignal()) {
this.isSignupSignal.set(false);
- this.isRegisterSignal.set(true);
- } else if (this.isRegisterSignal()) {
+ this.isSigninSignal.set(true);
+ } else if (this.isSigninSignal()) {
this.isSignupSignal.set(true);
- this.isRegisterSignal.set(false);
+ this.isSigninSignal.set(false);
}
}
@@ -188,8 +213,8 @@ export class RegisterRootComponent implements OnInit {
private handleRedirect(): void {
if (this.verified()) {
- this.isDisplayButtons.set(false);
- this.isRegisterSignal.set(false);
+ //this.isDisplayButtons.set(false);
+ this.isSigninSignal.set(false);
this.isSignupSignal.set(true);
}
if (this.email()) {
@@ -198,8 +223,8 @@ export class RegisterRootComponent implements OnInit {
if (this.login()) {
this.isSignupSignal.set(true);
- this.isDisplayButtons.set(false);
- this.isRegisterSignal.set(false);
+ //this.isDisplayButtons.set(false);
+ this.isSigninSignal.set(false);
}
}
@@ -294,6 +319,7 @@ export class RegisterRootComponent implements OnInit {
.signup(logiCredentials)
.subscribe((response: SuccessDtoApiModel) => {
if (response.success) {
+ this.openModal();
this.userSignupSuccess.set(true);
}
});
diff --git a/frontend/src/app/shared/service/background-pattern.service.ts b/frontend/src/app/shared/service/background-pattern.service.ts
new file mode 100644
index 0000000..b6914db
--- /dev/null
+++ b/frontend/src/app/shared/service/background-pattern.service.ts
@@ -0,0 +1,39 @@
+import { Injectable } from '@angular/core';
+
+import chroma from 'chroma-js';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class BackgroundPatternService {
+ public getWigglePattern(color: string, opacity: number = 0.08): string {
+ const colorHex = this.convertOklchStringToHex(color);
+ const encodedHex = encodeURIComponent(colorHex);
+ const pattern = `
+ data:image/svg+xml,
+ %3Csvg width='52' height='26' viewBox='0 0 52 26' xmlns='http://www.w3.org/2000/svg'%3E
+ %3Cg fill='none' fill-rule='evenodd'%3E
+ %3Cg fill='${encodedHex}' fill-opacity='${opacity}'%3E
+ %3Cpath d='M10 10c0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6h2c0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4v2c-3.314 0-6-2.686-6-6 0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6zm25.464-1.95l8.486 8.486-1.414 1.414-8.486-8.486 1.414-1.414z' /%3E
+ %3C/g%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]);
+ const c = parseFloat(parts[1]);
+ const h = parseFloat(parts[2]);
+
+ return this.convertOklchToHex(l / 100, c, h);
+ }
+
+ private convertOklchToHex(l: number, c: number, h: number): string {
+ const rgb = chroma.oklch(l, c, h).rgb();
+
+ return chroma(rgb).hex();
+ }
+}
diff --git a/frontend/src/app/shared/service/index.ts b/frontend/src/app/shared/service/index.ts
index 3d097fd..02c9641 100644
--- a/frontend/src/app/shared/service/index.ts
+++ b/frontend/src/app/shared/service/index.ts
@@ -2,3 +2,4 @@ export * from './auth.service';
export * from './local-storage.service';
export * from './session-storage.service';
export * from './theme.service';
+export * from './background-pattern.service';
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js
index 195c258..272b1e9 100644
--- a/frontend/tailwind.config.js
+++ b/frontend/tailwind.config.js
@@ -6,7 +6,7 @@ module.exports = {
theme: {
extend: {},
},
- plugins: [require('daisyui')],
+ plugins: [require('daisyui'), require('tailwindcss-animated')],
daisyui: {
themes: ["light", "dark"],
darkMode: ['class', '[data-theme="dark"]']