ソースを参照

contractor and employee

IbrahimNour 8 ヶ月 前
コミット
c28bc9e0a1

+ 2 - 1
src/app/app.module.ts

@@ -10,6 +10,7 @@ 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';
+import { interceptorsProvidors } from '@core/interceptors/interceptor';
 
 export function createTranslateLoader(http: HttpClient) {
   return new TranslateHttpLoader(http, './assets/i18n/', '.json');
@@ -33,7 +34,7 @@ export function createTranslateLoader(http: HttpClient) {
     }),
     StoreModule.forRoot({ user: profileReducer }),
   ],
-  providers: [],
+  providers: [interceptorsProvidors],
   bootstrap: [AppComponent],
 })
 export class AppModule {}

+ 91 - 4
src/app/authentication/auth-sign-up/signup-contractor/signup-contractor.component.html

@@ -21,6 +21,10 @@
             placeholder="Enter your Name"
             formControlName="firstName"
           />
+          <app-error-form
+            [name]="'firstName'"
+            [control]="form.get('firstName')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -43,6 +47,10 @@
             placeholder="Select Date"
             formControlName="dateOfBirth"
           />
+          <app-error-form
+            [name]="'dateOfBirth'"
+            [control]="form.get('dateOfBirth')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -61,6 +69,10 @@
             placeholder="ID Number"
             formControlName="idNumber"
           />
+          <app-error-form
+            [name]="'idNumber'"
+            [control]="form.get('idNumber')!"
+          ></app-error-form>
         </div>
       </div>
       <div class="gap-36 mt-2" fxLayout="row wrap" fxLayoutAlign="center start">
@@ -71,7 +83,7 @@
           fxFlex.lt-md="45"
           fxFlex.gt-sm="31"
         >
-          <label for="country">
+          <label for="last_name">
             <img src="assets/images/authorized_name.svg" alt="" title="" />
             <span>Last Name <span class="red">*</span></span>
           </label>
@@ -81,6 +93,10 @@
             id="last_name"
             formControlName="lastName"
           />
+          <app-error-form
+            [name]="'lastName'"
+            [control]="form.get('lastName')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -103,6 +119,10 @@
             placeholder="Enter your email"
             formControlName="email"
           />
+          <app-error-form
+            [name]="'email'"
+            [control]="form.get('email')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -121,6 +141,10 @@
             placeholder="Passport Number"
             formControlName="passportNumber"
           />
+          <app-error-form
+            [name]="'passportNumber'"
+            [control]="form.get('passportNumber')!"
+          ></app-error-form>
         </div>
       </div>
 
@@ -142,6 +166,10 @@
             id="favourite_name"
             formControlName="favoriteName"
           />
+          <app-error-form
+            [name]="'favoriteName'"
+            [control]="form.get('favoriteName')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -164,6 +192,10 @@
             placeholder="Mobile Number"
             formControlName="phoneNumber"
           />
+          <app-error-form
+            [name]="'phoneNumber'"
+            [control]="form.get('phoneNumber')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -193,6 +225,10 @@
             />
             <input type="text" class="calc" placeholder="0.0" />
           </div>
+          <app-error-form
+            [name]="'incomeTaxValue'"
+            [control]="form.get('incomeTaxValue')!"
+          ></app-error-form>
         </div>
       </div>
 
@@ -204,7 +240,7 @@
           fxFlex.lt-md="45"
           fxFlex.gt-sm="31"
         >
-          <label for="country">
+          <label for="user_name">
             <img src="assets/images/authorized_name.svg" alt="" title="" />
             <span>User Name <span class="red">*</span></span>
           </label>
@@ -214,6 +250,10 @@
             id="user_name"
             formControlName="userName"
           />
+          <app-error-form
+            [name]="'userName'"
+            [control]="form.get('userName')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -232,6 +272,10 @@
             placeholder="Enter your password"
             formControlName="password"
           />
+          <app-error-form
+            [name]="'password'"
+            [control]="form.get('password')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -250,6 +294,10 @@
             placeholder="Enter Linkedin url"
             formControlName="linkedInLink"
           />
