Skip to content

Commit c96b243

Browse files
committed
CCM-11148 Update features provider
1 parent 150959a commit c96b243

File tree

4 files changed

+51
-37
lines changed

4 files changed

+51
-37
lines changed
Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
'use server';
22

3-
import { NextResponse, NextRequest } from 'next/server';
3+
import { NextRequest, NextResponse } from 'next/server';
44
import { getSessionServer } from '@utils/amplify-utils';
5-
import {
6-
clientConfigurationApiClient,
7-
ClientFeatures,
8-
} from 'nhs-notify-backend-client';
9-
import { initialFeatureFlags } from '@providers/features-provider';
5+
import { fetchClient } from '@utils/server-features';
6+
import { FEATURES, initialFeatureFlags } from '@utils/features';
107

118
export async function GET(request: NextRequest) {
129
const internalHeader = request.headers.get('x-internal-request');
@@ -16,22 +13,20 @@ export async function GET(request: NextRequest) {
1613
}
1714

1815
const session = await getSessionServer();
19-
const token = session?.accessToken;
2016

21-
if (!token) {
22-
return NextResponse.json(initialFeatureFlags, { status: 401 });
17+
if (!session?.accessToken) {
18+
return NextResponse.json(initialFeatureFlags);
2319
}
2420

25-
const result = await clientConfigurationApiClient.fetch(token);
21+
const result = await fetchClient(session.accessToken);
2622

27-
if (result.error) {
28-
return NextResponse.json(initialFeatureFlags, { status: 500 });
23+
if (result.error || !result.data?.features) {
24+
return NextResponse.json(initialFeatureFlags);
2925
}
3026

31-
const features: ClientFeatures = {
32-
routing: result.data?.features.routing ?? false,
33-
proofing: result.data?.features.proofing ?? false,
34-
};
27+
const features = Object.fromEntries(
28+
FEATURES.map((key) => [key, result.data?.features?.[key] ?? false])
29+
);
3530

3631
return NextResponse.json(features);
3732
}

frontend/src/components/molecules/Header/HeaderNavigation.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import { useAuthStatus } from '@hooks/use-auth-status';
44
import type { AuthStatus } from '@aws-amplify/ui';
55
import content from '@content/content';
66
import Link from 'next/link';
7-
import { FeatureFlags, useFeatureFlags } from '@providers/features-provider';
7+
import { useFeatureFlags } from '@providers/features-provider';
8+
import { ClientFeatures } from 'nhs-notify-backend-client';
89

910
const headerContent = content.components.header;
1011

@@ -14,9 +15,9 @@ export function HeaderNavigation({
1415
initialAuthStatus: AuthStatus;
1516
}) {
1617
const authStatus = useAuthStatus(initialAuthStatus);
17-
const featureFlags = useFeatureFlags();
18+
const { featureFlags, loaded: featureFlagsLoaded } = useFeatureFlags();
1819

19-
if (authStatus !== 'authenticated') return null;
20+
if (authStatus !== 'authenticated' || !featureFlagsLoaded) return null;
2021

2122
return (
2223
<nav
@@ -29,7 +30,8 @@ export function HeaderNavigation({
2930
{headerContent.navigationMenu.links
3031
.filter(
3132
({ feature }) =>
32-
!feature || featureFlags[feature as keyof FeatureFlags] === true
33+
!feature ||
34+
featureFlags[feature as keyof ClientFeatures] === true
3335
)
3436
.map(({ text, href }, index) => (
3537
<li

frontend/src/components/providers/features-provider.tsx

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
'use client';
22

3-
import { ClientFeatures } from 'nhs-notify-backend-client';
43
import { createContext, useContext, useEffect, useState } from 'react';
54
import { useAuthStatus } from '@hooks/use-auth-status';
5+
import { initialFeatureFlags } from '@utils/features';
6+
import { ClientFeatures } from 'nhs-notify-backend-client';
67

7-
export type FeatureFlags = ClientFeatures;
8-
9-
export const FEATURE_KEYS: (keyof ClientFeatures)[] = ['proofing', 'routing'];
10-
11-
export const initialFeatureFlags: FeatureFlags = Object.fromEntries(
12-
FEATURE_KEYS.map((key) => [key, false])
13-
) as FeatureFlags;
14-
15-
const FeatureFlagContext = createContext<FeatureFlags>(initialFeatureFlags);
8+
const FeatureFlagContext = createContext<{
9+
featureFlags: ClientFeatures;
10+
loaded: boolean;
11+
}>({
12+
featureFlags: initialFeatureFlags,
13+
loaded: false,
14+
});
1615

1716
export const useFeatureFlags = () => useContext(FeatureFlagContext);
1817

@@ -21,12 +20,19 @@ export function FeatureFlagProvider({
2120
}: {
2221
children: React.ReactNode;
2322
}) {
24-
const [flags, setFlags] = useState<FeatureFlags>(initialFeatureFlags);
23+
const [featureFlags, setFeatureFlags] =
24+
useState<ClientFeatures>(initialFeatureFlags);
25+
26+
const [loaded, setLoaded] = useState<boolean>(false);
27+
2528
const authStatus = useAuthStatus();
2629

2730
useEffect(() => {
31+
if (authStatus === 'unauthenticated') {
32+
setFeatureFlags(initialFeatureFlags);
33+
return;
34+
}
2835
if (authStatus !== 'authenticated') {
29-
setFlags(initialFeatureFlags);
3036
return;
3137
}
3238

@@ -37,21 +43,25 @@ export function FeatureFlagProvider({
3743
'x-internal-request': 'true',
3844
},
3945
});
40-
if (!response.ok) setFlags(initialFeatureFlags);
4146

42-
const data: FeatureFlags = await response.json();
47+
if (!response.ok) {
48+
setFeatureFlags(initialFeatureFlags);
49+
}
4350

44-
setFlags(data);
51+
const data: ClientFeatures = await response.json();
52+
setFeatureFlags(data);
4553
} catch {
46-
setFlags(initialFeatureFlags);
54+
setFeatureFlags(initialFeatureFlags);
55+
} finally {
56+
setLoaded(true);
4757
}
4858
};
4959

5060
fetchFeatureFlags();
5161
}, [authStatus]);
5262

5363
return (
54-
<FeatureFlagContext.Provider value={flags}>
64+
<FeatureFlagContext.Provider value={{ featureFlags, loaded }}>
5565
{children}
5666
</FeatureFlagContext.Provider>
5767
);

frontend/src/utils/features.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { ClientFeatures } from 'nhs-notify-backend-client';
2+
3+
export const FEATURES: (keyof ClientFeatures)[] = ['proofing', 'routing'];
4+
5+
export const initialFeatureFlags: ClientFeatures = Object.fromEntries(
6+
FEATURES.map((key) => [key, false])
7+
) as ClientFeatures;

0 commit comments

Comments
 (0)