Skip to content

Commit 9ba4645

Browse files
committed
Make root path render skjemavelger
1 parent 133cfcf commit 9ba4645

File tree

10 files changed

+138
-93
lines changed

10 files changed

+138
-93
lines changed

src/App.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ const App = () => (
99
<Router>
1010
<Layout>
1111
<Switch>
12-
{routesConfig.map(route => {
13-
return <Route key={route.path} {...route} />;
12+
{routesConfig.map((route, index) => {
13+
return <Route key={index} {...route} />;
1414
})}
1515
</Switch>
1616
</Layout>

src/__snapshots__/App.test.tsx.snap

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ Array [
7676
>
7777
<a
7878
className="lenkepanel lenkepanel-flex lenkepanel--border"
79-
href="/arbeid"
79+
href="/klage-anke/arbeid"
8080
onClick={[Function]}
8181
>
8282
<div>
@@ -97,7 +97,7 @@ Array [
9797
</a>
9898
<a
9999
className="lenkepanel lenkepanel-flex lenkepanel--border"
100-
href="/familie-og-barn"
100+
href="/klage-anke/familie-og-barn"
101101
onClick={[Function]}
102102
>
103103
<div>

src/components/klage-eller-anke/klage-eller-anke-innsending.tsx

+7-27
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,24 @@ import React from 'react';
33
import BookWithShield from '../../assets/images/icons/BookWithShield';
44
import LetterOpened from '../../assets/images/icons/LetterOpened';
55
import { Margin40Container, MarginContainer, MarginTopContainer } from '../../styled-components/main-styled-components';
6-
import { ensureStringIsTema, Tema, TemaKey } from '../../types/tema';
6+
import { Tema, TemaKey } from '../../types/tema';
77
import { LenkepanelBase } from 'nav-frontend-lenkepanel';
88
import Lenke from 'nav-frontend-lenker';
99
import MobilePhone from '../../assets/images/icons/MobilePhone';
10-
import { RouteComponentProps } from 'react-router-dom';
11-
import { getKategori, hasDigitalForm } from '../../data/klage-eller-anke-temaer';
12-
import NotFoundPage from '../../pages/not-found/not-found-page';
10+
import { hasDigitalForm } from '../../data/klage-eller-anke-temaer';
1311
import KlageLinkPanel from '../link/link';
1412

15-
interface MatchParams {
16-
kategori: string;
17-
tema: string;
18-
}
19-
20-
interface Props extends RouteComponentProps<MatchParams> {}
21-
22-
const KlageEllerAnkeInnsending = (props: Props) => {
23-
const kategori = getKategori(props.match.params.kategori);
24-
if (kategori === null) {
25-
return <NotFoundPage />;
26-
}
27-
28-
const tema = ensureStringIsTema(props.match.params.tema);
29-
if (tema === null) {
30-
return <NotFoundPage />;
31-
}
32-
33-
const isDigital = hasDigitalForm(kategori, tema);
34-
35-
const ytelse = Tema[tema];
13+
const KlageEllerAnkeInnsending = (temaKey: TemaKey) => {
14+
const isDigital = hasDigitalForm(temaKey);
15+
const temaTittel = Tema[temaKey];
3616

3717
return (
3818
<div>
39-
<Sidetittel>{ytelse}</Sidetittel>
19+
<Sidetittel>{temaTittel}</Sidetittel>
4020
<Margin40Container>
4121
<Intro isDigital />
4222
</Margin40Container>
43-
<DigitalContent isDigital={isDigital} tema={tema} />
23+
<DigitalContent isDigital={isDigital} tema={temaKey} />
4424
<Margin40Container>
4525
<LenkepanelBase href="#" border>
4626
<div className="lenkepanel-content-with-image">

src/components/klage-eller-anke/klage-eller-anke-tema.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const KlageEllerAnkeTema = () => (
3737

3838
const getLinks = () =>
3939
KLAGE_ELLER_ANKE_TEMAER.map(tema => (
40-
<KlageLinkPanel key={tema.tittel} href={`${tema.path}`} className="lenkepanel-flex" border>
40+
<KlageLinkPanel key={tema.tittel} href={`/klage-anke/${tema.path}`} className="lenkepanel-flex" border>
4141
<div>
4242
<Undertittel className="lenkepanel__heading">{tema.tittel}</Undertittel>
4343
<Normaltekst>{tema.beskrivelse}</Normaltekst>

src/components/klage-eller-anke/klage-eller-anke-ytelse.tsx

+20-32
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,35 @@
11
import { Sidetittel, Systemtittel, Undertittel } from 'nav-frontend-typografi';
22
import React from 'react';
3-
import { getKategori, KategoriTema } from '../../data/klage-eller-anke-temaer';
3+
import { KategoriTema, KlageAnkeTema } from '../../data/klage-eller-anke-temaer';
44
import {
55
Margin40Container,
66
Margin40TopContainer,
77
PointsFlexListContainer
88
} from '../../styled-components/main-styled-components';
9-
import { RouteComponentProps } from 'react-router-dom';
10-
import NotFoundPage from '../../pages/not-found/not-found-page';
119
import KlageLinkPanel from '../link/link';
1210

13-
interface MatchParams {
14-
kategori: string;
15-
}
16-
17-
interface Props extends RouteComponentProps<MatchParams> {}
18-
19-
const KlageEllerAnkeYtelse = (props: Props) => {
20-
const kategori = getKategori(props.match.params.kategori);
21-
if (kategori === null) {
22-
return <NotFoundPage />;
23-
}
24-
25-
return (
26-
<section>
27-
<div>
28-
<Margin40TopContainer>
29-
<Sidetittel>{kategori.tittel}</Sidetittel>
30-
</Margin40TopContainer>
31-
<Margin40Container>
32-
<Systemtittel>Hvilken tjeneste eller ytelse gjelder det?</Systemtittel>
33-
</Margin40Container>
34-
</div>
35-
<PointsFlexListContainer>
36-
{getLinks(props.match.params.kategori, kategori.underkategorier)}
37-
</PointsFlexListContainer>
38-
</section>
39-
);
40-
};
11+
const KlageEllerAnkeYtelse = (kategori: KlageAnkeTema) => (
12+
<section>
13+
<div>
14+
<Margin40TopContainer>
15+
<Sidetittel>{kategori.tittel}</Sidetittel>
16+
</Margin40TopContainer>
17+
<Margin40Container>
18+
<Systemtittel>Hvilken tjeneste eller ytelse gjelder det?</Systemtittel>
19+
</Margin40Container>
20+
</div>
21+
<PointsFlexListContainer>{getLinks(kategori.path, kategori.underkategorier)}</PointsFlexListContainer>
22+
</section>
23+
);
4124

4225
const getLinks = (kategori: string, underkategorier: KategoriTema[]) =>
4326
underkategorier.map(tema => (
44-
<KlageLinkPanel key={tema.tittel} href={`${kategori}/${tema.tema}`} className="lenkepanel-flex" border>
27+
<KlageLinkPanel
28+
key={tema.tittel}
29+
href={`/klage-anke/${kategori}/${tema.tema}`}
30+
className="lenkepanel-flex"
31+
border
32+
>
4533
<div>
4634
<Undertittel className="lenkepanel__heading">{tema.tittel}</Undertittel>
4735
</div>

src/data/klage-eller-anke-temaer.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export interface KategoriTema {
88
bareAnke: boolean;
99
}
1010

11-
interface KlageAnkeTema {
11+
export interface KlageAnkeTema {
1212
tittel: string;
1313
path: string;
1414
beskrivelse: string;
@@ -18,6 +18,8 @@ interface KlageAnkeTema {
1818
export const KLAGE_ELLER_ANKE_TEMAER: KlageAnkeTema[] = JSON.parse(JSON.stringify(data.temaer));
1919

2020
export const getKategori = (kategori: string) => KLAGE_ELLER_ANKE_TEMAER.find(({ path }) => path === kategori) ?? null;
21+
export const getKategoriFromTema = (temaKey: TemaKey) =>
22+
KLAGE_ELLER_ANKE_TEMAER.find(({ underkategorier }) => underkategorier.some(({ tema }) => tema === temaKey)) ?? null;
2123

22-
export const hasDigitalForm = (kategori: KlageAnkeTema, tema: TemaKey) =>
23-
kategori.underkategorier.some(t => t.digital && t.tema === tema);
24+
export const hasDigitalForm = (tema: TemaKey) =>
25+
KLAGE_ELLER_ANKE_TEMAER.some(({ underkategorier }) => underkategorier.some(t => t.digital && t.tema === tema));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { ensureStringIsTema } from '../../types/tema';
2+
import { getRedirectPath, getTemaKey } from './root-only-tema';
3+
4+
describe('Tema in query should be parsed', () => {
5+
it('Should parse a valid tema key from query', () => {
6+
const search = '?tema=FOR';
7+
const temaKey = getTemaKey(search);
8+
expect(temaKey).toBe('FOR');
9+
});
10+
11+
it('Should return null for invalid tema key in query', () => {
12+
const invalidSearch = '?tema=INVALID';
13+
const temaKey = getTemaKey(invalidSearch);
14+
expect(temaKey).toBeNull();
15+
});
16+
17+
it('Should return null for invalid query', () => {
18+
const invalidSearch = 'Not a query';
19+
const temaKey = getTemaKey(invalidSearch);
20+
expect(temaKey).toBeNull();
21+
});
22+
});
23+
24+
describe('Generate redirect path from tema key', () => {
25+
it('Should generate a valid path from supported tema key', () => {
26+
const temaKey = ensureStringIsTema('FOR');
27+
const redirectPath = getRedirectPath(temaKey);
28+
expect(redirectPath).toBe('/klage-anke/FOR');
29+
});
30+
31+
it('Should generate valid path for an unsupported tema key', () => {
32+
const temaKey = ensureStringIsTema('KOM');
33+
const redirectPath = getRedirectPath(temaKey);
34+
expect(redirectPath).toBe('/klage-anke/KOM');
35+
});
36+
37+
it('Should generate root path for an invalid tema key', () => {
38+
const temaKey = ensureStringIsTema('INVALID');
39+
const redirectPath = getRedirectPath(temaKey);
40+
expect(redirectPath).toBe('/klage-anke');
41+
});
42+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React from 'react';
2+
import { Redirect, useLocation } from 'react-router';
3+
import queryString from 'query-string';
4+
import { ensureStringIsTema, TemaKey } from '../../types/tema';
5+
6+
const RootOnlyTema = () => {
7+
const location = useLocation();
8+
const temaKey = getTemaKey(location.search);
9+
const redirectPath = getRedirectPath(temaKey);
10+
return <Redirect to={redirectPath} />;
11+
};
12+
13+
export function getRedirectPath(temaKey: TemaKey | null) {
14+
if (temaKey === null) {
15+
return '/klage-anke';
16+
}
17+
18+
return `/klage-anke/${temaKey}`;
19+
}
20+
21+
export function getTemaKey(search: string) {
22+
const { tema } = queryString.parse(search);
23+
if (typeof tema === 'string' && tema.length !== 0) {
24+
return ensureStringIsTema(tema);
25+
}
26+
return null;
27+
}
28+
29+
export default RootOnlyTema;

src/types/tema.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export enum Tema {
6666

6767
export type TemaKey = keyof typeof Tema;
6868

69-
const TEMA_KEYS = Object.keys(Tema);
69+
export const TEMA_KEYS = Object.keys(Tema) as TemaKey[];
7070

7171
export const getYtelseByTema = (temaKey: TemaKey | string | null): Tema | null => {
7272
const ensuredTemaKey = ensureStringIsTema(temaKey);
@@ -80,5 +80,5 @@ export const ensureStringIsTema = (potentialTemaKey: string | null): TemaKey | n
8080
if (potentialTemaKey === null) {
8181
return null;
8282
}
83-
return TEMA_KEYS.includes(potentialTemaKey) ? (potentialTemaKey as TemaKey) : null;
83+
return TEMA_KEYS.includes(potentialTemaKey as TemaKey) ? (potentialTemaKey as TemaKey) : null;
8484
};

src/utils/routes.config.tsx

+28-24
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,19 @@ import OppsummeringSkjemaPage from '../pages/oppsummering-skjema-page/oppsummeri
44
import DummyRedirectPage from '../pages/dummy-redirect/dummy-redirect-page';
55
import KvitteringPage from '../pages/kvittering/kvittering-page';
66
import NotFoundPage from '../pages/not-found/not-found-page';
7-
import { JSXElementConstructor } from 'react';
87
import KlageEllerAnkeYtelse from '../components/klage-eller-anke/klage-eller-anke-ytelse';
98
import KlageEllerAnkeTema from '../components/klage-eller-anke/klage-eller-anke-tema';
109
import KlageEllerAnkeInnsending from '../components/klage-eller-anke/klage-eller-anke-innsending';
10+
import RootOnlyTema from '../pages/root-only-tema/root-only-tema';
11+
import { TEMA_KEYS } from '../types/tema';
12+
import { RouteProps } from 'react-router';
13+
import { KLAGE_ELLER_ANKE_TEMAER } from '../data/klage-eller-anke-temaer';
1114

12-
export type RouteType = {
15+
export interface FormStep extends RouteProps {
1316
step?: number;
14-
path: string;
15-
component: JSXElementConstructor<any>;
16-
redirect?: string;
17-
exact: boolean;
18-
};
19-
20-
export type FormStep = {
21-
step?: number;
22-
path: string;
23-
component: JSXElementConstructor<any>;
2417
label: string;
2518
redirect?: string;
26-
exact: boolean;
27-
};
19+
}
2820

2921
export const formSteps: FormStep[] = [
3022
{
@@ -43,12 +35,7 @@ export const formSteps: FormStep[] = [
4335
}
4436
];
4537

46-
export const routesPages: RouteType[] = [
47-
{
48-
path: `/`,
49-
component: KlageEllerAnkeTema,
50-
exact: true
51-
},
38+
export const routesPages: RouteProps[] = [
5239
{
5340
path: `/redirect`,
5441
component: DummyRedirectPage,
@@ -70,13 +57,30 @@ export const routesPages: RouteType[] = [
7057
exact: true
7158
},
7259
{
73-
path: `/:kategori`,
74-
component: KlageEllerAnkeYtelse,
60+
path: `/klage-anke`,
61+
component: KlageEllerAnkeTema,
7562
exact: true
7663
},
64+
...TEMA_KEYS.map<RouteProps>(temaKey => ({
65+
path: `/klage-anke/${temaKey}`,
66+
render: () => KlageEllerAnkeInnsending(temaKey),
67+
exact: true
68+
})),
69+
...KLAGE_ELLER_ANKE_TEMAER.map<RouteProps>(kategori => ({
70+
path: `/klage-anke/${kategori.path}`,
71+
render: () => KlageEllerAnkeYtelse(kategori),
72+
exact: true
73+
})),
74+
...KLAGE_ELLER_ANKE_TEMAER.flatMap<RouteProps>(kategori =>
75+
kategori.underkategorier.map<RouteProps>(tema => ({
76+
path: `/klage-anke/${kategori.path}/${tema.tema}`,
77+
render: () => KlageEllerAnkeInnsending(tema.tema),
78+
exact: true
79+
}))
80+
),
7781
{
78-
path: `/:kategori/:tema`,
79-
component: KlageEllerAnkeInnsending,
82+
path: `/`,
83+
component: RootOnlyTema,
8084
exact: true
8185
},
8286
{

0 commit comments

Comments
 (0)