| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
729f581027 | Add review non compliance step to the investigation flow | 3 years ago |
|
|
b76fa9616b | Minor changes | 3 years ago |
|
|
09ab184a0f | Conserve state and show screens based on logged in user | 3 years ago |
| @@ -25,6 +25,7 @@ import { ModifyCaseDetailsComponent } from './pages/investigate-business-entitie | |||
| import { AssignPanelComponent } from './pages/investigate-business-entities-and-individuals/assign-panel/assign-panel.component'; | |||
| import { TextareaComponent } from './widgets/form/textarea/textarea.component'; | |||
| import { MultiFileUploadComponent } from './widgets/form/multi-file-upload/multi-file-upload.component'; | |||
| import { ReviewNonComplianceComponent } from './pages/investigate-business-entities-and-individuals/review-non-compliance/review-non-compliance.component'; | |||
| @NgModule({ | |||
| declarations: [ | |||
| @@ -48,7 +49,8 @@ import { MultiFileUploadComponent } from './widgets/form/multi-file-upload/multi | |||
| ModifyCaseDetailsComponent, | |||
| AssignPanelComponent, | |||
| TextareaComponent, | |||
| MultiFileUploadComponent | |||
| MultiFileUploadComponent, | |||
| ReviewNonComplianceComponent | |||
| ], | |||
| imports: [ | |||
| BrowserModule, | |||
| @@ -22,6 +22,7 @@ export class NotificationsComponent implements OnInit { | |||
| }, { | |||
| text: 'Request to create a new Committee', | |||
| timeStamp: '2 hours ago', | |||
| redirectionUrl: '/tabs/investigate-business-entities-and-individuals', | |||
| }, { | |||
| text: 'New name application has been submitted', | |||
| description: 'A new Applicant in the company name Kimao has applied for an appeal', | |||
| @@ -27,9 +27,11 @@ | |||
| <img src="assets/icons/chevron-down.svg" alt="chevron down image"> | |||
| </ng-container> | |||
| <ng-container *ngIf="showLogout"> | |||
| <img src="assets/icons/logout.svg" class="logout-icon" alt="logout icon"> | |||
| <span> Log me out </span> | |||
| <img src="assets/icons/chevron-down.svg" alt="chevron down image"> | |||
| <a [routerLink]="['/login']"> | |||
| <img src="assets/icons/logout.svg" class="logout-icon" alt="logout icon"> | |||
| <span> Log me out </span> | |||
| <img src="assets/icons/chevron-down.svg" alt="chevron down image"> | |||
| </a> | |||
| </ng-container> | |||
| </section> | |||
| @@ -9,26 +9,39 @@ | |||
| <span class="current-page"> Investigating Business Entities and Individuals </span> | |||
| </section> | |||
| <app-check-status | |||
| *ngIf="!canExecute" | |||
| [status]="state" | |||
| [assignedTo]="executingRole" | |||
| ></app-check-status> | |||
| <app-view-case-details | |||
| *ngIf="state === 'VIEW INITIAL DETAILS'" | |||
| [hasEnoughData]="hasEnoughData" | |||
| (updateHasEnoughData)="hasEnoughData = $event" | |||
| ></app-view-case-details> | |||
| <app-modify-case-details | |||
| *ngIf="state === 'ENTER MORE DETAILS'" | |||
| ></app-modify-case-details> | |||
| <app-assign-panel | |||
| *ngIf="state === 'ASSIGN COMMITTEE'" | |||
| ></app-assign-panel> | |||
| <ng-container *ngIf="canExecute"> | |||
| <app-view-case-details | |||
| *ngIf="state === 'VIEW INITIAL DETAILS'" | |||
| [hasEnoughData]="hasEnoughData" | |||
| (updateHasEnoughData)="hasEnoughData = $event" | |||
| ></app-view-case-details> | |||
| <div class="form-action-buttons"> | |||
| <button class="common-button neutral" *ngIf="stateHistory.length > 0" (click)="goBack()"> | |||
| Back | |||
| </button> | |||
| <button class="common-button" (click)="proceed()"> | |||
| Proceed | |||
| </button> | |||
| </div> | |||
| <app-modify-case-details | |||
| *ngIf="state === 'ENTER MORE DETAILS'" | |||
| ></app-modify-case-details> | |||
| <app-assign-panel | |||
| *ngIf="state === 'ASSIGN COMMITTEE'" | |||
| ></app-assign-panel> | |||
| <app-review-non-compliance | |||
| *ngIf="state === 'REVIEW NON COMPLIANCE'" | |||
| [isNonCompliant]="isNonCompliant" | |||
| (onNonComplianceUpdate)="isNonCompliant = $event" | |||
| ></app-review-non-compliance> | |||
| <div class="form-action-buttons"> | |||
| <button class="common-button neutral" *ngIf="stateHistory.length > 0" (click)="goBack()"> | |||
| Back | |||
| </button> | |||
| <button class="common-button" (click)="proceed()"> | |||
| Proceed | |||
| </button> | |||
| </div> | |||
| </ng-container> | |||
| @@ -1,6 +1,7 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| type State = 'VIEW INITIAL DETAILS'|'ENTER MORE DETAILS'|'ASSIGN COMMITTEE'; | |||
| type State = 'VIEW INITIAL DETAILS'|'ENTER MORE DETAILS'|'ASSIGN COMMITTEE'|'REVIEW NON COMPLIANCE'; | |||
| type Role = 'Investigator'|'Hod'|'Panel'; | |||
| @Component({ | |||
| selector: 'app-investigate-business-entities-and-individuals', | |||
| @@ -9,11 +10,50 @@ type State = 'VIEW INITIAL DETAILS'|'ENTER MORE DETAILS'|'ASSIGN COMMITTEE'; | |||
| }) | |||
| export class InvestigateBusinessEntitiesAndIndividualsComponent implements OnInit { | |||
| hasEnoughData = false; | |||
| isNonCompliant = false; | |||
| state: State = 'VIEW INITIAL DETAILS'; | |||
| state: State; | |||
| stateHistory: Array<State> = []; | |||
| constructor() { } | |||
| loginRole: Role; | |||
| canExecute: boolean; | |||
| executingRole: Role; | |||
| constructor() { | |||
| const loginEmail = localStorage.getItem('loginEmail'); | |||
| if (loginEmail && loginEmail.toLocaleLowerCase().startsWith('hod')) { | |||
| this.loginRole = 'Hod'; | |||
| } else if (loginEmail && loginEmail.toLocaleLowerCase().startsWith('panel')) { | |||
| this.loginRole = 'Panel'; | |||
| } else { | |||
| this.loginRole = 'Investigator'; | |||
| } | |||
| const savedState = localStorage.getItem('state'); | |||
| switch (savedState) { | |||
| case 'ENTER MORE DETAILS': | |||
| this.state = 'ENTER MORE DETAILS'; | |||
| this.executingRole = 'Investigator'; | |||
| break; | |||
| case 'ASSIGN COMMITTEE': | |||
| this.state = 'ASSIGN COMMITTEE'; | |||
| this.executingRole = 'Hod'; | |||
| break; | |||
| case 'REVIEW NON COMPLIANCE': | |||
| this.state = 'REVIEW NON COMPLIANCE'; | |||
| this.executingRole = 'Investigator'; | |||
| break; | |||
| default: | |||
| this.state = 'VIEW INITIAL DETAILS'; | |||
| this.executingRole = 'Investigator'; | |||
| } | |||
| this.canExecute = this.loginRole === this.executingRole; | |||
| } | |||
| proceed() { | |||
| this.stateHistory.push(this.state); | |||
| @@ -22,14 +62,25 @@ export class InvestigateBusinessEntitiesAndIndividualsComponent implements OnIni | |||
| case 'VIEW INITIAL DETAILS': | |||
| if (this.hasEnoughData) { | |||
| this.state = 'ASSIGN COMMITTEE'; | |||
| this.executingRole = 'Hod'; | |||
| } else { | |||
| this.state = 'ENTER MORE DETAILS'; | |||
| this.executingRole = 'Investigator'; | |||
| } | |||
| break; | |||
| case 'ENTER MORE DETAILS': | |||
| this.state = 'ASSIGN COMMITTEE'; | |||
| this.executingRole = 'Hod'; | |||
| break; | |||
| case 'ASSIGN COMMITTEE': | |||
| this.state = 'REVIEW NON COMPLIANCE'; | |||
| this.executingRole = 'Investigator'; | |||
| break; | |||
| } | |||
| localStorage.setItem('state', this.state); | |||
| this.canExecute = this.loginRole === this.executingRole; | |||
| } | |||
| goBack() { | |||
| @@ -38,6 +89,18 @@ export class InvestigateBusinessEntitiesAndIndividualsComponent implements OnIni | |||
| if (state) { | |||
| this.state = state; | |||
| } | |||
| switch (this.state) { | |||
| case 'ASSIGN COMMITTEE': | |||
| this.executingRole = 'Hod'; | |||
| break; | |||
| default: | |||
| this.executingRole = 'Investigator'; | |||
| } | |||
| localStorage.setItem('state', this.state); | |||
| this.canExecute = this.loginRole === this.executingRole; | |||
| } | |||
| ngOnInit(): void { | |||
| @@ -0,0 +1,37 @@ | |||
| <div class="screen-holder"> | |||
| <h3>Review compliance of entity</h3> | |||
| <div class="files-heading">Financial statements:</div> | |||
| <div class="files-holder"> | |||
| <app-file | |||
| name="Account statement Q1" | |||
| [sizeInBytes]="300000" | |||
| extension="xls" | |||
| link="/assets/files/spreadsheet.xlsx" | |||
| ></app-file> | |||
| <app-file | |||
| name="Account statement Q2" | |||
| [sizeInBytes]="340000" | |||
| extension="xls" | |||
| link="/assets/files/spreadsheet.xlsx" | |||
| ></app-file> | |||
| <app-file | |||
| name="Account statement Q3" | |||
| [sizeInBytes]="320000" | |||
| extension="xls" | |||
| link="/assets/files/spreadsheet.xlsx" | |||
| ></app-file> | |||
| </div> | |||
| <app-multi-file-upload label="Analysis documents"></app-multi-file-upload> | |||
| <app-textarea | |||
| label="Remarks" | |||
| ></app-textarea> | |||
| <div class="compliance-check"> | |||
| <label> | |||
| <input type="checkbox" [(ngModel)]="isNonCompliant" (ngModelChange)="toggleIsNonCompliant($event)"> | |||
| <span>The entity is observed to have been non-compliant with the regulations</span> | |||
| </label> | |||
| </div> | |||
| @@ -0,0 +1,39 @@ | |||
| .screen-holder { | |||
| width: calc(70% - 2rem); | |||
| padding: 4rem; | |||
| margin: 0 auto; | |||
| } | |||
| h3 { | |||
| font-size: 2rem; | |||
| color: var(--dark-grey); | |||
| filter: brightness(80%); | |||
| font-weight: 500; | |||
| margin: 2rem 0; | |||
| } | |||
| .files-heading { | |||
| font-size: 1.4rem; | |||
| color: var(--primary); | |||
| font-weight: 400; | |||
| letter-spacing: 0.5px; | |||
| margin-bottom: 5px; | |||
| } | |||
| .files-holder { | |||
| & > * { | |||
| margin-right: 15px; | |||
| } | |||
| } | |||
| .compliance-check { | |||
| font-size: 1.4rem; | |||
| color: var(--dark-grey); | |||
| padding: 2rem; | |||
| text-align: center; | |||
| margin-top: 20px; | |||
| input { | |||
| margin-right: 10px; | |||
| } | |||
| } | |||
| @@ -0,0 +1,25 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { ReviewNonComplianceComponent } from './review-non-compliance.component'; | |||
| describe('ReviewNonComplianceComponent', () => { | |||
| let component: ReviewNonComplianceComponent; | |||
| let fixture: ComponentFixture<ReviewNonComplianceComponent>; | |||
| beforeEach(async () => { | |||
| await TestBed.configureTestingModule({ | |||
| declarations: [ ReviewNonComplianceComponent ] | |||
| }) | |||
| .compileComponents(); | |||
| }); | |||
| beforeEach(() => { | |||
| fixture = TestBed.createComponent(ReviewNonComplianceComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,22 @@ | |||
| import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; | |||
| @Component({ | |||
| selector: 'app-review-non-compliance', | |||
| templateUrl: './review-non-compliance.component.html', | |||
| styleUrls: ['./review-non-compliance.component.scss'] | |||
| }) | |||
| export class ReviewNonComplianceComponent implements OnInit { | |||
| @Input() isNonCompliant = false; | |||
| @Output() onNonComplianceUpdate = new EventEmitter<boolean>(); | |||
| constructor() { } | |||
| ngOnInit(): void { | |||
| } | |||
| toggleIsNonCompliant(isNonCompliant: boolean) { | |||
| this.isNonCompliant = isNonCompliant; | |||
| this.onNonComplianceUpdate.emit(isNonCompliant); | |||
| } | |||
| } | |||
| @@ -8,8 +8,10 @@ | |||
| <app-generic-input | |||
| type="email" | |||
| placeholder="johndoe@mail.com" | |||
| placeholder="e.g. johndoe@mail.com" | |||
| label="Email ID" | |||
| [value]="email" | |||
| (onChange)="updateEmail($event)" | |||
| ></app-generic-input> | |||
| <app-generic-input | |||
| @@ -6,10 +6,17 @@ import { Component, OnInit } from '@angular/core'; | |||
| styleUrls: ['./login.component.scss'] | |||
| }) | |||
| export class LoginComponent implements OnInit { | |||
| email = ''; | |||
| constructor() { } | |||
| ngOnInit(): void { | |||
| } | |||
| updateEmail(email: string) { | |||
| this.email = email; | |||
| localStorage.setItem('loginEmail', email); | |||
| } | |||
| } | |||
| @@ -53,7 +53,7 @@ | |||
| ></app-select-input> | |||
| </ng-container> | |||
| <ng-container *ngIf="registerInput.type === 'text' || registerInput.type === 'email' || registerInput.type === 'number'"> | |||
| <ng-container *ngIf="registerInput.type === 'text' || registerInput.type === 'email'"> | |||
| <app-generic-input | |||
| [label]="registerInput.name" | |||
| [type]="registerInput.type" | |||
| @@ -1,13 +1,7 @@ | |||
| <header class="tab-header"> | |||
| <h2> | |||
| Application Status | |||
| </h2> | |||
| </header> | |||
| <div class="search-input-container"> | |||
| <section class="form-message" [ngClass]="{'error' : error.type === 'DANGER', 'warning' : error.type === 'WARNING' }" *ngIf="error"> | |||
| <p> <strong> Assigned To: </strong> {{ error.assignedTo }} </p> | |||
| <h5> {{ error.status }} </h5> | |||
| <div class="message-container"> | |||
| <section class="form-message" [ngClass]="{'error' : type === 'DANGER', 'warning' : type === 'WARNING' }" > | |||
| <p> <strong> Assigned To: </strong> {{ assignedTo }} </p> | |||
| <h5> {{ status }} </h5> | |||
| </section> | |||
| <p class="note">Please wait for the assigned user to continue this process.</p> | |||
| </div> | |||
| @@ -1,4 +1,4 @@ | |||
| .search-input-container { | |||
| .message-container { | |||
| width: 60%; | |||
| margin: 0 auto; | |||
| text-align: center; | |||
| @@ -33,4 +33,9 @@ | |||
| color: var(--dark-grey); | |||
| } | |||
| } | |||
| } | |||
| .note { | |||
| font-size: 1.4rem; | |||
| font-style: italic; | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| import { Component, OnInit } from '@angular/core'; | |||
| import { Component, Input, OnInit } from '@angular/core'; | |||
| @Component({ | |||
| selector: 'app-check-status', | |||
| @@ -6,20 +6,12 @@ import { Component, OnInit } from '@angular/core'; | |||
| styleUrls: ['./check-status.component.scss'] | |||
| }) | |||
| export class CheckStatusComponent implements OnInit { | |||
| error?: { | |||
| status: string, | |||
| assignedTo: string, | |||
| type: 'SUCCESS' | 'WARNING' | 'DANGER', | |||
| }; | |||
| @Input() status = 'PENDING'; | |||
| @Input() assignedTo = 'Another User'; | |||
| @Input() type: 'SUCCESS' | 'WARNING' | 'DANGER' = 'WARNING'; | |||
| constructor() { } | |||
| ngOnInit(): void { | |||
| this.error = { | |||
| status: 'In Progress', | |||
| assignedTo: 'Mr Miyagi', | |||
| type: 'WARNING' | |||
| }; | |||
| } | |||
| } | |||
| @@ -1,5 +1,5 @@ | |||
| <div class="input-holder"> | |||
| <input [type]="type" [placeholder]="placeholder ? placeholder : ''"> | |||
| <input [type]="type" [placeholder]="placeholder ? placeholder : ''" [ngModel]="value" (ngModelChange)="updateValue($event)"> | |||
| <label> {{ label }}: </label> | |||
| </div> | |||
| @@ -1,8 +1,8 @@ | |||
| import { Component, Input, OnInit } from '@angular/core'; | |||
| import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core'; | |||
| export interface GenericInputProperties { | |||
| name: string, | |||
| type: 'text' | 'email' | 'number' | 'password', | |||
| type: 'text' | 'email' | 'password', | |||
| placeholder?: string, | |||
| } | |||
| @@ -14,11 +14,19 @@ export interface GenericInputProperties { | |||
| export class GenericInputComponent implements OnInit { | |||
| @Input() label = ''; | |||
| @Input() placeholder: string|undefined; | |||
| @Input() type: 'text'|'email'|'number'|'password' = 'text'; | |||
| @Input() type: 'text'|'email'|'password' = 'text'; | |||
| @Input() value = ''; | |||
| @Output() onChange = new EventEmitter<string>(); | |||
| constructor() { } | |||
| ngOnInit(): void { | |||
| } | |||
| updateValue(value: string) { | |||
| this.onChange.emit(value); | |||
| } | |||
| } | |||
| @@ -12,7 +12,7 @@ const HARDCODED_USERS: Array<SelectableEntity> = [{ | |||
| id: 0, | |||
| name: "Alfred E. Kaplan", | |||
| avatar: '../../assets/avatars/1.jpg', | |||
| subTitle: 'Engineer', | |||
| subTitle: 'Analyst', | |||
| isSelected: false | |||
| }, { | |||
| id: 0, | |||
| @@ -24,13 +24,13 @@ const HARDCODED_USERS: Array<SelectableEntity> = [{ | |||
| id: 0, | |||
| name: "Leslie L. Barber", | |||
| avatar: '../../assets/avatars/3.jpg', | |||
| subTitle: 'Engineer', | |||
| subTitle: 'Analyst', | |||
| isSelected: false | |||
| }, { | |||
| id: 0, | |||
| name: "Todd K. Carrico", | |||
| avatar: '../../assets/avatars/4.jpg', | |||
| subTitle: 'Engineer', | |||
| subTitle: 'Analyst', | |||
| isSelected: false | |||
| }, { | |||
| id: 0, | |||
| @@ -42,13 +42,13 @@ const HARDCODED_USERS: Array<SelectableEntity> = [{ | |||
| id: 0, | |||
| name: "Jessica R. Folger", | |||
| avatar: '../../assets/avatars/6.jpg', | |||
| subTitle: 'Engineer', | |||
| subTitle: 'Analyst', | |||
| isSelected: false | |||
| }, { | |||
| id: 0, | |||
| name: "Charles M. Pollard", | |||
| avatar: '../../assets/avatars/7.jpg', | |||
| subTitle: 'Engineer', | |||
| subTitle: 'Analyst', | |||
| isSelected: false | |||
| }, { | |||
| id: 0, | |||
| @@ -60,7 +60,7 @@ const HARDCODED_USERS: Array<SelectableEntity> = [{ | |||
| id: 0, | |||
| name: "Julia R. Bedwell", | |||
| avatar: '../../assets/avatars/9.jpg', | |||
| subTitle: 'Engineer', | |||
| subTitle: 'Analyst', | |||
| isSelected: false | |||
| }]; | |||