Skip to content

Commit 17d5b42

Browse files
committed
update application decision condition card and APPCON board card
- add 'Go to condition card' button in application header - add application condition status pill to APPCON board cards - add decision order - add new toast service snack bar with navigate feature - fix tooltip not working on already in use conditions - fix UI css
1 parent 3956bb0 commit 17d5b42

File tree

15 files changed

+130
-16
lines changed

15 files changed

+130
-16
lines changed

alcs-frontend/src/app/features/application/application.component.html

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
[application]="application"
55
[modifications]="modifications"
66
[reconsiderations]="reconsiderations"
7+
[conditionCards]="decisionConditionCards"
78
[showStatus]="true"
89
[submissionStatusService]="applicationStatusService"
910
[applicationDetailService]="applicationDetailService"

alcs-frontend/src/app/features/application/application.component.ts

+8
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ import { ReviewComponent } from './review/review.component';
3030
import { ApplicationSubmissionStatusService } from '../../services/application/application-submission-status/application-submission-status.service';
3131
import { ApplicationTagService } from '../../services/application/application-tag/application-tag.service';
3232
import { FileTagService } from '../../services/common/file-tag.service';
33+
import { ApplicationDecisionV2Service } from '../../services/application/decision/application-decision-v2/application-decision-v2.service';
34+
import { ApplicationDecisionConditionCardDto } from '../../services/application/decision/application-decision-v2/application-decision-v2.dto';
35+
import { ApplicationDecisionConditionCardService } from '../../services/application/decision/application-decision-v2/application-decision-condition/application-decision-condition-card/application-decision-condition-card.service';
3336

