Skip to content

Commit

Permalink
Merge branch 'master' into IS-2027-2-Add-age-filter
Browse files Browse the repository at this point in the history
  • Loading branch information
vetlesolgaard authored Mar 11, 2024
2 parents 0a723f0 + deef0f2 commit d76e49e
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import React, { ReactElement, useState } from 'react';
import Ekspanderbartpanel from 'nav-frontend-ekspanderbartpanel';
import BirthDateFilter from './filters/BirthDateFilter';
import CompanyFilter from './filters/CompanyFilter';
import BirthDateFilter from '../filters/BirthDateFilter';
import CompanyFilter from '../filters/CompanyFilter';
import { PersonregisterState } from '@/api/types/personregisterTypes';
import { mapPersonregisterToCompanyList } from '@/utils/personDataUtil';
import { useFilters } from '@/context/filters/FilterContext';
import { ActionType } from '@/context/filters/filterContextActions';
import { FristFilter } from '@/components/filters/FristFilter';
import { FristFilterOption } from '@/utils/hendelseFilteringUtils';
import {
AgeFilterOption,
FristFilterOption,
} from '@/utils/hendelseFilteringUtils';
import { AgeFilter } from '@/components/filters/AgeFilter';

const texts = {
panelTitle: 'Filter',
Expand Down Expand Up @@ -50,6 +54,13 @@ export const PersonFilter = ({
});
};

const onAgeFilterChange = (ageFilters: AgeFilterOption[]) => {
dispatchFilterAction({
type: ActionType.SetSelectedAgeFilter,
selectedAgeFilters: ageFilters,
});
};

return (
<Ekspanderbartpanel
apen={panelOpen}
Expand All @@ -67,6 +78,10 @@ export const PersonFilter = ({
onSelect={onBirthDateChange}
selectedDates={filterState.selectedBirthDates}
/>
<AgeFilter
onChange={onAgeFilterChange}
selectedAgeFilters={filterState.selectedAgeFilters}
/>
<FristFilter
onChange={onFristFilterChange}
selectedFristFilters={filterState.selectedFristFilters}
Expand Down
2 changes: 2 additions & 0 deletions src/components/Sokeresultat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useTildelVeileder } from '@/data/veiledereQueryHooks';
import { PersonregisterState } from '@/api/types/personregisterTypes';
import {
Filterable,
filterOnAge,
filterOnBirthDates,
filterOnCompany,
filterOnFodselsnummerOrName,
Expand Down Expand Up @@ -65,6 +66,7 @@ const Sokeresultat = ({ allEvents }: SokeresultatProps) => {
.applyFilter((v) => filterOnCompany(v, filterState.selectedCompanies))
.applyFilter((v) => filterOnBirthDates(v, filterState.selectedBirthDates))
.applyFilter((v) => filterOnFrist(v, filterState.selectedFristFilters))
.applyFilter((v) => filterOnAge(v, filterState.selectedAgeFilters))
.applyFilter((v) => filterOnPersonregister(v, selectedHendelsetypeFilter))
.applyFilter((v) =>
filterOnFodselsnummerOrName(v, filterState.tekstFilter)
Expand Down
51 changes: 51 additions & 0 deletions src/components/filters/AgeFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Checkbox, CheckboxGroup } from '@navikt/ds-react';
import React from 'react';
import { AgeFilterOption } from '@/utils/hendelseFilteringUtils';
import * as Amplitude from '@/utils/amplitude';
import { EventType } from '@/utils/amplitude';

const text = {
legend: 'Alder',
option: {
underThirty: 't.o.m. 30 år',
overThirty: 'Over 30 år',
},
};

interface Props {
onChange(value: AgeFilterOption[]): void;

selectedAgeFilters: AgeFilterOption[];
}

function logOptionSelectedEvent(option: AgeFilterOption[]) {
Amplitude.logEvent({
type: EventType.OptionSelected,
data: {
url: window.location.href,
tekst: 'Aldersfilter endret',
option: option.toString(),
},
});
}

export function AgeFilter({ onChange, selectedAgeFilters }: Props) {
return (
<CheckboxGroup
legend={text.legend}
onChange={(val: AgeFilterOption[]) => {
onChange(val);
logOptionSelectedEvent(val);
}}
value={selectedAgeFilters}
size="small"
>
<Checkbox value={AgeFilterOption.ThirtyAndUnder}>
{text.option.underThirty}
</Checkbox>
<Checkbox value={AgeFilterOption.OverThirty}>
{text.option.overThirty}
</Checkbox>
</CheckboxGroup>
);
}
2 changes: 1 addition & 1 deletion src/containers/Oversikt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
PersonregisterState,
} from '@/api/types/personregisterTypes';
import { toPersonData } from '@/utils/toPersondata';
import { PersonFilter } from '@/components/PersonFilter';
import { PersonFilter } from '@/components/Filter/PersonFilter';
import Sokeresultat from '@/components/Sokeresultat';
import styled from 'styled-components';
import { TekstFilter } from '@/components/filters/TekstFilter';
Expand Down
12 changes: 11 additions & 1 deletion src/context/filters/filterContextActions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { HendelseTypeFilters } from '@/context/filters/filterContextState';
import { FristFilterOption } from '@/utils/hendelseFilteringUtils';
import {
AgeFilterOption,
FristFilterOption,
} from '@/utils/hendelseFilteringUtils';

export enum ActionType {
SetTekstFilter,
Expand All @@ -8,6 +11,7 @@ export enum ActionType {
SetSelectedCompanies,
SetSelectedBirthDates,
SetSelectedFristFilter,
SetSelectedAgeFilter,
SetSelectedHendelseType,
ResetFilters,
}
Expand Down Expand Up @@ -37,6 +41,11 @@ export interface SetSelectedFristFilter {
selectedFristFilters: FristFilterOption[];
}

export interface SetSelectedAgeFilter {
type: ActionType.SetSelectedAgeFilter;
selectedAgeFilters: AgeFilterOption[];
}

export interface SetSelectedBirthDates {
type: ActionType.SetSelectedBirthDates;
selectedBirthDates: string[];
Expand All @@ -57,6 +66,7 @@ export type FilterActions =
| SetSelectedOptions
| SetSelectedCompanies
| SetSelectedFristFilter
| SetSelectedAgeFilter
| SetSelectedBirthDates
| SetSelectedHendelseType
| ResetFilters;
6 changes: 6 additions & 0 deletions src/context/filters/filterContextReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ export const filterReducer = (
selectedFristFilters: action.selectedFristFilters,
};
}
case ActionType.SetSelectedAgeFilter: {
return {
...state,
selectedAgeFilters: action.selectedAgeFilters,
};
}
case ActionType.SetSelectedVeilederIdents: {
return {
...state,
Expand Down
7 changes: 6 additions & 1 deletion src/context/filters/filterContextState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { FristFilterOption } from '@/utils/hendelseFilteringUtils';
import {
AgeFilterOption,
FristFilterOption,
} from '@/utils/hendelseFilteringUtils';

export interface HendelseTypeFilters {
arbeidsgiverOnskerMote: boolean;
Expand All @@ -20,6 +23,7 @@ export interface FilterState {
selectedCompanies: string[];
selectedBirthDates: string[];
selectedFristFilters: FristFilterOption[];
selectedAgeFilters: AgeFilterOption[];
selectedHendelseType: HendelseTypeFilters;
}

Expand All @@ -30,6 +34,7 @@ export const filterInitialState: FilterState = {
selectedCompanies: [],
selectedBirthDates: [],
selectedFristFilters: [],
selectedAgeFilters: [],
selectedHendelseType: {
arbeidsgiverOnskerMote: false,
onskerMote: false,
Expand Down
47 changes: 47 additions & 0 deletions src/utils/hendelseFilteringUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,53 @@ function isInFristFilter(
});
}

export enum AgeFilterOption {
ThirtyAndUnder = 'ThirtyAndUnder',
OverThirty = 'OverThirty',
}

export const filterOnAge = (
personregister: PersonregisterState,
selectedAgeFilters: AgeFilterOption[]
): PersonregisterState => {
const isNoFilter = selectedAgeFilters.length === 0;
if (isNoFilter) {
return personregister;
}
const currentYear = new Date().getFullYear();
const filtered = Object.entries(personregister).filter(([fnr]) => {
const age = ageFromFnr(fnr, currentYear);
return isAgeInFilters(age, selectedAgeFilters);
});
return Object.fromEntries(filtered);
};

function ageFromFnr(fnr: string, currentYear: number): number {
const currentYearLastTwoDigits = parseInt(currentYear.toString().slice(2));
const yearBornLastTwoDigits = parseInt(fnr.slice(4, 6));
let age;
if (currentYearLastTwoDigits > yearBornLastTwoDigits) {
age = currentYearLastTwoDigits - yearBornLastTwoDigits;
} else {
age = 100 - yearBornLastTwoDigits + currentYearLastTwoDigits;
}
return age;
}

function isAgeInFilters(
age: number,
selectedAgeFilters: AgeFilterOption[]
): boolean {
return selectedAgeFilters.some((ageFilter) => {
switch (ageFilter) {
case AgeFilterOption.ThirtyAndUnder:
return age <= 30;
case AgeFilterOption.OverThirty:
return age > 30;
}
});
}

type HendelseTypeFilterKey = keyof HendelseTypeFilters;

const matchesFilter = (
Expand Down
1 change: 1 addition & 0 deletions test/components/Sokeresultat.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ describe('Sokeresultat', () => {
selectedCompanies: [],
selectedBirthDates: [],
selectedFristFilters: [],
selectedAgeFilters: [],
selectedHendelseType: {
arbeidsgiverOnskerMote: false,
onskerMote: false,
Expand Down
65 changes: 65 additions & 0 deletions test/components/filteringUtils.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { AgeFilterOption, filterOnAge } from '@/utils/hendelseFilteringUtils';
import { PersonregisterState } from '@/api/types/personregisterTypes';
import { createPersonDataWithName } from '../utils/hendelseFilteringUtilsTest';
import { expect } from 'chai';

describe('Filters unit tests', () => {
const currentYear = new Date().getFullYear();
const yearBornTwentyFive = (currentYear - 25).toString().slice(2);
const yearBornThirty = (currentYear - 30).toString().slice(2);
const yearBornThirtyFive = (currentYear - 35).toString().slice(2);
const yearBornFourty = (currentYear - 40).toString().slice(2);
const yearBornFourtyFive = (currentYear - 45).toString().slice(2);

const twentyFiveFnr = `0101${yearBornTwentyFive}99999`;
const thirtyFnr = `0101${yearBornThirty}99999`;
const thirtyFiveFnr = `0101${yearBornThirtyFive}99999`;
const fourtyFnr = `0101${yearBornFourty}99999`;
const fourtyFiveFnr = `0101${yearBornFourtyFive}99999`;

console.log(
`FNR: ${twentyFiveFnr}, ${thirtyFnr}, ${thirtyFiveFnr}, ${fourtyFnr}, ${fourtyFiveFnr}`
);

const personregister: PersonregisterState = {
[twentyFiveFnr]: createPersonDataWithName('Bjarne Bjarnson'),
[thirtyFnr]: createPersonDataWithName('Vetle Vetlesen'),
[thirtyFiveFnr]: createPersonDataWithName('Geir Geirsson'),
[fourtyFnr]: createPersonDataWithName('Eirik Eiriksson'),
[fourtyFiveFnr]: createPersonDataWithName('John Johnson'),
};

it('Filters out all people over 30 years old', () => {
const thirtyAndUnderPersons = filterOnAge(personregister, [
AgeFilterOption.ThirtyAndUnder,
]);
expect(Object.values(thirtyAndUnderPersons).length).to.deep.equal(2);
expect(Object.values(thirtyAndUnderPersons)[0]?.navn).to.deep.equal(
'Bjarne Bjarnson'
);
expect(Object.values(thirtyAndUnderPersons)[1]?.navn).to.deep.equal(
'Vetle Vetlesen'
);
});

it('Filters out all people 30 years old and younger', () => {
const overThirtyPersons = filterOnAge(personregister, [
AgeFilterOption.OverThirty,
]);
expect(Object.values(overThirtyPersons).length).to.deep.equal(3);
expect(Object.values(overThirtyPersons)[0]?.navn).to.deep.equal(
'Geir Geirsson'
);
expect(Object.values(overThirtyPersons)[1]?.navn).to.deep.equal(
'Eirik Eiriksson'
);
expect(Object.values(overThirtyPersons)[2]?.navn).to.deep.equal(
'John Johnson'
);
});

it('Filters no persons when no age filter is selected', () => {
const noPersonsFiltered = filterOnAge(personregister, []);
expect(Object.values(noPersonsFiltered).length).to.deep.equal(5);
});
});
2 changes: 1 addition & 1 deletion test/utils/hendelseFilteringUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { testdata } from '../data/fellesTestdata';
import { HendelseTypeFilters } from '@/context/filters/filterContextState';
import { addWeeks, subWeeks } from 'date-fns';

const createPersonDataWithName = (name: string): PersonData => {
export const createPersonDataWithName = (name: string): PersonData => {
return {
navn: name,
harMotebehovUbehandlet: false,
Expand Down

0 comments on commit d76e49e

Please sign in to comment.