Autors | SHA1 | Ziņojums | Datums |
---|---|---|---|
|
729f581027 | Add review non compliance step to the investigation flow | pirms 3 gadiem |
|
b76fa9616b | Minor changes | pirms 3 gadiem |
|
09ab184a0f | Conserve state and show screens based on logged in user | pirms 3 gadiem |
@@ -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 | |||
}]; | |||