3437
export const unsubmittedRoutes = [
3538
{
@@ -184,6 +187,7 @@ export class ApplicationComponent implements OnInit, OnDestroy {
184187
application: ApplicationDto | undefined;
185188
reconsiderations: ApplicationReconsiderationDto[] = [];
186189
modifications: ApplicationModificationDto[] = [];
190+
decisionConditionCards: ApplicationDecisionConditionCardDto[] = [];
187191
submission?: ApplicationSubmissionDto;
188192

189193
isApplicantSubmission = false;
@@ -195,6 +199,7 @@ export class ApplicationComponent implements OnInit, OnDestroy {
195199
public applicationSubmissionService: ApplicationSubmissionService,
196200
private reconsiderationService: ApplicationReconsiderationService,
197201
private modificationService: ApplicationModificationService,
202+
private decisionConditionCardService: ApplicationDecisionConditionCardService,
198203
private route: ActivatedRoute,
199204
private titleService: Title,
200205
public applicationStatusService: ApplicationSubmissionStatusService,
@@ -214,6 +219,9 @@ export class ApplicationComponent implements OnInit, OnDestroy {
214219
this.reconsiderationService.fetchByApplication(application.fileNumber);
215220
this.modificationService.fetchByApplication(application.fileNumber);
216221

222+
this.decisionConditionCards =
223+
(await this.decisionConditionCardService.fetchByApplicationFileNumber(application.fileNumber)) || [];
224+
217225
this.isApplicantSubmission = application.source !== SYSTEM_SOURCE_TYPES.ALCS;
218226
let wasSubmittedToLfng = false;
219227

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ <h3>Create New Condition Card</h3>
2525
<div class="section">
2626
<span>Add one or more conditions*</span>
2727
<div class="table-container">
28-
<table mat-table class="conditions-table mat-elevation-z2" [dataSource]="dataSource" style="width: 100%">
28+
<table mat-table class="conditions-table mat-elevation-z3" [dataSource]="dataSource" style="width: 100%">
2929
<ng-container matColumnDef="select">
3030
<th mat-header-cell *matHeaderCellDef class="column-select"></th>
3131
<td mat-cell *matCellDef="let element" class="column-select">
@@ -53,6 +53,8 @@ <h3>Create New Condition Card</h3>
5353
mat-row
5454
*matRowDef="let row; columns: displayColumns"
5555
[class.disabled-row]="isConditionCardNotNull(row)"
56+
matTooltip="Condition is already used by another card"
57+
[matTooltipDisabled]="!isConditionCardNotNull(row)"
5658
></tr>
5759
</table>
5860
</div>

alcs-frontend/src/app/features/application/decision/conditions/condition-card-dialog/condition-card-dialog.component.scss

+4-3
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@
4343
.table-container {
4444
max-height: 300px;
4545
overflow-y: auto;
46+
padding: 2px;
4647
}
4748

4849
.disabled-row {
49-
background-color: #f0f0f0; // Light gray background
50-
pointer-events: none; // Disable interactions
51-
opacity: 0.6; // Make it look disabled
50+
background-color: #f0f0f0;
51+
opacity: 0.6;
52+
cursor: default;
5253
}

alcs-frontend/src/app/features/application/decision/conditions/condition-card-dialog/condition-card-dialog.component.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { ApplicationDecisionConditionCardService } from '../../../../../services
1111
import { BOARD_TYPE_CODES, BoardService } from '../../../../../services/board/board.service';
1212
import { BoardDto, BoardStatusDto } from '../../../../../services/board/board.dto';
1313
import { ToastService } from '../../../../../services/toast/toast.service';
14+
import { CardType } from '../../../../../shared/card/card.component';
1415

1516
@Component({
1617
selector: 'app-condition-card-dialog',
@@ -75,7 +76,11 @@ export class ConditionCardDialogComponent implements OnInit {
7576
};
7677
const res = await this.decisionConditionCardService.create(createDto);
7778
if (res) {
78-
this.toastService.showSuccessToast('Condition card created successfully');
79+
this.toastService.showSuccessToastWithLink(
80+
'Condition card created successfully',
81+
'GO TO BOARD',
82+
`/board/appcon?card=${res.cardUuid}&type=${CardType.APP_CON}`,
83+
);
7984
this.dialogRef.close({ action: 'save', result: true });
8085
} else {
8186
this.toastService.showErrorToast('Failed to create condition card');

alcs-frontend/src/app/features/board/board.component.ts

+16-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {
3131
RECON_TYPE_LABEL,
3232
RETROACTIVE_TYPE_LABEL,
3333
} from '../../shared/application-type-pill/application-type-pill.constants';
34-
import { CardData, CardSelectedEvent, CardType } from '../../shared/card/card.component';
34+
import { CardData, CardSelectedEvent, CardType, ConditionCardData } from '../../shared/card/card.component';
3535
import { DragDropColumn } from '../../shared/drag-drop-board/drag-drop-column.interface';
3636
import { AppModificationDialogComponent } from './dialogs/app-modification/app-modification-dialog.component';
3737
import { CreateAppModificationDialogComponent } from './dialogs/app-modification/create/create-app-modification-dialog.component';
@@ -507,7 +507,19 @@ export class BoardComponent implements OnInit, OnDestroy {
507507

508508
private mapApplicationDecisionConditionToCard(
509509
applicationDecisionCondition: ApplicationDecisionConditionCardBoardDto,
510-
): CardData {
510+
): ConditionCardData {
511+
let isExpired = false;
512+
let isPastDue = false;
513+
514+
for (const condition of applicationDecisionCondition.conditions) {
515+
if (condition.status === 'EXPIRED') {
516+
isExpired = true;
517+
}
518+
if (condition.status === 'PASTDUE') {
519+
isPastDue = true;
520+
}
521+
}
522+
511523
return {
512524
status: applicationDecisionCondition.card!.status.code,
513525
typeLabel: 'Application',
@@ -521,6 +533,8 @@ export class BoardComponent implements OnInit, OnDestroy {
521533
cardUuid: applicationDecisionCondition.card.uuid,
522534
paused: false,
523535
dateReceived: 0,
536+
isExpired,
537+
isPastDue,
524538
};
525539
}
526540

alcs-frontend/src/app/features/board/dialogs/application-decision-condition-dialog/application-decision-condition-dialog.component.html

+4-2
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ <h3 class="card-title">
110110
</div>
111111
<div class="conditions-container">
112112
<div class="conditions-header-container">
113-
<span class="conditions-header">Decision # - Conditions to Review</span>
113+
<span class="conditions-header"
114+
>Decision #{{ applicationDecisionConditionCard.decisionOrder }} - Conditions to Review</span
115+
>
114116
<div class="buttons-container">
115117
<ng-container *ngIf="!isEditing; else editMode">
116118
<button class="edit-button" mat-icon-button (click)="editClicked()">
@@ -168,7 +170,7 @@ <h3 class="card-title">
168170
mat-row
169171
*matRowDef="let row; columns: displayColumns"
170172
[class.disabled-row]="isConditionDisabled(row.condition)"
171-
matTooltip="Condition is being used by another card"
173+
matTooltip="Condition is already used by another card"
172174
[matTooltipDisabled]="!isConditionDisabled(row.condition)"
173175
></tr>
174176
</table>

alcs-frontend/src/app/features/board/dialogs/application-decision-condition-dialog/application-decision-condition-dialog.component.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
.disabled-row {
2222
background-color: #f0f0f0;
23-
pointer-events: none;
23+
cursor: default;
2424
opacity: 0.6;
2525
}
2626

alcs-frontend/src/app/features/board/dialogs/application-decision-condition-dialog/application-decision-condition-dialog.component.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ export class ApplicationDecisionConditionDialogComponent extends CardDialogCompo
110110
return false;
111111
}
112112
return condition.conditionCard?.uuid !== this.applicationDecisionConditionCard.uuid;
113-
// return condition.conditionCard?.uuid !== this.applicationDecisionConditionCard.uuid;
114113
}
115114

116115
getStatusPill(status: string) {
@@ -185,7 +184,6 @@ export class ApplicationDecisionConditionDialogComponent extends CardDialogCompo
185184
conditionsUuids: selectedConditions,
186185
};
187186

188-
console.log(updateDto);
189187
const res = await this.applicationDecisionConditionCardService.update(
190188
this.applicationDecisionConditionCard.uuid,
191189
updateDto,
@@ -195,6 +193,8 @@ export class ApplicationDecisionConditionDialogComponent extends CardDialogCompo
195193
} else {
196194
this.toastService.showErrorToast('Failed to update condition card');
197195
}
196+
this.isEditing = false;
197+
this.displayColumns = this.defaultColumns;
198198
}
199199

200200
isSaveDisabled(): boolean {

alcs-frontend/src/app/services/application/decision/application-decision-v2/application-decision-condition/application-decision-condition-card/application-decision-condition-card.service.ts

+14
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,18 @@ export class ApplicationDecisionConditionCardService {
6767
}
6868
return;
6969
}
70+
71+
async fetchByApplicationFileNumber(fileNumber: string): Promise<ApplicationDecisionConditionCardDto[] | undefined> {
72+
try {
73+
return await firstValueFrom(
74+
this.http.get<ApplicationDecisionConditionCardDto[]>(`${this.url}/application/${fileNumber}`),
75+
);
76+
} catch (e: any) {
77+
console.error(e);
78+
this.toastService.showErrorToast(
79+
'Failed to fetch Application Decision Condition Cards by Application File Number',
80+
);
81+
}
82+
return;
83+
}
7084
}

alcs-frontend/src/app/services/application/decision/application-decision-v2/application-decision-v2.dto.ts

+2
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ export interface ApplicationDecisionConditionCardDto {
302302
uuid: string;
303303
conditions: ApplicationDecisionConditionDto[];
304304
cardUuid: string;
305+
card: CardDto;
305306
decisionUuid: string;
306307
applicationFileNumber: string;
307308
}
@@ -326,6 +327,7 @@ export interface ApplicationDecisionConditionCardBoardDto {
326327
conditions: ApplicationDecisionConditionDto[];
327328
card: CardDto;
328329
decisionUuid: string;
330+
decisionOrder: number;
329331
fileNumber: string;
330332
applicant: string;
331333
type?: ApplicationTypeDto;

alcs-frontend/src/app/services/toast/toast.service.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import { Injectable } from '@angular/core';
22
import { MatSnackBar } from '@angular/material/snack-bar';
3+
import { Router } from '@angular/router';
34

45
@Injectable({
56
providedIn: 'root',
67
})
78
export class ToastService {
8-
constructor(private snackBar: MatSnackBar) {}
9+
constructor(
10+
private snackBar: MatSnackBar,
11+
private router: Router,
12+
) {}
913

1014
private TOAST_DURATION = 3000;
1115
private ACTION_TOAST_DURATION = 6000;
@@ -29,4 +33,21 @@ export class ToastService {
2933
panelClass: 'error',
3034
});
3135
}
36+
37+
showSuccessToastWithLink(text: string, action: string, link: string) {
38+
const snackBarRef = this.snackBar.open(text, action, {
39+
duration: action ? this.ACTION_TOAST_DURATION : this.TOAST_DURATION,
40+
panelClass: 'success',
41+
});
42+
43+
snackBarRef.onAction().subscribe(() => {
44+
const url = new URL(link, window.location.origin);
45+
const route = url.pathname;
46+
const queryParams: { [key: string]: string } = {};
47+
url.searchParams.forEach((value, key) => {
48+
queryParams[key] = value;
49+
});
50+
this.router.navigate([route], { queryParams });
51+
});
52+
}
3253
}

alcs-frontend/src/app/shared/card/card.component.html

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
</div>
3333
</div>
3434
<div class="lower-card">
35-
<div>
35+
<div *ngIf="!isConditionCard">
3636
<div
3737
*ngIf="cardData.activeDays !== undefined"
3838
class="day-count active-days center"
@@ -66,6 +66,10 @@
6666
>
6767
</div>
6868
</div>
69+
<div class="condition-status-pill">
70+
<app-application-type-pill *ngIf="isExpired" [type]="getStatusPill('EXPIRED')"></app-application-type-pill>
71+
<app-application-type-pill *ngIf="isPastDue" [type]="getStatusPill('PASTDUE')"></app-application-type-pill>
72+
</div>
6973
<app-avatar-circle
7074
*ngIf="cardData.assignee"
7175
[initials]="cardData.assignee.initials || ''"

alcs-frontend/src/app/shared/card/card.component.ts

+27-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
22
import { ApplicationDecisionMeetingDto } from '../../services/application/application.dto';
33
import { AssigneeDto } from '../../services/user/user.dto';
44
import { ApplicationPill } from '../application-type-pill/application-type-pill.component';
5+
import {
6+
DECISION_CONDITION_EXPIRED_LABEL,
7+
DECISION_CONDITION_PASTDUE_LABEL,
8+
} from '../application-type-pill/application-type-pill.constants';
59

610
export interface CardData {
711
id: string;
@@ -28,6 +32,11 @@ export interface CardData {
2832
showDueDate?: boolean;
2933
}
3034

35+
export interface ConditionCardData extends CardData {
36+
isExpired: boolean;
37+
isPastDue: boolean;
38+
}
39+
3140
export interface CardSelectedEvent {
3241
uuid: string;
3342
cardType: CardType;
@@ -42,7 +51,7 @@ export enum CardType {
4251
NOI_MODI = 'NOIM',
4352
NOTIFICATION = 'NOTI',
4453
INQUIRY = 'INQR',
45-
APP_CON = 'APP_CON',
54+
APP_CON = 'APPCON',
4655
}
4756

4857
const lineHeight = 24;
@@ -53,10 +62,14 @@ const lineHeight = 24;
5362
styleUrls: ['./card.component.scss'],
5463
})
5564
export class CardComponent implements OnInit {
56-
@Input() cardData!: CardData;
65+
@Input() cardData!: CardData | ConditionCardData;
5766

5867
@Output() cardSelected = new EventEmitter<CardSelectedEvent>();
5968

69+
isConditionCard = false;
70+
isExpired = false;
71+
isPastDue = false;
72+
6073
constructor() {}
6174

6275
onClick(uuid: string, cardType: CardType) {
@@ -82,6 +95,10 @@ export class CardComponent implements OnInit {
8295
this.cardData.latestDecisionDate = this.getLatestDecisionDate();
8396
}
8497
}
98+
99+
this.isConditionCard = this.cardData.cardType === CardType.APP_CON;
100+
this.isExpired = this.isConditionCard ? (this.cardData as ConditionCardData).isExpired : false;
101+
this.isPastDue = this.isConditionCard ? (this.cardData as ConditionCardData).isPastDue : false;
85102
}
86103

87104
onMouseHover(e: any) {
@@ -93,4 +110,12 @@ export class CardComponent implements OnInit {
93110

94111
return;
95112
}
113+
114+
getStatusPill(status: string) {
115+
if (status === 'PASTDUE') {
116+
return DECISION_CONDITION_PASTDUE_LABEL;
117+
} else {
118+
return DECISION_CONDITION_EXPIRED_LABEL;
119+
}
120+
}
96121
}

alcs-frontend/src/app/shared/details-header/details-header.component.ts

+15
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { UpcomingMeetingBoardMapDto } from '../../services/decision-meeting/deci
3030
import { IncomingFileService } from '../../services/incoming-file/incoming-file.service';
3131
import { IncomingFileBoardMapDto } from 'src/app/services/incoming-file/incoming-file.dto';
3232
import { FileTagService } from '../../services/common/file-tag.service';
33+
import { ApplicationDecisionConditionCardDto } from '../../services/application/decision/application-decision-v2/application-decision-v2.dto';
3334

3435
@Component({
3536
selector: 'app-details-header[application]',
@@ -125,6 +126,12 @@ export class DetailsHeaderComponent implements OnInit, OnDestroy {
125126
this.setupLinkedCards();
126127
}
127128

129+
_conditionCards: ApplicationDecisionConditionCardDto[] = [];
130+
@Input() set conditionCards(conditionCards: ApplicationDecisionConditionCardDto[]) {
131+
this._conditionCards = conditionCards;
132+
this.setupLinkedCards();
133+
}
134+
128135
reconLabel = RECON_TYPE_LABEL;
129136
modificationLabel = MODIFICATION_TYPE_LABEL;
130137
retroactiveLabel = RETROACTIVE_TYPE_LABEL;
@@ -246,6 +253,14 @@ export class DetailsHeaderComponent implements OnInit, OnDestroy {
246253
}));
247254
result.push(...mappedReconCards);
248255

256+
const mappedConditionCards = this._conditionCards
257+
.filter((conditionCard) => !!conditionCard.card)
258+
.map((conditionCard, index) => ({
259+
...conditionCard.card,
260+
displayName: `Condition Card #${index + 1}`,
261+
}));
262+
result.push(...mappedConditionCards);
263+
249264
this.linkedCards = result;
250265
}
251266

0 commit comments

Comments
 (0)