parent
5a4dfac8da
commit
11a8b6b14c
@ -1,11 +1,18 @@
|
|||||||
import { Routes } from '@angular/router';
|
import { inject } from '@angular/core';
|
||||||
|
import { CanActivateFn, Routes } from '@angular/router';
|
||||||
|
import { AuthComponent } from './auth/auth.component';
|
||||||
|
import { LoginService } from './login.service';
|
||||||
import { RecipeAddComponent } from './recipe-add/recipe-add.component';
|
import { RecipeAddComponent } from './recipe-add/recipe-add.component';
|
||||||
import { RecipeComponent } from './recipe/recipe.component';
|
import { RecipeComponent } from './recipe/recipe.component';
|
||||||
import { RecipesComponent } from './recipes/recipes.component';
|
import { RecipesComponent } from './recipes/recipes.component';
|
||||||
|
|
||||||
|
const LoggedGuard: CanActivateFn = () => inject(LoginService).isLoggedIn();
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{ path: 'recipes', component: RecipesComponent },
|
{ path: 'recipes', component: RecipesComponent },
|
||||||
{ path: 'recipe/add', component: RecipeAddComponent },
|
{ path: 'recipe/add', component: RecipeAddComponent },
|
||||||
{ path: 'recipe/:id', component: RecipeComponent },
|
{ path: 'recipe/:id', component: RecipeComponent },
|
||||||
{ path: 'recipe/:id/edit', component: RecipeAddComponent },
|
{ path: 'recipe/:id/edit', component: RecipeAddComponent },
|
||||||
|
{ path: 'ingredients', component: RecipesComponent, canActivate: [LoggedGuard] },
|
||||||
|
{ path: 'login', component: AuthComponent },
|
||||||
|
{ path: 'logout', component: AuthComponent, data: { registering: false }, canActivate: [LoggedGuard] },
|
||||||
];
|
];
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
<mat-card>
|
||||||
|
<mat-card-title>Login</mat-card-title>
|
||||||
|
<mat-card-content>
|
||||||
|
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
|
||||||
|
<div>
|
||||||
|
<mat-form-field>
|
||||||
|
<input mat-input type="text" matInput placeholder="Username" formControlName="login">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<mat-form-field>
|
||||||
|
<input mat-input type="password" matInput placeholder="Password" formControlName="password">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<button mat-button>Login</button>
|
||||||
|
</form>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { AuthComponent } from './auth.component';
|
||||||
|
|
||||||
|
describe('AuthComponent', () => {
|
||||||
|
let component: AuthComponent;
|
||||||
|
let fixture: ComponentFixture<AuthComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [AuthComponent],
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(AuthComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,48 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { MatCard, MatCardContent, MatCardTitle } from '@angular/material/card';
|
||||||
|
import { MatFormField } from '@angular/material/form-field';
|
||||||
|
import { MatInput } from '@angular/material/input';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import { LoginService } from '../login.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-auth',
|
||||||
|
standalone: true,
|
||||||
|
imports: [ReactiveFormsModule, MatCard, MatCardTitle, MatCardContent, MatFormField, MatInput],
|
||||||
|
templateUrl: './auth.component.html',
|
||||||
|
})
|
||||||
|
export class AuthComponent {
|
||||||
|
loginForm = this.formBuilder.group({
|
||||||
|
login: '',
|
||||||
|
password: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private loginService: LoginService,
|
||||||
|
private formBuilder: FormBuilder,
|
||||||
|
private router: Router,
|
||||||
|
activatedRoute: ActivatedRoute,
|
||||||
|
) {
|
||||||
|
activatedRoute.data.subscribe(({ registering }) => {
|
||||||
|
if (!registering) {
|
||||||
|
loginService.logOut();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(): void {
|
||||||
|
if (this.loginForm.invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const value = this.loginForm.value;
|
||||||
|
this.loginService.logIn(value.login!, value.password!)
|
||||||
|
.then((logged) => {
|
||||||
|
if (logged) {
|
||||||
|
this.router.navigateByUrl('/ingredients');
|
||||||
|
} else {
|
||||||
|
alert('Invalid login!');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { User } from '../cookbook/type';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class LoginService {
|
||||||
|
async logIn(username: string, password: string): Promise<boolean> {
|
||||||
|
const res = await fetch('https://dummyjson.com/user/login', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
expiresInMins: 30,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
if (res.status !== 200) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const user: User = await res.json();
|
||||||
|
localStorage.setItem('user', JSON.stringify(user));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
me(): Promise<User | null> {
|
||||||
|
const token = this.currentToken();
|
||||||
|
if (!token) {
|
||||||
|
return Promise.resolve(null);
|
||||||
|
}
|
||||||
|
return fetch('http://dummyjson.com/user/me', {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(res => res.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoggedIn(): boolean {
|
||||||
|
return this.currentToken() !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentToken(): string | null {
|
||||||
|
const json = localStorage?.getItem('user');
|
||||||
|
if (!json) return null;
|
||||||
|
return JSON.parse(json).token;
|
||||||
|
}
|
||||||
|
|
||||||
|
logOut(): void {
|
||||||
|
localStorage?.removeItem('user');
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue