Skip to content

Commit a232b80

Browse files
authored
Merge pull request #1998 from bcgov/feature/ALCS-2311-2393
Expand Admin for Conditions to Include Add/Remove Fields
2 parents 0580cf6 + 87981a1 commit a232b80

File tree

40 files changed

+1113
-283
lines changed

40 files changed

+1113
-283
lines changed

alcs-frontend/src/app/features/admin/decision-condition-types/decision-condition-types-dialog/decision-condition-types-dialog.component.html

+93-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<h4>{{ isEdit ? 'Edit' : 'Create' }} Decision Condition Type</h4>
33
</div>
44
<div mat-dialog-content class="dialog">
5-
<form (ngSubmit)="onSubmit()" #form="ngForm">
5+
<form (ngSubmit)="onSubmit()" [formGroup]="conditionTypeForm">
66
<div>
77
<mat-form-field class="code" appearance="outline">
88
<mat-label>Code</mat-label>
@@ -13,7 +13,7 @@ <h4>{{ isEdit ? 'Edit' : 'Create' }} Decision Condition Type</h4>
1313
minlength="4"
1414
matInput
1515
id="code"
16-
[(ngModel)]="code"
16+
formControlName="code"
1717
name="code"
1818
/>
1919
</mat-form-field>
@@ -22,16 +22,104 @@ <h4>{{ isEdit ? 'Edit' : 'Create' }} Decision Condition Type</h4>
2222
<div class="full-width">
2323
<mat-form-field class="label" appearance="outline">
2424
<mat-label>Label</mat-label>
25-
<input required matInput id="label" [(ngModel)]="label" name="label" />
25+
<input required matInput id="label" formControlName="label" name="label" />
2626
</mat-form-field>
2727
</div>
2828

2929
<div class="full-width">
3030
<mat-form-field class="description" appearance="outline">
3131
<mat-label>Description</mat-label>
32-
<input required matInput id="description" [(ngModel)]="description" name="description" />
32+
<input required matInput id="description" formControlName="description" name="description" />
3333
</mat-form-field>
3434
</div>
35+
36+
<div class="condition-fields-container full-width">
37+
<span>Click to select fields</span>
38+
39+
<div class="condition-field">
40+
<mat-checkbox formControlName="isComponentToConditionChecked">Component to Condition*</mat-checkbox>
41+
</div>
42+
43+
<div class="condition-field">
44+
<div class="condition-field-header">
45+
<div>
46+
<mat-checkbox formControlName="isAdministrativeFeeAmountChecked">Administrative Fee Amount</mat-checkbox>
47+
</div>
48+
49+
<div class="toggle" *ngIf="conditionTypeForm.get('isAdministrativeFeeAmountChecked')?.value">
50+
<mat-label
51+
[ngClass]="{ inactive: conditionTypeForm.get('isAdministrativeFeeAmountRequired')?.value ?? false }"
52+
>Mark Field as Required (*)
53+
</mat-label>
54+
<mat-slide-toggle
55+
formControlName="isAdministrativeFeeAmountRequired"
56+
aria-labelledby="isAdministrativeFeeAmountRequiredLabel"
57+
></mat-slide-toggle>
58+
</div>
59+
</div>
60+
61+
<div *ngIf="conditionTypeForm.get('isAdministrativeFeeAmountChecked')?.value">
62+
<mat-form-field appearance="outline" class="condition-field-input">
63+
<mat-label>Administrative Fee Amount</mat-label>
64+
<input
65+
matInput
66+
id="administrativeFeeAmount"
67+
formControlName="administrativeFeeAmount"
68+
name="administrativeFeeAmount"
69+
/>
70+
</mat-form-field>
71+
</div>
72+
</div>
73+
74+
<div class="condition-field">
75+
<div class="condition-field-header">
76+
<mat-checkbox formControlName="isSingleDateChecked">Single Date - Select date label</mat-checkbox>
77+
78+
<div class="toggle" *ngIf="conditionTypeForm.get('isSingleDateChecked')?.value">
79+
<mat-label [ngClass]="{ inactive: conditionTypeForm.get('isSingleDateRequired')?.value ?? false }"
80+
>Mark Field as Required (*)
81+
</mat-label>
82+
<mat-slide-toggle
83+
formControlName="isSingleDateRequired"
84+
aria-labelledby="isSingleDateRequiredLabel"
85+
></mat-slide-toggle>
86+
</div>
87+
</div>
88+
<div *ngIf="conditionTypeForm.get('isSingleDateChecked')?.value">
89+
<mat-button-toggle-group id="singleDateLabelId" formControlName="singleDateLabel" name="singleDateLabel">
90+
<mat-button-toggle value="Due Date">Due Date</mat-button-toggle>
91+
<mat-button-toggle value="End Date">End Date</mat-button-toggle>
92+
</mat-button-toggle-group>
93+
</div>
94+
</div>
95+
96+
<div class="condition-field">
97+
<div class="condition-field-header">
98+
<div>
99+
<mat-checkbox formControlName="isSecurityAmountChecked">Security Amount</mat-checkbox>
100+
</div>
101+
102+
<div class="toggle" *ngIf="conditionTypeForm.get('isSecurityAmountChecked')?.value">
103+
<mat-label [ngClass]="{ inactive: conditionTypeForm.get('isSecurityAmountRequired')?.value ?? false }"
104+
>Mark Field as Required (*)
105+
</mat-label>
106+
<mat-slide-toggle
107+
formControlName="isSecurityAmountRequired"
108+
aria-labelledby="isSecurityAmountRequiredLabel"
109+
></mat-slide-toggle>
110+
</div>
111+
</div>
112+
</div>
113+
114+
<div class="condition-field">
115+
<mat-checkbox formControlName="isDescriptionChecked">Description</mat-checkbox>
116+
</div>
117+
<div class="warning-section">
118+
<div class="warning" *ngIf="showWarning">
119+
<mat-icon>info</mat-icon> <b>Warning: </b>&nbsp; Changes made here will apply to all instances of this condition
120+
</div>
121+
</div>
122+
</div>
35123
</form>
36124