+          <app-error-form
+            [name]="'linkedInLink'"
+            [control]="form.get('linkedInLink')!"
+          ></app-error-form>
         </div>
       </div>
 
@@ -272,6 +320,10 @@
               {{ item.nameEn }}
             </option>
           </select>
+          <app-error-form
+            [name]="'qualificationId'"
+            [control]="form.get('qualificationId')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -290,6 +342,10 @@
               {{ item.nameEn }}
             </option>
           </select>
+          <app-error-form
+            [name]="'industryId'"
+            [control]="form.get('industryId')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -314,6 +370,10 @@
               {{ item.nameEn }}
             </option>
           </select>
+          <app-error-form
+            [name]="'universityId'"
+            [control]="form.get('universityId')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -332,6 +392,10 @@
               {{ jobTitle.nameEn }}
             </option>
           </select>
+          <app-error-form
+            [name]="'jobTitleId'"
+            [control]="form.get('jobTitleId')!"
+          ></app-error-form>
         </div>
       </div>
 
@@ -353,7 +417,11 @@
             <img src="assets/images/country.svg" alt="" title="" />
             <span>Country <span class="red">*</span></span>
           </label>
-          <select id="country" formControlName="countryId">
+          <select
+            id="country"
+            formControlName="countryId"
+            (change)="onChangeCountry($event)"
+          >
             <option disabled selected [value]="null">
               Select your country
             </option>
@@ -361,6 +429,10 @@
               {{ country.nameEn }}>
             </option>
           </select>
+          <app-error-form
+            [name]="'countryId'"
+            [control]="form.get('userAddress.countryId')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -374,8 +446,15 @@
             <span>City<span class="red">*</span></span>
           </label>
           <select id="city" formControlName="cityId">
-            <!-- <option disabled selected>Select your country</option> -->
+            <option disabled selected [value]="null">Select your city</option>
+            <option *ngFor="let city of cities" [value]="city.id">
+              {{ city.nameEn }}>
+            </option>
           </select>
+          <app-error-form
+            [name]="'cityId'"
+            [control]="form.get('userAddress.cityId')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -394,6 +473,10 @@
             placeholder="Postal code"
             formControlName="postalCode"
           />
+          <app-error-form
+            [name]="'postal'"
+            [control]="form.get('userAddress.postalCode')!"
+          ></app-error-form>
         </div>
         <div class="mt-2" fxFlex.lt-md="100" fxFlex.gt-sm="100">
           <div
@@ -415,6 +498,10 @@
               placeholder="Address"
               formControlName="addressDesc"
             />
+            <app-error-form
+              [name]="'addressDesc'"
+              [control]="form.get('addressDesc')!"
+            ></app-error-form>
           </div>
         </div>
       </div>

+ 51 - 32
src/app/authentication/auth-sign-up/signup-contractor/signup-contractor.component.ts

