IbrahimNour 8 månader sedan
förälder
incheckning
a4fd315aed

BIN
dist.zip


+ 1 - 1
package.json

@@ -21,7 +21,7 @@
     "@angular/platform-browser": "^16.2.0",
     "@angular/platform-browser-dynamic": "^16.2.0",
     "@angular/router": "^16.2.0",
-    "@ngrx/store": "^17.0.1",
+    "@ngrx/store": "^17.2.0",
     "@ngx-translate/core": "^15.0.0",
     "@ngx-translate/http-loader": "^8.0.0",
     "ngx-otp-input": "^0.11.4",

+ 4 - 0
src/app/app-routing.module.ts

@@ -1,6 +1,8 @@
 import { NgModule } from '@angular/core';
 import { RouterModule, Routes } from '@angular/router';
+import { UnAuthGuard } from '@core/guards/unauth.guard';
 import { AppComponent } from './app.component';
+import { AuthGuard } from './core/guards/auth.guard';
 
 const routes: Routes = [
   {
@@ -20,11 +22,13 @@ const routes: Routes = [
           import('./authentication/authentication.module').then(
             (m) => m.AuthenticationModule
           ),
+        canActivate: [UnAuthGuard],
       },
       {
         path: 'modules',
         loadChildren: () =>
           import('./modules/modules.module').then((m) => m.ModulesModule),
+        canActivate: [AuthGuard],
       },
     ],
   },

+ 32 - 3
src/app/app.component.ts

@@ -1,10 +1,39 @@
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
+import { ComponentBase } from '@core/base/common-base';
+import { AuthService } from '@core/services/authentication/auth.service';
+import { ADD_PROFILE } from '@core/state/profile/profile.actions';
+import { takeUntil } from 'rxjs';
+import { Store } from '@ngrx/store';
+import { USER } from '@core/models/authenticcation.model';
 
 @Component({
   selector: 'app-root',
   templateUrl: './app.component.html',
-  styleUrls: ['./app.component.scss']
+  styleUrls: ['./app.component.scss'],
 })
-export class AppComponent {
+export class AppComponent extends ComponentBase implements OnInit {
   title = 'mt-works';
+  constructor(
+    private readonly authService: AuthService,
+    private readonly store: Store<{ user: { profile: USER } }>
+  ) {
+    super();
+  }
+
+  ngOnInit(): void {
+    this.getProfile();
+  }
+
+  getProfile(): void {
+    this.authService
+      .getUserData()
+      .pipe(takeUntil(this.destroy$))
+      .subscribe((res) => {
+        this.store.dispatch(
+          ADD_PROFILE({
+            user: { userName: res.userName, email: res.email },
+          })
+        );
+      });
+  }
 }

+ 3 - 0
src/app/app.module.ts

@@ -8,6 +8,8 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
 import { HttpClient, HttpClientModule } from '@angular/common/http';
 import { TranslateHttpLoader } from '@ngx-translate/http-loader';
 import { ToastrModule } from 'ngx-toastr';
+import { StoreModule } from '@ngrx/store';
+import { profileReducer } from '@core/state/profile/profile.reducer';
 
 export function createTranslateLoader(http: HttpClient) {
   return new TranslateHttpLoader(http, './assets/i18n/', '.json');
@@ -29,6 +31,7 @@ export function createTranslateLoader(http: HttpClient) {
       },
       defaultLanguage: 'en',
     }),
+    StoreModule.forRoot({ user: profileReducer }),
   ],
   providers: [],
   bootstrap: [AppComponent],

+ 8 - 2
src/app/authentication/auth-sign-in/sign-in/sign-in.component.ts

@@ -11,6 +11,9 @@ import { AuthService } from '@core/services/authentication/auth.service';
 import { takeUntil } from 'rxjs';
 import { Router } from '@angular/router';
 import { ToastrService } from 'ngx-toastr';
+import { Store } from '@ngrx/store';
+import { Profile, USER } from '../../../core/models/authenticcation.model';
+import { ADD_PROFILE } from '../../../core/state/profile/profile.actions';
 
 @Component({
   selector: 'app-sign-in',
@@ -24,7 +27,8 @@ export class SignInComponent extends ComponentBase implements BaseForm, OnInit {
   constructor(
     private readonly authService: AuthService,
     private readonly router: Router,
-    private readonly toastr: ToastrService
+    private readonly toastr: ToastrService,
+    private readonly store: Store<{ user: Profile }>
   ) {
     super();
   }
@@ -49,7 +53,9 @@ export class SignInComponent extends ComponentBase implements BaseForm, OnInit {
         .Login(this.form.value)
         .pipe(takeUntil(this.destroy$))
         .subscribe((response) => {
-          console.log(response);
+          localStorage.setItem('token', response.token!);
+          localStorage.setItem('id', response.id!);
+          this.store.dispatch(ADD_PROFILE({ user: response }));
           this.router.navigate(['/modules']);
         });
     }

+ 17 - 0
src/app/core/guards/auth.guard.spec.ts

@@ -0,0 +1,17 @@
+import { TestBed } from '@angular/core/testing';
+import { CanActivateFn } from '@angular/router';
+
+import { authGuard } from './auth.guard';
+
+describe('authGuard', () => {
+  const executeGuard: CanActivateFn = (...guardParameters) => 
+      TestBed.runInInjectionContext(() => authGuard(...guardParameters));
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+  });
+
+  it('should be created', () => {
+    expect(executeGuard).toBeTruthy();
+  });
+});

+ 35 - 0
src/app/core/guards/auth.guard.ts

@@ -0,0 +1,35 @@
+import { Injectable } from '@angular/core';
+import {
+  CanActivate,
+  ActivatedRouteSnapshot,
+  RouterStateSnapshot,
+  UrlTree,
+  Router,
+} from '@angular/router';
+import { AuthService } from '@core/services/authentication/auth.service';
+import { Observable } from 'rxjs';
+
+@Injectable({
+  providedIn: 'root',
+})
+export class AuthGuard implements CanActivate {
+  constructor(private authservice: AuthService, private router: Router) {}
+
+  canActivate(
+    next: ActivatedRouteSnapshot,
+    state: RouterStateSnapshot
+  ):
+    | Observable<boolean | UrlTree>
+    | Promise<boolean | UrlTree>
+    | boolean
+    | UrlTree {
+    // Check if user is authenticated
+    if (this.authservice.isAuthenticated()) {
+      return true;
+    }
+
+    // If not authenticated, redirect to login page
+    this.router.navigate(['/auth']);
+    return false;
+  }
+}

+ 35 - 0
src/app/core/guards/unauth.guard.ts

@@ -0,0 +1,35 @@
+import { Injectable } from '@angular/core';
+import {
+  CanActivate,
+  ActivatedRouteSnapshot,
+  RouterStateSnapshot,
+  UrlTree,
+  Router,
+} from '@angular/router';
+import { AuthService } from '@core/services/authentication/auth.service';
+import { Observable } from 'rxjs';
+
+@Injectable({
+  providedIn: 'root',
+})
+export class UnAuthGuard implements CanActivate {
+  constructor(private authservice: AuthService, private router: Router) {}
+
+  canActivate(
+    next: ActivatedRouteSnapshot,
+    state: RouterStateSnapshot
+  ):
+    | Observable<boolean | UrlTree>
+    | Promise<boolean | UrlTree>
+    | boolean
+    | UrlTree {
+    // Check if user is authenticated
+    if (!this.authservice.isAuthenticated()) {
+      return true;
+    }
+
+    // If not authenticated, redirect to login page
+    this.router.navigate(['']);
+    return false;
+  }
+}

+ 57 - 0
src/app/core/models/authenticcation.model.ts

@@ -31,3 +31,60 @@ export interface CHANGE_PASSWORD {
 }
 
 export interface CHANGE_PASSWORD_RESPONSE {}
+
+export interface USER {
+  id?: string;
+  userName?: string;
+  email?: string;
+  token?: string;
+  expiration?: string;
+}
+
+export interface Profile {
+  id: string;
+  email: string;
+  firstName: string;
+  lastName: string;
+  phoneNumber: string;
+  linkedInLink: string;
+  userType: number;
+  userName: string;
+  password: string;
+  favoriteName: string;
+  passportNumber: string;
+  qualificationId: number;
+  universityId: number;
+  jobTitleId: number;
+  industryId: number;
+  countryId: number;
+  taxNumber: number;
+  incomeTaxValue: number;
+  userRoles: Role[];
+  userAttachments: Attachements[];
+  userAddress: Address;
+}
+
+export interface Address {
+  id: number;
+  readOnly: boolean;
+  countryId: number;
+  city: string;
+  postalCode: string;
+  addressDesc: string;
+}
+
+export interface Attachements {
+  id: number;
+  readOnly: boolean;
+  attachmentTypeId: number;
+  taskId: number;
+  attachmentTypeName: string;
+  fileData: string;
+  fileName: string;
+  originalName: string;
+}
+
+export interface Role {
+  roleId: string;
+  roleName: string;
+}

+ 3 - 5
src/app/core/services/api.service.ts

@@ -15,21 +15,19 @@ export class ApiService {
 
   getUploadHeaders() {
     const token: string | null = localStorage.getItem('token') || null;
+    const id: string | null = localStorage.getItem('id') || null;
     const language: string = localStorage.getItem('lang')
       ? String(localStorage.getItem('lang'))
       : this.translate.defaultLang;
 
-    if (token) {
+    if (token && id) {
       return {
         headers: new HttpHeaders()
           .set('lang', language)
           .set('Authorization', 'Bearer ' + token),
       };
-    } else {
-      return {
-        headers: new HttpHeaders().set('lang', language).set('AppId', '107'),
-      };
     }
+    return null;
   }
 
   public get<TResponse>(type: string, params?: any): Observable<TResponse> {

+ 11 - 0
src/app/core/services/authentication/auth.service.ts

@@ -10,6 +10,7 @@ import {
   LOGIN_RESPONSE,
   OTP,
   OTP_RESPONSE,
+  Profile,
 } from '@core/models/authenticcation.model';
 
 @Injectable({
@@ -22,6 +23,12 @@ export class AuthService {
     return this.apiService.post<LOGIN, LOGIN_RESPONSE>('Auth/login', data);
   }
 
+  getUserData(): Observable<Profile> {
+    return this.apiService.get<Profile>('User/Get', {
+      userId: localStorage.getItem('id'),
+    });
+  }
+
   ForgetPassword(data: FORGET_PASSWORD): Observable<FORGET_PASSWORD_RESPONSE> {
     return this.apiService.post<FORGET_PASSWORD, FORGET_PASSWORD_RESPONSE>(
       '',
@@ -39,4 +46,8 @@ export class AuthService {
       data
     );
   }
+
+  isAuthenticated(): boolean {
+    return !!localStorage.getItem('token');
+  }
 }

+ 10 - 0
src/app/core/state/profile/profile.actions.ts

@@ -0,0 +1,10 @@
+import {
+  LOGIN_RESPONSE,
+  Profile,
+  USER,
+} from '@core/models/authenticcation.model';
+import { createAction, props } from '@ngrx/store';
+export const ADD_PROFILE = createAction(
+  'ADD PROFILE',
+  props<{ user: LOGIN_RESPONSE }>()
+);

+ 19 - 0
src/app/core/state/profile/profile.reducer.ts

@@ -0,0 +1,19 @@
+import { createReducer, on } from '@ngrx/store';
+import { ADD_PROFILE } from './profile.actions';
+import {
+  LOGIN_RESPONSE,
+  Profile,
+  USER,
+} from '../../models/authenticcation.model';
+
+const initialState: { profile: LOGIN_RESPONSE | null } = {
+  profile: null,
+};
+
+export const profileReducer = createReducer(
+  initialState,
+  on(ADD_PROFILE, (state, { user }) => ({
+    ...state,
+    profile: user,
+  }))
+);

+ 9 - 1
src/app/landing-page/landing-header/landing-header.component.html

@@ -9,8 +9,16 @@
     </ul>
   </main>
 
-  <div class="actions" fxLayout="row" fxLayoutAlign="end center">
+  <div
+    class="actions"
+    fxLayout="row"
+    fxLayoutAlign="end center"
+    *ngIf="!(user$ | async)"
+  >
     <button class="actions__signin ptr" (click)="onSignIn()">Sign in</button>
     <button class="actions__sign-up ptr" (click)="onSignUp()">Sign Up</button>
   </div>
+  <p style="color: #fff" *ngIf="user$ | async">
+    {{ (user$ | async)?.userName }}
+  </p>
 </header>

+ 12 - 1
src/app/landing-page/landing-header/landing-header.component.ts

@@ -1,5 +1,8 @@
 import { Component } from '@angular/core';
 import { Router } from '@angular/router';
+import { USER } from '@core/models/authenticcation.model';
+import { select, Store } from '@ngrx/store';
+import { Observable } from 'rxjs';
 
 @Component({
   selector: 'app-landing-header',
@@ -7,7 +10,15 @@ import { Router } from '@angular/router';
   styleUrls: ['./landing-header.component.scss'],
 })
 export class LandingHeaderComponent {
-  constructor(private readonly router: Router) {}
+  user$!: Observable<USER>;
+
+  constructor(
+    private readonly router: Router,
+    private readonly store: Store<{ user: { profile: USER } }>
+  ) {
+    this.user$ = this.store.pipe(select((state) => state.user.profile));
+  }
+
   onSignIn(): void {
     this.router.navigate(['auth']);
   }

+ 5 - 3
src/app/modules/components/header/header.component.html

@@ -1,7 +1,9 @@
 <header fxLayout="row wrap" fxLayoutAlign="space-between center">
-  <h1 fxFlex.lt-md="100" fxFlex.gt-sm="20">Good morning, Mohamed!</h1>
+  <h1 fxFlex.lt-md="100" fxFlex.gt-sm="20">
+    Good morning, {{ user && user.userName }}!
+  </h1>
 
-  <div
+  <!-- <div
     fxFlex.lt-md="100"
     fxFlex.gt-sm="30"
     fxLayout="row"
@@ -10,7 +12,7 @@
   >
     <mat-slide-toggle> <span class="white"> Check In</span></mat-slide-toggle>
     <mat-slide-toggle><span class="white"> Check Out</span></mat-slide-toggle>
-  </div>
+  </div> -->
 
   <div
     class="gap-20"

+ 1 - 1
src/app/modules/components/header/header.component.scss

@@ -7,7 +7,7 @@
       padding: 10px 20px;
       h1 {
         color: $white-color;
-        font-size: 20px;
+        font-size: 18px;
       }
 
       .search {

+ 20 - 3
src/app/modules/components/header/header.component.ts

@@ -1,13 +1,30 @@
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
 import { Router } from '@angular/router';
+import { Store } from '@ngrx/store';
+import { USER } from '../../../core/models/authenticcation.model';
+import { ComponentBase } from '@core/base/common-base';
 
 @Component({
   selector: 'app-header',
   templateUrl: './header.component.html',
   styleUrls: ['./header.component.scss'],
 })
-export class HeaderComponent {
-  constructor(private readonly router: Router) {}
+export class HeaderComponent extends ComponentBase implements OnInit {
+  user!: USER;
+
+  constructor(
+    private readonly router: Router,
+    private readonly store: Store<{ user: { profile: USER } }>
+  ) {
+    super();
+  }
+
+  ngOnInit(): void {
+    this.store.select('user').subscribe((res) => {
+      this.user = res.profile;
+    });
+  }
+
   onOpenChat(): void {
     this.router.navigate(['/modules/chat']);
   }

+ 1 - 1
src/environments/environment.prod.ts

@@ -1,4 +1,4 @@
 export const environment = {
   production: true,
-  BASE_URL: 'https://20.83.171.3/api',
+  BASE_URL: 'https://20.83.171.3/api/',
 };

+ 1 - 1
src/environments/environment.ts

@@ -4,7 +4,7 @@
 
 export const environment = {
   production: false,
-  baseURL: 'https://20.83.171.3/api',
+  baseURL: 'https://20.83.171.3/api/',
 };
 
 /*

+ 4 - 4
yarn.lock

@@ -2187,10 +2187,10 @@
     "@material/theme" "15.0.0-canary.bc9ae6c9c.0"
     tslib "^2.1.0"
 
-"@ngrx/store@^17.0.1":
-  version "17.0.1"
-  resolved "https://registry.npmjs.org/@ngrx/store/-/store-17.0.1.tgz"
-  integrity sha512-BmVzN+fqyz0ZrVEmJ+jrNwePMKcpNL49vb8sbQ3yDDftxgZz2HqRKFMexqlXpz5ixwK5LqTOblHNQOgi9irsTw==
+"@ngrx/store@^17.2.0":
+  version "17.2.0"
+  resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-17.2.0.tgz#d1a588cd8bae18a190bb71582f07e992406a76fa"
+  integrity sha512-7wKgZ59B/6yQSvvsU0DQXipDqpkAXv7LwcXLD5Ww7nvqN0fQoRPThMh4+Wv55DCJhE0bQc1NEMciLA47uRt7Wg==
   dependencies:
     tslib "^2.0.0"