From 688929a3b1df6509dfd75241413682aceb0ada7b Mon Sep 17 00:00:00 2001 From: Kyra Antonio Date: Sat, 7 Sep 2024 16:23:17 +0800 Subject: [PATCH 1/9] Config for angular 14 - base branch --- angular.json | 4 +++- package.json | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/angular.json b/angular.json index f98c9205..9ae836ed 100644 --- a/angular.json +++ b/angular.json @@ -31,7 +31,9 @@ ], "styles": [ "src/styles.scss", - "src/assets/scss/argon.scss" + "src/assets/scss/argon.scss", + "src/assets/vendor/nucleo/css/nucleo.css", + "src/assets/vendor/@fortawesome/fontawesome-free/css/all.min.css" ], "scripts": [ "node_modules/chart.js/dist/Chart.min.js", diff --git a/package.json b/package.json index 89497054..42a0db26 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "test": "ng test", "lint": "ng lint", "e2e": "ng e2e", - "install:clean": "rm -rf node_modules/ && rm -rf package-lock.json && npm install && npm start" + "install:clean": "rm -rf node_modules/ && rm -rf package-lock.json && npm install --force && npm start" }, "private": true, "dependencies": { From 0672fa902e61507cd3e5f667d5c0563633896f09 Mon Sep 17 00:00:00 2001 From: Kyra Antonio Date: Sat, 7 Sep 2024 16:27:22 +0800 Subject: [PATCH 2/9] ng generate fix --- angular.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/angular.json b/angular.json index 9ae836ed..56c8adde 100644 --- a/angular.json +++ b/angular.json @@ -10,7 +10,7 @@ "prefix": "app", "schematics": { "@schematics/angular:component": { - "styleext": "scss" + "style": "scss" } }, "architect": { @@ -164,7 +164,7 @@ "defaultProject": "argon-dashboard-angular", "schematics": { "@schematics/angular:component": { - "styleext": "scss" + "style": "scss" } }, "cli": { From 44e6d3f4d5dbcfcc69447cd677c00d1f35d9532a Mon Sep 17 00:00:00 2001 From: redmanuel1 Date: Sun, 8 Sep 2024 12:47:39 +0800 Subject: [PATCH 3/9] Login with user role --- package.json | 12 +++-- src/app/app.module.ts | 11 +++- src/app/app.routing.ts | 2 +- src/app/models/user.model.ts | 6 +++ .../pages/dashboard/dashboard.component.ts | 8 +++ src/app/pages/login/login.component.html | 24 +++++++-- src/app/pages/login/login.component.ts | 42 +++++++++++++--- src/app/services/auth.service.ts | 50 +++++++++++++++++++ src/app/services/register.services.ts | 23 +++++++++ src/environments/environment.ts | 12 ++++- 10 files changed, 170 insertions(+), 20 deletions(-) create mode 100644 src/app/models/user.model.ts create mode 100644 src/app/services/auth.service.ts create mode 100644 src/app/services/register.services.ts diff --git a/package.json b/package.json index 42a0db26..6487f66c 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@angular/compiler": "^14.2.0", "@angular/core": "^14.2.0", "@angular/elements": "^14.2.0", + "@angular/fire": "^7.6.1", "@angular/forms": "^14.2.0", "@angular/google-maps": "^14.2.0", "@angular/localize": "^14.2.0", @@ -25,17 +26,18 @@ "@angular/platform-browser": "^14.2.0", "@angular/platform-browser-dynamic": "^14.2.0", "@angular/router": "^14.2.0", - "@ng-bootstrap/ng-bootstrap": "12.0.1", + "@ng-bootstrap/ng-bootstrap": "^13.0.0", "@popperjs/core": "^2.11.4", "bootstrap": "4.6.1", "chart.js": "2.9.4", "clipboard": "2.0.10", + "firebase": "^10.13.1", "ngx-clipboard": "15.0.1", "ngx-toastr": "14.2.2", "nouislider": "15.5.1", "rxjs": "~7.5.0", - "zone.js": "~0.11.4", - "web-animations-js": "2.3.2" + "web-animations-js": "2.3.2", + "zone.js": "~0.11.4" }, "devDependencies": { "@angular-devkit/build-angular": "^14.2.7", @@ -46,6 +48,7 @@ "@types/jasminewd2": "~2.0.10", "@types/node": "^17.0.21", "codelyzer": "6.0.2", + "cross-env": "^7.0.3", "jasmine-core": "~4.4.0", "jasmine-spec-reporter": "~7.0.0", "karma": "~6.4.0", @@ -56,7 +59,6 @@ "karma-jasmine-html-reporter": "~2.0.0", "protractor": "7.0.0", "ts-node": "~10.9.1", - "typescript": "~4.7.2", - "cross-env": "^7.0.3" + "typescript": "~4.7.2" } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 80a35bab..031e737b 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -12,6 +12,11 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { AppRoutingModule } from './app.routing'; import { ComponentsModule } from './components/components.module'; +import { environment } from '../environments/environment'; +import { AngularFireModule } from '@angular/fire/compat'; +import { AngularFireAuthModule } from '@angular/fire/compat/auth'; +import { AngularFirestoreModule } from '@angular/fire/compat/firestore'; +import { ToastrModule } from 'ngx-toastr'; @NgModule({ @@ -22,7 +27,11 @@ import { ComponentsModule } from './components/components.module'; ComponentsModule, NgbModule, RouterModule, - AppRoutingModule + AppRoutingModule, + AngularFireModule.initializeApp(environment.firebaseConfig), + AngularFireAuthModule, + AngularFirestoreModule , + ToastrModule.forRoot() ], declarations: [ AppComponent, diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index 29a17f41..adaa0c82 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -9,7 +9,7 @@ import { AuthLayoutComponent } from './layouts/auth-layout/auth-layout.component const routes: Routes =[ { path: '', - redirectTo: 'dashboard', + redirectTo: 'login', pathMatch: 'full', }, { path: '', diff --git a/src/app/models/user.model.ts b/src/app/models/user.model.ts new file mode 100644 index 00000000..276a9dce --- /dev/null +++ b/src/app/models/user.model.ts @@ -0,0 +1,6 @@ +export interface User { + idNo: string; + password: string; + role: string; + // Add other properties as needed + } \ No newline at end of file diff --git a/src/app/pages/dashboard/dashboard.component.ts b/src/app/pages/dashboard/dashboard.component.ts index f1850ae0..0b81209a 100644 --- a/src/app/pages/dashboard/dashboard.component.ts +++ b/src/app/pages/dashboard/dashboard.component.ts @@ -1,3 +1,4 @@ +import { AuthService } from 'src/app/services/auth.service'; import { Component, OnInit } from '@angular/core'; import Chart from 'chart.js'; @@ -21,6 +22,13 @@ export class DashboardComponent implements OnInit { public salesChart; public clicked: boolean = true; public clicked1: boolean = false; + userRole: string | null = null; + + constructor(private authService: AuthService) { + this.userRole = this.authService.getUserRole(); + console.log("test get user on dashboard", this.userRole) + } + ngOnInit() { diff --git a/src/app/pages/login/login.component.html b/src/app/pages/login/login.component.html index 617f5074..f790d2f2 100644 --- a/src/app/pages/login/login.component.html +++ b/src/app/pages/login/login.component.html @@ -43,7 +43,12 @@

Welcome!

- +
@@ -51,17 +56,25 @@

Welcome!

- +
- -
- + +
+
+ {{ errorMessage }}
@@ -77,3 +90,4 @@

Welcome!

+ diff --git a/src/app/pages/login/login.component.ts b/src/app/pages/login/login.component.ts index b1504f1b..1ddde478 100644 --- a/src/app/pages/login/login.component.ts +++ b/src/app/pages/login/login.component.ts @@ -1,16 +1,44 @@ -import { Component, OnInit, OnDestroy } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { AuthService } from 'src/app/services/auth.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.scss'] }) -export class LoginComponent implements OnInit, OnDestroy { - constructor() {} +export class LoginComponent implements OnInit { + idNo: string = ''; + password: string = ''; + errorMessage: string = ''; - ngOnInit() { - } - ngOnDestroy() { - } + constructor( + private authService: AuthService, + private router: Router + ) {} + ngOnInit() {} + + async login() { + try { + // Call the login method and wait for it to complete + const success = await this.authService.login(this.idNo, this.password); + if (success) { + // Retrieve the role after successful login + const role = this.authService.getUserRole(); + console.log('User role:', role); + // Redirect based on role + if (role === 'custodian') { + this.router.navigate(['/dashboard']); // Adjust as needed + } else { + this.router.navigate(['/dashboard']); // Adjust as needed + } + } else { + this.errorMessage = 'Login failed'; + } + } catch (error) { + console.error('Login error:', error); + this.errorMessage = 'An error occurred during login'; + } + } } diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts new file mode 100644 index 00000000..fd1bbcad --- /dev/null +++ b/src/app/services/auth.service.ts @@ -0,0 +1,50 @@ +import { Injectable } from '@angular/core'; +import { AngularFirestore } from '@angular/fire/compat/firestore'; +import { BehaviorSubject, Observable } from 'rxjs'; +// import { User } from './user.model'; // Import the User interface +import { User } from '../models/user.model'; + +@Injectable({ + providedIn: 'root' +}) +export class AuthService { + private userSubject: BehaviorSubject = new BehaviorSubject(null); + public user$: Observable = this.userSubject.asObservable(); + + constructor(private firestore: AngularFirestore) {} + + // Method to login the user + login(idNo: string, password: string): Promise { + return new Promise((resolve, reject) => { + this.firestore.collection('Users', ref => ref.where('idNo', '==', idNo)) + .get() + .subscribe(snapshot => { + if (!snapshot.empty) { + const user = snapshot.docs[0].data() as User; + if (user.password === password) { + this.userSubject.next(user); + resolve(true); // Login successful + } else { + resolve(false); // Incorrect password + } + } else { + resolve(false); // User not found + } + }, error => { + console.error("Error during login:", error); + reject(false); // Login failed + }); + }); + } + + getUserRole(): string | null { + const user = this.userSubject.value; + return user ? user.role || null : null; + } + + + // Method to log out + logout() { + this.userSubject.next(null); // Clear user data + } +} diff --git a/src/app/services/register.services.ts b/src/app/services/register.services.ts new file mode 100644 index 00000000..71226c15 --- /dev/null +++ b/src/app/services/register.services.ts @@ -0,0 +1,23 @@ +// src/app/services/firestore.service.ts +import { Injectable } from '@angular/core'; +import { AngularFirestore } from '@angular/fire/compat/firestore'; +import { Observable } from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class RegisterService { + + constructor(private firestore: AngularFirestore) { } + + // Method to add user to Firestore + addUser(user: any): Promise { + const userId = this.firestore.createId(); // Generate unique ID + return this.firestore.collection('users').doc(userId).set(user); + } + + // Method to get a user by idNo + getUserByIdNo(idNo: string): Observable { + return this.firestore.collection('users', ref => ref.where('idNo', '==', idNo)).valueChanges(); + } +} diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 7b4f817a..bb60e95c 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -3,7 +3,17 @@ // The list of file replacements can be found in `angular.json`. export const environment = { - production: false + production: false, + firebaseConfig : { + apiKey: "AIzaSyAor0vsOYA3yiXEFSNL_VyftuTZJTk4a60", + authDomain: "inventoryapp-2162b.firebaseapp.com", + projectId: "inventoryapp-2162b", + storageBucket: "inventoryapp-2162b.appspot.com", + messagingSenderId: "386387705752", + appId: "1:386387705752:web:325a619af00ebe2f8cf5ed", + measurementId: "G-3S6K26FVBL" + } + }; /* From 5423a381802c4bf6c31c1cb22b88bd551ef1217b Mon Sep 17 00:00:00 2001 From: redmanuel1 Date: Thu, 12 Sep 2024 14:48:49 +0800 Subject: [PATCH 4/9] basic-navigation --- src/app/app.routing.ts | 13 +++--- .../components/navbar/navbar.component.html | 2 +- src/app/components/navbar/navbar.component.ts | 8 +++- .../components/sidebar/sidebar.component.ts | 14 +++--- src/app/guards/auth.guard.ts | 44 +++++++++++++++++++ src/app/pages/login/login.component.ts | 26 ++++++++--- src/app/services/auth.service.ts | 15 ++++++- src/app/services/navigation.service.ts | 36 +++++++++++++++ 8 files changed, 137 insertions(+), 21 deletions(-) create mode 100644 src/app/guards/auth.guard.ts create mode 100644 src/app/services/navigation.service.ts diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index adaa0c82..ce710ec8 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -5,15 +5,17 @@ import { Routes, RouterModule } from '@angular/router'; import { AdminLayoutComponent } from './layouts/admin-layout/admin-layout.component'; import { AuthLayoutComponent } from './layouts/auth-layout/auth-layout.component'; +import { AuthGuard } from './guards/auth.guard'; const routes: Routes =[ { path: '', - redirectTo: 'login', + redirectTo: 'auth/login', pathMatch: 'full', }, { - path: '', + path: 'admin', component: AdminLayoutComponent, + canActivate: [AuthGuard], children: [ { path: '', @@ -21,8 +23,9 @@ const routes: Routes =[ } ] }, { - path: '', + path: 'auth', component: AuthLayoutComponent, + // canActivate: [AuthGuard], children: [ { path: '', @@ -31,7 +34,7 @@ const routes: Routes =[ ] }, { path: '**', - redirectTo: 'dashboard' + redirectTo: 'auth/login' } ]; @@ -40,7 +43,7 @@ const routes: Routes =[ CommonModule, BrowserModule, RouterModule.forRoot(routes,{ - useHash: true + useHash: false }) ], exports: [ diff --git a/src/app/components/navbar/navbar.component.html b/src/app/components/navbar/navbar.component.html index 533724cf..3a80971e 100644 --- a/src/app/components/navbar/navbar.component.html +++ b/src/app/components/navbar/navbar.component.html @@ -48,7 +48,7 @@
Welcome!
Support - + Logout diff --git a/src/app/components/navbar/navbar.component.ts b/src/app/components/navbar/navbar.component.ts index e4dd9fb8..a61b6f40 100644 --- a/src/app/components/navbar/navbar.component.ts +++ b/src/app/components/navbar/navbar.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit, ElementRef } from '@angular/core'; import { ROUTES } from '../sidebar/sidebar.component'; import { Location, LocationStrategy, PathLocationStrategy } from '@angular/common'; import { Router } from '@angular/router'; +import { AuthService } from 'src/app/services/auth.service'; @Component({ selector: 'app-navbar', @@ -12,7 +13,7 @@ export class NavbarComponent implements OnInit { public focus; public listTitles: any[]; public location: Location; - constructor(location: Location, private element: ElementRef, private router: Router) { + constructor(location: Location, private element: ElementRef, private router: Router, private authService: AuthService) { this.location = location; } @@ -33,4 +34,9 @@ export class NavbarComponent implements OnInit { return 'Dashboard'; } + logout(){ + this.authService.logout(); + this.router.navigate(['auth/login']) + } + } diff --git a/src/app/components/sidebar/sidebar.component.ts b/src/app/components/sidebar/sidebar.component.ts index e8e392eb..dde41c78 100644 --- a/src/app/components/sidebar/sidebar.component.ts +++ b/src/app/components/sidebar/sidebar.component.ts @@ -8,13 +8,13 @@ declare interface RouteInfo { class: string; } export const ROUTES: RouteInfo[] = [ - { path: '/dashboard', title: 'Dashboard', icon: 'ni-tv-2 text-primary', class: '' }, - { path: '/icons', title: 'Icons', icon:'ni-planet text-blue', class: '' }, - { path: '/maps', title: 'Maps', icon:'ni-pin-3 text-orange', class: '' }, - { path: '/user-profile', title: 'User profile', icon:'ni-single-02 text-yellow', class: '' }, - { path: '/tables', title: 'Tables', icon:'ni-bullet-list-67 text-red', class: '' }, - { path: '/login', title: 'Login', icon:'ni-key-25 text-info', class: '' }, - { path: '/register', title: 'Register', icon:'ni-circle-08 text-pink', class: '' } + { path: '/admin/dashboard', title: 'Dashboard', icon: 'ni-tv-2 text-primary', class: '' }, + { path: '/admin/icons', title: 'Icons', icon:'ni-planet text-blue', class: '' }, + { path: '/admin/maps', title: 'Maps', icon:'ni-pin-3 text-orange', class: '' }, + { path: '/admin/user-profile', title: 'User profile', icon:'ni-single-02 text-yellow', class: '' }, + { path: '/admin/tables', title: 'Tables', icon:'ni-bullet-list-67 text-red', class: '' }, + { path: '/admin/login', title: 'Login', icon:'ni-key-25 text-info', class: '' }, + { path: '/admin/register', title: 'Register', icon:'ni-circle-08 text-pink', class: '' } ]; @Component({ diff --git a/src/app/guards/auth.guard.ts b/src/app/guards/auth.guard.ts new file mode 100644 index 00000000..6de08d69 --- /dev/null +++ b/src/app/guards/auth.guard.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router'; +import { AuthService } from '../services/auth.service'; + +@Injectable({ + providedIn: 'root' +}) +export class AuthGuard implements CanActivate { + constructor(private authService: AuthService, private router: Router) {} + + canActivate(route: ActivatedRouteSnapshot): boolean { + const isLoggedIn = this.authService.isLoggedIn(); + const userRole = this.authService.getUserRole(); + const routePath = route.routeConfig?.path; + + if (isLoggedIn) { + // User is logged in + if (routePath === 'auth/login') { + // Redirect logged-in users away from the login page + this.router.navigate([`/${userRole}/dashboard`]); + return false; // Prevent further navigation + } + + // Allow access to routes based on user role + if (routePath === userRole || routePath === `${userRole}/dashboard` || routePath === '${userRole}/icons') { + return true; + } + + // Redirect to the respective dashboard if unauthorized + // this.router.navigate([`/${userRole}/dashboard`]); + return false; // Prevent access to the current route + } else { + // User is not logged in + if (routePath !== 'auth/login') { + // Redirect to the login page if not logged in and trying to access protected routes + this.router.navigate(['/auth/login']); + return false; // Prevent access to the current route + } + + // Allow access to the login page + return true; + } + } +} diff --git a/src/app/pages/login/login.component.ts b/src/app/pages/login/login.component.ts index 1ddde478..b3ff7956 100644 --- a/src/app/pages/login/login.component.ts +++ b/src/app/pages/login/login.component.ts @@ -1,6 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { AuthService } from 'src/app/services/auth.service'; +import { NavigationService } from 'src/app/services/navigation.service'; @Component({ selector: 'app-login', @@ -14,7 +15,8 @@ export class LoginComponent implements OnInit { constructor( private authService: AuthService, - private router: Router + private router: Router, + private navigationService: NavigationService ) {} ngOnInit() {} @@ -28,11 +30,7 @@ export class LoginComponent implements OnInit { const role = this.authService.getUserRole(); console.log('User role:', role); // Redirect based on role - if (role === 'custodian') { - this.router.navigate(['/dashboard']); // Adjust as needed - } else { - this.router.navigate(['/dashboard']); // Adjust as needed - } + this.navigationService.redirectBasedOnRole(role) } else { this.errorMessage = 'Login failed'; } @@ -41,4 +39,20 @@ export class LoginComponent implements OnInit { this.errorMessage = 'An error occurred during login'; } } + + private redirectBasedOnRole(role: string | null) { + switch (role) { + case 'admin': + this.router.navigate(['/admin/dashboard']); + break; + case 'student': + this.router.navigate(['/student/dashboard']); + break; + case 'custodian': + this.router.navigate(['/custodian/dashboard']); + break; + default: + this.router.navigate(['/auth/login']); + } + } } diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts index fd1bbcad..998ffd12 100644 --- a/src/app/services/auth.service.ts +++ b/src/app/services/auth.service.ts @@ -23,6 +23,7 @@ export class AuthService { const user = snapshot.docs[0].data() as User; if (user.password === password) { this.userSubject.next(user); + this.saveUserToLocalStorage(user); resolve(true); // Login successful } else { resolve(false); // Incorrect password @@ -41,10 +42,22 @@ export class AuthService { const user = this.userSubject.value; return user ? user.role || null : null; } - + + private saveUserToLocalStorage(user: User | null) { + if (user) { + localStorage.setItem('user', JSON.stringify(user)); + } else { + localStorage.removeItem('user'); + } + } + + isLoggedIn(): boolean { + return !!localStorage.getItem('user'); + } // Method to log out logout() { this.userSubject.next(null); // Clear user data + this.saveUserToLocalStorage(null); // Remove user from localStorage } } diff --git a/src/app/services/navigation.service.ts b/src/app/services/navigation.service.ts new file mode 100644 index 00000000..0f5cc1d0 --- /dev/null +++ b/src/app/services/navigation.service.ts @@ -0,0 +1,36 @@ +import { Injectable } from '@angular/core'; +import { Router } from '@angular/router'; +import { AuthService } from './auth.service'; + +@Injectable({ + providedIn: 'root' +}) +export class NavigationService { + + constructor(private authService: AuthService, private router: Router) {} + + // Redirect based on the user's role + redirectBasedOnRole(role: string | null) { + switch (role) { + case 'admin': + this.router.navigate(['/admin/dashboard']); + break; + case 'student': + this.router.navigate(['/student/dashboard']); + break; + case 'custodian': + this.router.navigate(['/custodian/dashboard']); + break; + default: + this.router.navigate(['/auth/login']); + } + } + + // Redirect user if already logged in + redirectIfLoggedIn() { + if (this.authService.isLoggedIn()) { + const role = this.authService.getUserRole(); + this.redirectBasedOnRole(role); + } + } +} From 675d8151f0af1ebf3ad76d8183fab15bf5f3056e Mon Sep 17 00:00:00 2001 From: redmanuel1 Date: Thu, 12 Sep 2024 15:07:50 +0800 Subject: [PATCH 5/9] admin-routing --- .../components/sidebar/sidebar.component.ts | 23 +++++++++++-------- .../admin-layout/admin-layout.component.html | 2 +- .../admin-layout/admin-layout.component.ts | 10 ++++++++ src/app/models/routes.model.ts | 6 +++++ 4 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 src/app/models/routes.model.ts diff --git a/src/app/components/sidebar/sidebar.component.ts b/src/app/components/sidebar/sidebar.component.ts index dde41c78..fcf9216a 100644 --- a/src/app/components/sidebar/sidebar.component.ts +++ b/src/app/components/sidebar/sidebar.component.ts @@ -1,12 +1,13 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import { Router } from '@angular/router'; +import { RouteInfo } from 'src/app/models/routes.model'; -declare interface RouteInfo { - path: string; - title: string; - icon: string; - class: string; -} +// declare interface RouteInfo { +// path: string; +// title: string; +// icon: string; +// class: string; +// } export const ROUTES: RouteInfo[] = [ { path: '/admin/dashboard', title: 'Dashboard', icon: 'ni-tv-2 text-primary', class: '' }, { path: '/admin/icons', title: 'Icons', icon:'ni-planet text-blue', class: '' }, @@ -26,13 +27,17 @@ export class SidebarComponent implements OnInit { public menuItems: any[]; public isCollapsed = true; + @Input() routes : RouteInfo[]; constructor(private router: Router) { } + ngOnInit() { - this.menuItems = ROUTES.filter(menuItem => menuItem); + if (this.routes) { + this.menuItems = this.routes.filter(menuItem => menuItem); + } this.router.events.subscribe((event) => { this.isCollapsed = true; - }); + }); } } diff --git a/src/app/layouts/admin-layout/admin-layout.component.html b/src/app/layouts/admin-layout/admin-layout.component.html index fe755a73..401d6503 100644 --- a/src/app/layouts/admin-layout/admin-layout.component.html +++ b/src/app/layouts/admin-layout/admin-layout.component.html @@ -1,5 +1,5 @@ - +
diff --git a/src/app/layouts/admin-layout/admin-layout.component.ts b/src/app/layouts/admin-layout/admin-layout.component.ts index ed43be94..db739c6f 100644 --- a/src/app/layouts/admin-layout/admin-layout.component.ts +++ b/src/app/layouts/admin-layout/admin-layout.component.ts @@ -1,4 +1,6 @@ import { Component, OnInit } from '@angular/core'; +import { AdminLayoutRoutes } from './admin-layout.routing'; +import { RouteInfo } from 'src/app/models/routes.model'; @Component({ selector: 'app-admin-layout', @@ -6,10 +8,18 @@ import { Component, OnInit } from '@angular/core'; styleUrls: ['./admin-layout.component.scss'] }) export class AdminLayoutComponent implements OnInit { + adminRoutes:RouteInfo[] = []; constructor() { } ngOnInit() { + this.adminRoutes = [ + { path: 'dashboard', title: 'Dashboard', icon: 'ni-tv-2 text-primary', class: '' }, + { path: 'user-profile', title: 'User Profile', icon: 'ni-single-02 text-yellow', class: '' }, + { path: 'tables', title: 'Tables', icon: 'ni-bullet-list-67 text-red', class: '' }, + { path: 'icons', title: 'Icons', icon: 'ni-planet text-blue', class: '' }, + { path: 'maps', title: 'Maps', icon: 'ni-pin-3 text-orange', class: '' } + ]; } } diff --git a/src/app/models/routes.model.ts b/src/app/models/routes.model.ts new file mode 100644 index 00000000..21bbea46 --- /dev/null +++ b/src/app/models/routes.model.ts @@ -0,0 +1,6 @@ +export interface RouteInfo { + path: string; + title: string; + icon: string; + class: string; +} \ No newline at end of file From 06b2a2b340cd721a9be82b3eebf74945b4416452 Mon Sep 17 00:00:00 2001 From: redmanuel1 Date: Thu, 12 Sep 2024 17:53:58 +0800 Subject: [PATCH 6/9] add student module and logout --- src/app/app.module.ts | 4 ++- src/app/app.routing.ts | 12 +++++++++ src/app/components/navbar/navbar.component.ts | 2 +- src/app/guards/auth.guard.ts | 24 +++++++++--------- .../student-layout.component.html | 11 ++++++++ .../student-layout.component.scss | 0 .../student-layout.component.spec.ts | 23 +++++++++++++++++ .../student-layout.component.ts | 25 +++++++++++++++++++ .../student-layout/student-layout.module.ts | 24 ++++++++++++++++++ .../student-layout/student-layout.routing.ts | 11 ++++++++ 10 files changed, 122 insertions(+), 14 deletions(-) create mode 100644 src/app/layouts/student-layout/student-layout.component.html create mode 100644 src/app/layouts/student-layout/student-layout.component.scss create mode 100644 src/app/layouts/student-layout/student-layout.component.spec.ts create mode 100644 src/app/layouts/student-layout/student-layout.component.ts create mode 100644 src/app/layouts/student-layout/student-layout.module.ts create mode 100644 src/app/layouts/student-layout/student-layout.routing.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 031e737b..cdcd31ae 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -17,6 +17,7 @@ import { AngularFireModule } from '@angular/fire/compat'; import { AngularFireAuthModule } from '@angular/fire/compat/auth'; import { AngularFirestoreModule } from '@angular/fire/compat/firestore'; import { ToastrModule } from 'ngx-toastr'; +import { StudentLayoutComponent } from './layouts/student-layout/student-layout.component'; @NgModule({ @@ -36,7 +37,8 @@ import { ToastrModule } from 'ngx-toastr'; declarations: [ AppComponent, AdminLayoutComponent, - AuthLayoutComponent + AuthLayoutComponent, + StudentLayoutComponent ], providers: [], bootstrap: [AppComponent] diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index ce710ec8..842d05c6 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -6,6 +6,7 @@ import { Routes, RouterModule } from '@angular/router'; import { AdminLayoutComponent } from './layouts/admin-layout/admin-layout.component'; import { AuthLayoutComponent } from './layouts/auth-layout/auth-layout.component'; import { AuthGuard } from './guards/auth.guard'; +import { StudentLayoutComponent } from './layouts/student-layout/student-layout.component'; const routes: Routes =[ { @@ -22,6 +23,17 @@ const routes: Routes =[ loadChildren: () => import('src/app/layouts/admin-layout/admin-layout.module').then(m => m.AdminLayoutModule) } ] + }, + { + path: 'student', + component: StudentLayoutComponent, + canActivate: [AuthGuard], // Add role guard to check if the user is a student + children: [ + { + path: '', + loadChildren: () => import('./layouts/student-layout/student-layout.module').then(m => m.StudentLayoutModule) + } + ] }, { path: 'auth', component: AuthLayoutComponent, diff --git a/src/app/components/navbar/navbar.component.ts b/src/app/components/navbar/navbar.component.ts index a61b6f40..a6836027 100644 --- a/src/app/components/navbar/navbar.component.ts +++ b/src/app/components/navbar/navbar.component.ts @@ -36,7 +36,7 @@ export class NavbarComponent implements OnInit { logout(){ this.authService.logout(); - this.router.navigate(['auth/login']) + this.router.navigate(['/auth/login']) } } diff --git a/src/app/guards/auth.guard.ts b/src/app/guards/auth.guard.ts index 6de08d69..476fc639 100644 --- a/src/app/guards/auth.guard.ts +++ b/src/app/guards/auth.guard.ts @@ -13,31 +13,31 @@ export class AuthGuard implements CanActivate { const userRole = this.authService.getUserRole(); const routePath = route.routeConfig?.path; + console.log('isLoggedIn:', isLoggedIn); + console.log('userRole:', userRole); + console.log('routePath:', routePath); + if (isLoggedIn) { - // User is logged in + // Redirect logged-in users away from the login page if (routePath === 'auth/login') { - // Redirect logged-in users away from the login page this.router.navigate([`/${userRole}/dashboard`]); - return false; // Prevent further navigation + return false; } - + // Allow access to routes based on user role - if (routePath === userRole || routePath === `${userRole}/dashboard` || routePath === '${userRole}/icons') { + if (routePath === userRole || routePath === `${userRole}/dashboard` || routePath === `${userRole}/icons`) { return true; } // Redirect to the respective dashboard if unauthorized - // this.router.navigate([`/${userRole}/dashboard`]); - return false; // Prevent access to the current route + this.router.navigate([`/${userRole}/dashboard`]); + return false; } else { - // User is not logged in + // Redirect to the login page if not logged in and trying to access protected routes if (routePath !== 'auth/login') { - // Redirect to the login page if not logged in and trying to access protected routes this.router.navigate(['/auth/login']); - return false; // Prevent access to the current route + return false; } - - // Allow access to the login page return true; } } diff --git a/src/app/layouts/student-layout/student-layout.component.html b/src/app/layouts/student-layout/student-layout.component.html new file mode 100644 index 00000000..64424358 --- /dev/null +++ b/src/app/layouts/student-layout/student-layout.component.html @@ -0,0 +1,11 @@ + + +
+ + + + +
+ +
+
diff --git a/src/app/layouts/student-layout/student-layout.component.scss b/src/app/layouts/student-layout/student-layout.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/layouts/student-layout/student-layout.component.spec.ts b/src/app/layouts/student-layout/student-layout.component.spec.ts new file mode 100644 index 00000000..ca62e76b --- /dev/null +++ b/src/app/layouts/student-layout/student-layout.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { StudentLayoutComponent } from './student-layout.component'; + +describe('StudentLayoutComponent', () => { + let component: StudentLayoutComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ StudentLayoutComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(StudentLayoutComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/layouts/student-layout/student-layout.component.ts b/src/app/layouts/student-layout/student-layout.component.ts new file mode 100644 index 00000000..4e7c8704 --- /dev/null +++ b/src/app/layouts/student-layout/student-layout.component.ts @@ -0,0 +1,25 @@ +import { Component, OnInit } from '@angular/core'; +import { RouteInfo } from 'src/app/models/routes.model'; + +@Component({ + selector: 'app-student-layout', + templateUrl: './student-layout.component.html', + styleUrls: ['./student-layout.component.scss'] +}) +export class StudentLayoutComponent implements OnInit { + studentRoutes: RouteInfo[] = [] + + constructor() { } + + ngOnInit() { + this.studentRoutes = [ + { path: 'dashboard', title: 'Dashboard', icon: 'ni-tv-2 text-primary', class: '' }, + { path: 'user-profile', title: 'User Profile', icon: 'ni-single-02 text-yellow', class: '' }, + { path: 'tables', title: 'Tables', icon: 'ni-bullet-list-67 text-red', class: '' }, + { path: 'icons', title: 'Icons', icon: 'ni-planet text-blue', class: '' }, + { path: 'maps', title: 'Maps', icon: 'ni-pin-3 text-orange', class: '' } + ]; + } + + +} diff --git a/src/app/layouts/student-layout/student-layout.module.ts b/src/app/layouts/student-layout/student-layout.module.ts new file mode 100644 index 00000000..976124e5 --- /dev/null +++ b/src/app/layouts/student-layout/student-layout.module.ts @@ -0,0 +1,24 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { StudentLayoutRoutes } from './student-layout.routing'; +import { RouterModule } from '@angular/router'; +import { StudentLayoutComponent } from './student-layout.component'; +import { FormsModule } from '@angular/forms'; +import { HttpClientModule } from '@angular/common/http'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { ClipboardModule } from 'ngx-clipboard'; + + +@NgModule({ + declarations: [], + imports: [ + CommonModule, + RouterModule.forChild(StudentLayoutRoutes), + FormsModule, + HttpClientModule, + NgbModule, + ClipboardModule + ] +}) +export class StudentLayoutModule { } diff --git a/src/app/layouts/student-layout/student-layout.routing.ts b/src/app/layouts/student-layout/student-layout.routing.ts new file mode 100644 index 00000000..0ea72c39 --- /dev/null +++ b/src/app/layouts/student-layout/student-layout.routing.ts @@ -0,0 +1,11 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { StudentLayoutComponent } from './student-layout.component'; +import { DashboardComponent } from 'src/app/pages/dashboard/dashboard.component'; +import { UserProfileComponent } from 'src/app/pages/user-profile/user-profile.component'; + +export const StudentLayoutRoutes: Routes = [ + { path: 'dashboard', component: DashboardComponent }, + { path: 'user-profile', component: UserProfileComponent }, + +]; \ No newline at end of file From bc8c486ec596c8c1573934a3adeb5312e2ae2d0b Mon Sep 17 00:00:00 2001 From: redmanuel1 Date: Thu, 12 Sep 2024 22:02:40 +0800 Subject: [PATCH 7/9] routing and products template --- .../components/cards/item/item.component.html | 8 +++++ .../components/cards/item/item.component.scss | 0 .../cards/item/item.component.spec.ts | 23 ++++++++++++++ .../components/cards/item/item.component.ts | 15 ++++++++++ src/app/components/components.module.ts | 7 +++-- src/app/components/navbar/navbar.component.ts | 30 +++++++++++-------- .../admin-layout/admin-layout.component.ts | 10 ++----- src/app/layouts/routes.ts | 17 +++++++++++ .../student-layout.component.html | 7 +++++ .../student-layout.component.ts | 11 ++----- .../student-layout/student-layout.module.ts | 8 +++-- .../student-layout/student-layout.routing.ts | 4 ++- .../student/products/products.component.html | 2 ++ .../student/products/products.component.scss | 0 .../products/products.component.spec.ts | 23 ++++++++++++++ .../student/products/products.component.ts | 14 +++++++++ 16 files changed, 145 insertions(+), 34 deletions(-) create mode 100644 src/app/components/cards/item/item.component.html create mode 100644 src/app/components/cards/item/item.component.scss create mode 100644 src/app/components/cards/item/item.component.spec.ts create mode 100644 src/app/components/cards/item/item.component.ts create mode 100644 src/app/layouts/routes.ts create mode 100644 src/app/pages/student/products/products.component.html create mode 100644 src/app/pages/student/products/products.component.scss create mode 100644 src/app/pages/student/products/products.component.spec.ts create mode 100644 src/app/pages/student/products/products.component.ts diff --git a/src/app/components/cards/item/item.component.html b/src/app/components/cards/item/item.component.html new file mode 100644 index 00000000..02dd2f08 --- /dev/null +++ b/src/app/components/cards/item/item.component.html @@ -0,0 +1,8 @@ +
+ Card image cap +
+
Card title
+

Some quick example text to build on the card title and make up the bulk of the card's content.

+ Go somewhere +
+
\ No newline at end of file diff --git a/src/app/components/cards/item/item.component.scss b/src/app/components/cards/item/item.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/components/cards/item/item.component.spec.ts b/src/app/components/cards/item/item.component.spec.ts new file mode 100644 index 00000000..03c464ad --- /dev/null +++ b/src/app/components/cards/item/item.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ItemComponent } from './item.component'; + +describe('ItemComponent', () => { + let component: ItemComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ItemComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ItemComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/cards/item/item.component.ts b/src/app/components/cards/item/item.component.ts new file mode 100644 index 00000000..e0f2de5d --- /dev/null +++ b/src/app/components/cards/item/item.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-item', + templateUrl: './item.component.html', + styleUrls: ['./item.component.scss'] +}) +export class ItemComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/src/app/components/components.module.ts b/src/app/components/components.module.ts index b1add21a..ca3ea568 100644 --- a/src/app/components/components.module.ts +++ b/src/app/components/components.module.ts @@ -5,6 +5,7 @@ import { NavbarComponent } from './navbar/navbar.component'; import { FooterComponent } from './footer/footer.component'; import { RouterModule } from '@angular/router'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { ItemComponent } from './cards/item/item.component'; @NgModule({ imports: [ @@ -15,12 +16,14 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; declarations: [ FooterComponent, NavbarComponent, - SidebarComponent + SidebarComponent, + ItemComponent ], exports: [ FooterComponent, NavbarComponent, - SidebarComponent + SidebarComponent, + ItemComponent ] }) export class ComponentsModule { } diff --git a/src/app/components/navbar/navbar.component.ts b/src/app/components/navbar/navbar.component.ts index a6836027..f20d3bd5 100644 --- a/src/app/components/navbar/navbar.component.ts +++ b/src/app/components/navbar/navbar.component.ts @@ -1,8 +1,9 @@ -import { Component, OnInit, ElementRef } from '@angular/core'; -import { ROUTES } from '../sidebar/sidebar.component'; +import { Component, OnInit, ElementRef, Input } from '@angular/core'; +// import { ROUTES } from '../sidebar/sidebar.component'; import { Location, LocationStrategy, PathLocationStrategy } from '@angular/common'; import { Router } from '@angular/router'; import { AuthService } from 'src/app/services/auth.service'; +import { RouteInfo } from 'src/app/models/routes.model'; @Component({ selector: 'app-navbar', @@ -10,6 +11,8 @@ import { AuthService } from 'src/app/services/auth.service'; styleUrls: ['./navbar.component.scss'] }) export class NavbarComponent implements OnInit { + // @Input() routes: RouteInfo[]; + public focus; public listTitles: any[]; public location: Location; @@ -18,20 +21,21 @@ export class NavbarComponent implements OnInit { } ngOnInit() { - this.listTitles = ROUTES.filter(listTitle => listTitle); + // if (this.routes) { + // this.listTitles = this.routes.filter(listTitle => listTitle); + // } else { + // this.listTitles = ROUTES.filter(listTitle => listTitle); + // } + } getTitle(){ - var titlee = this.location.prepareExternalUrl(this.location.path()); - if(titlee.charAt(0) === '#'){ - titlee = titlee.slice( 1 ); - } - - for(var item = 0; item < this.listTitles.length; item++){ - if(this.listTitles[item].path === titlee){ - return this.listTitles[item].title; - } + const titlee = this.location.prepareExternalUrl(this.location.path()); //eg. /student/dashboard + const titleArr = titlee.split("/"); + let title = "Dashboard"; + if (titleArr.length > 0) { + title = titleArr.pop(); } - return 'Dashboard'; + return title; // default is Dashboard } logout(){ diff --git a/src/app/layouts/admin-layout/admin-layout.component.ts b/src/app/layouts/admin-layout/admin-layout.component.ts index db739c6f..1b6b22b2 100644 --- a/src/app/layouts/admin-layout/admin-layout.component.ts +++ b/src/app/layouts/admin-layout/admin-layout.component.ts @@ -1,6 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { AdminLayoutRoutes } from './admin-layout.routing'; import { RouteInfo } from 'src/app/models/routes.model'; +import { ADMIN_ROUTES } from '../routes'; @Component({ selector: 'app-admin-layout', @@ -8,18 +9,11 @@ import { RouteInfo } from 'src/app/models/routes.model'; styleUrls: ['./admin-layout.component.scss'] }) export class AdminLayoutComponent implements OnInit { - adminRoutes:RouteInfo[] = []; + adminRoutes:RouteInfo[] = ADMIN_ROUTES; constructor() { } ngOnInit() { - this.adminRoutes = [ - { path: 'dashboard', title: 'Dashboard', icon: 'ni-tv-2 text-primary', class: '' }, - { path: 'user-profile', title: 'User Profile', icon: 'ni-single-02 text-yellow', class: '' }, - { path: 'tables', title: 'Tables', icon: 'ni-bullet-list-67 text-red', class: '' }, - { path: 'icons', title: 'Icons', icon: 'ni-planet text-blue', class: '' }, - { path: 'maps', title: 'Maps', icon: 'ni-pin-3 text-orange', class: '' } - ]; } } diff --git a/src/app/layouts/routes.ts b/src/app/layouts/routes.ts new file mode 100644 index 00000000..eab5c1b1 --- /dev/null +++ b/src/app/layouts/routes.ts @@ -0,0 +1,17 @@ +import { RouteInfo } from "../models/routes.model"; + +export const ADMIN_ROUTES: RouteInfo[] = [ + { path: 'dashboard', title: 'Dashboard', icon: 'ni-tv-2 text-primary', class: '' }, + { path: 'user-profile', title: 'User Profile', icon: 'ni-single-02 text-yellow', class: '' }, + { path: 'tables', title: 'Tables', icon: 'ni-bullet-list-67 text-red', class: '' }, + { path: 'icons', title: 'Icons', icon: 'ni-planet text-blue', class: '' }, + { path: 'maps', title: 'Maps', icon: 'ni-pin-3 text-orange', class: '' } +]; + +export const STUDENT_ROUTES: RouteInfo[] = [ + { path: 'dashboard', title: 'Dashboard', icon: 'ni-tv-2 text-primary', class: '' }, + { path: 'user-profile', title: 'User Profile', icon: 'ni-single-02 text-yellow', class: '' }, + { path: 'products', title: 'Products', icon: 'ni-bullet-list-67 text-red', class: '' }, + { path: 'icons', title: 'Icons', icon: 'ni-planet text-blue', class: '' }, + { path: 'maps', title: 'Maps', icon: 'ni-pin-3 text-orange', class: '' } +]; diff --git a/src/app/layouts/student-layout/student-layout.component.html b/src/app/layouts/student-layout/student-layout.component.html index 64424358..7768729b 100644 --- a/src/app/layouts/student-layout/student-layout.component.html +++ b/src/app/layouts/student-layout/student-layout.component.html @@ -1,6 +1,13 @@
+ +
+
+
+
+
+
diff --git a/src/app/layouts/student-layout/student-layout.component.ts b/src/app/layouts/student-layout/student-layout.component.ts index 4e7c8704..398b0186 100644 --- a/src/app/layouts/student-layout/student-layout.component.ts +++ b/src/app/layouts/student-layout/student-layout.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { RouteInfo } from 'src/app/models/routes.model'; +import { STUDENT_ROUTES } from '../routes'; @Component({ selector: 'app-student-layout', @@ -7,18 +8,12 @@ import { RouteInfo } from 'src/app/models/routes.model'; styleUrls: ['./student-layout.component.scss'] }) export class StudentLayoutComponent implements OnInit { - studentRoutes: RouteInfo[] = [] + studentRoutes: RouteInfo[] = STUDENT_ROUTES; constructor() { } ngOnInit() { - this.studentRoutes = [ - { path: 'dashboard', title: 'Dashboard', icon: 'ni-tv-2 text-primary', class: '' }, - { path: 'user-profile', title: 'User Profile', icon: 'ni-single-02 text-yellow', class: '' }, - { path: 'tables', title: 'Tables', icon: 'ni-bullet-list-67 text-red', class: '' }, - { path: 'icons', title: 'Icons', icon: 'ni-planet text-blue', class: '' }, - { path: 'maps', title: 'Maps', icon: 'ni-pin-3 text-orange', class: '' } - ]; + } diff --git a/src/app/layouts/student-layout/student-layout.module.ts b/src/app/layouts/student-layout/student-layout.module.ts index 976124e5..ca919691 100644 --- a/src/app/layouts/student-layout/student-layout.module.ts +++ b/src/app/layouts/student-layout/student-layout.module.ts @@ -3,17 +3,21 @@ import { CommonModule } from '@angular/common'; import { StudentLayoutRoutes } from './student-layout.routing'; import { RouterModule } from '@angular/router'; -import { StudentLayoutComponent } from './student-layout.component'; import { FormsModule } from '@angular/forms'; import { HttpClientModule } from '@angular/common/http'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { ClipboardModule } from 'ngx-clipboard'; +import { ProductsComponent } from 'src/app/pages/student/products/products.component'; +import { ComponentsModule } from 'src/app/components/components.module'; @NgModule({ - declarations: [], + declarations: [ + ProductsComponent + ], imports: [ CommonModule, + ComponentsModule, RouterModule.forChild(StudentLayoutRoutes), FormsModule, HttpClientModule, diff --git a/src/app/layouts/student-layout/student-layout.routing.ts b/src/app/layouts/student-layout/student-layout.routing.ts index 0ea72c39..8e6cb248 100644 --- a/src/app/layouts/student-layout/student-layout.routing.ts +++ b/src/app/layouts/student-layout/student-layout.routing.ts @@ -1,11 +1,13 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { StudentLayoutComponent } from './student-layout.component'; import { DashboardComponent } from 'src/app/pages/dashboard/dashboard.component'; +import { ProductsComponent } from 'src/app/pages/student/products/products.component'; import { UserProfileComponent } from 'src/app/pages/user-profile/user-profile.component'; export const StudentLayoutRoutes: Routes = [ { path: 'dashboard', component: DashboardComponent }, { path: 'user-profile', component: UserProfileComponent }, + { path: 'products', component: ProductsComponent }, + ]; \ No newline at end of file diff --git a/src/app/pages/student/products/products.component.html b/src/app/pages/student/products/products.component.html new file mode 100644 index 00000000..7520beda --- /dev/null +++ b/src/app/pages/student/products/products.component.html @@ -0,0 +1,2 @@ +

products works!

+ \ No newline at end of file diff --git a/src/app/pages/student/products/products.component.scss b/src/app/pages/student/products/products.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/pages/student/products/products.component.spec.ts b/src/app/pages/student/products/products.component.spec.ts new file mode 100644 index 00000000..623e5fef --- /dev/null +++ b/src/app/pages/student/products/products.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProductsComponent } from './products.component'; + +describe('ProductsComponent', () => { + let component: ProductsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ProductsComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ProductsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/pages/student/products/products.component.ts b/src/app/pages/student/products/products.component.ts new file mode 100644 index 00000000..8c2c5fcf --- /dev/null +++ b/src/app/pages/student/products/products.component.ts @@ -0,0 +1,14 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-products', + templateUrl: './products.component.html', + styleUrls: ['./products.component.scss'] +}) +export class ProductsComponent implements OnInit { + constructor() { } + + ngOnInit(): void { + } + +} From 6a4cd853b50972ad53bdcf6b04edc72557b2130c Mon Sep 17 00:00:00 2001 From: redmanuel1 Date: Thu, 12 Sep 2024 22:10:48 +0800 Subject: [PATCH 8/9] loginguard --- src/app/guards/auth.guard.ts | 71 ++++++++++++++++++++++++++++++ src/app/guards/login.guard.spec.ts | 16 +++++++ src/app/guards/login.guard.ts | 30 +++++++++++++ src/app/services/auth.service.ts | 65 +++++++++++++++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 src/app/guards/auth.guard.ts create mode 100644 src/app/guards/login.guard.spec.ts create mode 100644 src/app/guards/login.guard.ts create mode 100644 src/app/services/auth.service.ts diff --git a/src/app/guards/auth.guard.ts b/src/app/guards/auth.guard.ts new file mode 100644 index 00000000..f278858d --- /dev/null +++ b/src/app/guards/auth.guard.ts @@ -0,0 +1,71 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; +import { Observable } from 'rxjs'; +import { AuthService } from '../services/auth.service'; + +@Injectable({ + providedIn: 'root' +}) +export class AuthGuard implements CanActivate { + constructor(private authService: AuthService, private router: Router) {} + + canActivate(route: ActivatedRouteSnapshot): boolean { + const isLoggedIn = this.authService.isLoggedIn(); + const userRole = this.authService.getUserRole(); + const routePath = route.routeConfig?.path; + + if (routePath === 'logout') { + // Handle logout + this.authService.logout(); + this.router.navigate(['/auth/login']); + return false; // Prevent further navigation + } + + if (isLoggedIn) { + // Redirect logged-in users away from login page + if (routePath === 'auth/login') { + this.router.navigate([`/${userRole}/dashboard`]); + return false; + } + + // Allow access to routes based on user role + if (routePath === userRole) { + return true; + } + + // Redirect to the respective dashboard if unauthorized + this.router.navigate([`/${userRole}/dashboard`]); + return false; + } else { + // Redirect not-logged-in users to the login page + if (routePath !== 'auth/login') { + this.router.navigate(['/auth/login']); + } + return false; + } + + // const userRole = this.authService.getUserRole(); // Retrieve the user role + // const isLoggedIn = this.authService.isLoggedIn(); // Check if the user is logged in + + // if (isLoggedIn) { + // // If the user is logged in, check their role and redirect if necessary + // if (route.routeConfig?.path === 'student' && userRole === 'student') { + // return true; // Allow access to student route + // } else if (userRole === 'admin') { + // this.router.navigate(['/admin/dashboard']); // Redirect admin to admin dashboard + // return false; // Block the current navigation + // } else if (userRole === 'custodian') { + // this.router.navigate(['/custodian/dashboard']); // Redirect custodian to custodian dashboard + // return false; // Block the current navigation + // } else { + // // Handle any other roles if necessary + // return false; + // } + // } else { + // // If not logged in, redirect to the login page + // this.router.navigate(['/auth/login']); + // return false; // Block access to the route + // } + } + +} diff --git a/src/app/guards/login.guard.spec.ts b/src/app/guards/login.guard.spec.ts new file mode 100644 index 00000000..38aefa04 --- /dev/null +++ b/src/app/guards/login.guard.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { LoginGuard } from './login.guard'; + +describe('LoginGuard', () => { + let guard: LoginGuard; + + beforeEach(() => { + TestBed.configureTestingModule({}); + guard = TestBed.inject(LoginGuard); + }); + + it('should be created', () => { + expect(guard).toBeTruthy(); + }); +}); diff --git a/src/app/guards/login.guard.ts b/src/app/guards/login.guard.ts new file mode 100644 index 00000000..14ead011 --- /dev/null +++ b/src/app/guards/login.guard.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; +import { Observable } from 'rxjs'; +import { AuthService } from '../services/auth.service'; + +@Injectable({ + providedIn: 'root' +}) +export class LoginGuard implements CanActivate { + constructor(private authService: AuthService, private router: Router){ + + } + + canActivate(): boolean { + if (this.authService.isLoggedIn()) { + // If the user is logged in, redirect them to their dashboard + const role = this.authService.getUserRole(); + if (role === 'admin') { + this.router.navigate(['/admin/dashboard']); + } else if (role === 'student') { + this.router.navigate(['/student/dashboard']); + } else if (role === 'custodian') { + this.router.navigate(['/custodian/dashboard']); + } + return false; // Prevent navigation to the login page + } + return true; // Allow navigation to the login page if not logged in + } + +} diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts new file mode 100644 index 00000000..6bab64b0 --- /dev/null +++ b/src/app/services/auth.service.ts @@ -0,0 +1,65 @@ +import { User } from './../models/user.model'; +import { Injectable } from '@angular/core'; +import { AngularFirestore } from '@angular/fire/compat/firestore'; +import { BehaviorSubject, Observable } from 'rxjs'; + + +@Injectable({ + providedIn: 'root' +}) +export class AuthService { + private userSubject: BehaviorSubject = new BehaviorSubject(null); + public user$: Observable = this.userSubject.asObservable(); + + constructor(private firestore: AngularFirestore) { + // Initialize user data from localStorage if available + const storedUser = localStorage.getItem('authUser'); + if (storedUser) { + this.userSubject.next(JSON.parse(storedUser)); + } + } + + // Method to login the user + login(idNo: string, password: string): Promise { + return new Promise((resolve, reject) => { + this.firestore.collection('Users', ref => ref.where('idNo', '==', idNo)) + .get() + .subscribe(snapshot => { + if (!snapshot.empty) { + const user = snapshot.docs[0].data() as User; + if (user.password === password) { + + // Store user in localStorage + localStorage.setItem('authUser', JSON.stringify(user)); + + this.userSubject.next(user); + resolve(true); // Login successful + } else { + resolve(false); // Incorrect password + } + } else { + resolve(false); // User not found + } + }, error => { + console.error("Error during login:", error); + reject(false); // Login failed + }); + }); + } + + getUserRole(): string | null { + const user = this.userSubject.value; + return user ? user.role || null : null; + } + + // Method to check if user is logged in + isLoggedIn(): boolean { + return this.userSubject.value !== null; + } + + // Method to log out + logout() { + localStorage.removeItem('authUser'); // Clear user data from localStorage + this.userSubject.next(null); // Clear user data + } +} From 94afdbf278b5cb26c31fa65aa63b78eded348684 Mon Sep 17 00:00:00 2001 From: redmanuel1 Date: Thu, 12 Sep 2024 22:25:53 +0800 Subject: [PATCH 9/9] dupe --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index b634e3bd..7ed4e28a 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ "chart.js": "2.9.4", "clipboard": "2.0.10", "firebase": "^10.13.1", - "firebase": "^10.13.1", "ngx-clipboard": "15.0.1", "ngx-toastr": "^19.0.0", "nouislider": "15.5.1",