37125
<mat-dialog-actions align="end">
@@ -43,7 +131,7 @@ <h4>{{ isEdit ? 'Edit' : 'Create' }} Decision Condition Type</h4>
43131
mat-flat-button
44132
color="primary"
45133
type="submit"
46-
[disabled]="!form.form.valid"
134+
[disabled]="!conditionTypeForm.valid"
47135
>
48136
Save
49137
</button>

alcs-frontend/src/app/features/admin/decision-condition-types/decision-condition-types-dialog/decision-condition-types-dialog.component.scss

+64
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@use '../../../../../styles/colors';
2+
13
.dialog {
24
padding: 24px;
35

@@ -6,6 +8,7 @@
68
grid-template-columns: 1fr 1fr;
79
row-gap: 24px;
810
column-gap: 24px;
11+
margin-top: 12px;
912
margin-bottom: 12px;
1013

1114
.full-width {
@@ -15,5 +18,66 @@
1518
.mat-mdc-form-field {
1619
width: 100%;
1720
}
21+
22+
.condition-fields-container {
23+
display: flex;
24+
flex-direction: column;
25+
}
26+
27+
.condition-field {
28+
display: grid;
29+
gap: 5px;
30+
margin-bottom: 5px;
31+
}
32+
33+
.condition-field-header {
34+
display: flex;
35+
flex-direction: row;
36+
justify-content: space-between;
37+
align-items: center;
38+
}
39+
40+
.condition-field-input {
41+
width: 95%;
42+
margin-left: 25px;
43+
}
44+
45+
::ng-deep .mdc-checkbox {
46+
--mdc-checkbox-selected-icon-color: #{colors.$primary-color};
47+
--mdc-checkbox-selected-focus-icon-color: #{colors.$primary-color};
48+
--mdc-checkbox-selected-focus-icon-color: #{colors.$primary-color};
49+
--mdc-checkbox-selected-hover-icon-color: #{colors.$primary-color};
50+
--mdc-checkbox-selected-pressed-icon-color: #{colors.$primary-color};
51+
}
52+
53+
::ng-deep .mat-mdc-slide-toggle.mat-accent {
54+
--mdc-switch-selected-focus-state-layer-color: #{colors.$primary-color};
55+
--mdc-switch-selected-handle-color: #{colors.$primary-color};
56+
--mdc-switch-selected-hover-state-layer-color: #{colors.$primary-color};
57+
--mdc-switch-selected-pressed-state-layer-color: #{colors.$primary-color};
58+
--mdc-switch-selected-focus-handle-color: #{colors.$primary-color};
59+
--mdc-switch-selected-hover-handle-color: #{colors.$primary-color};
60+
--mdc-switch-selected-pressed-handle-color: #{colors.$primary-color};
61+
--mdc-switch-selected-focus-track-color: #94c6ac61;
62+
--mdc-switch-selected-hover-track-color: #94c6ac61;
63+
--mdc-switch-selected-pressed-track-color: #94c6ac61;
64+
--mdc-switch-selected-track-color: #94c6ac61;
65+
}
66+
}
67+
}
68+
69+
.warning {
70+
padding: 16px;
71+
font-size: 14px;
72+
background-color: rgba(colors.$field-warning-bg-color, 0.5);
73+
border-radius: 8px;
74+
display: flex;
75+
align-items: center;
76+
color: colors.$dark-contrast-text;
77+
margin-top: 18px;
78+
79+
mat-icon {
80+
color: colors.$dark-contrast-text;
81+
margin-right: 16px;
1882
}
1983
}

