-
Notifications
You must be signed in to change notification settings - Fork 1
PO-1849 #2417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
PO-1849 #2417
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,7 @@ export class FinesAccDefendantDetailsEnforcementTab { | |
| @Input() hasAccountMaintenancePermission: boolean = false; | ||
| @Input() hasEnterEnforcementPermission: boolean = false; | ||
| @Output() addEnforcementOverride = new EventEmitter<void>(); | ||
| @Output() changeEnforcementCourt = new EventEmitter<number | null>(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if the null should be here |
||
|
|
||
| /** | ||
| * Emits an event to add an enforcement override if the user has the necessary permissions and there is no existing enforcement override result. | ||
|
|
@@ -53,4 +54,13 @@ export class FinesAccDefendantDetailsEnforcementTab { | |
| this.addEnforcementOverride.emit(); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Emits the current enforcement court id when the user can change it. | ||
| */ | ||
| public handleChangeEnforcementCourt(): void { | ||
| if (this.hasAccountMaintenancePermission) { | ||
| this.changeEnforcementCourt.emit(this.tabData.enforcement_overview.enforcement_court?.court_id ?? null); | ||
| } | ||
| } | ||
|
Comment on lines
+61
to
+65
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would the link not be wrapped around this permission to prevent users who didn't have this permission to click a link they can't actually click on. Also, I don't think the link should show if the court_id was null. We could put an if statement in the HTML which looks for the permission and the court_id and pass that into the |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -55,6 +55,7 @@ import { FINES_ACCOUNT_TYPES } from '../../constants/fines-account-types.constan | |
| import { IOpalFinesResultRefData } from '@services/fines/opal-fines-service/interfaces/opal-fines-result-ref-data.interface'; | ||
| import { FinesAccDefendantDetailsEnforcementTab } from './fines-acc-defendant-details-enforcement-tab/fines-acc-defendant-details-enforcement-tab.component'; | ||
| import { FinesAccSummaryHeaderComponent } from '../fines-acc-summary-header/fines-acc-summary-header.component'; | ||
| import { FINES_ACC_ENF_COURT_CHANGE_ROUTING_PATHS } from '../fines-acc-enf-court-change/constants/fines-acc-enf-court-change-routing-paths.constant'; | ||
|
|
||
| @Component({ | ||
| selector: 'app-fines-acc-defendant-details', | ||
|
|
@@ -458,4 +459,21 @@ export class FinesAccDefendantDetailsComponent extends AbstractTabData implement | |
| relativeTo: this.activatedRoute, | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Navigates to the change enforcement court page, preserving the current court id for no-op submissions. | ||
| * | ||
| * @param currentEnforcementCourtId The current enforcement court id shown on the enforcement tab. | ||
| */ | ||
| public navigateToChangeEnforcementCourtPage(currentEnforcementCourtId: number | null): void { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure about passing in the enforcement court id here. This would be cached data so we could just grab that on the component, this is being treated as throwaway data
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we not use the resolver here? |
||
| this['router'].navigate( | ||
| [ | ||
| `../${FINES_ACC_DEFENDANT_ROUTING_PATHS.children.enforcement}/${FINES_ACC_ENF_COURT_CHANGE_ROUTING_PATHS.root}/${FINES_ACC_ENF_COURT_CHANGE_ROUTING_PATHS.children.change}`, | ||
| ], | ||
| { | ||
| relativeTo: this.activatedRoute, | ||
| state: { currentEnforcementCourtId }, | ||
| }, | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import { IFinesAccEnfCourtChangeFieldErrors } from '../interfaces/fines-acc-enf-court-change-field-errors.interface'; | ||
|
|
||
| export const FINES_ACC_ENF_COURT_CHANGE_FIELD_ERRORS: IFinesAccEnfCourtChangeFieldErrors = { | ||
| facc_enf_court: { | ||
| required: { | ||
| message: 'Select an enforcement court', | ||
| priority: 1, | ||
| }, | ||
| }, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import { IFinesAccEnfCourtChangeRoutingPaths } from '../interfaces/fines-acc-enf-court-change-routing-paths.interface'; | ||
|
|
||
| export const FINES_ACC_ENF_COURT_CHANGE_ROUTING_PATHS: IFinesAccEnfCourtChangeRoutingPaths = { | ||
| root: 'court', | ||
| children: { | ||
| change: 'change', | ||
| }, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import { IFinesAccEnfCourtChangeRoutingPaths } from '../interfaces/fines-acc-enf-court-change-routing-paths.interface'; | ||
|
|
||
| export const FINES_ACC_ENF_COURT_CHANGE_ROUTING_TITLES: IFinesAccEnfCourtChangeRoutingPaths = { | ||
| root: 'Enforcement court', | ||
| children: { | ||
| change: 'Change enforcement court', | ||
| }, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export const FINES_ACC_ENF_COURT_CHANGE_SUCCESS_MESSAGE = 'Enforcement court changed'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| <opal-lib-govuk-heading-with-caption | ||
| [captionText]="`${accountNumber} - ${partyName}`" | ||
| [headingText]="'Change enforcement court'" | ||
| headingClasses="govuk-heading-l govuk-!-margin-bottom-30" | ||
| > | ||
| </opal-lib-govuk-heading-with-caption> | ||
| <opal-lib-govuk-error-summary | ||
| [errors]="formErrorSummaryMessage" | ||
| (errorClick)="scrollTo($event)" | ||
| ></opal-lib-govuk-error-summary> | ||
| <form (submit)="handleFormSubmit($event)" [formGroup]="form" class="govuk-form"> | ||
| <opal-lib-alphagov-accessible-autocomplete | ||
| [control]="form.get('facc_enf_court')" | ||
| labelText="Enforcement court" | ||
| labelClasses="govuk-fieldset__legend--m" | ||
| inputId="facc_enf_court" | ||
| inputName="facc_enf_court" | ||
| label="Enforcement court" | ||
| [autoCompleteItems]="courtOptions" | ||
| [errors]="formControlErrorMessages['facc_enf_court']" | ||
| [tabIndex]="0" | ||
| ></opal-lib-alphagov-accessible-autocomplete> | ||
|
|
||
| <div class="govuk-button-group"> | ||
| <opal-lib-govuk-button buttonId="submitForm" type="submit" buttonClasses="nested-flow govuk-button--primary"> | ||
| Change | ||
| </opal-lib-govuk-button> | ||
| <opal-lib-govuk-cancel-link (linkClickEvent)="handleCancel()"></opal-lib-govuk-cancel-link> | ||
| </div> | ||
| </form> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
| import { ActivatedRoute } from '@angular/router'; | ||
| import { beforeEach, describe, expect, it, vi } from 'vitest'; | ||
| import { FinesAccEnfCourtChangeFormComponent } from './fines-acc-enf-court-change-form.component'; | ||
|
|
||
| describe('FinesAccEnfCourtChangeFormComponent', () => { | ||
| let component: FinesAccEnfCourtChangeFormComponent; | ||
| let fixture: ComponentFixture<FinesAccEnfCourtChangeFormComponent>; | ||
|
|
||
| beforeEach(async () => { | ||
| await TestBed.configureTestingModule({ | ||
| imports: [FinesAccEnfCourtChangeFormComponent], | ||
| providers: [{ provide: ActivatedRoute, useValue: { snapshot: { params: {}, data: {} } } }], | ||
| }).compileComponents(); | ||
|
|
||
| fixture = TestBed.createComponent(FinesAccEnfCourtChangeFormComponent); | ||
| component = fixture.componentInstance; | ||
| component.accountNumber = '123456'; | ||
| component.courtOptions = [{ value: 101, name: 'Test Court (101)' }]; | ||
| component.partyName = 'Mr Test PERSON'; | ||
| fixture.detectChanges(); | ||
| }); | ||
|
|
||
| it('should create', () => { | ||
| expect(component).toBeTruthy(); | ||
| }); | ||
|
|
||
| it('should initialize the enforcement court control as required', () => { | ||
| const control = component.form.get('facc_enf_court'); | ||
|
|
||
| expect(control).toBeTruthy(); | ||
| expect(control?.hasError('required')).toBe(true); | ||
| }); | ||
|
|
||
| it('should emit cancel when handleCancel is called', () => { | ||
| const emitSpy = vi.spyOn(component.cancelRequested, 'emit'); | ||
|
|
||
| component.handleCancel(); | ||
|
|
||
| expect(emitSpy).toHaveBeenCalled(); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; | ||
| import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; | ||
| import { AbstractFormBaseComponent } from '@hmcts/opal-frontend-common/components/abstract/abstract-form-base'; | ||
| import { | ||
| IAbstractFormBaseFieldErrors, | ||
| IAbstractFormBaseForm, | ||
| } from '@hmcts/opal-frontend-common/components/abstract/abstract-form-base/interfaces'; | ||
| import { IAbstractFormControlErrorMessage } from '@hmcts/opal-frontend-common/components/abstract/interfaces'; | ||
| import { AlphagovAccessibleAutocompleteComponent } from '@hmcts/opal-frontend-common/components/alphagov/alphagov-accessible-autocomplete'; | ||
| import { IAlphagovAccessibleAutocompleteItem } from '@hmcts/opal-frontend-common/components/alphagov/alphagov-accessible-autocomplete/interfaces'; | ||
| import { GovukButtonComponent } from '@hmcts/opal-frontend-common/components/govuk/govuk-button'; | ||
| import { GovukCancelLinkComponent } from '@hmcts/opal-frontend-common/components/govuk/govuk-cancel-link'; | ||
| import { GovukErrorSummaryComponent } from '@hmcts/opal-frontend-common/components/govuk/govuk-error-summary'; | ||
| import { GovukHeadingWithCaptionComponent } from '@hmcts/opal-frontend-common/components/govuk/govuk-heading-with-caption'; | ||
| import { FINES_ACC_ENF_COURT_CHANGE_FIELD_ERRORS } from '../constants/fines-acc-enf-court-change-field-errors.constant'; | ||
| import { IFinesAccEnfCourtChangeFormState } from '../interfaces/fines-acc-enf-court-change-form-state.interface'; | ||
|
|
||
| @Component({ | ||
| selector: 'app-fines-acc-enf-court-change-form', | ||
| imports: [ | ||
| FormsModule, | ||
| ReactiveFormsModule, | ||
| AlphagovAccessibleAutocompleteComponent, | ||
| GovukButtonComponent, | ||
| GovukCancelLinkComponent, | ||
| GovukErrorSummaryComponent, | ||
| GovukHeadingWithCaptionComponent, | ||
| ], | ||
| templateUrl: './fines-acc-enf-court-change-form.component.html', | ||
| changeDetection: ChangeDetectionStrategy.OnPush, | ||
| standalone: true, | ||
| }) | ||
| export class FinesAccEnfCourtChangeFormComponent extends AbstractFormBaseComponent implements OnInit, OnDestroy { | ||
| protected override fieldErrors: IAbstractFormBaseFieldErrors = { | ||
| ...FINES_ACC_ENF_COURT_CHANGE_FIELD_ERRORS, | ||
| }; | ||
| protected override formSubmit = new EventEmitter<IAbstractFormBaseForm<IFinesAccEnfCourtChangeFormState>>(); | ||
| @Output() public cancelRequested = new EventEmitter<void>(); | ||
| public override formControlErrorMessages: IAbstractFormControlErrorMessage = {}; | ||
| @Input({ required: true }) public accountNumber!: string; | ||
| @Input({ required: true }) public courtOptions!: IAlphagovAccessibleAutocompleteItem[]; | ||
| @Input({ required: true }) public partyName!: string; | ||
|
|
||
| /** | ||
| * Sets up the enforcement court change form with the required court control. | ||
| */ | ||
| private setupForm(): void { | ||
| this.form = new FormGroup({ | ||
| facc_enf_court: new FormControl<number | null>(null, Validators.required), | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Initializes the form before wiring up the shared form behaviour. | ||
| */ | ||
| public override ngOnInit(): void { | ||
| this.setupForm(); | ||
| super.ngOnInit(); | ||
| } | ||
|
|
||
| /** | ||
| * Emits the cancel action to the parent component. | ||
| */ | ||
| public handleCancel(): void { | ||
| this.cancelRequested.emit(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <div class="govuk-grid-column-two-thirds"> | ||
| <app-fines-acc-enf-court-change-form | ||
| [accountNumber]="accountNumber" | ||
| [courtOptions]="courtOptions" | ||
| [partyName]="partyName" | ||
| (cancelRequested)="handleCancel()" | ||
| (unsavedChanges)="handleUnsavedChanges($event)" | ||
| (formSubmit)="handleSubmit($event)" | ||
| ></app-fines-acc-enf-court-change-form> | ||
| </div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could pass in
tabData.enforcement_overview.enforcement_court.court_idhere