diff --git a/angular.json b/angular.json
index 63a3c15..a615ab1 100644
--- a/angular.json
+++ b/angular.json
@@ -118,5 +118,8 @@
"@schematics/angular:resolver": {
"typeSeparator": "."
}
+ },
+ "cli": {
+ "analytics": false
}
}
diff --git a/src/app/app.component.css b/src/app/app.component.css
deleted file mode 100644
index e69de29..0000000
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 36093e1..67e7bd4 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,336 +1 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Hello, {{ title }}
-
Congratulations! Your app is running. 🎉
-
-
-
-
- @for (item of [
- { title: 'Explore the Docs', link: 'https://angular.dev' },
- { title: 'Learn with Tutorials', link: 'https://angular.dev/tutorials' },
- { title: 'CLI Docs', link: 'https://angular.dev/tools/cli' },
- { title: 'Angular Language Service', link: 'https://angular.dev/tools/language-service' },
- { title: 'Angular DevTools', link: 'https://angular.dev/tools/devtools' },
- ]; track item.title) {
-
- {{ item.title }}
-
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts
deleted file mode 100644
index 24c5989..0000000
--- a/src/app/app.component.spec.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { TestBed } from '@angular/core/testing';
-import { AppComponent } from './app.component';
-
-describe('AppComponent', () => {
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- imports: [AppComponent],
- }).compileComponents();
- });
-
- it('should create the app', () => {
- const fixture = TestBed.createComponent(AppComponent);
- const app = fixture.componentInstance;
- expect(app).toBeTruthy();
- });
-
- it(`should have the 'auth' title`, () => {
- const fixture = TestBed.createComponent(AppComponent);
- const app = fixture.componentInstance;
- expect(app.title).toEqual('auth');
- });
-
- it('should render title', () => {
- const fixture = TestBed.createComponent(AppComponent);
- fixture.detectChanges();
- const compiled = fixture.nativeElement as HTMLElement;
- expect(compiled.querySelector('h1')?.textContent).toContain('Hello, auth');
- });
-});
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index d176687..c9770ba 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -5,8 +5,6 @@ import { RouterOutlet } from '@angular/router';
selector: 'app-root',
imports: [RouterOutlet],
templateUrl: './app.component.html',
- styleUrl: './app.component.css'
})
export class AppComponent {
- title = 'auth';
}
diff --git a/src/app/app.config.ts b/src/app/app.config.ts
index a1e7d6f..4973533 100644
--- a/src/app/app.config.ts
+++ b/src/app/app.config.ts
@@ -1,8 +1,14 @@
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
-import { provideRouter } from '@angular/router';
+import {provideRouter, withDebugTracing} from '@angular/router';
import { routes } from './app.routes';
+import {provideHttpClient, withInterceptors} from "@angular/common/http";
+import {httpInterceptor} from "./service/http.interceptor";
export const appConfig: ApplicationConfig = {
- providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes)]
+ providers: [
+ provideZoneChangeDetection({ eventCoalescing: true }),
+ provideRouter(routes, withDebugTracing()),
+ provideHttpClient(withInterceptors([httpInterceptor])),
+ ]
};
diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
index dc39edb..161940d 100644
--- a/src/app/app.routes.ts
+++ b/src/app/app.routes.ts
@@ -1,3 +1,33 @@
import { Routes } from '@angular/router';
+import {authGuard} from "./service/auth.guard";
-export const routes: Routes = [];
+export const routes: Routes = [
+ {
+ path: 'auth',
+ children: [
+ {
+ path: 'register',
+ loadComponent: () => import('./component/auth/register/register.component'),
+ },
+ {
+ path: 'login',
+ loadComponent: () => import('./component/auth/login/login.component'),
+ },
+ ],
+ },
+ {
+ path: '',
+ loadComponent: () => import('./component/random-ahh/random-ahh.component'),
+ children: [
+ {
+ path: 'dashboard',
+ loadComponent: () => import('./component/dashboard/dashboard.component'),
+ },
+ {
+ path: 'users',
+ loadComponent: () => import('./component/users/users.component'),
+ },
+ ],
+ canActivate: [authGuard],
+ }
+];
diff --git a/src/app/component/auth/login/login.component.html b/src/app/component/auth/login/login.component.html
new file mode 100644
index 0000000..9c539cd
--- /dev/null
+++ b/src/app/component/auth/login/login.component.html
@@ -0,0 +1,6 @@
+
diff --git a/src/app/component/auth/login/login.component.ts b/src/app/component/auth/login/login.component.ts
new file mode 100644
index 0000000..4f19f4d
--- /dev/null
+++ b/src/app/component/auth/login/login.component.ts
@@ -0,0 +1,37 @@
+import {Component, inject} from '@angular/core';
+import {FormBuilder, FormGroup, ReactiveFormsModule, Validators} from "@angular/forms";
+import AuthService from "../../../service/auth.service";
+import {AuthResponse, Token} from "../../../models";
+import {Router} from "@angular/router";
+
+@Component({
+ selector: 'app-login',
+ imports: [
+ ReactiveFormsModule
+ ],
+ templateUrl: './login.component.html',
+})
+export default class LoginComponent {
+ fb: FormBuilder = inject(FormBuilder);
+ authService: AuthService = inject(AuthService);
+ router: Router = inject(Router);
+
+ form: FormGroup = this.fb.group({
+ username: [null, [Validators.required]],
+ password: [null, [Validators.required]],
+ });
+
+ login() {
+ if (this.form.invalid) {
+ console.log(this.form.errors)
+ return;
+ }
+
+ this.authService.login(this.form.value).subscribe((r: AuthResponse) => {
+ localStorage.setItem('access_token', r.accessToken);
+ localStorage.setItem('refresh_token', r.refreshToken);
+
+ this.router.navigate(['dashboard'])
+ });
+ }
+}
diff --git a/src/app/component/auth/register/register.component.html b/src/app/component/auth/register/register.component.html
new file mode 100644
index 0000000..4b201d5
--- /dev/null
+++ b/src/app/component/auth/register/register.component.html
@@ -0,0 +1,48 @@
+
diff --git a/src/app/component/auth/register/register.component.ts b/src/app/component/auth/register/register.component.ts
new file mode 100644
index 0000000..ee56e6f
--- /dev/null
+++ b/src/app/component/auth/register/register.component.ts
@@ -0,0 +1,52 @@
+import {Component, inject} from '@angular/core';
+import {FormBuilder, FormGroup, ReactiveFormsModule, Validators} from "@angular/forms";
+import AuthService from "../../../service/auth.service";
+import CustomValidators from "../../../service/custom.validators";
+
+@Component({
+ selector: 'app-register',
+ imports: [
+ ReactiveFormsModule
+ ],
+ templateUrl: './register.component.html',
+})
+export default class RegisterComponent {
+ registerService: AuthService = inject(AuthService);
+
+ fb: FormBuilder = inject(FormBuilder);
+
+ emailGroup: FormGroup = this.fb.group({
+ email: ['', Validators.required, Validators.email],
+ confirmEmail: ['', Validators.required, Validators.email],
+ });
+
+ passwordGroup: FormGroup = this.fb.group({
+ password: ['', Validators.required],
+ confirmPassword: ['', Validators.required],
+ });
+
+ addressGroup: FormGroup = this.fb.group({
+ city: ['', Validators.required],
+ state: ['', Validators.required],
+ zip: ['', Validators.required],
+ street: ['', Validators.required],
+ nr: ['', Validators.required],
+ });
+
+ form: FormGroup = this.fb.group({
+ firstname: [null, Validators.required],
+ lastname: [null, Validators.required],
+ password: [this.passwordGroup, CustomValidators.password()],
+ email: [this.emailGroup, CustomValidators.email()],
+ address: [this.addressGroup, CustomValidators.address()],
+ });
+
+ submit() {
+ if (!this.form.valid) {
+ console.log(this.form.controls);
+ return;
+ }
+
+ this.registerService.register(this.form.value);
+ }
+}
diff --git a/src/app/component/dashboard/dashboard.component.html b/src/app/component/dashboard/dashboard.component.html
new file mode 100644
index 0000000..8bc168b
--- /dev/null
+++ b/src/app/component/dashboard/dashboard.component.html
@@ -0,0 +1,3 @@
+random ahh dashboard
+
+
diff --git a/src/app/component/dashboard/dashboard.component.ts b/src/app/component/dashboard/dashboard.component.ts
new file mode 100644
index 0000000..d9c5ccb
--- /dev/null
+++ b/src/app/component/dashboard/dashboard.component.ts
@@ -0,0 +1,14 @@
+import {Component} from '@angular/core';
+import "../side/side.component";
+import {RouterOutlet} from "@angular/router";
+
+@Component({
+ selector: 'app-dashboard',
+ imports: [
+ RouterOutlet
+ ],
+ templateUrl: './dashboard.component.html',
+})
+export default class DashboardComponent {
+
+}
diff --git a/src/app/component/header/header.component.html b/src/app/component/header/header.component.html
new file mode 100644
index 0000000..cfa62db
--- /dev/null
+++ b/src/app/component/header/header.component.html
@@ -0,0 +1,10 @@
+
diff --git a/src/app/component/header/header.component.ts b/src/app/component/header/header.component.ts
new file mode 100644
index 0000000..3f1ddc7
--- /dev/null
+++ b/src/app/component/header/header.component.ts
@@ -0,0 +1,13 @@
+import {Component} from '@angular/core';
+import {RouterLink} from "@angular/router";
+
+@Component({
+ selector: 'app-header',
+ imports: [
+ RouterLink
+ ],
+ templateUrl: './header.component.html',
+})
+export default class HeaderComponent {
+
+}
diff --git a/src/app/component/random-ahh/random-ahh.component.html b/src/app/component/random-ahh/random-ahh.component.html
new file mode 100644
index 0000000..08fbdeb
--- /dev/null
+++ b/src/app/component/random-ahh/random-ahh.component.html
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/app/component/random-ahh/random-ahh.component.ts b/src/app/component/random-ahh/random-ahh.component.ts
new file mode 100644
index 0000000..1f0b126
--- /dev/null
+++ b/src/app/component/random-ahh/random-ahh.component.ts
@@ -0,0 +1,17 @@
+import { Component } from '@angular/core';
+import HeaderComponent from "../header/header.component";
+import SideComponent from "../side/side.component";
+import {RouterOutlet} from "@angular/router";
+
+@Component({
+ selector: 'app-random-ahh',
+ imports: [
+ HeaderComponent,
+ SideComponent,
+ RouterOutlet
+ ],
+ templateUrl: './random-ahh.component.html',
+})
+export default class RandomAhhComponent {
+
+}
diff --git a/src/app/component/side/side.component.html b/src/app/component/side/side.component.html
new file mode 100644
index 0000000..4db32ea
--- /dev/null
+++ b/src/app/component/side/side.component.html
@@ -0,0 +1 @@
+
diff --git a/src/app/component/side/side.component.ts b/src/app/component/side/side.component.ts
new file mode 100644
index 0000000..104aed7
--- /dev/null
+++ b/src/app/component/side/side.component.ts
@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-side',
+ imports: [],
+ templateUrl: './side.component.html',
+})
+export default class SideComponent {
+
+}
diff --git a/src/app/component/users/users.component.html b/src/app/component/users/users.component.html
new file mode 100644
index 0000000..d5b09c3
--- /dev/null
+++ b/src/app/component/users/users.component.html
@@ -0,0 +1 @@
+mf users gng
diff --git a/src/app/component/users/users.component.ts b/src/app/component/users/users.component.ts
new file mode 100644
index 0000000..7260a71
--- /dev/null
+++ b/src/app/component/users/users.component.ts
@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-users',
+ imports: [],
+ templateUrl: './users.component.html',
+})
+export default class UsersComponent {
+
+}
diff --git a/src/app/models.ts b/src/app/models.ts
new file mode 100644
index 0000000..39238d6
--- /dev/null
+++ b/src/app/models.ts
@@ -0,0 +1,16 @@
+export interface Token {
+ accessToken: string;
+ refreshToken: string;
+}
+
+export interface User {
+ id: number;
+ username: string;
+ email: string;
+ firstName: string;
+ lastName: string;
+ gender: string;
+ image: string;
+}
+
+export interface AuthResponse extends User, Token {}
diff --git a/src/app/service/auth.guard.ts b/src/app/service/auth.guard.ts
new file mode 100644
index 0000000..0b831d1
--- /dev/null
+++ b/src/app/service/auth.guard.ts
@@ -0,0 +1,18 @@
+import {CanActivateFn} from "@angular/router";
+import {inject} from "@angular/core";
+import {HttpClient, HttpErrorResponse, HttpResponse} from "@angular/common/http";
+import {catchError, map, of} from "rxjs";
+import {User} from "../models";
+
+export const authGuard: CanActivateFn = () => {
+ return inject(HttpClient).get('https://dummyjson.com/auth/me', { observe: 'response' }).pipe(
+ map((res: HttpResponse) => {
+ console.log(res);
+ return res.status === 200;
+ }),
+ catchError((err: HttpErrorResponse) => {
+ console.log(err);
+ return of(false);
+ })
+ );
+};
diff --git a/src/app/service/auth.service.ts b/src/app/service/auth.service.ts
new file mode 100644
index 0000000..012ee00
--- /dev/null
+++ b/src/app/service/auth.service.ts
@@ -0,0 +1,21 @@
+import {inject, Injectable} from "@angular/core";
+import {HttpClient} from "@angular/common/http";
+import {AuthResponse} from "../models";
+
+
+@Injectable({
+ providedIn: 'root',
+})
+export default class AuthService {
+ http: HttpClient = inject(HttpClient);
+
+ register(data: { email: string, password: string }): void {
+ console.log(data);
+
+ }
+
+ login(loginData: { username: string, password: string }) {
+ return this.http.post('https://dummyjson.com/auth/login', loginData)
+ }
+}
+
diff --git a/src/app/service/custom.validators.ts b/src/app/service/custom.validators.ts
new file mode 100644
index 0000000..3fb6391
--- /dev/null
+++ b/src/app/service/custom.validators.ts
@@ -0,0 +1,31 @@
+import {AbstractControl, ValidatorFn} from "@angular/forms";
+
+
+export default class CustomValidators {
+ public static email(): ValidatorFn {
+ return (emailGroup: AbstractControl) => {
+ if (emailGroup.get('email')?.value !== emailGroup.get('confirmEmail')) {
+ return {emailMismatch: true}
+ }
+
+ return {};
+ }
+ }
+
+ public static password(): ValidatorFn {
+ return (passwordGroup: AbstractControl) => {
+ if (passwordGroup.get('password')?.value !== passwordGroup.get('confirmPassword')) {
+ return {emailMismatch: true}
+ }
+
+ return {};
+ }
+ }
+
+ static address(): ValidatorFn {
+ return (addressGroup: AbstractControl) => {
+
+ return {};
+ }
+ }
+}
diff --git a/src/app/service/http.interceptor.ts b/src/app/service/http.interceptor.ts
new file mode 100644
index 0000000..e030ba3
--- /dev/null
+++ b/src/app/service/http.interceptor.ts
@@ -0,0 +1,9 @@
+import {HttpHandlerFn, HttpInterceptorFn, HttpRequest} from "@angular/common/http";
+
+export const httpInterceptor: HttpInterceptorFn = (req: HttpRequest, next: HttpHandlerFn) => {
+ return next(req.clone({
+ setHeaders: {
+ Authorization: "Bearer " + localStorage.getItem('access_token')
+ }
+ }));
+}