alcs-frontend/src/app/features/admin/decision-condition-types/decision-condition-types-dialog/decision-condition-types-dialog.component.spec.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
55
import { ApplicationDecisionConditionTypesService } from '../../../../services/application/application-decision-condition-types/application-decision-condition-types.service';
66

77
import { DecisionConditionTypesDialogComponent } from './decision-condition-types-dialog.component';
8+
import { MatCheckboxModule } from '@angular/material/checkbox';
89

910
describe('DecisionConditionTypesDialogComponent', () => {
1011
let component: DecisionConditionTypesDialogComponent;
1112
let fixture: ComponentFixture<DecisionConditionTypesDialogComponent>;
1213

1314
beforeEach(async () => {
1415
await TestBed.configureTestingModule({
15-
imports: [ReactiveFormsModule, FormsModule],
16+
imports: [ReactiveFormsModule, FormsModule, MatCheckboxModule],
1617
declarations: [DecisionConditionTypesDialogComponent],
1718
providers: [
1819
{ provide: MAT_DIALOG_DATA, useValue: undefined },

alcs-frontend/src/app/features/admin/decision-condition-types/decision-condition-types-dialog/decision-condition-types-dialog.component.ts

+72-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { Component, Inject } from '@angular/core';
22
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
3+
import {
4+
ApplicationDecisionConditionTypeDto,
5+
DateLabel,
6+
} from '../../../../services/application/decision/application-decision-v2/application-decision-v2.dto';
37
import { ApplicationDecisionConditionTypesService } from '../../../../services/application/application-decision-condition-types/application-decision-condition-types.service';
8+
import { FormControl, FormGroup, Validators } from '@angular/forms';
49
import { DecisionDialogDataInterface } from '../decision-dialog-data.interface';
510
import { NoticeofIntentDecisionConditionTypesService } from '../../../../services/notice-of-intent/notice-of-intent-decision-condition-types/notice-of-intent-decision-condition-types.service';
611

@@ -10,37 +15,91 @@ import { NoticeofIntentDecisionConditionTypesService } from '../../../../service
1015
styleUrls: ['./decision-condition-types-dialog.component.scss'],
1116
})
1217
export class DecisionConditionTypesDialogComponent {
13-
description = '';
14-
label = '';
15-
code = '';
18+
conditionTypeForm: FormGroup;
1619

1720
isLoading = false;
1821
isEdit = false;
22+
showWarning = false;
23+
1924
service: ApplicationDecisionConditionTypesService | NoticeofIntentDecisionConditionTypesService | undefined;
25+
2026
constructor(
2127
@Inject(MAT_DIALOG_DATA) public data: DecisionDialogDataInterface | undefined,
2228
private dialogRef: MatDialogRef<DecisionConditionTypesDialogComponent>,
2329
) {
2430
this.service = data?.service;
25-
if (data?.content) {
26-
this.description = data.content.description;
27-
this.label = data.content.label;
28-
this.code = data.content.code;
29-
}
3031
this.isEdit = !!data?.content;
32+
this.conditionTypeForm = new FormGroup({
33+
description: new FormControl(this.data?.content?.description ? this.data.content.description : '', [
34+
Validators.required,
35+
]),
36+
label: new FormControl(this.data?.content?.label ? this.data.content.label : '', [Validators.required]),
37+
code: new FormControl(this.data?.content?.code ? this.data.content.code : '', [Validators.required]),
38+
isComponentToConditionChecked: new FormControl(
39+
this.data?.content?.isComponentToConditionChecked ? this.data.content.isComponentToConditionChecked : true,
40+
),
41+
isDescriptionChecked: new FormControl(
42+
this.data?.content?.isDescriptionChecked ? this.data.content.isDescriptionChecked : true,
43+
),
44+
isAdministrativeFeeAmountChecked: new FormControl(
45+
this.data?.content?.isAdministrativeFeeAmountChecked
46+
? this.data.content.isAdministrativeFeeAmountChecked
47+
: false,
48+
),
49+
isAdministrativeFeeAmountRequired: new FormControl(
50+
this.data?.content?.isAdministrativeFeeAmountRequired
51+
? this.data.content.isAdministrativeFeeAmountRequired
52+
: false,
53+
),
54+
administrativeFeeAmount: new FormControl(
55+
this.data?.content?.administrativeFeeAmount ? this.data.content.administrativeFeeAmount : '',
56+
),
57+
isSingleDateChecked: new FormControl(
58+
this.data?.content?.isSingleDateChecked ? this.data.content.isSingleDateChecked : false,
59+
),
60+
isSingleDateRequired: new FormControl(
61+
this.data?.content?.isSingleDateRequired ? this.data.content.isSingleDateRequired : false,
62+
),
63+
singleDateLabel: new FormControl(
64+
this.data?.content?.singleDateLabel ? this.data.content.singleDateLabel : DateLabel.DUE_DATE,
65+
),
66+
isSecurityAmountChecked: new FormControl(
67+
this.data?.content?.isSecurityAmountChecked ? this.data.content.isSecurityAmountChecked : false,
68+
),
69+
isSecurityAmountRequired: new FormControl(
70+
this.data?.content?.isSecurityAmountRequired ? this.data.content.isSecurityAmountRequired : false,
71+
),
72+
});
73+
74+
this.conditionTypeForm.get('isComponentToConditionChecked')?.disable();
75+
this.conditionTypeForm.get('isDescriptionChecked')?.disable();
76+
}
77+
78+
ngOnInit(): void {
79+
this.conditionTypeForm.valueChanges.subscribe( () => {
80+
this.showWarning = this.isEdit ? true : false;
81+
});
3182
}
3283

3384
async onSubmit() {
3485
this.isLoading = true;
3586

36-
const dto = {
37-
code: this.code,
38-
label: this.label,
39-
description: this.description,
87+
const dto: ApplicationDecisionConditionTypeDto | NoticeofIntentDecisionConditionTypesService = {
88+
code: this.conditionTypeForm.get('code')?.value,
89+
label: this.conditionTypeForm.get('label')?.value,
90+
description: this.conditionTypeForm.get('description')?.value,
91+
isAdministrativeFeeAmountChecked: this.conditionTypeForm.get('isAdministrativeFeeAmountChecked')?.value,
92+
isAdministrativeFeeAmountRequired: this.conditionTypeForm.get('isAdministrativeFeeAmountRequired')?.value,
93+
administrativeFeeAmount: this.conditionTypeForm.get('administrativeFeeAmount')?.value,
94+
isSingleDateChecked: this.conditionTypeForm.get('isSingleDateChecked')?.value,
95+
isSingleDateRequired: this.conditionTypeForm.get('isSingleDateRequired')?.value,
96+
singleDateLabel: this.conditionTypeForm.get('singleDateLabel')?.value,
97+
isSecurityAmountChecked: this.conditionTypeForm.get('isSecurityAmountChecked')?.value,
98+
isSecurityAmountRequired: this.conditionTypeForm.get('isSecurityAmountRequired')?.value,
4099
};
41100
if (!this.service) return;
42101
if (this.isEdit) {
43-
await this.service.update(this.code, dto);
102+
await this.service.update(dto.code, dto);
44103
} else {
45104
await this.service.create(dto);
46105
}

alcs-frontend/src/app/features/application/decision/conditions/condition/condition.component.html

+13-7
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,24 @@ <h4 *ngIf="condition.type">{{ condition.type.label }}</h4>
1414
<app-no-data *ngIf="!condition.componentLabelsStr"></app-no-data>
1515
</div>
1616

17-
<div>
17+
<div *ngIf="showAdmFeeField">
18+
<div class="subheading2">Administrative Fee Amount</div>
19+
{{ condition.administrativeFee }}
20+
<app-no-data
21+
*ngIf="condition.administrativeFee === null || condition.administrativeFee === undefined"
22+
></app-no-data>
23+
</div>
24+
25+
<div *ngIf="showSecurityAmountField">
1826
<div class="subheading2">Security Amount</div>
1927
{{ condition.securityAmount }}
2028
<app-no-data *ngIf="condition.securityAmount === null || condition.securityAmount === undefined"></app-no-data>
2129
</div>
2230

23-
<div>
24-
<div class="subheading2">Admin Fee</div>
25-
{{ condition.administrativeFee }}
26-
<app-no-data
27-
*ngIf="condition.administrativeFee === null || condition.administrativeFee === undefined"
28-
></app-no-data>
31+
<div *ngIf="showSingleDateField">
32+
<div class="subheading2">{{ singleDateLabel }}</div>
33+
{{ singleDateFormated }}
34+
<app-no-data *ngIf="condition.singleDate === null || condition.singleDate === undefined"></app-no-data>
2935
</div>
3036

3137
<div>

0 commit comments

Comments
 (0)