Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
68a9ba1
RET-5415 (#2034)
LahiruOshara Jun 25, 2025
3c9f9b1
RET-5419 (#2049)
LahiruOshara Jun 30, 2025
815b182
Merge branch 'master' into feature/noc-claimant-rep
LahiruOshara Jun 30, 2025
7bf4bed
fix build issue
LahiruOshara Jun 30, 2025
0b87022
notification text change
LahiruOshara Jul 1, 2025
09053b0
Merge branch 'master' into feature/noc-claimant-rep
LahiruOshara Jul 1, 2025
1838711
notification text change
LahiruOshara Jul 2, 2025
a5efd15
org name fetch issue fix
LahiruOshara Jul 8, 2025
27218ea
Merge branch 'master' into feature/noc-claimant-rep
LahiruOshara Jul 8, 2025
a7f6b1d
org name fetch issue fix
LahiruOshara Jul 8, 2025
b863599
Merge remote-tracking branch 'origin/feature/noc-claimant-rep' into f…
LahiruOshara Jul 8, 2025
10d4310
fetch apps from CLAIMANT_REP
LahiruOshara Jul 11, 2025
12fea78
modify app show logic
LahiruOshara Jul 11, 2025
10eab56
RET-5419-fixes (#2080)
LahiruOshara Jul 14, 2025
742b0b9
Merge branch 'master' into feature/noc-claimant-rep
LahiruOshara Jul 14, 2025
97f50cf
Merge branch 'master' into feature/noc-claimant-rep
JustMehmet Jul 18, 2025
0b024cf
suppress issues
LahiruOshara Jul 23, 2025
0182b64
suppress issues
LahiruOshara Jul 23, 2025
3babd53
Merge branch 'master' into feature/noc-claimant-rep
JustMehmet Aug 2, 2025
61a3e2e
welsh translations (#2123)
LahiruOshara Aug 6, 2025
773937a
citizen-hub welsh update
LahiruOshara Aug 14, 2025
bba3308
appoint-legal-representative welsh update
LahiruOshara Aug 14, 2025
58131c9
citizen-hub welsh update
LahiruOshara Aug 15, 2025
f1b90be
appoint-legal-representative welsh update
LahiruOshara Aug 15, 2025
060704c
appoint-legal-representative welsh update
LahiruOshara Aug 15, 2025
44baa71
RET-5416 (#2050)
JustMehmet Aug 15, 2025
b1b3d44
Merge branch 'master' into feature/noc-claimant-rep
JustMehmet Aug 15, 2025
c72a699
fix welsh
LahiruOshara Aug 15, 2025
1c5ad52
Merge branch 'master' into feature/noc-claimant-rep
JustMehmet Aug 27, 2025
d4743c6
Welsh noc change legal rep (#2135)
LahiruOshara Sep 1, 2025
fd2758f
Merge branch 'master' into feature/noc-claimant-rep
JustMehmet Sep 4, 2025
aeff984
Merge branch 'master' into feature/noc-claimant-rep
JustMehmet Sep 11, 2025
99ea75a
Updates for appoint-legal-representative page.
JustMehmet Sep 11, 2025
8722191
Updates for change legal representative page.
JustMehmet Sep 11, 2025
4e01cae
Updates for notification banner of claimant no longer represented value.
JustMehmet Sep 11, 2025
c8aab2b
Updates for notification banner of claimant no longer represented value.
JustMehmet Sep 11, 2025
3c4d8f6
Updates for notification banner of claimant no longer represented value.
JustMehmet Sep 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/main/controllers/AppointLegalRepController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Response } from 'express';

import { AppRequest } from '../definitions/appRequest';
import { PageUrls, TranslationKeys } from '../definitions/constants';

import { getLanguageParam } from './helpers/RouterHelpers';

export default class AppointLegalRepController {
public get = async (req: AppRequest, res: Response): Promise<void> => {
const content = {
...req.t(TranslationKeys.COMMON, { returnObjects: true }),
...req.t(TranslationKeys.APPOINT_LEGAL_REPRESENTATIVE, { returnObjects: true }),
};

const languageParam = getLanguageParam(req.url);
const userCase = req.session.userCase;
const allDocumentsUrl = PageUrls.ALL_DOCUMENTS;

res.render(TranslationKeys.APPOINT_LEGAL_REPRESENTATIVE, {
...req.t(TranslationKeys.APPOINT_LEGAL_REPRESENTATIVE, { returnObjects: true }),
...content,
currentUrl: '/appoint-legal-representative',
languageParam,
userCase,
allDocumentsUrl,
});
};
}
84 changes: 84 additions & 0 deletions src/main/controllers/ChangeLegalRepresentativeController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Response } from 'express';

import { Form } from '../components/form/form';
import { isFieldFilledIn } from '../components/form/validator';
import { AppRequest } from '../definitions/appRequest';
import { LEGAL_REPRESENTATIVE_CHANGE_OPTIONS, PageUrls, TranslationKeys } from '../definitions/constants';
import { FormContent, FormFields } from '../definitions/form';
import { AnyRecord } from '../definitions/util-types';
import { getLogger } from '../logger';

import { removeClaimantRepresentative } from './helpers/CaseRoleHelper';
import { getPageContent } from './helpers/FormHelpers';
import { conditionalRedirect, getLanguageParam } from './helpers/RouterHelpers';

const logger = getLogger('RespondentApplicationDetailsController');

export default class ChangeLegalRepresentativeController {
private readonly form: Form;
private readonly changeLegalRepresentativeContent: FormContent = {
fields: {
legalRep: {
id: 'legalRep',
type: 'radios',
label: (l: AnyRecord): string => l.h1,
labelHidden: false,
labelSize: 'xl',
classes: 'govuk-radios--inline',
values: [
{
label: (l: AnyRecord): string => l.legalRepresentativeChange,
value: LEGAL_REPRESENTATIVE_CHANGE_OPTIONS.change,
},
{
label: (l: AnyRecord): string => l.legalRepresentativeRemove,
value: LEGAL_REPRESENTATIVE_CHANGE_OPTIONS.remove,
},
],
validator: isFieldFilledIn,
},
},
submit: {
text: (l: AnyRecord): string => l.submitBtn,
},
};

constructor() {
this.form = new Form(<FormFields>this.changeLegalRepresentativeContent.fields);
}

public post = async (req: AppRequest, res: Response): Promise<void> => {
const formData = this.form.getParsedBody(req.body, this.form.getFormFields());
req.session.errors = this.form.getValidatorErrors(formData);
if (req.session.errors.length > 0) {
return res.redirect(req.url);
}
try {
const redirectUrl = conditionalRedirect(
req,
this.form.getFormFields(),
LEGAL_REPRESENTATIVE_CHANGE_OPTIONS.change
)
? PageUrls.APPOINT_LEGAL_REPRESENTATIVE
: await removeClaimantRepresentative(req);
res.redirect(redirectUrl);
} catch (error) {
logger.info(error);
req.session.errors.push({ propertyName: 'legalRep', errorType: 'backEndError' });
res.redirect(req.url);
}
};

public get = async (req: AppRequest, res: Response): Promise<void> => {
const content = getPageContent(req, this.changeLegalRepresentativeContent, [
TranslationKeys.COMMON,
TranslationKeys.SIDEBAR_CONTACT_US,
TranslationKeys.CHANGE_LEGAL_REPRESENTATIVE,
]);
res.render(TranslationKeys.CHANGE_LEGAL_REPRESENTATIVE, {
...content,
PageUrls,
languageParam: getLanguageParam(req.url),
});
};
}
49 changes: 27 additions & 22 deletions src/main/controllers/ContactTheTribunalController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,43 +19,47 @@ export default class ContactTheTribunalController {
const bundlesEnabled = await getFlagValue(FEATURE_FLAGS.BUNDLES, null);
const DOCUMENTS = 'documents';
const { hearingCollection } = req.session.userCase;
const claimantRepresented = req.session.userCase.claimantRepresentative;

const translations: AnyRecord = {
...req.t(TranslationKeys.CONTACT_THE_TRIBUNAL, { returnObjects: true }),
};

const languageParam = getLanguageParam(req.url);
let applicationsToDisplay;
let applicationsAccordionItems;

// if bundles not enabled or no hearings in future then remove documents from displayed application types
const allowBundlesFlow =
bundlesEnabled && hearingCollection?.length && createRadioBtnsForHearings(hearingCollection)?.length;

if (!allowBundlesFlow) {
applicationsToDisplay = applications.filter(app => app !== DOCUMENTS);
} else {
applicationsToDisplay = applications;
}
if (!claimantRepresented) {
if (!allowBundlesFlow) {
applicationsToDisplay = applications.filter(app => app !== DOCUMENTS);
} else {
applicationsToDisplay = applications;
}

const applicationsAccordionItems = applicationsToDisplay.map(application => {
const label = translations.sections[application].label;
const link =
application === DOCUMENTS
? PageUrls.PREPARE_DOCUMENTS + languageParam
: `/contact-the-tribunal/${application}${languageParam}`;
return {
heading: {
text: label,
},
content: {
bodyText: translations.sections[application].body,
link: {
href: link,
applicationsAccordionItems = applicationsToDisplay.map(application => {
const label = translations.sections[application].label;
const link =
application === DOCUMENTS
? PageUrls.PREPARE_DOCUMENTS + languageParam
: `/contact-the-tribunal/${application}${languageParam}`;
return {
heading: {
text: label,
},
},
};
});
content: {
bodyText: translations.sections[application].body,
link: {
href: link,
text: label,
},
},
};
});
}

const content = getPageContent(req, <FormContent>{}, [
TranslationKeys.COMMON,
Expand All @@ -65,6 +69,7 @@ export default class ContactTheTribunalController {
...content,
hideContactUs: true,
applicationsAccordionItems,
claimantRepresented,
welshEnabled,
});
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/controllers/ContactTheTribunalSelectedController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ export default class ContactTheTribunalSelectedController {
return;
}

if (req.session.userCase.claimantRepresentative !== undefined) {
return res.redirect(ErrorPages.NOT_FOUND);
}

const userCase = req.session?.userCase;
if (selectedApplication !== userCase.contactApplicationType) {
clearTseFields(userCase);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export default class RespondentApplicationDetailsController {
decisionContent,
respondButton,
isAdminRespondButton: responseToTribunalRequired(selectedApplication),
isClaimantRepresented: req.session.userCase.claimantRepresentative !== undefined,
adminRespondRedirectUrl,
allResponses,
welshEnabled,
Expand Down
7 changes: 7 additions & 0 deletions src/main/controllers/citizen-hub/CitizenHubController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Response } from 'express';

import { AppRequest } from '../../definitions/appRequest';
import { YesOrNo } from '../../definitions/case';
import { PageUrls, TranslationKeys } from '../../definitions/constants';
import {
HubLinkNames,
Expand Down Expand Up @@ -167,6 +168,7 @@ export default class CitizenHubController {

let judgmentBannerContent = undefined;
let decisionBannerContent = undefined;
let showNoLongerRepresentedNotification: boolean = false;
const claimantTribunalResponseBannerContent = getClaimantTribunalResponseBannerContent(
notifications,
languageParam
Expand All @@ -178,6 +180,9 @@ export default class CitizenHubController {
}

const showMultipleData = await showMutipleData(userCase);
if (YesOrNo.YES === userCase?.claimantRepresentativeRemoved) {
showNoLongerRepresentedNotification = true;
}

res.render(TranslationKeys.CITIZEN_HUB, {
...req.t(TranslationKeys.COMMON, { returnObjects: true }),
Expand All @@ -194,6 +199,7 @@ export default class CitizenHubController {
hideContactUs: true,
processingDueDate: getDueDate(formatDate(userCase.submittedDate), DAYS_FOR_PROCESSING),
showSubmittedAlert: shouldShowSubmittedAlert(userCase),
claimantRepresented: userCase.claimantRepresentative,
showAcknowledgementAlert: getAcknowledgementAlert(userCase, hubLinksStatuses),
showRejectionAlert: shouldShowRejectionAlert(userCase, hubLinksStatuses),
showRespondentResponseReceived: shouldShowRespondentResponseReceived(allApplications),
Expand All @@ -218,6 +224,7 @@ export default class CitizenHubController {
welshEnabled,
showMultipleData,
multiplePanelData: await getMultiplePanelData(userCase, translations, showMultipleData),
showNoLongerRepresentedNotification,
});
}
}
9 changes: 9 additions & 0 deletions src/main/controllers/helpers/CaseRoleHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { AppRequest } from '../../definitions/appRequest';
import { getCaseApi } from '../../services/CaseService';

import { getLanguageParam } from './RouterHelpers';

export const removeClaimantRepresentative = async (req: AppRequest): Promise<string> => {
await getCaseApi(req.session.user?.accessToken)?.removeClaimantRepresentative(req);
return '/citizen-hub/' + req.session.userCase.id + getLanguageParam(req.url);
};
6 changes: 4 additions & 2 deletions src/main/controllers/helpers/CitizenHubHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,9 @@ export const shouldHubLinkBeClickable = (status: HubLinkStatus, linkName: string
};

export const getAllClaimantApplications = (userCase: CaseWithId): GenericTseApplicationTypeItem[] => {
return userCase.genericTseApplicationCollection?.filter(item => item.value.applicant === Applicant.CLAIMANT);
return userCase.genericTseApplicationCollection?.filter(
item => item.value.applicant === Applicant.CLAIMANT || item.value.applicant === Applicant.CLAIMANT_REP
);
};

export const getClaimantAppsAndUpdateStatusTag = (userCase: CaseWithId): void => {
Expand Down Expand Up @@ -234,7 +236,7 @@ export const updateYourApplicationsStatusTag = (
// If claimant responds to tribunal request, hub link status set to 'In progress'
// Only set if it is not already set to 'Updated', as 'Updated' is the higher priority status
if (
lastItem.value.from === Applicant.CLAIMANT &&
(lastItem.value.from === Applicant.CLAIMANT || lastItem.value.from === Applicant.CLAIMANT_REP) &&
isAdmin &&
citizenHubHighestPriorityStatus !== HubLinkStatus.UPDATED
) {
Expand Down
5 changes: 4 additions & 1 deletion src/main/controllers/helpers/PageContentHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ export const populateAppItemsWithRedirectLinksCaptionsAndStatusColors = (
const claimantItems = [];
if (items?.length) {
for (let i = items.length - 1; i >= 0; i--) {
if (items[i].value.applicant?.includes(Applicant.CLAIMANT)) {
if (
items[i].value.applicant?.includes(Applicant.CLAIMANT) ||
items[i].value.applicant?.includes(Applicant.CLAIMANT_REP)
) {
claimantItems[i] = items[i];
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/definitions/api/caseApiResponse.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CaseType, CaseTypeId, Document, YesOrNo } from '../case';
import { ClaimantRepresentative } from '../complexTypes/ClaimantRepresentative';
import { ClaimantCorrespondence } from '../complexTypes/claimantCorrespondence';
import { ClaimantEmploymentDetails } from '../complexTypes/claimantEmploymentDetails';
import { ClaimantHearingPreference } from '../complexTypes/claimantHearingPreference';
Expand Down Expand Up @@ -76,6 +77,8 @@ export interface CaseData {
multipleFlag?: YesOrNo;
leadClaimant?: YesOrNo;
batchCaseStayed?: YesOrNo;
representativeClaimantType?: ClaimantRepresentative;
claimantRepresentativeRemoved?: YesOrNo;
}

export type HearingBundleType = {
Expand Down
3 changes: 3 additions & 0 deletions src/main/definitions/case.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { HearingModel } from './api/caseApiResponse';
import { ClaimantRepresentative } from './complexTypes/ClaimantRepresentative';
import { DocumentTypeItem } from './complexTypes/documentTypeItem';
import { Et1Address } from './complexTypes/et1Address';
import { GenericTseApplicationTypeItem, TseRespondTypeItem } from './complexTypes/genericTseApplicationTypeItem';
Expand Down Expand Up @@ -216,6 +217,8 @@ export interface Case {
multipleFlag?: YesOrNo;
leadClaimant?: YesOrNo;
caseStayed?: YesOrNo;
claimantRepresentative?: ClaimantRepresentative;
claimantRepresentativeRemoved?: YesOrNo;
}

export const enum StillWorking {
Expand Down
7 changes: 7 additions & 0 deletions src/main/definitions/complexTypes/ClaimantRepresentative.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Organisation } from './Organisation';

export interface ClaimantRepresentative {
name_of_representative?: string;
myHmctsOrganisation?: Organisation;
name_of_organisation?: string;
}
4 changes: 4 additions & 0 deletions src/main/definitions/complexTypes/Organisation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface Organisation {
OrganisationID?: string;
OrganisationName?: string;
}
16 changes: 16 additions & 0 deletions src/main/definitions/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export const TranslationKeys = {
CITIZEN_HUB_RESPONSE_REJECTION: 'response-rejection',
CITIZEN_HUB_RESPONSE_ACKNOWLEDGEMENT: 'response-acknowledgement',
CITIZEN_HUB_RESPONSE_FROM_RESPONDENT: 'response-from-respondent',
APPOINT_LEGAL_REPRESENTATIVE: 'appoint-legal-representative',
RESPONDENT_CONTACT_DETAILS: 'respondent-contact-details',
CONTACT_THE_TRIBUNAL: 'contact-the-tribunal',
TRIBUNAL_CONTACT_SELECTED: 'contact-the-tribunal-selected',
Expand Down Expand Up @@ -152,6 +153,7 @@ export const TranslationKeys = {
RULE92_HOLDING_PAGE: 'rule92-holding-page',
RESPOND_TO_TRIBUNAL_RESPONSE: 'respond-to-tribunal-response',
HEARING_DETAILS: 'hearing-details',
CHANGE_LEGAL_REPRESENTATIVE: 'change-legal-representative',
} as const;

export const PageUrls = {
Expand Down Expand Up @@ -289,7 +291,9 @@ export const PageUrls = {
AGREEING_DOCUMENTS_FOR_HEARING: '/agreeing-documents-for-hearing',
RULE92_HOLDING_PAGE: '/holding-page',
RESPOND_TO_TRIBUNAL_RESPONSE: '/respond-to-tribunal-response/:appId',
APPOINT_LEGAL_REPRESENTATIVE: '/appoint-legal-representative',
HEARING_DETAILS: '/hearing-details',
CHANGE_LEGAL_REPRESENTATIVE: '/change-legal-representative',
} as const;

export const InterceptPaths = {
Expand Down Expand Up @@ -349,6 +353,8 @@ export const JavaApiUrls = {
SUBMIT_STORED_RESPOND_TO_TRIBUNAL: 'store/submit-stored-respond-to-tribunal',
UPDATE_ADMIN_DECISION_STATE: '/tseAdmin/update-admin-decision-state',
SUBMIT_BUNDLES: 'bundles/submit-bundles',
REVOKE_CASE_USER_ROLES: '/manageCaseRole/modifyCaseUserRoles?modificationType=Revoke',
REVOKE_CLAIMANT_SOLICITOR: '/manageCaseRole/revokeClaimantSolicitorRole',
} as const;

export const Urls = {
Expand Down Expand Up @@ -473,6 +479,7 @@ export const Applicant = {
CLAIMANT: 'Claimant',
RESPONDENT: 'Respondent',
ADMIN: 'Admin',
CLAIMANT_REP: 'Claimant Representative',
} as const;

export const AllDocumentTypes = {
Expand Down Expand Up @@ -558,3 +565,12 @@ export const FEATURE_FLAGS = {
ECC: 'ecc',
MUL2: 'MUL2',
} as const;

export const LEGAL_REPRESENTATIVE_CHANGE_OPTIONS = {
change: 'change',
remove: 'remove',
} as const;

export const ServiceErrors = {
ERROR_REVOKING_USER_ROLE: 'Error revoking user role: ',
} as const;
Loading