diff --git a/src/app/app.component.ts b/src/app/app.component.ts index c9ef524..317f787 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -8,6 +8,8 @@ import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; import { IngredientListComponent } from './ingredient-list/ingredient-list.component'; +import { AuthService } from './services/auth.service'; +import { MenuService } from './services/menu.service'; @Component({ selector: 'app-root', @@ -22,6 +24,7 @@ import { IngredientListComponent } from './ingredient-list/ingredient-list.compo ], templateUrl: './app.component.html', styleUrl: './app.component.scss', + providers: [AuthService, MenuService], }) export class AppComponent { title = 'Lasagna'; diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index f662ef8..82fdc55 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -4,12 +4,21 @@ import { RecipeListComponent } from './recipe-list/recipe-list.component'; import { HomeComponent } from './home/home.component'; import { RecipeAddComponent } from './recipe-add/recipe-add.component'; import { IngredientListComponent } from './ingredient-list/ingredient-list.component'; +import { LoginComponent } from './login/login.component'; +import { LogoutComponent } from './logout/logout.component'; +import { authGuard } from './guards/auth.guard'; export const routes: Routes = [ { path: 'add', component: RecipeAddComponent }, { path: 'recipe/:id', component: RecipeComponent }, { path: 'list', component: RecipeListComponent }, - { path: 'ingredients', component: IngredientListComponent }, + { + path: 'ingredients', + component: IngredientListComponent, + canActivate: [authGuard], + }, + { path: 'login', component: LoginComponent }, + { path: 'logout', component: LogoutComponent }, { path: '', component: HomeComponent }, { path: '**', redirectTo: '' }, ]; diff --git a/src/app/guards/auth.guard.ts b/src/app/guards/auth.guard.ts new file mode 100644 index 0000000..2ac3e31 --- /dev/null +++ b/src/app/guards/auth.guard.ts @@ -0,0 +1,15 @@ +import { inject } from '@angular/core'; +import { CanActivateFn, Router } from '@angular/router'; +import { AuthService } from '../services/auth.service'; + +export const authGuard: CanActivateFn = (route, state) => { + const authService = inject(AuthService); + const router = inject(Router); + + if (authService.isLoggedIn()) { + return true; + } else { + router.navigate(['/home']); + return false; + } +}; diff --git a/src/app/login/login.component.ts b/src/app/login/login.component.ts new file mode 100644 index 0000000..65b4f89 --- /dev/null +++ b/src/app/login/login.component.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; +import { AuthService } from '../services/auth.service'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'app-login', + template: ``, +}) +export class LoginComponent { + constructor(private authService: AuthService, private router: Router) { + this.authService.login(); + this.router.navigate(['/ingredients']); + } +} diff --git a/src/app/logout/logout.component.ts b/src/app/logout/logout.component.ts new file mode 100644 index 0000000..e0a0539 --- /dev/null +++ b/src/app/logout/logout.component.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; +import { AuthService } from '../services/auth.service'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'app-logout', + template: ``, +}) +export class LogoutComponent { + constructor(private authService: AuthService, private router: Router) { + this.authService.logout(); + this.router.navigate(['/home']); + } +} diff --git a/src/app/menu/menu.component.ts b/src/app/menu/menu.component.ts index ae1fb6b..ecd5153 100644 --- a/src/app/menu/menu.component.ts +++ b/src/app/menu/menu.component.ts @@ -4,6 +4,7 @@ import { MatMenuModule } from '@angular/material/menu'; import { MenuService } from '../services/menu.service'; import { CommonModule } from '@angular/common'; import { RouterLink } from '@angular/router'; +import { Subscription } from 'rxjs'; @Component({ selector: 'app-menu', @@ -15,9 +16,17 @@ import { RouterLink } from '@angular/router'; export class MenuComponent implements OnInit { menuItems: { label: string; link: string }[] | undefined; + private subscription: Subscription = new Subscription(); + constructor(private menuService: MenuService) {} ngOnInit(): void { - this.menuItems = this.menuService.getMenuItems(); + this.subscription = this.menuService.getMenuItems().subscribe((items) => { + this.menuItems = items; + }); + } + + ngOnDestroy(): void { + this.subscription.unsubscribe(); } } diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts new file mode 100644 index 0000000..33f4520 --- /dev/null +++ b/src/app/services/auth.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class AuthService { + private readonly adminKey = 'isAdmin'; + private loggedInSubject: BehaviorSubject = + new BehaviorSubject(this.isLoggedIn()); + + get loggedIn$(): Observable { + return this.loggedInSubject.asObservable(); + } + + login() { + localStorage.setItem(this.adminKey, 'true'); + this.loggedInSubject.next(true); + } + + logout() { + localStorage.removeItem(this.adminKey); + this.loggedInSubject.next(false); + } + + isLoggedIn(): boolean { + return localStorage.getItem(this.adminKey) === 'true'; + } +} diff --git a/src/app/services/menu.service.ts b/src/app/services/menu.service.ts index 8408467..65fa1f4 100644 --- a/src/app/services/menu.service.ts +++ b/src/app/services/menu.service.ts @@ -1,4 +1,6 @@ import { Injectable } from '@angular/core'; +import { AuthService } from './auth.service'; +import { Observable } from 'rxjs'; interface MenuItem { label: string; @@ -16,7 +18,17 @@ export class MenuService { { label: 'List ingredients', link: '/ingredients' }, ]; - getMenuItems(): MenuItem[] { - return this.menuItems; + constructor(private authService: AuthService) {} + + getMenuItems(): Observable { + return new Observable((observer) => { + this.authService.loggedIn$.subscribe((isLoggedIn) => { + const authItems = isLoggedIn + ? [{ label: 'Logout', link: '/logout' }] + : [{ label: 'Login', link: '/login' }]; + + observer.next([...this.menuItems, ...authItems]); + }); + }); } }