Skip to content

Commit 2b08fcd

Browse files
committed
Add changerole page
1 parent c0e4918 commit 2b08fcd

File tree

4 files changed

+303
-15
lines changed

4 files changed

+303
-15
lines changed
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
'use client'
2+
import React, {useState, useEffect, useContext, useCallback} from "react"
3+
import {useRouter} from 'next/navigation'
4+
import {Container, Col, Row, Details, Table, ErrorSummary, Button, InsetText} from "nhsuk-react-components"
5+
6+
import {AuthContext} from "@/context/AuthProvider"
7+
8+
import EpsCard, {EpsCardProps} from "@/components/EpsCard"
9+
import EpsSpinner from "@/components/EpsSpinner";
10+
11+
import {CHANGE_YOUR_ROLE_PAGE_TEXT} from "@/constants/ui-strings/ChangeRolePageStrings"
12+
13+
import { RoleDetails, TrackerUserInfo } from "@/types/TrackerUserInfoTypes"
14+
15+
// Extends the EpsCardProps to include a unique identifier
16+
export type RolesWithAccessProps = EpsCardProps & {
17+
uuid: string
18+
}
19+
20+
export type RolesWithoutAccessProps = {
21+
uuid: string
22+
orgName: string
23+
odsCode: string
24+
roleName: string
25+
}
26+
27+
const trackerUserInfoEndpoint = "/api/tracker-user-info"
28+
29+
const {
30+
title,
31+
caption,
32+
insetText,
33+
confirmButton,
34+
alternativeMessage,
35+
organisation,
36+
role,
37+
roles_without_access_table_title,
38+
noOrgName,
39+
rolesWithoutAccessHeader,
40+
noODSCode,
41+
noRoleName,
42+
noAddress,
43+
errorDuringRoleSelection
44+
} = CHANGE_YOUR_ROLE_PAGE_TEXT;
45+
46+
export default function SelectYourRolePage() {
47+
const [loading, setLoading] = useState<boolean>(true)
48+
const [error, setError] = useState<string | null>(null)
49+
const [redirecting, setRedirecting] = useState<boolean>(false)
50+
const [rolesWithAccess, setRolesWithAccess] = useState<RolesWithAccessProps[]>([])
51+
const [rolesWithoutAccess, setRolesWithoutAccess] = useState<RolesWithoutAccessProps[]>([])
52+
53+
const router = useRouter()
54+
const auth = useContext(AuthContext)
55+
56+
const fetchTrackerUserInfo = useCallback(async () => {
57+
setLoading(true)
58+
setError(null)
59+
setRolesWithAccess([])
60+
setRolesWithoutAccess([])
61+
62+
if (!auth?.isSignedIn || !auth) {
63+
setLoading(false)
64+
setError(null)
65+
return;
66+
}
67+
68+
try {
69+
const response = await fetch(trackerUserInfoEndpoint, {
70+
headers: {
71+
Authorization: `Bearer ${auth?.idToken}`,
72+
'NHSD-Session-URID': '555254242106'
73+
}
74+
})
75+
76+
if (response.status !== 200) {
77+
throw new Error(`Server did not return CPT user info, response ${response.status}`)
78+
}
79+
80+
const data = await response.json()
81+
82+
if (!data.userInfo) {
83+
throw new Error("Server response did not contain data")
84+
}
85+
86+
const userInfo: TrackerUserInfo = data.userInfo
87+
88+
const rolesWithAccess = userInfo.roles_with_access
89+
const rolesWithoutAccess = userInfo.roles_without_access
90+
// Unused for now
91+
// const currentlySelectedRole = userInfo.currently_selected_role ? {
92+
// ...userInfo.currently_selected_role,
93+
// uuid: `selected_role_0`
94+
// } : undefined
95+
96+
// Populate the EPS card props
97+
setRolesWithAccess(
98+
rolesWithAccess.map((role: RoleDetails, index: number) => ({
99+
uuid: `{role_with_access_${index}}`,
100+
orgName: role.org_name ? role.org_name : noOrgName,
101+
odsCode: role.org_code ? role.org_code : noODSCode,
102+
siteAddress: role.site_address ? role.site_address : noAddress,
103+
roleName: role.role_name ? role.role_name : noRoleName,
104+
link: "yourselectedrole"
105+
}))
106+
)
107+
108+
setRolesWithoutAccess(
109+
rolesWithoutAccess.map((role: RoleDetails, index: number) => ({
110+
uuid: `{role_without_access_${index}}`,
111+
roleName: role.role_name ? role.role_name : noRoleName,
112+
orgName: role.org_name ? role.org_name : noOrgName,
113+
odsCode: role.org_code ? role.org_code : noODSCode
114+
}))
115+
)
116+
117+
// Redirect if conditions are met
118+
if (rolesWithAccess.length === 1 && rolesWithoutAccess.length === 0) {
119+
setRedirecting(true)
120+
router.push("/searchforaprescription")
121+
return
122+
}
123+
124+
} catch (err) {
125+
setError("Failed to fetch CPT user info")
126+
console.error("error fetching tracker user info:", err)
127+
} finally {
128+
setLoading(false)
129+
}
130+
}, [auth, router])
131+
132+
useEffect(() => {
133+
if (auth?.isSignedIn === undefined) {
134+
return
135+
}
136+
137+
if (auth?.isSignedIn) {
138+
fetchTrackerUserInfo()
139+
}
140+
}, [auth?.isSignedIn, fetchTrackerUserInfo])
141+
142+
useEffect(() => {
143+
console.log("Auth error updated:", auth?.error)
144+
// Have to do this to make `<string | null | undefined>` work with `<string | null>`
145+
setError(auth?.error ?? null)
146+
if (auth?.error) {
147+
setLoading(false)
148+
}
149+
}, [auth?.error])
150+
151+
// Skip rendering if redirecting
152+
if (redirecting) {
153+
return null
154+
}
155+
156+
// If the data is being fetched, replace the content with a spinner
157+
if (loading) {
158+
return (
159+
<main id="main-content" className="nhsuk-main-wrapper">
160+
<Container>
161+
<Row>
162+
<Col width="full">
163+
<EpsSpinner />
164+
</Col>
165+
</Row>
166+
</Container>
167+
</main>
168+
)
169+
}
170+
171+
// If the process encounters an error, replace the content with an error summary
172+
if (error) {
173+
return (
174+
<main id="main-content" className="nhsuk-main-wrapper">
175+
<Container>
176+
<Row>
177+
<ErrorSummary>
178+
<ErrorSummary.Title>
179+
{errorDuringRoleSelection}
180+
</ErrorSummary.Title>
181+
<ErrorSummary.List>
182+
<ErrorSummary.Item href="PLACEHOLDER/contact/us">
183+
{error}
184+
</ErrorSummary.Item>
185+
</ErrorSummary.List>
186+
</ErrorSummary>
187+
</Row>
188+
</Container>
189+
</main>
190+
)
191+
}
192+
193+
return (
194+
<main id="main-content" className="nhsuk-main-wrapper">
195+
<Container role="contentinfo">
196+
{/* Title Section */}
197+
<Row>
198+
<Col width="two-thirds">
199+
<h1 className='nhsuk-heading-xl'>
200+
<span role="text" data-testid="eps_header_selectYourRole">
201+
<span className="nhsuk-title">{title}</span>
202+
<span className="nhsuk-caption-l nhsuk-caption--bottom">
203+
<span className="nhsuk-u-visually-hidden"> - </span>
204+
{caption}
205+
</span>
206+
</span>
207+
</h1>
208+
{/* Inset Text Section */}
209+
<section aria-label="Login Information">
210+
<InsetText>
211+
<span className="nhsuk-u-visually-hidden">{insetText.visuallyHidden}</span>
212+
<p>{insetText.message}</p>
213+
</InsetText>
214+
{/* Confirm Button */}
215+
<Button href={confirmButton.link}>{confirmButton.text}</Button>
216+
<p>{alternativeMessage}</p>
217+
</section>
218+
</Col>
219+
220+
{/* Roles with access Section */}
221+
<Col width="two-thirds">
222+
<div className="section">
223+
{rolesWithAccess.map((role: RolesWithAccessProps) => (
224+
<EpsCard {...role} key={role.uuid} />
225+
))}
226+
</div>
227+
</Col>
228+
229+
{/* Roles without access Section */}
230+
<Col width="two-thirds">
231+
<h2>{rolesWithoutAccessHeader}</h2>
232+
<Details expander>
233+
<Details.Summary>
234+
{roles_without_access_table_title}
235+
</Details.Summary>
236+
<Details.Text>
237+
<Table>
238+
<Table.Head>
239+
<Table.Row>
240+
<Table.Cell>{organisation}</Table.Cell>
241+
<Table.Cell>{role}</Table.Cell>
242+
</Table.Row>
243+
</Table.Head>
244+
<Table.Body>
245+
{rolesWithoutAccess.map((role: RolesWithoutAccessProps) => (
246+
<Table.Row key={role.uuid}>
247+
<Table.Cell>
248+
{role.orgName} (ODS: {role.odsCode})
249+
</Table.Cell>
250+
<Table.Cell>
251+
{role.roleName}
252+
</Table.Cell>
253+
</Table.Row>
254+
))}
255+
</Table.Body>
256+
</Table>
257+
</Details.Text>
258+
</Details>
259+
</Col>
260+
</Row>
261+
</Container>
262+
</main>
263+
)
264+
}

