IbrahimNour 1 éve
szülő
commit
cd689bed61
35 módosított fájl, 2100 hozzáadás és 51 törlés
  1. 1 0
      angular.json
  2. 4 1
      package.json
  3. 23 1
      src/app/app.module.ts
  4. 22 8
      src/app/authentication/auth-sign-in/forget-password/forget-password.component.html
  5. 52 2
      src/app/authentication/auth-sign-in/forget-password/forget-password.component.ts
  6. 37 11
      src/app/authentication/auth-sign-in/sign-in/sign-in.component.html
  7. 49 2
      src/app/authentication/auth-sign-in/sign-in/sign-in.component.ts
  8. 19 0
      src/app/core/models/authenticcation.model.ts
  9. 27 0
      src/app/core/models/error-message.model.ts
  10. 26 11
      src/app/core/services/api.service.ts
  11. 12 3
      src/app/core/services/authentication/auth.service.ts
  12. 2 2
      src/app/modules/profile/basic-information/basic-information.component.html
  13. 13 2
      src/app/modules/teams/components/team-info-header/team-info-header.component.html
  14. 1 1
      src/app/modules/teams/components/teams-filter/teams-filter.component.html
  15. 2 2
      src/app/modules/teams/list/item/item.component.html
  16. 14 2
      src/app/modules/teams/team-info/team-info-card/team-info-card.component.html
  17. 7 0
      src/app/modules/teams/teams.component.scss
  18. 21 0
      src/app/shared/components/error-form/error-form.component.html
  19. 13 0
      src/app/shared/components/error-form/error-form.component.scss
  20. 46 0
      src/app/shared/components/error-form/error-form.component.spec.ts
  21. 22 0
      src/app/shared/components/error-form/error-form.component.ts
  22. 6 1
      src/app/shared/shared.module.ts
  23. 14 0
      src/assets/i18n/ar.json
  24. 14 0
      src/assets/i18n/en.json
  25. 3 0
      src/assets/images/arrow.svg
  26. 7 0
      src/assets/images/chat_icon.svg
  27. BIN
      src/assets/images/market_info_avatar.png
  28. BIN
      src/assets/images/market_info_avatar/Ellipse 204@2x.png
  29. BIN
      src/assets/images/market_info_avatar/market_info_avatar.png
  30. 1581 0
      src/assets/images/markting_img.svg
  31. 12 0
      src/assets/images/team-settings.svg
  32. 10 0
      src/assets/images/teams_icon.svg
  33. 4 0
      src/environments/environment.prod.ts
  34. 17 0
      src/environments/environment.ts
  35. 19 2
      yarn.lock

+ 1 - 0
angular.json

@@ -25,6 +25,7 @@
             "inlineStyleLanguage": "scss",
             "assets": ["src/favicon.ico", "src/assets"],
             "styles": [
+              "node_modules/ngx-toastr/toastr.css",
               "@angular/material/prebuilt-themes/indigo-pink.css",
               "src/styles.scss"
             ],

+ 4 - 1
package.json