@@ -10,6 +10,7 @@ import { ComponentBase } from '@core/base/common-base';
 import { AuthService } from '@core/services/authentication/auth.service';
 
 import {
+  CITY,
   COUNTRY,
   INDUSTRY,
   JOB_TITLE,
@@ -17,7 +18,9 @@ import {
   UNIVERISTY,
 } from '@core/models/authenticcation.model';
 import { takeUntil } from 'rxjs';
-import { ActivatedRoute, Params } from '@angular/router';
+import { ActivatedRoute, Params, Router } from '@angular/router';
+import { ToastrService } from 'ngx-toastr';
+import { SharedService } from '../../../core/services/shared.service';
 
 @Component({
   selector: 'app-signup-contractor',
@@ -29,15 +32,19 @@ export class SignupContractorComponent
   implements OnInit, BaseForm
 {
   form!: FormGroup;
-  multiPartForm = new FormData();
   jobTitles: JOB_TITLE[] = [];
   qualificationList: QUALIFICATION[] = [];
   univerisites: UNIVERISTY[] = [];
   countries: COUNTRY[] = [];
   industriesList: INDUSTRY[] = [];
+  cities: CITY[] = [];
+
   constructor(
     private readonly authService: AuthService,
-    private readonly route: ActivatedRoute
+    private readonly route: ActivatedRoute,
+    private readonly toastr: ToastrService,
+    private readonly sharedService: SharedService,
+    private readonly router: Router
   ) {
     super();
   }
@@ -71,8 +78,15 @@ export class SignupContractorComponent
       phoneNumber: new UntypedFormControl(null, [Validators.required]),
       userType: new UntypedFormControl(null, [Validators.required]),
       linkedInLink: new UntypedFormControl(null, [Validators.required]),
-      userName: new UntypedFormControl(null, [Validators.required]),
-      password: new UntypedFormControl(null, [Validators.required]),
+      userName: new UntypedFormControl(null, [
+        Validators.required,
+        Validators.minLength(6),
+      ]),
+      password: new UntypedFormControl(null, [
+        Validators.required,
+        Validators.pattern(this.sharedService.StrongPasswordRegx),
+        Validators.minLength(8),
+      ]),
       favoriteName: new UntypedFormControl(null, [Validators.required]),
       passportNumber: new UntypedFormControl(null, [Validators.required]),
       qualificationId: new UntypedFormControl(null, [Validators.required]),
@@ -81,6 +95,11 @@ export class SignupContractorComponent
       industryId: new UntypedFormControl(null, [Validators.required]),
       taxNumber: new UntypedFormControl(null, [Validators.required]),
       incomeTaxValue: new UntypedFormControl(null, Validators.required),
+      cvAttach: new UntypedFormControl(null),
+      passportAttach: new UntypedFormControl(null),
+      eduCertificateAttach: new UntypedFormControl(null),
+      experienceCertificateAttach: new UntypedFormControl(null),
+      profCertificateAttach: new UntypedFormControl(null),
       userAddress: new UntypedFormGroup({
         countryId: new UntypedFormControl(null, [Validators.required]),
         cityId: new UntypedFormControl(null, [Validators.required]),
@@ -137,39 +156,39 @@ export class SignupContractorComponent
 
   onUploadFile(event: any): void {
     if (event.file) {
-      this.multiPartForm.append(event.type, event.file);
+      this.form.patchValue({ [event.type]: event.file });
     } else {
-      this.multiPartForm.delete(event.type);
+      this.form.patchValue({ [event.type]: null });
     }
   }
 
-  onSubmit(): void {
-    for (const key in this.form.value) {
-      if (this.form.value.hasOwnProperty(key)) {
-        this.multiPartForm.append(key, this.form.value[key]);
-      }
-    }
+  onChangeCountry(event: any): void {
+    this.authService
+      .getCities({ CountryId: event.target.value })
+      .subscribe((res) => {
+        this.cities = res;
+      });
+  }
 
-    // this.multiPartForm.append(
-    //   'userAddress',
-    //   JSON.stringify({
-    //     countryId: this.form.get('countryId')?.value,
-    //     cityId: 1,
-    //     postalCode: this.form.get('postalCode')?.value,
-    //     addressDesc: this.form.get('addressDesc')?.value,
-    //   })
-    // );
+  onSubmit(): void {
+    this.router.navigate(['/auth']);
 
-    this.authService
-      .addEmployee(this.multiPartForm)
-      .pipe(takeUntil(this.destroy$))
-      .subscribe(
-        (res) => {
-          console.log(res);
-        },
-        (err) => {
-          console.log(err);
+    const multiPartForm = new FormData();
+    if (this.submitValidity(this.form)) {
+      for (const key in { ...this.form.value }) {
+        if (this.form.value.hasOwnProperty(key)) {
+          if (this.form.get(key)?.value) {
+            multiPartForm.append(key, this.form.get(key)?.value);
+          }
         }
-      );
+      }
+
+      this.authService
+        .addEmployee(multiPartForm)
+        .pipe(takeUntil(this.destroy$))
+        .subscribe((res) => {
+          this.toastr.success('Registeration Successfully !');
+        });
+    }
   }
 }

+ 91 - 4
src/app/authentication/auth-sign-up/signup-employee/signup-employee.component.html

@@ -21,6 +21,10 @@
             placeholder="Enter your Name"
             formControlName="firstName"
           />
+          <app-error-form
+            [name]="'firstName'"
+            [control]="form.get('firstName')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -43,6 +47,10 @@
             placeholder="Select Date"
             formControlName="dateOfBirth"
           />
+          <app-error-form
+            [name]="'dateOfBirth'"
+            [control]="form.get('dateOfBirth')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -61,6 +69,10 @@
             placeholder="ID Number"
             formControlName="idNumber"
           />
+          <app-error-form
+            [name]="'idNumber'"
+            [control]="form.get('idNumber')!"
+          ></app-error-form>
         </div>
       </div>
       <div class="gap-36 mt-2" fxLayout="row wrap" fxLayoutAlign="center start">
@@ -71,7 +83,7 @@
           fxFlex.lt-md="45"
           fxFlex.gt-sm="31"
         >
-          <label for="country">
+          <label for="last_name">
             <img src="assets/images/authorized_name.svg" alt="" title="" />
             <span>Last Name <span class="red">*</span></span>
           </label>
@@ -81,6 +93,10 @@
             id="last_name"
             formControlName="lastName"
           />
+          <app-error-form
+            [name]="'lastName'"
+            [control]="form.get('lastName')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -103,6 +119,10 @@
             placeholder="Enter your email"
             formControlName="email"
           />
+          <app-error-form
+            [name]="'email'"
+            [control]="form.get('email')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -121,6 +141,10 @@
             placeholder="Passport Number"
             formControlName="passportNumber"
           />
+          <app-error-form
+            [name]="'passportNumber'"
+            [control]="form.get('passportNumber')!"
+          ></app-error-form>
         </div>
       </div>
 
@@ -142,6 +166,10 @@
             id="favourite_name"
             formControlName="favoriteName"
           />
+          <app-error-form
+            [name]="'favoriteName'"
+            [control]="form.get('favoriteName')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -164,6 +192,10 @@
             placeholder="Mobile Number"
             formControlName="phoneNumber"
           />
+          <app-error-form
+            [name]="'phoneNumber'"
+            [control]="form.get('phoneNumber')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -193,6 +225,10 @@
             />
             <input type="text" class="calc" placeholder="0.0" />
           </div>
+          <app-error-form
+            [name]="'incomeTaxValue'"
+            [control]="form.get('incomeTaxValue')!"
+          ></app-error-form>
         </div>
       </div>
 
@@ -204,7 +240,7 @@
           fxFlex.lt-md="45"
           fxFlex.gt-sm="31"
         >
-          <label for="country">
+          <label for="user_name">
             <img src="assets/images/authorized_name.svg" alt="" title="" />
             <span>User Name <span class="red">*</span></span>
           </label>
@@ -214,6 +250,10 @@
             id="user_name"
             formControlName="userName"
           />
+          <app-error-form
+            [name]="'userName'"
+            [control]="form.get('userName')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -232,6 +272,10 @@
             placeholder="Enter your password"
             formControlName="password"
           />
+          <app-error-form
+            [name]="'password'"
+            [control]="form.get('password')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -250,6 +294,10 @@
             placeholder="Enter Linkedin url"
             formControlName="linkedInLink"
           />
+          <app-error-form
+            [name]="'linkedInLink'"
+            [control]="form.get('linkedInLink')!"
+          ></app-error-form>
         </div>
       </div>
 
@@ -272,6 +320,10 @@
               {{ item.nameEn }}
             </option>
           </select>
+          <app-error-form
+            [name]="'qualificationId'"
+            [control]="form.get('qualificationId')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -290,6 +342,10 @@
               {{ item.nameEn }}
             </option>
           </select>
+          <app-error-form
+            [name]="'industryId'"
+            [control]="form.get('industryId')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -314,6 +370,10 @@
               {{ item.nameEn }}
             </option>
           </select>
+          <app-error-form
+            [name]="'universityId'"
+            [control]="form.get('universityId')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -332,6 +392,10 @@
               {{ jobTitle.nameEn }}
             </option>
           </select>
+          <app-error-form
+            [name]="'jobTitleId'"
+            [control]="form.get('jobTitleId')!"
+          ></app-error-form>
         </div>
       </div>
 
@@ -353,7 +417,11 @@
             <img src="assets/images/country.svg" alt="" title="" />
             <span>Country <span class="red">*</span></span>
           </label>
-          <select id="country" formControlName="countryId">
+          <select
+            id="country"
+            formControlName="countryId"
+            (change)="onChangeCountry($event)"
+          >
             <option disabled selected [value]="null">
               Select your country
             </option>
@@ -361,6 +429,10 @@
               {{ country.nameEn }}>
             </option>
           </select>
+          <app-error-form
+            [name]="'countryId'"
+            [control]="form.get('userAddress.countryId')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -374,8 +446,15 @@
             <span>City<span class="red">*</span></span>
           </label>
           <select id="city" formControlName="cityId">
-            <!-- <option disabled selected>Select your country</option> -->
+            <option disabled selected [value]="null">Select your city</option>
+            <option *ngFor="let city of cities" [value]="city.id">
+              {{ city.nameEn }}>
+            </option>
           </select>
+          <app-error-form
+            [name]="'cityId'"
+            [control]="form.get('userAddress.cityId')!"
+          ></app-error-form>
         </div>
         <div
           class="form-input"
@@ -394,6 +473,10 @@
             placeholder="Postal code"
             formControlName="postalCode"
           />
+          <app-error-form
+            [name]="'postal'"
+            [control]="form.get('userAddress.postalCode')!"
+          ></app-error-form>
         </div>
         <div class="mt-2" fxFlex.lt-md="100" fxFlex.gt-sm="100">
           <div
@@ -415,6 +498,10 @@
               placeholder="Address"
               formControlName="addressDesc"
             />
+            <app-error-form
+              [name]="'addressDesc'"
+              [control]="form.get('addressDesc')!"
+            ></app-error-form>
           </div>
         </div>
       </div>

+ 50 - 33
src/app/authentication/auth-sign-up/signup-employee/signup-employee.component.ts

@@ -1,9 +1,11 @@
 import { Component, OnInit } from '@angular/core';
-import { ActivatedRoute, Params } from '@angular/router';
+import { ActivatedRoute, Params, Router } from '@angular/router';
 import { ComponentBase } from '@core/base/common-base';
-import { take, takeUntil } from 'rxjs';
+import { from, take, takeUntil } from 'rxjs';
 import { BaseForm } from '@core/base/base-form';
 import { AuthService } from '@core/services/authentication/auth.service';
+import { ToastrService } from 'ngx-toastr';
+import { SharedService } from '../../../core/services/shared.service';
 
 import {
   FormGroup,
@@ -17,6 +19,7 @@ import {
   UNIVERISTY,
   COUNTRY,
   INDUSTRY,
+  CITY,
 } from '@core/models/authenticcation.model';
 
 @Component({
@@ -34,11 +37,15 @@ export class SignupEmployeeComponent
   qualificationList: QUALIFICATION[] = [];
   univerisites: UNIVERISTY[] = [];
   countries: COUNTRY[] = [];
+  cities: CITY[] = [];
   industriesList: INDUSTRY[] = [];
 
   constructor(
     private readonly route: ActivatedRoute,
-    private readonly authService: AuthService
+    private readonly authService: AuthService,
+    private readonly toastr: ToastrService,
+    private readonly sharedService: SharedService,
+    private readonly router: Router
   ) {
     super();
   }
@@ -72,8 +79,15 @@ export class SignupEmployeeComponent
       phoneNumber: new UntypedFormControl(null, [Validators.required]),
       userType: new UntypedFormControl(null, [Validators.required]),
       linkedInLink: new UntypedFormControl(null, [Validators.required]),
-      userName: new UntypedFormControl(null, [Validators.required]),
-      password: new UntypedFormControl(null, [Validators.required]),
+      userName: new UntypedFormControl(null, [
+        Validators.required,
+        Validators.minLength(6),
+      ]),
+      password: new UntypedFormControl(null, [
+        Validators.required,
+        Validators.pattern(this.sharedService.StrongPasswordRegx),
+        Validators.minLength(8),
+      ]),
       favoriteName: new UntypedFormControl(null, [Validators.required]),
       passportNumber: new UntypedFormControl(null, [Validators.required]),
       qualificationId: new UntypedFormControl(null, [Validators.required]),
@@ -82,6 +96,11 @@ export class SignupEmployeeComponent
       industryId: new UntypedFormControl(null, [Validators.required]),
       taxNumber: new UntypedFormControl(null, [Validators.required]),
       incomeTaxValue: new UntypedFormControl(null, Validators.required),
+      cvAttach: new UntypedFormControl(null),
+      passportAttach: new UntypedFormControl(null),
+      eduCertificateAttach: new UntypedFormControl(null),
+      experienceCertificateAttach: new UntypedFormControl(null),
+      profCertificateAttach: new UntypedFormControl(null),
       userAddress: new UntypedFormGroup({
         countryId: new UntypedFormControl(null, [Validators.required]),
         cityId: new UntypedFormControl(null, [Validators.required]),
@@ -136,42 +155,40 @@ export class SignupEmployeeComponent
       });
   }
 
+  onChangeCountry(event: any): void {
+    this.authService
+      .getCities({ CountryId: event.target.value })
+      .subscribe((res) => {
+        this.cities = res;
+      });
+  }
+
   onUploadFile(event: any): void {
     if (event.file) {
-      this.multiPartForm.append(event.type, event.file);
+      this.form.patchValue({ [event.type]: event.file });
     } else {
-      this.multiPartForm.delete(event.type);
+      this.form.patchValue({ [event.type]: null });
     }
   }
 
   onSubmit(): void {
-    console.log(this.form.get('userName')?.value);
-    for (const key in this.form.value) {
-      if (this.form.value.hasOwnProperty(key)) {
-        this.multiPartForm.append(key, this.form.value[key]);
+    const multiPartForm = new FormData();
+    if (this.submitValidity(this.form)) {
+      for (const key in { ...this.form.value }) {
+        if (this.form.value.hasOwnProperty(key)) {
+          if (this.form.get(key)?.value) {
+            multiPartForm.append(key, this.form.get(key)?.value);
+          }
+        }
       }
-    }
 
-    // this.multiPartForm.append(
-    //   'userAddress',
-    //   JSON.stringify({
-    //     countryId: this.form.get('countryId')?.value,
-    //     cityId: 1,
-    //     postalCode: this.form.get('postalCode')?.value,
-    //     addressDesc: this.form.get('addressDesc')?.value,
-    //   })
-    // );
-
-    this.authService
-      .addEmployee(this.multiPartForm)
-      .pipe(takeUntil(this.destroy$))
-      .subscribe(
-        (res) => {
-          console.log(res);
-        },
-        (err) => {
-          console.log(err);
-        }
-      );
+      this.authService
+        .addEmployee(multiPartForm)
+        .pipe(takeUntil(this.destroy$))
+        .subscribe((res) => {
+          this.toastr.success('Registeration Successfully !');
+          this.router.navigate(['/auth']);
+        });
+    }
   }
 }

+ 13 - 1
src/app/core/base/common-base.ts

@@ -1,5 +1,5 @@
 import { Directive, OnDestroy } from '@angular/core';
-import { FormGroup } from '@angular/forms';
+import { FormGroup, UntypedFormArray, UntypedFormGroup } from '@angular/forms';
 import { Subject } from 'rxjs';
 @Directive({
   selector: '[appComponentBase]',
@@ -16,7 +16,19 @@ export abstract class ComponentBase implements OnDestroy {
   markControlAsToushed(form: FormGroup): void {
     Object.values(form.controls).forEach((control) => {
       control.markAsTouched();
+      if (control instanceof UntypedFormGroup) {
+        this.markControlAsToushed(control);
+      }
     });
+    // Object.values(form.controls).forEach((control: any) => {
+    //   control.markAsTouched();
+    //   if (control?.controls) {
+    //     Object.values(form.controls).forEach((control: any) => {
+    //       console.log(control);
+    //       control.markAsTouched();
+    //     });
+    //   }
+    // });
   }
 
   submitValidity(form: FormGroup): boolean {

+ 16 - 0
src/app/core/interceptors/error.interceptor.spec.ts

@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { ErrorInterceptor } from './error.interceptor';
+
+describe('ErrorInterceptor', () => {
+  beforeEach(() => TestBed.configureTestingModule({
+    providers: [
+      ErrorInterceptor
+      ]
+  }));
+
+  it('should be created', () => {
+    const interceptor: ErrorInterceptor = TestBed.inject(ErrorInterceptor);
+    expect(interceptor).toBeTruthy();
+  });
+});

+ 81 - 0
src/app/core/interceptors/error.interceptor.ts

@@ -0,0 +1,81 @@
+import { ToastrService } from 'ngx-toastr';
+import { Injectable } from '@angular/core';
+// import { catchError } from 'rxjs/operators';
+
+import {
+  HttpRequest,
+  HttpHandler,
+  HttpEvent,
+  HttpInterceptor,
+  HttpErrorResponse,
+} from '@angular/common/http';
+import { catchError, Observable, throwError } from 'rxjs';
+
+@Injectable()
+export class ErrorInterceptor implements HttpInterceptor {
+  constructor(private readonly toastr: ToastrService) {}
+
+  intercept(
+    request: HttpRequest<any>,
+    next: HttpHandler
+  ): Observable<HttpEvent<any>> {
+    return next.handle(request).pipe(
+      catchError((error: HttpErrorResponse) => {
+        let errorMsg = '';
+        if (error?.error instanceof ErrorEvent) {
+          errorMsg = `Error: ${error.error.message}`;
+        } else {
+          this.handleServerSideError(error);
+          errorMsg = `Error Code: ${error?.status},  Message: ${error?.message}`;
+        }
+        return throwError(errorMsg);
+      })
+    );
+  }
+
+  handleServerSideError(error: HttpErrorResponse): void {
+    console.log('error => ', error);
+    switch (error?.status) {
+      case 401:
+        this.toastr.error('You are not authorized , Please login again !');
+
+        break;
+
+      case 403:
+        this.toastr.error(error?.error?.errorMsg);
+        break;
+
+      case 402:
+        this.toastr.error(error?.error?.errorMsg);
+        break;
+
+      case 422:
+        this.toastr.error(error?.error?.errorMsg);
+        break;
+
+      case 400:
+        this.toastr.error(error?.error?.errorMsg);
+        break;
+
+      case 412:
+        this.toastr.error(error?.error?.errorMsg);
+        break;
+
+      case 500:
+        this.toastr.error('SERVER ERROR, TRY AGAIN  !');
+        break;
+
+      case 425:
+        this.toastr.error(error?.error?.errorMsg);
+        break;
+
+      case 415:
+        this.toastr.error(error?.error?.errorMsg);
+        break;
+
+      case 404:
+        this.toastr.error(error?.error?.errorMsg);
+        break;
+    }
+  }
+}

+ 6 - 0
src/app/core/interceptors/interceptor.ts

@@ -0,0 +1,6 @@
+import { HTTP_INTERCEPTORS } from '@angular/common/http';
+import { ErrorInterceptor } from './error.interceptor';
+
+export const interceptorsProvidors = [
+  { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
+];

+ 16 - 0
src/app/core/interceptors/status.interceptor.spec.ts

@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { StatusInterceptor } from './status.interceptor';
+
+describe('StatusInterceptor', () => {
+  beforeEach(() => TestBed.configureTestingModule({
+    providers: [
+      StatusInterceptor
+      ]
+  }));
+
+  it('should be created', () => {
+    const interceptor: StatusInterceptor = TestBed.inject(StatusInterceptor);
+    expect(interceptor).toBeTruthy();
+  });
+});

+ 30 - 0
src/app/core/interceptors/status.interceptor.ts

@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import {
+  HttpRequest,
+  HttpHandler,
+  HttpEvent,
+  HttpInterceptor,
+  HttpResponse,
+} from '@angular/common/http';
+import { Observable, tap } from 'rxjs';
+
+@Injectable()
+export class StatusInterceptor implements HttpInterceptor {
+  constructor() {}
+
+  intercept(
+    request: HttpRequest<any>,
+    next: HttpHandler
+  ): Observable<HttpEvent<any>> {
+    return next.handle(request).pipe(
+      tap((event) => {
+        if (
+          event instanceof HttpResponse &&
+          event.status >= 200 &&
+          event.status < 300
+        ) {
+        }
+      })
+    );
+  }
+}

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

@@ -125,3 +125,11 @@ export interface INDUSTRY {
   nameAr: string;
   nameEn: string;
 }
+
+export interface CITY {
+  id: number;
+  readOnly: boolean;
+  nameAr: string;
+  nameEn: string;
+  countryId: number;
+}

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

@@ -17,6 +17,7 @@ import {
   UNIVERISTY,
   COUNTRY,
   INDUSTRY,
+  CITY,
 } from '@core/models/authenticcation.model';
 
 @Injectable({
@@ -74,6 +75,10 @@ export class AuthService {
     return this.apiService.get<INDUSTRY[]>('Lookup/GetAllIndustries');
   }
 
+  getCities(params: { CountryId: number }): Observable<CITY[]> {
+    return this.apiService.get<CITY[]>('Lookup/GetCityByCountry', params);
+  }
+
   isAuthenticated(): boolean {
     return !!(localStorage.getItem('token') && localStorage.getItem('id'));
   }

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

@@ -0,0 +1,11 @@
+import { Injectable } from '@angular/core';
+
+@Injectable({
+  providedIn: 'root',
+})
+export class SharedService {
+  constructor() {}
+
+  StrongPasswordRegx: RegExp =
+    /^(?=[^A-Z]*[A-Z])(?=[^a-z]*[a-z])(?=\D*\d).{8,}$/;
+}

+ 29 - 0
src/app/shared/components/error-form/error-form.component.html

@@ -18,4 +18,33 @@
   <mat-error class="error-message" *ngIf="control.errors?.['email']">
     {{ "VALID_EMAIL" | translate }} !</mat-error
   >
+
+  <mat-error
+    class="error-message"
+    *ngIf="name === 'password' && !control.value?.match('^(?=.*[A-Z])')"
+    >At least oneu ppercase letter.</mat-error
+  >
+  <mat-error
+    class="error-message"
+    *ngIf="name === 'password' && !control?.value?.match('(?=.*[a-z])')"
+    >At least one lowercase letter.</mat-error
+  >
+
+  <mat-error
+    class="error-message"
+    *ngIf="name === 'password' && !control?.value?.match('(.*[0-9].*)')"
+    >At least one digit.</mat-error
+  >
+
+  <mat-error
+    class="error-message"
+    *ngIf="name === 'password' && !control?.value?.match('(?=.*[!@#$%^&*])')"
+    >At least one special character.</mat-error
+  >
+
+  <mat-error
+    class="error-message"
+    *ngIf="name === 'password' && !control?.value?.match('(?=.*[!@#$%^&*])')"
+    >At least one special character.</mat-error
+  >
 </span>

+ 2 - 1
src/assets/i18n/ar.json

@@ -20,5 +20,6 @@
   "CONFIRM_PASSWORD": "تأكيد كلمة المرور",
   "PASSWORD": "كلمة المرور",
   "REQUIRED": "مطلوب",
-  "VALID_EMAIL": "أدخل إيميل صحيح !"
+  "VALID_EMAIL": "أدخل إيميل صحيح !",
+  "REQUIRED_MIN_LENGTH": "ليس أقل من"
 }

+ 2 - 1
src/assets/i18n/en.json

@@ -20,5 +20,6 @@
   "CONFIRM_PASSWORD": "Confirm password",
   "PASSWORD": "Password",
   "REQUIRED": "Required",
-  "VALID_EMAIL": "Enter valid email !"
+  "VALID_EMAIL": "Enter valid email !",
+  "REQUIRED_MIN_LENGTH": "not less than"
 }