WEB-954: Migrate Subscription management : clients and savings - #3633
Conversation
|
Note
|
| Layer / File(s) | Summary |
|---|---|
Client Stepper & Datatable Components Form Typing src/app/clients/client-stepper/client-datatable-step/*, src/app/clients/client-stepper/client-general-step/*, src/app/clients/client-stepper/client-family-members-step/client-family-member-dialog/* |
ClientDatatableStepComponent, ClientGeneralStepComponent (removes OnDestroy), and ClientFamilyMemberDialogComponent switch from UntypedFormGroup to FormGroup, add DestroyRef injection, and use takeUntilDestroyed for all form valueChanges subscriptions. |
Address Tab & Charges Overview Components src/app/clients/clients-view/address-tab/*, src/app/clients/clients-view/charges/charges-overview/*, src/app/clients/clients-view/charges/client-pay-charges/*, src/app/clients/clients-view/charges/view-charge/* |
AddressTabComponent, ChargesOverviewComponent, ClientPayChargesComponent, and ViewChargeComponent update to typed FormGroup and automatic route.data subscription cleanup via DestroyRef. |
Client Action Components Form Typing & Lifecycle src/app/clients/clients-view/client-actions/accept-client-transfer/*, src/app/clients/clients-view/client-actions/activate-client/*, src/app/clients/clients-view/client-actions/add-client-charge/*, src/app/clients/clients-view/client-actions/add-client-collateral/*, src/app/clients/clients-view/client-actions/client-assign-staff/*, src/app/clients/clients-view/client-actions/client-screen-reports/*, src/app/clients/clients-view/client-actions/close-client/*, src/app/clients/clients-view/client-actions/reactivate-client/*, src/app/clients/clients-view/client-actions/reject-client-transfer/*, src/app/clients/clients-view/client-actions/reject-client/* |
Ten client action components updated to typed FormBuilder/FormGroup and lifecycle-bound subscriptions with DestroyRef. |
Additional Client Action & Survey Components src/app/clients/clients-view/client-actions/take-survey/*, src/app/clients/clients-view/client-actions/transfer-client/*, src/app/clients/clients-view/client-actions/undo-client-rejection/*, src/app/clients/clients-view/client-actions/undo-client-transfer/*, src/app/clients/clients-view/client-actions/update-client-savings-account/*, src/app/clients/clients-view/client-actions/view-survey/*, src/app/clients/clients-view/client-actions/withdraw-client/* |
Seven additional client action and survey components migrated to typed forms and DestroyRef-managed lifecycle. |
ClientsViewComponent, ClientsComponent, & CreateClient src/app/clients/clients-view/clients-view.component.ts, src/app/clients/clients.component.ts, src/app/clients/create-client/create-client.component.ts |
All three components replace destroy$ Subject pattern with DestroyRef + takeUntilDestroyed for automatic route.data subscription cleanup. |
EditClientComponent, Custom Dialogs, & Tabs src/app/clients/edit-client/*, src/app/clients/clients-view/custom-dialogs/edit-notes-dialog/*, src/app/clients/clients-view/custom-dialogs/upload-document-dialog/*, src/app/clients/clients-view/datatable-tab/*, src/app/clients/clients-view/documents-tab/* |
EditClientComponent migrated to typed FormGroup with DestroyRef, legalFormId valueChanges now automatically managed; dialog and tab components updated for automatic subscription cleanup. |
Family Members Tab & Dialog Components src/app/clients/clients-view/family-members-tab/add-family-member/*, src/app/clients/clients-view/family-members-tab/edit-family-member/*, src/app/clients/clients-view/family-members-tab/family-members-tab.component.ts |
AddFamilyMemberComponent and EditFamilyMemberComponent updated to typed forms with DestroyRef-managed dateOfBirth→age recalculation subscriptions. |
GeneralTabComponent & PersonalDataTabComponent src/app/clients/clients-view/general-tab/general-tab.component.ts, src/app/clients/clients-view/personal-data-tab/personal-data-tab.component.ts |
Both tabs replace destroy$ Subject with DestroyRef; PersonalDataTabComponent now uses takeUntilDestroyed for KYC datatable, validation save, and Pentaho report observables. |
NotesTabComponent & ExternalNationalIdService src/app/clients/clients-view/notes-tab/notes-tab.component.ts, src/app/clients/services/external-national-id.service.ts |
NotesTabComponent updated for automatic subscription cleanup; ExternalNationalIdService removes OnDestroy, adds DestroyRef, and updates all method signatures to accept typed FormGroup instead of UntypedFormGroup. |
Savings Create & Edit Account Components src/app/savings/create-savings-account/*, src/app/savings/edit-savings-account/* |
Both components inject DestroyRef and apply takeUntilDestroyed to route.data subscriptions for automatic cleanup. |
Savings GSIM & Action Overview Components src/app/savings/gsim-account/create-gsim-account/*, src/app/savings/gsim-account/gsim-account.component.ts, src/app/savings/saving-account-actions/saving-account-actions.component.ts |
CreateGsimAccountComponent, GsimAccountComponent, and SavingAccountActionsComponent updated with DestroyRef and automatic route subscriptions via takeUntilDestroyed. |
Savings Action Activate & Charge Components src/app/savings/saving-account-actions/activate-savings-account/*, src/app/savings/saving-account-actions/add-charge-savings-account/*, src/app/savings/saving-account-actions/apply-annual-fees-savings-account/*, src/app/savings/saving-account-actions/approve-savings-account/* |
Four savings action components updated to typed FormBuilder/FormGroup and automatic subscription cleanup via DestroyRef. |
Savings Action Close, Manage, & Interest Components src/app/savings/saving-account-actions/close-savings-account/*, src/app/savings/saving-account-actions/manage-savings-account/*, src/app/savings/saving-account-actions/post-interest-as-on-savings-account/*, src/app/savings/saving-account-actions/reject-savings-account/* |
Four additional savings action components updated to typed forms with DestroyRef lifecycle management for route and valueChanges subscriptions. |
Savings Action Assign, Unassign, & Transaction Components src/app/savings/saving-account-actions/savings-account-assign-staff/*, src/app/savings/saving-account-actions/savings-account-transactions/*, src/app/savings/saving-account-actions/savings-account-unassign-staff/*, src/app/savings/saving-account-actions/undo-approval-savings-account/* |
Four additional savings action components migrated to typed forms and automatic subscription cleanup. |
Savings Action Withdraw & Stepper Components src/app/savings/saving-account-actions/withdraw-by-client-savings-account/*, src/app/savings/savings-account-stepper/savings-account-charges-step/*, src/app/savings/savings-account-stepper/savings-account-details-step/*, src/app/savings/savings-account-stepper/savings-account-terms-step/* |
Withdraw component updated to typed FormGroup; stepper components switch from UntypedFormGroup to FormGroup and add DestroyRef for automatic productId/allowOverdraft valueChanges cleanup. |
Savings View Datatable, Notes & Document Tabs src/app/savings/savings-account-view/datatable-tabs/*, src/app/savings/savings-account-view/notes-tab/*, src/app/savings/savings-account-view/savings-documents-tab/* |
All three view tabs updated with DestroyRef injection and takeUntilDestroyed for automatic route.data subscription lifecycle management. |
Savings View Account & Export Components src/app/savings/savings-account-view/savings-account-view.component.ts, src/app/savings/savings-account-view/transactions-tab/export-transactions/export-transactions.component.ts |
SavingsAccountViewComponent refactored for automatic subscription cleanup; ExportTransactionsComponent updated to typed FormBuilder and DestroyRef-managed route.parent.parent.data subscription. |
Savings Transactions Tab & Edit Components src/app/savings/savings-account-view/transactions-tab/transactions-tab.component.ts, src/app/savings/savings-account-view/transactions/edit-transaction/edit-transaction.component.ts |
TransactionsTabComponent switched from UntypedFormControl to typed FormControl fields; EditTransactionComponent updated to typed forms with automatic subscription cleanup. |
Savings View Receipt & Datatable Transaction Tabs src/app/savings/savings-account-view/transactions/view-reciept/*, src/app/savings/savings-account-view/transactions/view-transaction/datatable-transaction-tab/* |
Both components updated with DestroyRef injection and takeUntilDestroyed for automatic route.data subscription management. |
Savings Transaction General Tab & View Components src/app/savings/savings-account-view/transactions/view-transaction/savings-transaction-general-tab/*, src/app/savings/savings-account-view/transactions/view-transaction/view-transaction.component.ts |
Both components updated with DestroyRef and takeUntilDestroyed for automatic route.data subscription cleanup on component destruction. |
Savings View Charge Component src/app/savings/savings-account-view/view-charge/* |
ViewChargeComponent refactored to use DestroyRef + takeUntilDestroyed for both chargeData and savingsAccountData route subscriptions, replacing unscoped subscribe calls. |
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly Related PRs
- openMF/web-app#3629: Parallel migration of additional Angular components to DestroyRef + takeUntilDestroyed and typed reactive forms across the codebase.
- openMF/web-app#3065: Previous changes to ClientGeneralStepComponent's subscription teardown that this PR extends and modernizes.
Suggested Reviewers
- IOhacker
- adamsaghy
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/app/clients/clients-view/family-members-tab/family-members-tab.component.ts (1)
82-84:⚠️ Potential issue | 🟠 Major | ⚡ Quick winHandle canceled dialog result safely.
afterClosed()may emitundefined;response.deletecan throw on cancel and interrupt the component flow.Suggested fix
deleteFamilyMemberDialogRef.afterClosed().subscribe((response: any) => { - if (response.delete) { + if (response?.delete) { this.clientsService.deleteFamilyMember(clientId, id).subscribe(() => { this.clientFamilyMembers.splice(index, 1); }); } });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients-view/family-members-tab/family-members-tab.component.ts` around lines 82 - 84, The dialog close handler in FamilyMembersTabComponent uses deleteFamilyMemberDialogRef.afterClosed().subscribe((response: any) => { if (response.delete) { ... } }) which will throw when response is undefined; update the callback to guard the value before accessing .delete (e.g., check response truthiness or use optional chaining like response?.delete) and only call clientsService.deleteFamilyMember(clientId, id).subscribe(...) when the guard passes so canceled/undefined dialog results are handled safely.src/app/clients/clients-view/clients-view.component.ts (1)
426-427:⚠️ Potential issue | 🟠 Major | ⚡ Quick winGuard dialog close result before property access.
afterClosed()can returnundefined(cancel/backdrop close). Accessingresponse.deletewithout a null check can throw and break the action flow.Suggested fix
deleteClientImageDialogRef.afterClosed().subscribe((response: any) => { - if (response.delete) { + if (response?.delete) { this.clientsService.deleteClientProfileImage(this.clientViewData.id).subscribe(() => { this.reload(); }); } });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients-view/clients-view.component.ts` around lines 426 - 427, The subscription callback on deleteClientImageDialogRef.afterClosed() accesses response.delete without guarding for undefined; update the handler in clients-view.component.ts (the callback passed to deleteClientImageDialogRef.afterClosed().subscribe) to first check that response is defined (e.g., response && response.delete or response?.delete) or narrow its type (make response optional) before accessing .delete, and ensure the branch that performs the delete action runs only when that guarded check passes.
🧹 Nitpick comments (1)
src/app/clients/services/external-national-id.service.ts (1)
46-49: ⚡ Quick winUpdate stale lifecycle documentation comment.
The class comment still says cleanup happens via
ngOnDestroy, but the service no longer implementsOnDestroyand now relies onDestroyRefteardown. Please align the comment with the current implementation.Also applies to: 57-57
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/services/external-national-id.service.ts` around lines 46 - 49, Update the stale class comment to reflect that cleanup is performed via Angular's DestroyRef teardown instead of ngOnDestroy/OnDestroy: replace references to "ngOnDestroy" and "implements OnDestroy" with a note that the service is provided at the component level and uses DestroyRef to automatically teardown subscriptions when the host is destroyed (mention the service uses DestroyRef in constructor or teardown logic). Ensure both occurrences (around the existing comment and the other instance) are updated to match the current implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/app/clients/clients-view/client-actions/add-client-charge/add-client-charge.component.ts`:
- Around line 91-99: The add/remove control logic in AddClientChargeComponent is
adding controls unconditionally which can throw if the control already exists;
update the block that manipulates this.clientChargeForm so you only call
addControl('dueDate') or addControl('feeOnMonthDay') when the control is not
already present (e.g. check this.clientChargeForm.get('dueDate') or
.get('feeOnMonthDay') is null/undefined before adding), and only call
removeControl when the control exists, preserving the existing conditional
intent around chargeDetails.dueDateNotRequired and
chargeDetails.chargeTimeTypeAnnualOrMonth.
- Around line 81-82: The monthly-fee branch is broken by an id/value mismatch:
you set const chargeTimeType = data.chargeTimeType.id but later check
chargeTimeType.value and therefore never hit the monthly-fee path to add
feeInterval; fix by keeping the same shape—either assign const chargeTimeType =
data.chargeTimeType (the whole object) or assign const chargeTimeType =
data.chargeTimeType.value (the primitive) and update the subsequent checks
accordingly (references around the monthly-fee conditional and feeInterval
creation that use chargeTimeType.value should match the chosen form).
In
`@src/app/clients/clients-view/client-actions/add-client-collateral/add-client-collateral.component.ts`:
- Around line 86-92: The quantity valueChanges handler dereferences
this.collateralDetails (basePrice and pctToBase) before ensuring collateral is
loaded, which can throw when quantity changes early; update the subscriber on
clientCollateralForm.controls.quantity.valueChanges (inside
add-client-collateral.component) to guard against missing collateralDetails by
checking that this.collateralDetails and its basePrice/pctToBase are defined
before computing totals, and skip or set totals to 0/null if not available, then
call this.clientCollateralForm.patchValue only with safe computed values.
In
`@src/app/savings/saving-account-actions/add-charge-savings-account/add-charge-savings-account.component.ts`:
- Around line 86-87: The condition checking the monthly-fee branch uses
chargeTimeType.value but chargeTimeType is assigned as the primitive
data.chargeTimeType.id; update the condition in
add-charge-savings-account.component (the block using chargeTimeType and adding
the feeInterval FormControl) to compare the primitive chargeTimeType directly
(e.g., chargeTimeType === <expected id string/enum>) instead of accessing
.value, so the Monthly Fee branch will run and feeInterval will be added to the
form.
- Around line 81-85: Replace the nested subscribe on
this.savingsChargeForm.controls.chargeId.valueChanges + inner
this.savingsService.getChargeTemplate subscription with a single observable
pipeline that cancels prior HTTP calls: pipe valueChanges through filter to
ignore empty values, takeUntilDestroyed(this.destroyRef), switchMap(chargeId =>
this.savingsService.getChargeTemplate(chargeId)), and then subscribe once to set
this.chargeDetails and update form controls; remove the inner subscribe to avoid
stale writes. Apply the same change (use switchMap and a single subscription) in
the corresponding handlers in the add-charge-recurring-deposits-account and
add-charge-fixed-deposits-account components as well.
In
`@src/app/savings/saving-account-actions/close-savings-account/close-savings-account.component.ts`:
- Around line 10-12: Run the repository's mandatory pre-merge checks and fix any
lint/format/header failures for the CloseSavingsAccountComponent in
close-savings-account.component.ts: install dependencies, run npm run lint and
npm run headers:check; if lint/format issues appear run npx prettier --write .
and address eslint/stylelint errors, then add missing headers with npm run
headers:add; ensure the imports and component file (symbols like
ChangeDetectionStrategy, Component, DestroyRef, OnInit, inject) conform to the
project's style rules before committing.
In
`@src/app/savings/savings-account-stepper/savings-account-details-step/savings-account-details-step.component.ts`:
- Around line 126-133: In buildDependencies(), replace the nested subscription
on this.savingsAccountDetailsForm.get('productId').valueChanges that calls
this.savingsService.getSavingsAccountTemplate(...) with a flattened stream
(e.g., use switchMap) so previous in-flight template requests are cancelled and
only the latest response is processed; on receiving the template, emit via
this.savingsAccountProductTemplate.emit(response) and always update
this.fieldOfficerData and handle this.fieldOfficerId patching in a way that
respects rapid changes (either reset or re-evaluate this.isFieldOfficerPatched
per new productId or always patch the fieldOfficerId from the latest response
when appropriate) so late responses cannot overwrite newer selections (refer to
productId valueChanges, getSavingsAccountTemplate,
savingsAccountProductTemplate.emit, fieldOfficerData, fieldOfficerId,
isFieldOfficerPatched).
In
`@src/app/savings/savings-account-stepper/savings-account-terms-step/savings-account-terms-step.component.ts`:
- Around line 193-207: The valueChanges subscription on
savingsAccountTermsForm.get('allowOverdraft') currently calls addControl
unconditionally, causing errors when controls already exist; update the
subscription in the component (savingsAccountTermsForm valueChanges handler for
allowOverdraft) to check form.contains('minOverdraftForInterestCalculation'),
'nominalAnnualInterestRateOverdraft' and 'overdraftLimit' before calling
addControl (or call removeControl first) so registration is idempotent; ensure
the guard runs when allowOverdraft is truthy and that you still add the three
controls with Validators.min(0) only if they are not present.
---
Outside diff comments:
In `@src/app/clients/clients-view/clients-view.component.ts`:
- Around line 426-427: The subscription callback on
deleteClientImageDialogRef.afterClosed() accesses response.delete without
guarding for undefined; update the handler in clients-view.component.ts (the
callback passed to deleteClientImageDialogRef.afterClosed().subscribe) to first
check that response is defined (e.g., response && response.delete or
response?.delete) or narrow its type (make response optional) before accessing
.delete, and ensure the branch that performs the delete action runs only when
that guarded check passes.
In
`@src/app/clients/clients-view/family-members-tab/family-members-tab.component.ts`:
- Around line 82-84: The dialog close handler in FamilyMembersTabComponent uses
deleteFamilyMemberDialogRef.afterClosed().subscribe((response: any) => { if
(response.delete) { ... } }) which will throw when response is undefined; update
the callback to guard the value before accessing .delete (e.g., check response
truthiness or use optional chaining like response?.delete) and only call
clientsService.deleteFamilyMember(clientId, id).subscribe(...) when the guard
passes so canceled/undefined dialog results are handled safely.
---
Nitpick comments:
In `@src/app/clients/services/external-national-id.service.ts`:
- Around line 46-49: Update the stale class comment to reflect that cleanup is
performed via Angular's DestroyRef teardown instead of ngOnDestroy/OnDestroy:
replace references to "ngOnDestroy" and "implements OnDestroy" with a note that
the service is provided at the component level and uses DestroyRef to
automatically teardown subscriptions when the host is destroyed (mention the
service uses DestroyRef in constructor or teardown logic). Ensure both
occurrences (around the existing comment and the other instance) are updated to
match the current implementation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 640c8084-ec18-4510-a2f9-3bc139d4f4ca
📒 Files selected for processing (72)
src/app/clients/client-stepper/client-datatable-step/client-datatable-step.component.tssrc/app/clients/client-stepper/client-family-members-step/client-family-member-dialog/client-family-member-dialog.component.tssrc/app/clients/client-stepper/client-general-step/client-general-step.component.tssrc/app/clients/clients-view/address-tab/address-tab.component.tssrc/app/clients/clients-view/charges/charges-overview/charges-overview.component.tssrc/app/clients/clients-view/charges/client-pay-charges/client-pay-charges.component.tssrc/app/clients/clients-view/charges/view-charge/view-charge.component.tssrc/app/clients/clients-view/client-actions/accept-client-transfer/accept-client-transfer.component.tssrc/app/clients/clients-view/client-actions/activate-client/activate-client.component.tssrc/app/clients/clients-view/client-actions/add-client-charge/add-client-charge.component.tssrc/app/clients/clients-view/client-actions/add-client-collateral/add-client-collateral.component.tssrc/app/clients/clients-view/client-actions/client-assign-staff/client-assign-staff.component.tssrc/app/clients/clients-view/client-actions/client-screen-reports/client-screen-reports.component.tssrc/app/clients/clients-view/client-actions/close-client/close-client.component.tssrc/app/clients/clients-view/client-actions/reactivate-client/reactivate-client.component.tssrc/app/clients/clients-view/client-actions/reject-client-transfer/reject-client-transfer.component.tssrc/app/clients/clients-view/client-actions/reject-client/reject-client.component.tssrc/app/clients/clients-view/client-actions/take-survey/take-survey.component.tssrc/app/clients/clients-view/client-actions/transfer-client/transfer-client.component.tssrc/app/clients/clients-view/client-actions/undo-client-rejection/undo-client-rejection.component.tssrc/app/clients/clients-view/client-actions/undo-client-transfer/undo-client-transfer.component.tssrc/app/clients/clients-view/client-actions/update-client-savings-account/update-client-savings-account.component.tssrc/app/clients/clients-view/client-actions/view-survey/view-survey.component.tssrc/app/clients/clients-view/client-actions/withdraw-client/withdraw-client.component.tssrc/app/clients/clients-view/clients-view.component.tssrc/app/clients/clients-view/custom-dialogs/edit-notes-dialog/edit-notes-dialog.component.tssrc/app/clients/clients-view/custom-dialogs/upload-document-dialog/upload-document-dialog.component.tssrc/app/clients/clients-view/datatable-tab/datatable-tab.component.tssrc/app/clients/clients-view/documents-tab/documents-tab.component.tssrc/app/clients/clients-view/family-members-tab/add-family-member/add-family-member.component.tssrc/app/clients/clients-view/family-members-tab/edit-family-member/edit-family-member.component.tssrc/app/clients/clients-view/family-members-tab/family-members-tab.component.tssrc/app/clients/clients-view/general-tab/general-tab.component.tssrc/app/clients/clients-view/notes-tab/notes-tab.component.tssrc/app/clients/clients-view/personal-data-tab/personal-data-tab.component.tssrc/app/clients/clients.component.tssrc/app/clients/create-client/create-client.component.tssrc/app/clients/edit-client/edit-client.component.tssrc/app/clients/services/external-national-id.service.tssrc/app/savings/create-savings-account/create-savings-account.component.tssrc/app/savings/edit-savings-account/edit-savings-account.component.tssrc/app/savings/gsim-account/create-gsim-account/create-gsim-account.component.tssrc/app/savings/gsim-account/gsim-account.component.tssrc/app/savings/saving-account-actions/activate-savings-account/activate-savings-account.component.tssrc/app/savings/saving-account-actions/add-charge-savings-account/add-charge-savings-account.component.tssrc/app/savings/saving-account-actions/apply-annual-fees-savings-account/apply-annual-fees-savings-account.component.tssrc/app/savings/saving-account-actions/approve-savings-account/approve-savings-account.component.tssrc/app/savings/saving-account-actions/close-savings-account/close-savings-account.component.tssrc/app/savings/saving-account-actions/manage-savings-account/manage-savings-account.component.tssrc/app/savings/saving-account-actions/post-interest-as-on-savings-account/post-interest-as-on-savings-account.component.tssrc/app/savings/saving-account-actions/reject-savings-account/reject-savings-account.component.tssrc/app/savings/saving-account-actions/saving-account-actions.component.tssrc/app/savings/saving-account-actions/savings-account-assign-staff/savings-account-assign-staff.component.tssrc/app/savings/saving-account-actions/savings-account-transactions/savings-account-transactions.component.tssrc/app/savings/saving-account-actions/savings-account-unassign-staff/savings-account-unassign-staff.component.tssrc/app/savings/saving-account-actions/undo-approval-savings-account/undo-approval-savings-account.component.tssrc/app/savings/saving-account-actions/withdraw-by-client-savings-account/withdraw-by-client-savings-account.component.tssrc/app/savings/savings-account-stepper/savings-account-charges-step/savings-account-charges-step.component.tssrc/app/savings/savings-account-stepper/savings-account-details-step/savings-account-details-step.component.tssrc/app/savings/savings-account-stepper/savings-account-terms-step/savings-account-terms-step.component.tssrc/app/savings/savings-account-view/datatable-tabs/datatable-tabs.component.tssrc/app/savings/savings-account-view/notes-tab/notes-tab.component.tssrc/app/savings/savings-account-view/savings-account-view.component.tssrc/app/savings/savings-account-view/savings-documents-tab/savings-documents-tab.component.tssrc/app/savings/savings-account-view/transactions-tab/export-transactions/export-transactions.component.tssrc/app/savings/savings-account-view/transactions-tab/transactions-tab.component.tssrc/app/savings/savings-account-view/transactions/edit-transaction/edit-transaction.component.tssrc/app/savings/savings-account-view/transactions/view-reciept/view-reciept.component.tssrc/app/savings/savings-account-view/transactions/view-transaction/datatable-transaction-tab/datatable-transaction-tab.component.tssrc/app/savings/savings-account-view/transactions/view-transaction/savings-transaction-general-tab/savings-transaction-general-tab.component.tssrc/app/savings/savings-account-view/transactions/view-transaction/view-transaction.component.tssrc/app/savings/savings-account-view/view-charge/view-charge.component.ts
Description
Replace manual subscribe/unsubscribe patterns with DestroyRef + takeUntilDestroyed across clients and savings components and directives. Also replace UntypedFormBuilder/Group/Control/Array with typed Angular equivalents.
Related issues and discussion
WEB-954
Screenshots, if any
Checklist
Please make sure these boxes are checked before submitting your pull request - thanks!
If you have multiple commits please combine them into one commit by squashing them.
Read and understood the contribution guidelines at
web-app/.github/CONTRIBUTING.md.Summary by CodeRabbit