packages/cpt-ui/app/selectyourrole/page.tsx

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,7 @@ import EpsSpinner from "@/components/EpsSpinner";
1010

1111
import {SELECT_YOUR_ROLE_PAGE_TEXT} from "@/constants/ui-strings/CardStrings"
1212

13-
export type RoleDetails = {
14-
role_name?: string
15-
role_id?: string
16-
org_code?: string
17-
org_name?: string
18-
site_name?: string
19-
site_address?: string
20-
uuid?: string
21-
}
22-
23-
export type TrackerUserInfo = {
24-
roles_with_access: Array<RoleDetails>
25-
roles_without_access: Array<RoleDetails>
26-
currently_selected_role?: RoleDetails
27-
}
13+
import { RoleDetails, TrackerUserInfo } from "@/types/TrackerUserInfoTypes"
2814

2915
// Extends the EpsCardProps to include a unique identifier
3016
export type RolesWithAccessProps = EpsCardProps & {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export const CHANGE_YOUR_ROLE_PAGE_TEXT = {
2+
title: "Change your role",
3+
caption: "Select the role you wish to use to access the service.",
4+
insetText: {
5+
visuallyHidden: "Information: ",
6+
message:
7+
"You are currently logged in at GREENE'S PHARMACY (ODS: FG419) with Health Professional Access Role."
8+
},
9+
confirmButton: {
10+
text: "Continue to find a prescription",
11+
link: "tracker-presc-no"
12+
},
13+
alternativeMessage: "Alternatively, you can choose a new role below.",
14+
organisation: "Organisation",
15+
role: "Role",
16+
roles_without_access_table_title: "View your roles without access to the clinical prescription tracking service.",
17+
noOrgName: "NO ORG NAME",
18+
rolesWithoutAccessHeader: "Your roles without access",
19+
noODSCode: "No ODS code",
20+
noRoleName: "No role name",
21+
noAddress: "Address not found",
22+
errorDuringRoleSelection: "Error during role selection"
23+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export type RoleDetails = {
2+
role_name?: string
3+
role_id?: string
4+
org_code?: string
5+
org_name?: string
6+
site_name?: string
7+
site_address?: string
8+
uuid?: string
9+
}
10+
11+
export type TrackerUserInfo = {
12+
roles_with_access: Array<RoleDetails>
13+
roles_without_access: Array<RoleDetails>
14+
currently_selected_role?: RoleDetails
15+
}

0 commit comments

Comments
 (0)