@@ -10,7 +10,7 @@
   },
   "private": true,
   "dependencies": {
-    "@angular/animations": "^16.2.0",
+    "@angular/animations": "^16.2.1",
     "@angular/cdk": "^17.0.4",
     "@angular/common": "^16.2.0",
     "@angular/compiler": "^16.2.0",
@@ -22,7 +22,10 @@
     "@angular/platform-browser-dynamic": "^16.2.0",
     "@angular/router": "^16.2.0",
     "@ngrx/store": "^17.0.1",
+    "@ngx-translate/core": "^15.0.0",
+    "@ngx-translate/http-loader": "^8.0.0",
     "ngx-otp-input": "^0.11.4",
+    "ngx-toastr": "^18.0.0",
     "node-sass": "^9.0.0",
     "rxjs": "~7.8.0",
     "sass-loader": "^13.3.3",

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

@@ -4,10 +4,32 @@ import { BrowserModule } from '@angular/platform-browser';
 import { AppRoutingModule } from './app-routing.module';
 import { AppComponent } from './app.component';
 import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+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';
+
+export function createTranslateLoader(http: HttpClient) {
+  return new TranslateHttpLoader(http, './assets/i18n/', '.json');
+}
 
 @NgModule({
   declarations: [AppComponent],
-  imports: [BrowserModule, AppRoutingModule, BrowserAnimationsModule],
+  imports: [
+    BrowserModule,
+    AppRoutingModule,
+    BrowserAnimationsModule,
+    HttpClientModule,
+    ToastrModule.forRoot(),
+    TranslateModule.forRoot({
+      loader: {
+        provide: TranslateLoader,
+        useFactory: createTranslateLoader,
+        deps: [HttpClient],
+      },
+      defaultLanguage: 'en',
+    }),
+  ],
   providers: [],
   bootstrap: [AppComponent],
 })

+ 22 - 8
src/app/authentication/auth-sign-in/forget-password/forget-password.component.html

@@ -1,16 +1,30 @@
-<form class="form" fxLayout="column" fxLayoutAlign="start stretch">
+<form
+  class="form"
+  fxLayout="column"
+  fxLayoutAlign="start stretch"
+  [formGroup]="form"
+  (submit)="onSubmit()"
+>
   <main>
-    <h1>Forget Password</h1>
+    <h1>{{ "FORGET_PASSWORD" | translate }}</h1>
     <span
-      >The verification E-mail will be sent to <br />
-      the mailbox. please check it.</span
+      >{{ "VERFICATION_TITLE_1" | translate }} <br />
+      {{ "EMAIL_TITLE" | translate }}</span
     >
   </main>
 
-  <label class="label">Email</label>
-  <input type="email" placeholder="Enter your email address" />
+  <label class="label">{{ "EMAIL" | translate }}</label>
+  <input
+    type="email"
+    [placeholder]="'EMAIL' | translate"
+    formControlName="email"
+  />
+  <app-error-form
+    [name]="'EMAIL'"
+    [control]="form.get('email')!"
+  ></app-error-form>
 
-  <button type="submit" [routerLink]="['../verify']">
-    Send verification E-mail
+  <button type="submit">
+    {{ "SEND_VERFICATION_EMAIL" | translate }}
   </button>
 </form>

+ 52 - 2
src/app/authentication/auth-sign-in/forget-password/forget-password.component.ts

@@ -1,8 +1,58 @@
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
+import {
+  FormGroup,
+  UntypedFormControl,
+  UntypedFormGroup,
+  Validators,
+} from '@angular/forms';
+import { Router } from '@angular/router';
+import { BaseForm } from '@core/base/base-form';
+import { ComponentBase } from '@core/base/common-base';
+import { AuthService } from '@core/services/authentication/auth.service';
+import { ToastrService } from 'ngx-toastr';
+import { takeUntil } from 'rxjs';
 
 @Component({
   selector: 'app-forget-password',
   templateUrl: './forget-password.component.html',
   styleUrls: ['./forget-password.component.scss'],
 })
-export class ForgetPasswordComponent {}
+export class ForgetPasswordComponent
+  extends ComponentBase
+  implements BaseForm, OnInit
+{
+  form!: FormGroup;
+  constructor(
+    private readonly toastr: ToastrService,
+    private readonly router: Router,
+    private readonly authService: AuthService
+  ) {
+    super();
+  }
+
+  ngOnInit(): void {
+    this.initForm();
+  }
+
+  initForm(): void {
+    this.form = new UntypedFormGroup({
+      email: new UntypedFormControl(null, [
+        Validators.required,
+        Validators.email,
+      ]),
+    });
+  }
+
+  onSubmit(): void {
+    if (super.submitValidity(this.form)) {
+      this.authService
+        .ForgetPassword(this.form.value)
+        .pipe(takeUntil(this.destroy$))
+        .subscribe((response) => {
+          console.log(response);
+          this.toastr.success('Successfully !');
+          this.router.navigate(['../verify']);
+        });
+    }
+  }
+}

+ 37 - 11
src/app/authentication/auth-sign-in/sign-in/sign-in.component.html

@@ -1,7 +1,13 @@
-<form class="form" fxLayout="column" fxLayoutAlign="start stretch">
+<form
+  class="form"
+  fxLayout="column"
+  fxLayoutAlign="start stretch"
+  [formGroup]="form"
+  (submit)="onSubmit()"
+>
   <main>
-    <h1>Welcome Back!</h1>
-    <span>Sign in to continue</span>
+    <h1>{{ "WELCOME_BACK" | translate }}</h1>
+    <span>{{ "SIGN_IN_TO_COUNTINUE" | translate }}</span>
   </main>
 
   <label class="label gap-5" fxLayout="row" fxLayoutAlign="start center">
@@ -11,9 +17,18 @@
       title="email"
       style="width: 15px"
     />
-    <span>Email</span></label
+    <span>{{ "EMAIL" | translate }}</span></label
   >
-  <input type="email" placeholder="Enter your email address" />
+  <input
+    type="email"
+    placeholder="Enter your email address"
+    formControlName="email"
+  />
+
+  <app-error-form
+    [name]="'EMAIL'"
+    [control]="form.get('email')!"
+  ></app-error-form>
 
   <label class="label mt-1 gap-5" fxLayout="row" fxLayoutAlign="start center">
     <img
@@ -21,17 +36,28 @@
       alt="password.jpg"
       title="password"
     />
-    <span> Enter your password</span></label
+    <span> {{ "ENTER_YOUR_PASSWORD" | translate }}</span></label
   >
-  <input type="password" placeholder="Enter password" />
+  <input
+    type="PASSWORD"
+    placeholder="Enter password"
+    formControlName="password"
+  />
+
+  <app-error-form
+    [name]="'password'"
+    [control]="form.get('password')!"
+  ></app-error-form>
 
   <p fxLayout="row" fxLayoutAlign="end center">
-    <a [routerLink]="['./forget-password']">Forget Password?</a>
+    <a [routerLink]="['./forget-password']">{{
+      "FORGET_PASSWORD" | translate
+    }}</a>
   </p>
 
-  <button type="submit" [routerLink]="['/modules']">Sign in</button>
+  <button type="submit">{{ "SIGN_IN" | translate }}</button>
   <h5>
-    Don't have an account yet ?
-    <span [routerLink]="['/auth/signUp']">Sign Up</span>
+    {{ "DONT_HAVE_ACCOUNT" | translate }}
+    <span [routerLink]="['/auth/signUp']">{{ "SIGN_UP" | translate }}</span>
   </h5>
 </form>

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

@@ -1,10 +1,57 @@
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
+import { BaseForm } from '../../../core/base/base-form';
+import { ComponentBase } from '@core/base/common-base';
+import {
+  FormGroup,
+  UntypedFormControl,
+  UntypedFormGroup,
+  Validators,
+} from '@angular/forms';
+import { AuthService } from '@core/services/authentication/auth.service';
+import { takeUntil } from 'rxjs';
+import { Router } from '@angular/router';
+import { ToastrService } from 'ngx-toastr';
 
 @Component({
   selector: 'app-sign-in',
   templateUrl: './sign-in.component.html',
   styleUrls: ['./sign-in.component.scss'],
 })
-export class SignInComponent {
+export class SignInComponent extends ComponentBase implements BaseForm, OnInit {
   hide: boolean = true;
+  form!: FormGroup;
+
+  constructor(
+    private readonly authService: AuthService,
+    private readonly router: Router,
+    private readonly toastr: ToastrService
+  ) {
+    super();
+  }
+
+  ngOnInit(): void {
+    this.initForm();
+  }
+
+  initForm(): void {
+    this.form = new UntypedFormGroup({
+      email: new UntypedFormControl(null, [
+        Validators.email,
+        Validators.required,
+      ]),
+      password: new UntypedFormControl(null, [Validators.required]),
+    });
+  }
+
+  onSubmit(): void {
+    if (super.submitValidity(this.form)) {
+      this.authService
+        .Login(this.form.value)
+        .pipe(takeUntil(this.destroy$))
+        .subscribe((response) => {
+          console.log(response);
+          this.router.navigate(['/modules']);
+        });
+    }
+  }
 }

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

@@ -0,0 +1,19 @@
+export interface LOGIN {
+  email?: string;
+  password?: string;
+}
+export interface LOGIN_RESPONSE {
+  id?: string;
+  userName?: string;
+  email?: string;
+  token?: string;
+  expiration?: string;
+}
+
+export interface FORGET_PASSWORD {
+  email?: string;
+}
+
+export interface FORGET_PASSWORD_RESPONSE {
+  email?: string;
+}

+ 27 - 0
src/app/core/models/error-message.model.ts

@@ -0,0 +1,27 @@
+export interface ErrorsMessages {
+  required: string;
+  minLength: string;
+  maxLength: string;
+  uniqueness: string;
+  notUnique: string;
+  minMaxRangeError: string;
+  categoryHasNoOptions: string;
+  minDate: string;
+  maxDate: string;
+  invalid: string;
+  startOutScope: string;
+  endOutScope: string;
+  min: string;
+  max: string;
+  minTime: string;
+  maxTime: string;
+  minMonth: string;
+  maxMonth: string;
+  invalidRange: string;
+  pattern: string;
+  urlInvalid: string;
+  valueIsAlreadyExist: string;
+  noTimeLinesExist: string;
+  notAllFieldsSelected: string;
+  validatePhoneNumber: string;
+}

+ 26 - 11
src/app/core/services/api.service.ts

@@ -2,13 +2,16 @@ import { Observable } from 'rxjs';
 import { HttpClient, HttpHeaders } from '@angular/common/http';
 import { Injectable } from '@angular/core';
 import { TranslateService } from '@ngx-translate/core';
-import { environment } from 'src/environments/environment.development';
+import { environment } from 'src/environments/environment.prod';
 
 @Injectable({
   providedIn: 'root',
 })
 export class ApiService {
-  constructor(private readonly http: HttpClient, private readonly translate: TranslateService) {}
+  constructor(
+    private readonly http: HttpClient,
+    private readonly translate: TranslateService
+  ) {}
 
   getUploadHeaders() {
     const token: string | null = localStorage.getItem('token') || null;
@@ -18,7 +21,9 @@ export class ApiService {
 
     if (token) {
       return {
-        headers: new HttpHeaders().set('lang', language).set('Authorization', 'Bearer ' + token),
+        headers: new HttpHeaders()
+          .set('lang', language)
+          .set('Authorization', 'Bearer ' + token),
       };
     } else {
       return {
@@ -28,37 +33,47 @@ export class ApiService {
   }
 
   public get<TResponse>(type: string, params?: any): Observable<TResponse> {
-    return this.http.get<TResponse>(environment.baseURL + type, {
+    return this.http.get<TResponse>(environment.BASE_URL + type, {
       params: { ...params },
       ...this.getUploadHeaders(),
     });
   }
 
-  public post<TInput, TResponse>(type: string, data: TInput): Observable<TResponse> {
+  public post<TInput, TResponse>(
+    type: string,
+    data: TInput
+  ): Observable<TResponse> {
     // if (type === 'File/Upload') {
     //   return this.http.post<TResponse>(environment.BASE_FILE_URL + type, data, {
     //     ...this.getUploadHeaders(),
     //   });
     // }
-    return this.http.post<TResponse>(environment.baseURL + type, data ?? {}, {
+    return this.http.post<TResponse>(environment.BASE_URL + type, data ?? {}, {
       ...this.getUploadHeaders(),
     });
   }
 
-  public put<TInput, TResponse>(type: string, data: TInput, params?: any): Observable<TResponse> {
-    return this.http.put<TResponse>(environment.baseURL + type, data, {
+  public put<TInput, TResponse>(
+    type: string,
+    data: TInput,
+    params?: any
+  ): Observable<TResponse> {
+    return this.http.put<TResponse>(environment.BASE_URL + type, data, {
       params: { ...params },
       ...this.getUploadHeaders(),
     });
   }
 
-  public delete<TInput, TResponse>(type: string, id?: TInput): Observable<TResponse> {
+  public delete<TInput, TResponse>(
+    type: string,
+    id?: TInput
+  ): Observable<TResponse> {
     if (id) {
-      return this.http.delete<TResponse>(environment.baseURL + type + id, {
+      return this.http.delete<TResponse>(environment.BASE_URL + type + id, {
         ...this.getUploadHeaders(),
       });
     } else {
-      return this.http.delete<TResponse>(environment.baseURL + type, {
+      return this.http.delete<TResponse>(environment.BASE_URL + type, {
         ...this.getUploadHeaders(),
       });
     }

+ 12 - 3
src/app/core/services/authentication/auth.service.ts

@@ -1,7 +1,12 @@
 import { Injectable } from '@angular/core';
-import { VerifySSP } from '@core/models/authentication.model';
 import { ApiService } from '../api.service';
 import { Observable } from 'rxjs';
+import {
+  FORGET_PASSWORD,
+  FORGET_PASSWORD_RESPONSE,
+  LOGIN,
+  LOGIN_RESPONSE,
+} from '@core/models/authenticcation.model';
 
 @Injectable({
   providedIn: 'root',
@@ -9,7 +14,11 @@ import { Observable } from 'rxjs';
 export class AuthService {
   constructor(private readonly apiService: ApiService) {}
 
-  verifySSP(data: VerifySSP): Observable<any> {
-    return this.apiService.post<VerifySSP, any>('', data);
+  Login(data: LOGIN): Observable<LOGIN_RESPONSE> {
+    return this.apiService.post<LOGIN, LOGIN_RESPONSE>('/login', data);
+  }
+
+  ForgetPassword(data: FORGET_PASSWORD): Observable<FORGET_PASSWORD_RESPONSE> {
+    return this.apiService.post('', data);
   }
 }

+ 2 - 2
src/app/modules/profile/basic-information/basic-information.component.html

@@ -43,7 +43,7 @@
           fxFlex.lt-md="100"
           fxFlex.gt-sm="50"
         >
-          <label for="birth_date" class="plr-30">
+          <label for="birth_date">
             <img
               src="assets/images/birthday-cake-candle-pie-svgrepo-com.svg"
               alt=""
@@ -61,7 +61,7 @@
           fxFlex.lt-md="100"
           fxFlex.gt-sm="50"
         >
-          <label for="tax_no" class="plr-30">
+          <label for="tax_no">
             <img src="assets/images/id-card-svgrepo-com.svg" alt="" title="" />
             <span>ID Number <span class="red">*</span></span>
           </label>

+ 13 - 2
src/app/modules/teams/components/team-info-header/team-info-header.component.html

@@ -9,7 +9,7 @@
     class="gap-10 ptr"
     (click)="onBack()"
   >
-    <img src="../../../../../assets/images/teams.svg" alt="" title="" />
+    <img src="../../../../../assets/images/arrow.svg" alt="" title="" />
     <span class="bold">Marketing Team Information</span>
   </h1>
   <div
@@ -17,6 +17,17 @@
     fxLayout="row"
     fxLayoutAlign="end center"
   >
-    <button class="team-setting">Team Setting</button>
+    <button
+      class="team-setting gap-5"
+      fxLayout="row"
+      fxLayoutAlign="center center"
+    >
+      <img
+        src="../../../../../assets/images/team-settings.svg"
+        alt=""
+        title=""
+      />
+      Team Setting
+    </button>
   </div>
 </section>

+ 1 - 1
src/app/modules/teams/components/teams-filter/teams-filter.component.html

@@ -4,7 +4,7 @@
   fxLayoutAlign="space-between center"
 >
   <h1 fxLayout="row" fxLayoutAlign="start center" class="gap-10">
-    <img src="../../../../../assets/images/teams.svg" alt="" title="" />
+    <img src="../../../../../assets/images/teams_icon.svg" alt="" title="" />
     <span class="bold">Teams</span>
   </h1>
   <div

+ 2 - 2
src/app/modules/teams/list/item/item.component.html

@@ -1,10 +1,10 @@
 <section
-  class="team-card gap-20"
+  class="team-card gap-20 ptr"
   fxLayout="column"
   fxLayoutAlign="center center"
   (click)="onTeamInfo()"
 >
-  <img src="" alt="" title="" />
+  <img src="../../../../../assets/images/markting_img.svg" alt="" title="" />
   <h2 class="bold">Marketing Team</h2>
   <p class="bold">Members : 25</p>
 </section>

+ 14 - 2
src/app/modules/teams/team-info/team-info-card/team-info-card.component.html

@@ -1,6 +1,18 @@
 <section class="team-info-card" fxLayout="column" fxLayoutAlign="start start">
-  <img src="../../../../../assets/images/avatar.png" alt="" title="" />
+  <img
+    src="../../../../../assets/images/market_info_avatar.png"
+    alt=""
+    title=""
+  />
   <h2>George Tarielashvili</h2>
-  <span>Senior UI/UX Designer</span>
+  <span fxLayout="row" fxLayoutAlign="space-between center" class="w-100">
+    <span> Senior UI/UX Designer </span>
+    <img
+      src="../../../../../assets/images/chat_icon.svg"
+      alt=""
+      title=""
+      class="chat"
+    />
+  </span>
   <span>User@gmail.com</span>
 </section>

+ 7 - 0
src/app/modules/teams/teams.component.scss

@@ -72,6 +72,13 @@
           margin-bottom: 10px;
         }
 
+        .chat {
+          width: 20px;
+          height: 20px;
+          object-fit: cover;
+          margin-top: 5px;
+        }
+
         h2 {
           color: #4b5155;
           font-size: 18px;

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

@@ -0,0 +1,21 @@
+<span *ngIf="control && control.touched">
+  <mat-error
+    class="error-message"
+    *ngIf="control.errors?.['required']"
+    [ngClass]="{'show': control.errors?.['required']}"
+    >{{ name | translate }} {{ "REQUIRED" | translate }} !</mat-error
+  >
+
+  <mat-error class="error-message" *ngIf="control.errors?.['minlength']">
+    {{ name | translate }} {{ "REQUIRED_MIN_LENGTH" | translate }}
+    {{ minLength }} !</mat-error
+  >
+
+  <mat-error class="error-message" *ngIf="control.errors?.['maxlength']">
+    {{ name | translate }} must not be more than {{ maxLength }} !</mat-error
+  >
+
+  <mat-error class="error-message" *ngIf="control.errors?.['email']">
+    {{ "VALID_EMAIL" | translate }} !</mat-error
+  >
+</span>

+ 13 - 0
src/app/shared/components/error-form/error-form.component.scss

@@ -0,0 +1,13 @@
+.error-message {
+  width: 100%;
+  display: block;
+  color: red;
+  padding: 0 0.5rem;
+  font-size: 11px;
+  opacity: 1;
+  transition: opacity 1s ease-in-out; /* Adjust the duration and easing as needed */
+}
+
+.error-message.show {
+  opacity: 1;
+}

+ 46 - 0
src/app/shared/components/error-form/error-form.component.spec.ts

@@ -0,0 +1,46 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ErrorFormComponent } from './error-form.component';
+import { TranslateService } from '@ngx-translate/core';
+import {
+  ReactiveFormsModule,
+  FormsModule,
+  NgModel,
+  AbstractControl,
+} from '@angular/forms';
+
+describe('ErrorFormComponent', () => {
+  let component: ErrorFormComponent;
+  let fixture: ComponentFixture<ErrorFormComponent>;
+  let translateService: TranslateService;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [ErrorFormComponent, ReactiveFormsModule, FormsModule],
+      providers: [TranslateService],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(ErrorFormComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+  it('should have default minLength set to 8', () => {
+    expect(component.minLength).toEqual(8);
+  });
+
+  it('should have default maxLength set to 24', () => {
+    expect(component.maxLength).toEqual(24);
+  });
+
+  it('should have messages input set', () => {
+    const messages = { required: 'This field is required' };
+    component.messages = messages;
+    fixture.detectChanges();
+
+    expect(component.messages).toEqual(messages);
+  });
+});

+ 22 - 0
src/app/shared/components/error-form/error-form.component.ts

@@ -0,0 +1,22 @@
+import { Component, Input } from '@angular/core';
+import { AbstractControl, NgModel } from '@angular/forms';
+import { ErrorsMessages } from '@core/models/error-message.model';
+import { TranslateService } from '@ngx-translate/core';
+
+@Component({
+  selector: 'app-error-form',
+  templateUrl: './error-form.component.html',
+  styleUrls: ['./error-form.component.scss'],
+})
+export class ErrorFormComponent {
+  formValues: any;
+  @Input() minLength: number = 8;
+  @Input() maxLength: number = 24;
+  @Input() name!: string;
+  @Input() control!: AbstractControl | NgModel;
+  @Input() messages: Partial<ErrorsMessages> = {};
+
+  constructor(public readonly translate: TranslateService) {}
+
+  ngOnInit(): void {}
+}

+ 6 - 1
src/app/shared/shared.module.ts

@@ -22,6 +22,8 @@ import { MatSelectModule } from '@angular/material/select';
 import { MatSliderModule } from '@angular/material/slider';
 import { MatSlideToggleModule } from '@angular/material/slide-toggle';
 import { MatDialogModule } from '@angular/material/dialog';
+import { ErrorFormComponent } from './components/error-form/error-form.component';
+import { TranslateModule } from '@ngx-translate/core';
 
 const MATERIAL_MODULES = [
   FlexLayoutModule,
@@ -45,7 +47,8 @@ const MATERIAL_MODULES = [
   MatDialogModule,
 ];
 
-const COMPONENTS = [WarningComponent, FileUploadComponent];
+const COMPONENTS = [ErrorFormComponent, WarningComponent, FileUploadComponent];
+const MODULES = [TranslateModule];
 @NgModule({
   declarations: [WarningComponent, ...COMPONENTS, FileUploadComponent],
   imports: [
@@ -53,12 +56,14 @@ const COMPONENTS = [WarningComponent, FileUploadComponent];
     ReactiveFormsModule,
     CommonModule,
     ...MATERIAL_MODULES,
+    ...MODULES,
   ],
   exports: [
     FormsModule,
     ReactiveFormsModule,
     ...MATERIAL_MODULES,
     ...COMPONENTS,
+    ...MODULES,
   ],
   providers: [NativeDateAdapter],
 })

+ 14 - 0
src/assets/i18n/ar.json

@@ -0,0 +1,14 @@
+{
+  "LOGIN": "تسجيل الدخول",
+  "ENTER_YOUR_PASSWORD": "ادخل رقمك السري",
+  "EMAIL": "الإيميل",
+  "FORGET_PASSWORD": "نسيت كلمة المرور",
+  "SIGN_IN": "تسجيل الدخول",
+  "SIGN_UP": "التسجبل",
+  "DONT_HAVE_ACCOUNT": "ليس لديك حساب ؟",
+  "WELCOME_BACK": "مرحبا بعودتك",
+  "SIGN_IN_TO_COUNTINUE": "قم بتسجل الدخول للأستمرار",
+  "VERFICATION_TITLE_1": "سيتم إرسال البريد الإلكتروني للتحقق إلى",
+  "EMAIL_TITLE": "صندوق البريد. رجاءا تأكد.",
+  "SEND_VERFICATION_EMAIL": "ارسل ايميل التفعيل"
+}

+ 14 - 0
src/assets/i18n/en.json

@@ -0,0 +1,14 @@
+{
+  "LOGIN": "Login",
+  "ENTER_YOUR_PASSWORD": "Enter Your Password",
+  "EMAIL": "Email",
+  "FORGET_PASSWORD": "Forget Password",
+  "SIGN_IN": "Sign In",
+  "SIGN_UP": "Sign Up",
+  "DONT_HAVE_ACCOUNT": "Don't Have Account ?",
+  "WELCOME_BACK": "Welcome Back",
+  "SIGN_IN_TO_COUNTINUE": "Sign In To continue",
+  "VERFICATION_TITLE_1": "The verification E-mail will be sent to",
+  "EMAIL_TITLE": "the mailbox. please check it.",
+  "SEND_VERFICATION_EMAIL": "Send verification E-mail"
+}

+ 3 - 0
src/assets/images/arrow.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+  <path id="Icon_material-arrow_back" data-name="Icon material-arrow_back" d="M26,14.75H10.787l6.988-6.988L16,6,6,16,16,26l1.762-1.763L10.787,17.25H26Z" transform="translate(-6 -6)" fill="#2f2c83"/>
+</svg>

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 7 - 0
src/assets/images/chat_icon.svg


BIN
src/assets/images/market_info_avatar.png


BIN
src/assets/images/market_info_avatar/Ellipse 204@2x.png


BIN
src/assets/images/market_info_avatar/market_info_avatar.png


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1581 - 0
src/assets/images/markting_img.svg


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 12 - 0
src/assets/images/team-settings.svg


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 10 - 0
src/assets/images/teams_icon.svg


+ 4 - 0
src/environments/environment.prod.ts

@@ -0,0 +1,4 @@
+export const environment = {
+  production: true,
+  BASE_URL: 'https://sas-api.azurewebsites.net/api/sas/',
+};

+ 17 - 0
src/environments/environment.ts

@@ -0,0 +1,17 @@
+// This file can be replaced during build by using the `fileReplacements` array.
+// `ng build` replaces `environment.ts` with `environment.prod.ts`.
+// The list of file replacements can be found in `angular.json`.
+
+export const environment = {
+  production: false,
+  baseURL: 'https://sas-api.azurewebsites.net/api/sas/',
+};
+
+/*
+ * For easier debugging in development mode, you can import the following file
+ * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
+ *
+ * This import should be commented out in production mode because it will have a negative impact
+ * on performance if an error is thrown.
+ */
+// import 'zone.js/plugins/zone-error';  // Included with Angular CLI.

+ 19 - 2
yarn.lock

@@ -121,9 +121,9 @@
     ora "5.4.1"
     rxjs "7.8.1"
 
-"@angular/animations@^16.2.0":
+"@angular/animations@^16.2.1":
   version "16.2.12"
-  resolved "https://registry.npmjs.org/@angular/animations/-/animations-16.2.12.tgz"
+  resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-16.2.12.tgz#27744d8176e09e70e0f6d837c3abcfcee843a936"
   integrity sha512-MD0ElviEfAJY8qMOd6/jjSSvtqER2RDAi0lxe6EtUacC1DHCYkaPrKW4vLqY+tmZBg1yf+6n+uS77pXcHHcA3w==
   dependencies:
     tslib "^2.3.0"
@@ -2199,6 +2199,16 @@
   resolved "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.11.tgz"
   integrity sha512-4ndXJ4s94ZsryVGSDk/waIDrUqXqdGWftoOEn81Zu+nkL9ncI/G1fNUlSJ5OqeKmMLxMFouoy+BuJfvT+gEgnQ==
 
+"@ngx-translate/core@^15.0.0":
+  version "15.0.0"
+  resolved "https://registry.yarnpkg.com/@ngx-translate/core/-/core-15.0.0.tgz#0fe55b9bd47e75b03d1123658f15fb7b5a534f3c"
+  integrity sha512-Am5uiuR0bOOxyoercDnAA3rJVizo4RRqJHo8N3RqJ+XfzVP/I845yEnMADykOHvM6HkVm4SZSnJBOiz0Anx5BA==
+
+"@ngx-translate/http-loader@^8.0.0":
+  version "8.0.0"
+  resolved "https://registry.yarnpkg.com/@ngx-translate/http-loader/-/http-loader-8.0.0.tgz#e02c25dbe33c6b1edee73e3654ab8a161572cdfb"
+  integrity sha512-SFMsdUcmHF5OdZkL1CHEoSAwbP5EbAOPTLLboOCRRoOg21P4GJx+51jxGdJeGve6LSKLf4Pay7BkTwmE6vxYlg==
+
 "@nodelib/fs.scandir@2.1.5":
   version "2.1.5"
   resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
@@ -5676,6 +5686,13 @@ ngx-otp-input@^0.11.4:
   dependencies:
     tslib "^2.0.0"
 
+ngx-toastr@^18.0.0:
+  version "18.0.0"
+  resolved "https://registry.yarnpkg.com/ngx-toastr/-/ngx-toastr-18.0.0.tgz#0016e897108817eb6b2ee16ff130b4c42fc214b0"
+  integrity sha512-jZ3rOG6kygl8ittY8OltIMSo47P1VStuS01igm3MZXK6InJwHVvxU7wDHI/HGMlXSyNvWncyOuFHnnMEAifsew==
+  dependencies:
+    tslib "^2.3.0"
+
 nice-napi@^1.0.2:
   version "1.0.2"
   resolved "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz"