From c19332b7e9fb83d5425ab35ced10d5bc9f574ed1 Mon Sep 17 00:00:00 2001 From: Hallvard Andreas Stark Date: Tue, 21 Nov 2023 15:06:54 +0100 Subject: [PATCH] omsorgen for --- .../behandling-omsorgspenger/package.json | 2 +- .../src/components/OmsorgenFor.tsx | 2 +- .../behandling-opplaeringspenger/package.json | 2 +- .../src/components/OmsorgenFor.tsx | 2 +- packages/behandling-pleiepenger/package.json | 2 +- .../src/components/OmsorgenFor.tsx | 2 +- packages/fakta-omsorgen-for/index.html | 26 ++ packages/fakta-omsorgen-for/index.ts | 2 + packages/fakta-omsorgen-for/mock/api-mock.ts | 17 + packages/fakta-omsorgen-for/mock/browser.ts | 6 + .../mock/mocked-data/mockedOmsorgsperioder.ts | 43 +++ packages/fakta-omsorgen-for/package.json | 59 ++++ .../public/mockServiceWorker.js | 302 ++++++++++++++++++ .../src/constants/dateConstants.ts | 9 + packages/fakta-omsorgen-for/src/dev/app.ts | 13 + packages/fakta-omsorgen-for/src/nb_NO.js | 19 ++ .../src/types/ContainerContract.ts | 12 + .../src/types/Omsorgsperiode.ts | 85 +++++ .../src/types/Omsorgsperiodeoversikt.ts | 38 +++ .../src/types/OmsorgsperioderResponse.ts | 10 + .../fakta-omsorgen-for/src/types/Relasjon.ts | 9 + .../src/types/Vurderingsresultat.ts | 7 + .../src/types/Ytelsestype.ts | 6 + .../src/ui/MainComponent.tsx | 73 +++++ .../fakta-omsorgen-for/src/ui/actionTypes.ts | 7 + .../ui/components/add-button/AddButton.tsx | 19 ++ .../ui/components/add-button/addButton.css | 14 + .../components/delete-button/DeleteButton.tsx | 17 + .../components/delete-button/deleteButton.css | 12 + .../ui/components/fosterbarn/Fosterbarn.tsx | 106 ++++++ .../OmsorgsperiodeVurderingsdetaljer.tsx | 104 ++++++ .../omsorgsperiodeVurderingsdetaljer.css | 3 + .../OmsorgsperiodeoversiktMessages.tsx | 29 ++ .../omsorgsperiodeoversiktMessages.css | 3 + .../Omsorgsperiodeoversikt.tsx | 76 +++++ .../PeriodeSomSkalVurderes.tsx | 29 ++ .../periodeSomSkalVurderes.css | 28 ++ .../periodenavigasjon/Periodenavigasjon.tsx | 80 +++++ .../periodenavigasjon/periodenavigasjon.css | 26 ++ .../VurderingAvOmsorgsperioderForm.tsx | 236 ++++++++++++++ .../vurderingAvOmsorgsperioderForm.css | 3 + .../VurderingsperiodeElement.tsx | 52 +++ .../vurderingsperiodeElement.css | 35 ++ .../WriteAccessBoundContent.tsx | 20 ++ .../src/ui/context/ContainerContext.ts | 5 + .../src/ui/form/validators/index.ts | 73 +++++ .../src/ui/mainComponent.css | 4 + packages/fakta-omsorgen-for/src/ui/reducer.ts | 40 +++ .../fakta-omsorgen-for/src/util/dateUtils.ts | 13 + packages/fakta-omsorgen-for/src/util/hooks.ts | 10 + .../src/util/periodUtils.ts | 31 ++ .../fakta-omsorgen-for/src/util/renderers.tsx | 24 ++ packages/fakta-omsorgen-for/src/util/utils.ts | 14 + .../webpack/webpack-config.development.js | 40 +++ .../webpack/webpack.common.js | 77 +++++ packages/sak-app/package.json | 2 +- packages/sak-app/src/app/AppIndex.tsx | 1 - yarn.lock | 108 +++---- 58 files changed, 2026 insertions(+), 63 deletions(-) create mode 100644 packages/fakta-omsorgen-for/index.html create mode 100644 packages/fakta-omsorgen-for/index.ts create mode 100644 packages/fakta-omsorgen-for/mock/api-mock.ts create mode 100644 packages/fakta-omsorgen-for/mock/browser.ts create mode 100644 packages/fakta-omsorgen-for/mock/mocked-data/mockedOmsorgsperioder.ts create mode 100644 packages/fakta-omsorgen-for/package.json create mode 100644 packages/fakta-omsorgen-for/public/mockServiceWorker.js create mode 100644 packages/fakta-omsorgen-for/src/constants/dateConstants.ts create mode 100644 packages/fakta-omsorgen-for/src/dev/app.ts create mode 100644 packages/fakta-omsorgen-for/src/nb_NO.js create mode 100644 packages/fakta-omsorgen-for/src/types/ContainerContract.ts create mode 100644 packages/fakta-omsorgen-for/src/types/Omsorgsperiode.ts create mode 100644 packages/fakta-omsorgen-for/src/types/Omsorgsperiodeoversikt.ts create mode 100644 packages/fakta-omsorgen-for/src/types/OmsorgsperioderResponse.ts create mode 100644 packages/fakta-omsorgen-for/src/types/Relasjon.ts create mode 100644 packages/fakta-omsorgen-for/src/types/Vurderingsresultat.ts create mode 100644 packages/fakta-omsorgen-for/src/types/Ytelsestype.ts create mode 100644 packages/fakta-omsorgen-for/src/ui/MainComponent.tsx create mode 100644 packages/fakta-omsorgen-for/src/ui/actionTypes.ts create mode 100644 packages/fakta-omsorgen-for/src/ui/components/add-button/AddButton.tsx create mode 100644 packages/fakta-omsorgen-for/src/ui/components/add-button/addButton.css create mode 100644 packages/fakta-omsorgen-for/src/ui/components/delete-button/DeleteButton.tsx create mode 100644 packages/fakta-omsorgen-for/src/ui/components/delete-button/deleteButton.css create mode 100644 packages/fakta-omsorgen-for/src/ui/components/fosterbarn/Fosterbarn.tsx create mode 100644 packages/fakta-omsorgen-for/src/ui/components/omsorgsperiode-vurderingsdetaljer/OmsorgsperiodeVurderingsdetaljer.tsx create mode 100644 packages/fakta-omsorgen-for/src/ui/components/omsorgsperiode-vurderingsdetaljer/omsorgsperiodeVurderingsdetaljer.css create mode 100644 packages/fakta-omsorgen-for/src/ui/components/omsorgsperiodeoversikt-messages/OmsorgsperiodeoversiktMessages.tsx create mode 100644 packages/fakta-omsorgen-for/src/ui/components/omsorgsperiodeoversikt-messages/omsorgsperiodeoversiktMessages.css create mode 100644 packages/fakta-omsorgen-for/src/ui/components/omsorgsperiodeoversikt/Omsorgsperiodeoversikt.tsx create mode 100644 packages/fakta-omsorgen-for/src/ui/components/periode-som-skal-vurderes/PeriodeSomSkalVurderes.tsx create mode 100644 packages/fakta-omsorgen-for/src/ui/components/periode-som-skal-vurderes/periodeSomSkalVurderes.css create mode 100644 packages/fakta-omsorgen-for/src/ui/components/periodenavigasjon/Periodenavigasjon.tsx create mode 100644 packages/fakta-omsorgen-for/src/ui/components/periodenavigasjon/periodenavigasjon.css create mode 100644 packages/fakta-omsorgen-for/src/ui/components/vurdering-av-omsorgsperioder-form/VurderingAvOmsorgsperioderForm.tsx create mode 100644 packages/fakta-omsorgen-for/src/ui/components/vurdering-av-omsorgsperioder-form/vurderingAvOmsorgsperioderForm.css create mode 100644 packages/fakta-omsorgen-for/src/ui/components/vurderingsperiode/VurderingsperiodeElement.tsx create mode 100644 packages/fakta-omsorgen-for/src/ui/components/vurderingsperiode/vurderingsperiodeElement.css create mode 100644 packages/fakta-omsorgen-for/src/ui/components/write-access-bound-content/WriteAccessBoundContent.tsx create mode 100644 packages/fakta-omsorgen-for/src/ui/context/ContainerContext.ts create mode 100644 packages/fakta-omsorgen-for/src/ui/form/validators/index.ts create mode 100644 packages/fakta-omsorgen-for/src/ui/mainComponent.css create mode 100644 packages/fakta-omsorgen-for/src/ui/reducer.ts create mode 100644 packages/fakta-omsorgen-for/src/util/dateUtils.ts create mode 100644 packages/fakta-omsorgen-for/src/util/hooks.ts create mode 100644 packages/fakta-omsorgen-for/src/util/periodUtils.ts create mode 100644 packages/fakta-omsorgen-for/src/util/renderers.tsx create mode 100644 packages/fakta-omsorgen-for/src/util/utils.ts create mode 100644 packages/fakta-omsorgen-for/webpack/webpack-config.development.js create mode 100644 packages/fakta-omsorgen-for/webpack/webpack.common.js diff --git a/packages/behandling-omsorgspenger/package.json b/packages/behandling-omsorgspenger/package.json index 8ea6b8c61a..2e2ec9caa2 100644 --- a/packages/behandling-omsorgspenger/package.json +++ b/packages/behandling-omsorgspenger/package.json @@ -25,6 +25,7 @@ "@k9-sak-web/fakta-barn-og-overfoeringsdager": "1.0.0", "@k9-sak-web/fakta-barn-oms": "1.0.0", "@k9-sak-web/fakta-inntektsmelding": "1.0.0", + "@k9-sak-web/fakta-omsorgen-for": "1.0.0", "@k9-sak-web/konstanter": "1.0.0", "@k9-sak-web/prosess-aarskvantum-oms": "1.0.0", "@k9-sak-web/prosess-vilkar-soknadsfrist": "1.0.0", @@ -36,7 +37,6 @@ "@navikt/ft-fakta-fordel-beregningsgrunnlag": "7.3.16", "@navikt/ft-prosess-beregningsgrunnlag": "6.3.16", "@navikt/k9-fe-http-utils": "1.0.6", - "@navikt/k9-fe-omsorgen-for": "0.0.8", "nav-frontend-popover": "2.0.4", "react": "18.2.0", "react-intl": "6.5.2", diff --git a/packages/behandling-omsorgspenger/src/components/OmsorgenFor.tsx b/packages/behandling-omsorgspenger/src/components/OmsorgenFor.tsx index 4aa0b0e90a..9926f004ba 100644 --- a/packages/behandling-omsorgspenger/src/components/OmsorgenFor.tsx +++ b/packages/behandling-omsorgspenger/src/components/OmsorgenFor.tsx @@ -3,7 +3,7 @@ import { findAksjonspunkt, findEndpointsForMicrofrontend, httpErrorHandler } fro import { useRestApiErrorDispatcher } from '@k9-sak-web/rest-api-hooks'; import { Aksjonspunkt, BehandlingAppKontekst, Fagsak } from '@k9-sak-web/types'; import React from 'react'; -import { OmsorgenFor } from '@navikt/k9-fe-omsorgen-for'; +import { OmsorgenFor } from '@k9-sak-web/fakta-omsorgen-for'; interface OmsorgenForProps { behandling: BehandlingAppKontekst; diff --git a/packages/behandling-opplaeringspenger/package.json b/packages/behandling-opplaeringspenger/package.json index 8c8d46d88b..ef527a4349 100644 --- a/packages/behandling-opplaeringspenger/package.json +++ b/packages/behandling-opplaeringspenger/package.json @@ -30,6 +30,7 @@ "@k9-sak-web/fakta-institusjon": "1.0.0", "@k9-sak-web/fakta-medisinsk-vilkar": "1.0.0", "@k9-sak-web/fakta-om-barnet": "1.0.0", + "@k9-sak-web/fakta-omsorgen-for": "1.0.0", "@k9-sak-web/konstanter": "1.0.0", "@k9-sak-web/prosess-vilkar-soknadsfrist": "1.0.0", "@k9-sak-web/prosess-vilkar-sykdom": "1.0.0", @@ -42,7 +43,6 @@ "@navikt/ft-fakta-fordel-beregningsgrunnlag": "7.3.16", "@navikt/ft-prosess-beregningsgrunnlag": "6.3.16", "@navikt/k9-fe-http-utils": "1.0.6", - "@navikt/k9-fe-omsorgen-for": "0.0.8", "@navikt/k9-fe-uttak": "0.0.8", "axios": "1.6.2", "nav-frontend-alertstriper": "4.0.2", diff --git a/packages/behandling-opplaeringspenger/src/components/OmsorgenFor.tsx b/packages/behandling-opplaeringspenger/src/components/OmsorgenFor.tsx index 07fe36d3f0..12bd8dda64 100644 --- a/packages/behandling-opplaeringspenger/src/components/OmsorgenFor.tsx +++ b/packages/behandling-opplaeringspenger/src/components/OmsorgenFor.tsx @@ -3,7 +3,7 @@ import { findAksjonspunkt, findEndpointsForMicrofrontend, httpErrorHandler } fro import { useRestApiErrorDispatcher } from '@k9-sak-web/rest-api-hooks'; import { Aksjonspunkt, BehandlingAppKontekst } from '@k9-sak-web/types'; import React from 'react'; -import { OmsorgenFor } from '@navikt/k9-fe-omsorgen-for'; +import { OmsorgenFor } from '@k9-sak-web/fakta-omsorgen-for'; interface OmsorgenForProps { behandling: BehandlingAppKontekst; diff --git a/packages/behandling-pleiepenger/package.json b/packages/behandling-pleiepenger/package.json index 8ea0102c5f..2823853795 100644 --- a/packages/behandling-pleiepenger/package.json +++ b/packages/behandling-pleiepenger/package.json @@ -29,6 +29,7 @@ "@k9-sak-web/fakta-inntektsmelding": "1.0.0", "@k9-sak-web/fakta-medisinsk-vilkar": "1.0.0", "@k9-sak-web/fakta-om-barnet": "1.0.0", + "@k9-sak-web/fakta-omsorgen-for": "1.0.0", "@k9-sak-web/fakta-utenlandsopphold": "1.0.0", "@k9-sak-web/konstanter": "1.0.0", "@k9-sak-web/prosess-vilkar-soknadsfrist": "1.0.0", @@ -43,7 +44,6 @@ "@navikt/ft-fakta-fordel-beregningsgrunnlag": "7.3.16", "@navikt/ft-prosess-beregningsgrunnlag": "6.3.16", "@navikt/k9-fe-http-utils": "1.0.6", - "@navikt/k9-fe-omsorgen-for": "0.0.8", "@navikt/k9-fe-uttak": "0.0.8", "axios": "1.6.2", "nav-frontend-alertstriper": "4.0.2", diff --git a/packages/behandling-pleiepenger/src/components/OmsorgenFor.tsx b/packages/behandling-pleiepenger/src/components/OmsorgenFor.tsx index 6a4e306476..177095bdfb 100644 --- a/packages/behandling-pleiepenger/src/components/OmsorgenFor.tsx +++ b/packages/behandling-pleiepenger/src/components/OmsorgenFor.tsx @@ -2,7 +2,7 @@ import aksjonspunktCodes from '@fpsak-frontend/kodeverk/src/aksjonspunktCodes'; import { findAksjonspunkt, findEndpointsForMicrofrontend, httpErrorHandler } from '@fpsak-frontend/utils'; import { useRestApiErrorDispatcher } from '@k9-sak-web/rest-api-hooks'; import { Aksjonspunkt, BehandlingAppKontekst } from '@k9-sak-web/types'; -import { OmsorgenFor } from '@navikt/k9-fe-omsorgen-for'; +import { OmsorgenFor } from '@k9-sak-web/fakta-omsorgen-for'; import React from 'react'; interface OmsorgenForProps { diff --git a/packages/fakta-omsorgen-for/index.html b/packages/fakta-omsorgen-for/index.html new file mode 100644 index 0000000000..0a56017f6c --- /dev/null +++ b/packages/fakta-omsorgen-for/index.html @@ -0,0 +1,26 @@ + + + Omsorgen for + + + +
+ + + diff --git a/packages/fakta-omsorgen-for/index.ts b/packages/fakta-omsorgen-for/index.ts new file mode 100644 index 0000000000..1fac2e4662 --- /dev/null +++ b/packages/fakta-omsorgen-for/index.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/prefer-default-export +export { default as OmsorgenFor } from './src/ui/MainComponent'; diff --git a/packages/fakta-omsorgen-for/mock/api-mock.ts b/packages/fakta-omsorgen-for/mock/api-mock.ts new file mode 100644 index 0000000000..c465b51ff3 --- /dev/null +++ b/packages/fakta-omsorgen-for/mock/api-mock.ts @@ -0,0 +1,17 @@ +/* eslint-disable import/prefer-default-export */ +import { rest } from 'msw'; +import mockedOmsorgsperioder from './mocked-data/mockedOmsorgsperioder'; + +export const handlers = [ + rest.get('http://localhost:8082/mock/omsorgsperioder', (req, res, ctx) => + res( + ctx.status(200), + ctx.json({ + omsorgsperioder: mockedOmsorgsperioder, + registrertSammeBosted: true, + registrertForeldrerelasjon: true, + tvingManuellVurdering: false, + }), + ), + ), +]; diff --git a/packages/fakta-omsorgen-for/mock/browser.ts b/packages/fakta-omsorgen-for/mock/browser.ts new file mode 100644 index 0000000000..4ac10c54c5 --- /dev/null +++ b/packages/fakta-omsorgen-for/mock/browser.ts @@ -0,0 +1,6 @@ +/* eslint-disable import/prefer-default-export */ +/* eslint-disable import/no-extraneous-dependencies */ +import { setupWorker } from 'msw'; +import { handlers } from './api-mock'; +// This configures a Service Worker with the given request handlers. +export const worker = setupWorker(...handlers); diff --git a/packages/fakta-omsorgen-for/mock/mocked-data/mockedOmsorgsperioder.ts b/packages/fakta-omsorgen-for/mock/mocked-data/mockedOmsorgsperioder.ts new file mode 100644 index 0000000000..e5c6f663dd --- /dev/null +++ b/packages/fakta-omsorgen-for/mock/mocked-data/mockedOmsorgsperioder.ts @@ -0,0 +1,43 @@ +import Vurderingsresultat from '../../src/types/Vurderingsresultat'; + +const omsorgsperioder = [ + { + begrunnelse: null, + periode: { fom: '2021-03-20', tom: '2021-03-25' } as any, + relasjon: 'Annet', + relasjonsbeskrivelse: 'Nabo', + resultat: Vurderingsresultat.IKKE_VURDERT, + resultatEtterAutomatikk: Vurderingsresultat.IKKE_VURDERT, + }, + { + begrunnelse: 'Fordi foo og bar', + periode: { fom: '2021-03-16', tom: '2021-03-20' } as any, + relasjon: 'Annet', + relasjonsbeskrivelse: 'Nabo', + resultat: Vurderingsresultat.IKKE_OPPFYLT, + resultatEtterAutomatikk: Vurderingsresultat.IKKE_VURDERT, + }, + { + periode: { fom: '2021-03-09', tom: '2021-03-15' } as any, + resultat: Vurderingsresultat.IKKE_VURDERT, + resultatEtterAutomatikk: Vurderingsresultat.OPPFYLT, + }, + { + begrunnelse: 'Fordi ditt og datt', + periode: { fom: '2021-03-01', tom: '2021-03-05' } as any, + relasjon: 'Far', + relasjonsbeskrivelse: null, + resultat: Vurderingsresultat.OPPFYLT, + resultatEtterAutomatikk: Vurderingsresultat.OPPFYLT, + }, + { + begrunnelse: 'Fordi sånn og sånn', + periode: { fom: '2021-02-01', tom: '2021-02-05' } as any, + relasjon: 'Far', + relasjonsbeskrivelse: null, + resultat: Vurderingsresultat.OPPFYLT, + resultatEtterAutomatikk: Vurderingsresultat.OPPFYLT, + }, +]; + +export default omsorgsperioder; diff --git a/packages/fakta-omsorgen-for/package.json b/packages/fakta-omsorgen-for/package.json new file mode 100644 index 0000000000..99a9274590 --- /dev/null +++ b/packages/fakta-omsorgen-for/package.json @@ -0,0 +1,59 @@ +{ + "name": "@k9-sak-web/fakta-omsorgen-for", + "version": "1.0.0", + "module": "index.ts", + "keywords": [], + "author": "NAV IT", + "license": "MIT", + "private": true, + "scripts": { + "dev": "node webpack/webpack-config.development.js" + }, + "dependencies": { + "@navikt/ds-css": "5.10.0", + "@navikt/ds-icons": "3.4.3", + "@navikt/ds-react": "5.10.0", + "@navikt/fnrvalidator": "1.3.3", + "@navikt/ft-plattform-komponenter": "2.3.6", + "@navikt/k9-fe-array-utils": "1.0.4", + "@navikt/k9-fe-date-utils": "1.0.6", + "@navikt/k9-fe-form-utils": "1.0.10", + "@navikt/k9-fe-http-utils": "1.0.5", + "@navikt/k9-fe-period-utils": "1.0.9", + "@popperjs/core": "2.11.8", + "axios": "1.6.2", + "classnames": "2.3.2", + "dayjs": "1.11.10", + "lodash.throttle": "4.1.1", + "nav-frontend-alertstriper": "4.0.2", + "nav-frontend-alertstriper-style": "3.0.2", + "nav-frontend-chevron": "1.0.30", + "nav-frontend-chevron-style": "1.0.4", + "nav-frontend-core": "6.0.1", + "nav-frontend-ikoner-assets": "3.0.1", + "nav-frontend-ikonknapper": "2.1.3", + "nav-frontend-js-utils": "1.0.20", + "nav-frontend-knapper": "3.1.3", + "nav-frontend-knapper-style": "2.1.2", + "nav-frontend-lenker": "2.0.2", + "nav-frontend-lenker-style": "2.0.2", + "nav-frontend-paneler": "3.0.2", + "nav-frontend-paneler-style": "2.0.2", + "nav-frontend-skjema": "4.0.6", + "nav-frontend-skjema-style": "3.0.3", + "nav-frontend-spinner": "3.0.1", + "nav-frontend-spinner-style": "1.0.2", + "nav-frontend-typografi": "4.0.2", + "nav-frontend-typografi-style": "2.0.2", + "object-hash": "3.0.0", + "react": "18.2.0", + "react-collapse": "5.1.1", + "react-dom": "18.2.0", + "react-hook-form": "7.47.0", + "react-intl": "6.5.2", + "react-popper": "2.3.0" + }, + "msw": { + "workerDirectory": "public" + } +} diff --git a/packages/fakta-omsorgen-for/public/mockServiceWorker.js b/packages/fakta-omsorgen-for/public/mockServiceWorker.js new file mode 100644 index 0000000000..95835ef353 --- /dev/null +++ b/packages/fakta-omsorgen-for/public/mockServiceWorker.js @@ -0,0 +1,302 @@ +/* eslint-disable */ +/* tslint:disable */ + +/** + * Mock Service Worker (1.3.2). + * @see https://github.com/mswjs/msw + * - Please do NOT modify this file. + * - Please do NOT serve this file on production. + */ + +const INTEGRITY_CHECKSUM = '3d6b9f06410d179a7f7404d4bf4c3c70'; +const activeClientIds = new Set(); + +self.addEventListener('install', function () { + self.skipWaiting(); +}); + +self.addEventListener('activate', function (event) { + event.waitUntil(self.clients.claim()); +}); + +self.addEventListener('message', async function (event) { + const clientId = event.source.id; + + if (!clientId || !self.clients) { + return; + } + + const client = await self.clients.get(clientId); + + if (!client) { + return; + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }); + + switch (event.data) { + case 'KEEPALIVE_REQUEST': { + sendToClient(client, { + type: 'KEEPALIVE_RESPONSE', + }); + break; + } + + case 'INTEGRITY_CHECK_REQUEST': { + sendToClient(client, { + type: 'INTEGRITY_CHECK_RESPONSE', + payload: INTEGRITY_CHECKSUM, + }); + break; + } + + case 'MOCK_ACTIVATE': { + activeClientIds.add(clientId); + + sendToClient(client, { + type: 'MOCKING_ENABLED', + payload: true, + }); + break; + } + + case 'MOCK_DEACTIVATE': { + activeClientIds.delete(clientId); + break; + } + + case 'CLIENT_CLOSED': { + activeClientIds.delete(clientId); + + const remainingClients = allClients.filter(client => { + return client.id !== clientId; + }); + + // Unregister itself when there are no more clients + if (remainingClients.length === 0) { + self.registration.unregister(); + } + + break; + } + } +}); + +self.addEventListener('fetch', function (event) { + const { request } = event; + const accept = request.headers.get('accept') || ''; + + // Bypass server-sent events. + if (accept.includes('text/event-stream')) { + return; + } + + // Bypass navigation requests. + if (request.mode === 'navigate') { + return; + } + + // Opening the DevTools triggers the "only-if-cached" request + // that cannot be handled by the worker. Bypass such requests. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + return; + } + + // Bypass all requests when there are no active clients. + // Prevents the self-unregistered worked from handling requests + // after it's been deleted (still remains active until the next reload). + if (activeClientIds.size === 0) { + return; + } + + // Generate unique request ID. + const requestId = Math.random().toString(16).slice(2); + + event.respondWith( + handleRequest(event, requestId).catch(error => { + if (error.name === 'NetworkError') { + console.warn( + '[MSW] Successfully emulated a network error for the "%s %s" request.', + request.method, + request.url, + ); + return; + } + + // At this point, any exception indicates an issue with the original request/response. + console.error( + `\ +[MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`, + request.method, + request.url, + `${error.name}: ${error.message}`, + ); + }), + ); +}); + +async function handleRequest(event, requestId) { + const client = await resolveMainClient(event); + const response = await getResponse(event, client, requestId); + + // Send back the response clone for the "response:*" life-cycle events. + // Ensure MSW is active and ready to handle the message, otherwise + // this message will pend indefinitely. + if (client && activeClientIds.has(client.id)) { + (async function () { + const clonedResponse = response.clone(); + sendToClient(client, { + type: 'RESPONSE', + payload: { + requestId, + type: clonedResponse.type, + ok: clonedResponse.ok, + status: clonedResponse.status, + statusText: clonedResponse.statusText, + body: clonedResponse.body === null ? null : await clonedResponse.text(), + headers: Object.fromEntries(clonedResponse.headers.entries()), + redirected: clonedResponse.redirected, + }, + }); + })(); + } + + return response; +} + +// Resolve the main client for the given event. +// Client that issues a request doesn't necessarily equal the client +// that registered the worker. It's with the latter the worker should +// communicate with during the response resolving phase. +async function resolveMainClient(event) { + const client = await self.clients.get(event.clientId); + + if (client?.frameType === 'top-level') { + return client; + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }); + + return allClients + .filter(client => { + // Get only those clients that are currently visible. + return client.visibilityState === 'visible'; + }) + .find(client => { + // Find the client ID that's recorded in the + // set of clients that have registered the worker. + return activeClientIds.has(client.id); + }); +} + +async function getResponse(event, client, requestId) { + const { request } = event; + const clonedRequest = request.clone(); + + function passthrough() { + // Clone the request because it might've been already used + // (i.e. its body has been read and sent to the client). + const headers = Object.fromEntries(clonedRequest.headers.entries()); + + // Remove MSW-specific request headers so the bypassed requests + // comply with the server's CORS preflight check. + // Operate with the headers as an object because request "Headers" + // are immutable. + delete headers['x-msw-bypass']; + + return fetch(clonedRequest, { headers }); + } + + // Bypass mocking when the client is not active. + if (!client) { + return passthrough(); + } + + // Bypass initial page load requests (i.e. static assets). + // The absence of the immediate/parent client in the map of the active clients + // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet + // and is not ready to handle requests. + if (!activeClientIds.has(client.id)) { + return passthrough(); + } + + // Bypass requests with the explicit bypass header. + // Such requests can be issued by "ctx.fetch()". + if (request.headers.get('x-msw-bypass') === 'true') { + return passthrough(); + } + + // Notify the client that a request has been intercepted. + const clientMessage = await sendToClient(client, { + type: 'REQUEST', + payload: { + id: requestId, + url: request.url, + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + cache: request.cache, + mode: request.mode, + credentials: request.credentials, + destination: request.destination, + integrity: request.integrity, + redirect: request.redirect, + referrer: request.referrer, + referrerPolicy: request.referrerPolicy, + body: await request.text(), + bodyUsed: request.bodyUsed, + keepalive: request.keepalive, + }, + }); + + switch (clientMessage.type) { + case 'MOCK_RESPONSE': { + return respondWithMock(clientMessage.data); + } + + case 'MOCK_NOT_FOUND': { + return passthrough(); + } + + case 'NETWORK_ERROR': { + const { name, message } = clientMessage.data; + const networkError = new Error(message); + networkError.name = name; + + // Rejecting a "respondWith" promise emulates a network error. + throw networkError; + } + } + + return passthrough(); +} + +function sendToClient(client, message) { + return new Promise((resolve, reject) => { + const channel = new MessageChannel(); + + channel.port1.onmessage = event => { + if (event.data && event.data.error) { + return reject(event.data.error); + } + + resolve(event.data); + }; + + client.postMessage(message, [channel.port2]); + }); +} + +function sleep(timeMs) { + return new Promise(resolve => { + setTimeout(resolve, timeMs); + }); +} + +async function respondWithMock(response) { + await sleep(response.delay); + return new Response(response.body, response); +} diff --git a/packages/fakta-omsorgen-for/src/constants/dateConstants.ts b/packages/fakta-omsorgen-for/src/constants/dateConstants.ts new file mode 100644 index 0000000000..1cdcbb3994 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/constants/dateConstants.ts @@ -0,0 +1,9 @@ +import dayjs from 'dayjs'; + +export const today = dayjs().utc(true).startOf('day'); +export const tomorrow = today.add(1, 'day').startOf('day'); + +export default { + today, + tomorrow, +}; diff --git a/packages/fakta-omsorgen-for/src/dev/app.ts b/packages/fakta-omsorgen-for/src/dev/app.ts new file mode 100644 index 0000000000..a8a555d772 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/dev/app.ts @@ -0,0 +1,13 @@ +import { ContainerContract } from '../types/ContainerContract'; +import renderers from '../util/renderers'; +import '@navikt/ft-plattform-komponenter/dist/style.css'; +import '@navikt/ds-css'; + +interface ExtendedWindow extends Window { + renderOmsorgenForApp: (id: string, contract: ContainerContract) => void; +} + +(window as Partial).renderOmsorgenForApp = async (appId, data) => { + const { renderAppInSuccessfulState } = renderers; + renderAppInSuccessfulState(appId, data); +}; diff --git a/packages/fakta-omsorgen-for/src/nb_NO.js b/packages/fakta-omsorgen-for/src/nb_NO.js new file mode 100644 index 0000000000..0cbd3eec3b --- /dev/null +++ b/packages/fakta-omsorgen-for/src/nb_NO.js @@ -0,0 +1,19 @@ +export const felles = {}; + +export const omsorgspenger = { + ...felles, + 'vurdering.tittel': 'Vurdering', + 'vurdering.harOmsorgenFor': 'Er vilkåret oppfylt for denne perioden?', + 'vurdering.hjemmel': 'Vurder om søker har omsorg for barn etter § 9-5.', + 'vurdering.hjemmel.hjelpetekst': + 'Hvis søker ikke oppfyller vilkåret etter § 9-5, så skal vilkåret likevel settes oppfylt dersom søker kan ha fått fordelt eller overført dager etter § 9-6, femte og sjette ledd', + 'vurdering.advarsel': 'Vurder om søker har omsorgen for barn i perioden.', +}; + +export const pleiepenger = { + ...felles, + 'vurdering.tittel': 'Vurdering av omsorg', + 'vurdering.harOmsorgenFor': 'Har søker omsorgen for barnet i denne perioden?', + 'vurdering.hjemmel': 'Vurder om søker har omsorgen for barnet etter § 9-10, første ledd.', + 'vurdering.advarsel': 'Vurder om søker har omsorgen for barnet i {perioder}.', +}; diff --git a/packages/fakta-omsorgen-for/src/types/ContainerContract.ts b/packages/fakta-omsorgen-for/src/types/ContainerContract.ts new file mode 100644 index 0000000000..5981b41841 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/types/ContainerContract.ts @@ -0,0 +1,12 @@ +import { HttpErrorHandler } from '@navikt/k9-fe-http-utils'; + +export interface ContainerContract { + endpoints: { + omsorgsperioder: string; + }; + readOnly: boolean; + onFinished: (vurdering, fosterbarnForOmsorgspenger) => void; + httpErrorHandler: HttpErrorHandler; + sakstype?: string; + saksbehandlere: { [key: string]: string }; +} diff --git a/packages/fakta-omsorgen-for/src/types/Omsorgsperiode.ts b/packages/fakta-omsorgen-for/src/types/Omsorgsperiode.ts new file mode 100644 index 0000000000..8d4214e0ec --- /dev/null +++ b/packages/fakta-omsorgen-for/src/types/Omsorgsperiode.ts @@ -0,0 +1,85 @@ +import { Period } from '@navikt/k9-fe-period-utils'; +import Vurderingsresultat from './Vurderingsresultat'; + +class Omsorgsperiode { + periode: Period; + + relasjon: string; + + relasjonsbeskrivelse?: string; + + resultat: Vurderingsresultat; + + resultatEtterAutomatikk: Vurderingsresultat; + + begrunnelse?: string; + + vurdertAv?: string; + + vurdertTidspunkt?: string; + + constructor({ + periode, + resultatEtterAutomatikk, + resultat, + relasjonsbeskrivelse, + begrunnelse, + relasjon, + vurdertAv, + vurdertTidspunkt, + }: Partial) { + this.periode = new Period(periode.fom, periode.tom); + this.resultatEtterAutomatikk = resultatEtterAutomatikk; + this.resultat = resultat; + this.relasjonsbeskrivelse = relasjonsbeskrivelse; + this.begrunnelse = begrunnelse; + this.relasjon = relasjon ? relasjon[0].toUpperCase() + relasjon.slice(1).toLowerCase() : ''; + this.vurdertAv = vurdertAv; + this.vurdertTidspunkt = vurdertTidspunkt; + } + + erOppfylt(): boolean { + return this.resultat === Vurderingsresultat.OPPFYLT || this.resultatEtterAutomatikk === Vurderingsresultat.OPPFYLT; + } + + erIkkeOppfylt(): boolean { + return ( + this.resultat === Vurderingsresultat.IKKE_OPPFYLT || + this.resultatEtterAutomatikk === Vurderingsresultat.IKKE_OPPFYLT + ); + } + + erAutomatiskVurdert(): boolean { + return ( + this.resultatEtterAutomatikk === Vurderingsresultat.OPPFYLT || + this.resultatEtterAutomatikk === Vurderingsresultat.IKKE_OPPFYLT + ); + } + + erManueltVurdert(): boolean { + return this.resultat === Vurderingsresultat.OPPFYLT || this.resultat === Vurderingsresultat.IKKE_OPPFYLT; + } + + erVurdert(): boolean { + return this.erManueltVurdert() || this.erAutomatiskVurdert(); + } + + manglerVurdering(): boolean { + return ( + this.resultat === Vurderingsresultat.IKKE_VURDERT && + this.resultatEtterAutomatikk === Vurderingsresultat.IKKE_VURDERT + ); + } + + hentResultat(): Vurderingsresultat { + if (this.resultat === Vurderingsresultat.IKKE_VURDERT) { + return this.resultatEtterAutomatikk; + } + if (this.resultatEtterAutomatikk === Vurderingsresultat.IKKE_VURDERT) { + return this.resultat; + } + return this.resultat || this.resultatEtterAutomatikk; + } +} + +export default Omsorgsperiode; diff --git a/packages/fakta-omsorgen-for/src/types/Omsorgsperiodeoversikt.ts b/packages/fakta-omsorgen-for/src/types/Omsorgsperiodeoversikt.ts new file mode 100644 index 0000000000..44b19c4325 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/types/Omsorgsperiodeoversikt.ts @@ -0,0 +1,38 @@ +import Omsorgsperiode from './Omsorgsperiode'; +import OmsorgsperioderResponse from './OmsorgsperioderResponse'; + +class Omsorgsperiodeoversikt { + perioder: Omsorgsperiode[]; + + registrertSammeBosted: boolean; + + registrertForeldrerelasjon: boolean; + + tvingManuellVurdering: boolean; + + constructor({ + tvingManuellVurdering, + omsorgsperioder, + registrertForeldrerelasjon, + registrertSammeBosted, + }: OmsorgsperioderResponse) { + this.perioder = omsorgsperioder.map(omsorgsperiode => new Omsorgsperiode(omsorgsperiode)); + this.tvingManuellVurdering = tvingManuellVurdering; + this.registrertForeldrerelasjon = registrertForeldrerelasjon; + this.registrertSammeBosted = registrertSammeBosted; + } + + harPerioderTilVurdering(): boolean { + return this.perioder.some(omsorgspeiode => omsorgspeiode.manglerVurdering()); + } + + finnVurdertePerioder(): Omsorgsperiode[] { + return this.perioder.filter(omsorgsperiode => omsorgsperiode.erVurdert()); + } + + finnPerioderTilVurdering(): Omsorgsperiode[] { + return this.perioder.filter(omsorgsperiode => omsorgsperiode.manglerVurdering()); + } +} + +export default Omsorgsperiodeoversikt; diff --git a/packages/fakta-omsorgen-for/src/types/OmsorgsperioderResponse.ts b/packages/fakta-omsorgen-for/src/types/OmsorgsperioderResponse.ts new file mode 100644 index 0000000000..64473ef26a --- /dev/null +++ b/packages/fakta-omsorgen-for/src/types/OmsorgsperioderResponse.ts @@ -0,0 +1,10 @@ +import Omsorgsperiode from './Omsorgsperiode'; + +interface OmsorgsperioderResponse { + omsorgsperioder: Omsorgsperiode[]; + registrertSammeBosted: boolean; + registrertForeldrerelasjon: boolean; + tvingManuellVurdering: boolean; +} + +export default OmsorgsperioderResponse; diff --git a/packages/fakta-omsorgen-for/src/types/Relasjon.ts b/packages/fakta-omsorgen-for/src/types/Relasjon.ts new file mode 100644 index 0000000000..ad9f03cdd3 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/types/Relasjon.ts @@ -0,0 +1,9 @@ +enum Relajson { + MOR = 'Mor', + FAR = 'Far', + MEDMOR = 'Medmor', + FOSTERFORELDER = 'Fosterforelder', + ANNET = 'Annet', +} + +export default Relajson; diff --git a/packages/fakta-omsorgen-for/src/types/Vurderingsresultat.ts b/packages/fakta-omsorgen-for/src/types/Vurderingsresultat.ts new file mode 100644 index 0000000000..72915f2048 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/types/Vurderingsresultat.ts @@ -0,0 +1,7 @@ +enum Vurderingsresultat { + OPPFYLT = 'OPPFYLT', + IKKE_OPPFYLT = 'IKKE_OPPFYLT', + IKKE_VURDERT = 'IKKE_VURDERT', +} + +export default Vurderingsresultat; diff --git a/packages/fakta-omsorgen-for/src/types/Ytelsestype.ts b/packages/fakta-omsorgen-for/src/types/Ytelsestype.ts new file mode 100644 index 0000000000..64a3026da9 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/types/Ytelsestype.ts @@ -0,0 +1,6 @@ +enum Ytelsestype { + PSB = 'PSB', + OMP = 'OMP', +} + +export default Ytelsestype; diff --git a/packages/fakta-omsorgen-for/src/ui/MainComponent.tsx b/packages/fakta-omsorgen-for/src/ui/MainComponent.tsx new file mode 100644 index 0000000000..0c12de7ea9 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/MainComponent.tsx @@ -0,0 +1,73 @@ +import { Box, Margin, PageContainer } from '@navikt/ft-plattform-komponenter'; +import { get } from '@navikt/k9-fe-http-utils'; +import React from 'react'; +import { IntlProvider } from 'react-intl'; +import { ContainerContract } from '../types/ContainerContract'; +import OmsorgsperiodeoversiktType from '../types/Omsorgsperiodeoversikt'; +import OmsorgsperioderResponse from '../types/OmsorgsperioderResponse'; +import Ytelsestype from '../types/Ytelsestype'; +import { teksterForSakstype } from '../util/utils'; +import ActionType from './actionTypes'; +import Omsorgsperiodeoversikt from './components/omsorgsperiodeoversikt/Omsorgsperiodeoversikt'; +import ContainerContext from './context/ContainerContext'; +import styles from './mainComponent.css'; +import mainComponentReducer from './reducer'; + +interface MainComponentProps { + data: ContainerContract; +} + +const MainComponent = ({ data }: MainComponentProps): JSX.Element => { + const { sakstype } = data; + const [state, dispatch] = React.useReducer(mainComponentReducer, { + isLoading: true, + omsorgsperiodeoversiktHarFeilet: false, + omsorgsperiodeoversikt: null, + }); + + const { omsorgsperiodeoversikt, isLoading, omsorgsperiodeoversiktHarFeilet } = state; + + const controller = React.useMemo(() => new AbortController(), []); + + const getOmsorgsperioder = () => + get(data.endpoints.omsorgsperioder, data.httpErrorHandler, { + signal: controller.signal, + }); + + const handleError = () => { + dispatch({ type: ActionType.FAILED }); + }; + + React.useEffect(() => { + let isMounted = true; + getOmsorgsperioder() + .then((response: OmsorgsperioderResponse) => { + if (isMounted) { + const nyOmsorgsperiodeoversikt = new OmsorgsperiodeoversiktType(response); + dispatch({ type: ActionType.OK, omsorgsperiodeoversikt: nyOmsorgsperiodeoversikt }); + } + }) + .catch(handleError); + return () => { + isMounted = false; + controller.abort(); + }; + }, []); + + return ( + + +

{sakstype === Ytelsestype.OMP ? 'Omsorgen for' : 'Omsorg'}

+ + +
+ +
+
+
+
+
+ ); +}; + +export default MainComponent; diff --git a/packages/fakta-omsorgen-for/src/ui/actionTypes.ts b/packages/fakta-omsorgen-for/src/ui/actionTypes.ts new file mode 100644 index 0000000000..fe47614b80 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/actionTypes.ts @@ -0,0 +1,7 @@ +enum ActionType { + OK = 'OK', + FAILED = 'FAILED', + PENDING = 'PENDING', +} + +export default ActionType; diff --git a/packages/fakta-omsorgen-for/src/ui/components/add-button/AddButton.tsx b/packages/fakta-omsorgen-for/src/ui/components/add-button/AddButton.tsx new file mode 100644 index 0000000000..af85a24f9b --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/add-button/AddButton.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { PlusIcon } from '@navikt/ft-plattform-komponenter'; +import styles from './addButton.css'; + +interface AddButtonProps { + onClick: () => void; + label: string; + id?: string; + className?: string; +} + +const AddButton = ({ className, label, onClick, id }: AddButtonProps): JSX.Element => ( + +); + +export default AddButton; diff --git a/packages/fakta-omsorgen-for/src/ui/components/add-button/addButton.css b/packages/fakta-omsorgen-for/src/ui/components/add-button/addButton.css new file mode 100644 index 0000000000..00a1de3959 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/add-button/addButton.css @@ -0,0 +1,14 @@ +.addButton { + display: flex; + align-items: center; + padding: 0; + color: #0067c5; + border: none; + background: none; + height: 23px; + position: relative; + cursor: pointer; +} +.addButton__text { + margin-left: 0.5rem; +} diff --git a/packages/fakta-omsorgen-for/src/ui/components/delete-button/DeleteButton.tsx b/packages/fakta-omsorgen-for/src/ui/components/delete-button/DeleteButton.tsx new file mode 100644 index 0000000000..65fde20153 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/delete-button/DeleteButton.tsx @@ -0,0 +1,17 @@ +import * as React from 'react'; +import { BucketIcon } from '@navikt/ft-plattform-komponenter'; +import styles from './deleteButton.css'; + +interface DeleteButtonProps { + onClick: () => void; +} + +const DeleteButton = ({ onClick }: DeleteButtonProps): JSX.Element => ( +
+ +
+); + +export default DeleteButton; diff --git a/packages/fakta-omsorgen-for/src/ui/components/delete-button/deleteButton.css b/packages/fakta-omsorgen-for/src/ui/components/delete-button/deleteButton.css new file mode 100644 index 0000000000..8ff194c706 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/delete-button/deleteButton.css @@ -0,0 +1,12 @@ +.deleteButton__container { + margin-left: 1rem; + margin-bottom: 0.5rem; + align-self: flex-end; +} +.deleteButton__button { + padding: 0; + border: none; + background: none; + height: 23px; + cursor: pointer; +} diff --git a/packages/fakta-omsorgen-for/src/ui/components/fosterbarn/Fosterbarn.tsx b/packages/fakta-omsorgen-for/src/ui/components/fosterbarn/Fosterbarn.tsx new file mode 100644 index 0000000000..438006c820 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/fosterbarn/Fosterbarn.tsx @@ -0,0 +1,106 @@ +/* eslint-disable react/jsx-props-no-spreading */ +import { Delete } from '@navikt/ds-icons'; +import { Button, Heading, Panel, Table, TextField } from '@navikt/ds-react'; +import validator from '@navikt/fnrvalidator'; +import { Box, Margin } from '@navikt/ft-plattform-komponenter'; +import React, { useContext, useEffect } from 'react'; +import { useFieldArray, useForm, useWatch } from 'react-hook-form'; +import ContainerContext from '../../context/ContainerContext'; + +interface FosterbarnProps { + setFosterbarn: React.Dispatch>; +} + +const Fosterbarn = ({ setFosterbarn }: FosterbarnProps) => { + const { readOnly } = useContext(ContainerContext); + const { + control, + register, + formState: { errors }, + } = useForm({ mode: 'onBlur' }); + const { fields, append, remove } = useFieldArray({ + control, + name: 'fosterbarn', + }); + + const fosterbarnFormValues: { fødselsnummer: string }[] = useWatch({ name: 'fosterbarn', control }); + + useEffect(() => { + const unikeFosterbarn = new Set(fosterbarnFormValues?.map(fosterbarn => fosterbarn.fødselsnummer)); + setFosterbarn([...unikeFosterbarn]); + }, [fosterbarnFormValues]); + + return ( + + + + + Fosterbarn + + + {fields.length > 0 && ( + + + + + + Fødselsnummer + Fjern + + + + {fields.map((field, index) => ( + + {`Fosterbarn ${index + 1}`} + + { + if (validator.fnr(value).status === 'valid') { + return ''; + } + return 'Ugyldig fødselsnummer'; + }, + }, + })} + hideLabel + label="Fødselsnummer" + size="small" + htmlSize={11} + error={errors.fosterbarn?.[index]?.fødselsnummer?.message} + /> + + +
+
+ )} + + +
+
+ ); +}; + +export default Fosterbarn; diff --git a/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiode-vurderingsdetaljer/OmsorgsperiodeVurderingsdetaljer.tsx b/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiode-vurderingsdetaljer/OmsorgsperiodeVurderingsdetaljer.tsx new file mode 100644 index 0000000000..94512f1ab5 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiode-vurderingsdetaljer/OmsorgsperiodeVurderingsdetaljer.tsx @@ -0,0 +1,104 @@ +import { Box, Margin, DetailView, LabelledContent, LinkButton, AssessedBy } from '@navikt/ft-plattform-komponenter'; +import React, { useContext } from 'react'; +import { useIntl } from 'react-intl'; +import Omsorgsperiode from '../../../types/Omsorgsperiode'; +import Relasjon from '../../../types/Relasjon'; +import Ytelsestype from '../../../types/Ytelsestype'; +import ContainerContext from '../../context/ContainerContext'; +import WriteAccessBoundContent from '../write-access-bound-content/WriteAccessBoundContent'; +import styles from './omsorgsperiodeVurderingsdetaljer.css'; + +interface OmsorgsperiodeVurderingsdetaljerProps { + omsorgsperiode: Omsorgsperiode; + onEditClick: () => void; + registrertForeldrerelasjon: boolean; +} + +const OmsorgsperiodeVurderingsdetaljer = ({ + omsorgsperiode, + onEditClick, + registrertForeldrerelasjon, +}: OmsorgsperiodeVurderingsdetaljerProps): JSX.Element => { + const intl = useIntl(); + const { sakstype, saksbehandlere } = useContext(ContainerContext); + const erOMP = sakstype === Ytelsestype.OMP; + const begrunnelseRenderer = () => { + let label = intl.formatMessage({ id: 'vurdering.hjemmel' }); + let begrunnelse = ''; + if (omsorgsperiode.erManueltVurdert()) { + begrunnelse = omsorgsperiode.begrunnelse; + } else if (omsorgsperiode.erAutomatiskVurdert()) { + if (!erOMP) { + begrunnelse = registrertForeldrerelasjon + ? 'Søker er folkeregistrert forelder' + : 'Søker er ikke folkeregistrert forelder'; + } + label = 'Automatisk vurdert'; + } + return ( + <> + + + + ); + }; + + const resultatRenderer = () => { + if (omsorgsperiode.erOppfylt()) { + return 'Ja'; + } + if (omsorgsperiode.erIkkeOppfylt()) { + return 'Nei'; + } + return null; + }; + + const skalViseRelasjonsbeskrivelse = + omsorgsperiode.relasjon?.toUpperCase() === Relasjon.ANNET.toUpperCase() && omsorgsperiode.relasjonsbeskrivelse; + + const harSøkerOmsorgenLabel = erOMP + ? 'Er vilkåret oppfylt for denne perioden?' + : 'Har søker omsorgen for barnet i denne perioden?'; + + return ( + ( + ( + + Rediger vurdering + + )} + /> + )} + > + {omsorgsperiode.erManueltVurdert() && ( + <> + {omsorgsperiode.relasjon && ( + + + + )} + {skalViseRelasjonsbeskrivelse && ( + + + + )} + + )} + {begrunnelseRenderer()} + + + + + + + + ); +}; + +export default OmsorgsperiodeVurderingsdetaljer; diff --git a/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiode-vurderingsdetaljer/omsorgsperiodeVurderingsdetaljer.css b/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiode-vurderingsdetaljer/omsorgsperiodeVurderingsdetaljer.css new file mode 100644 index 0000000000..9411969476 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiode-vurderingsdetaljer/omsorgsperiodeVurderingsdetaljer.css @@ -0,0 +1,3 @@ +.endreLink { + margin-left: 1rem; +} diff --git a/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiodeoversikt-messages/OmsorgsperiodeoversiktMessages.tsx b/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiodeoversikt-messages/OmsorgsperiodeoversiktMessages.tsx new file mode 100644 index 0000000000..cdf8ca1856 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiodeoversikt-messages/OmsorgsperiodeoversiktMessages.tsx @@ -0,0 +1,29 @@ +import { Box, Margin } from '@navikt/ft-plattform-komponenter'; +import Alertstripe from 'nav-frontend-alertstriper'; +import React from 'react'; +import { FormattedMessage } from 'react-intl'; +import Omsorgsperiodeoversikt from '../../../types/Omsorgsperiodeoversikt'; +import { getStringMedPerioder } from '../../../util/periodUtils'; +import styles from './omsorgsperiodeoversiktMessages.css'; + +interface OmsorgsperiodeoversiktMessagesProps { + omsorgsperiodeoversikt: Omsorgsperiodeoversikt; +} + +const OmsorgsperiodeoversiktMessages = ({ + omsorgsperiodeoversikt, +}: OmsorgsperiodeoversiktMessagesProps): JSX.Element => { + if (omsorgsperiodeoversikt.harPerioderTilVurdering()) { + const perioderTilVurdering = omsorgsperiodeoversikt.finnPerioderTilVurdering().map(({ periode }) => periode); + return ( + + + + + + ); + } + return null; +}; + +export default OmsorgsperiodeoversiktMessages; diff --git a/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiodeoversikt-messages/omsorgsperiodeoversiktMessages.css b/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiodeoversikt-messages/omsorgsperiodeoversiktMessages.css new file mode 100644 index 0000000000..b28aea0b2f --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiodeoversikt-messages/omsorgsperiodeoversiktMessages.css @@ -0,0 +1,3 @@ +.alertstripe :global .alertstripe__tekst { + max-width: 50rem; +} diff --git a/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiodeoversikt/Omsorgsperiodeoversikt.tsx b/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiodeoversikt/Omsorgsperiodeoversikt.tsx new file mode 100644 index 0000000000..cbb976fd28 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/omsorgsperiodeoversikt/Omsorgsperiodeoversikt.tsx @@ -0,0 +1,76 @@ +import React, { useContext, useEffect } from 'react'; +import { NavigationWithDetailView } from '@navikt/ft-plattform-komponenter'; +import hash from 'object-hash'; +import OmsorgsperiodeoversiktType from '../../../types/Omsorgsperiodeoversikt'; +import Omsorgsperiode from '../../../types/Omsorgsperiode'; +import OmsorgsperiodeoversiktMessages from '../omsorgsperiodeoversikt-messages/OmsorgsperiodeoversiktMessages'; +import Periodenavigasjon from '../periodenavigasjon/Periodenavigasjon'; +import OmsorgsperiodeVurderingsdetaljer from '../omsorgsperiode-vurderingsdetaljer/OmsorgsperiodeVurderingsdetaljer'; +import VurderingAvOmsorgsperioderForm from '../vurdering-av-omsorgsperioder-form/VurderingAvOmsorgsperioderForm'; +import Fosterbarn from '../fosterbarn/Fosterbarn'; +import ContainerContext from '../../context/ContainerContext'; +import Ytelsestype from '../../../types/Ytelsestype'; + +interface OmsorgsperiodeoversiktProps { + omsorgsperiodeoversikt: OmsorgsperiodeoversiktType; +} + +const Omsorgsperiodeoversikt = ({ omsorgsperiodeoversikt }: OmsorgsperiodeoversiktProps): JSX.Element => { + const { readOnly, sakstype } = useContext(ContainerContext); + const [valgtPeriode, setValgtPeriode] = React.useState(null); + const [erRedigeringsmodus, setErRedigeringsmodus] = React.useState(false); + const [fosterbarn, setFosterbarn] = React.useState([]); + + const perioderTilVurdering = omsorgsperiodeoversikt.finnPerioderTilVurdering(); + const vurderteOmsorgsperioder = omsorgsperiodeoversikt.finnVurdertePerioder(); + + const velgPeriode = (periode: Omsorgsperiode) => { + setValgtPeriode(periode); + setErRedigeringsmodus(false); + }; + + useEffect(() => { + if (omsorgsperiodeoversikt.harPerioderTilVurdering()) { + setValgtPeriode(perioderTilVurdering[0]); + } + }, []); + + return ( + <> + + {sakstype === Ytelsestype.OMP && !readOnly && } + ( + + )} + showDetailSection={!!valgtPeriode} + detailSection={() => { + if (perioderTilVurdering.includes(valgtPeriode) || erRedigeringsmodus) { + return ( + velgPeriode(null)} + fosterbarn={fosterbarn} + /> + ); + } + return ( + setErRedigeringsmodus(true)} + registrertForeldrerelasjon={omsorgsperiodeoversikt.registrertForeldrerelasjon} + /> + ); + }} + /> + + ); +}; + +export default Omsorgsperiodeoversikt; diff --git a/packages/fakta-omsorgen-for/src/ui/components/periode-som-skal-vurderes/PeriodeSomSkalVurderes.tsx b/packages/fakta-omsorgen-for/src/ui/components/periode-som-skal-vurderes/PeriodeSomSkalVurderes.tsx new file mode 100644 index 0000000000..adb78200d0 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/periode-som-skal-vurderes/PeriodeSomSkalVurderes.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Period } from '@navikt/k9-fe-period-utils'; +import { ContentWithTooltip, WarningIcon } from '@navikt/ft-plattform-komponenter'; +import styles from './periodeSomSkalVurderes.css'; + +interface PeriodeSomSkalVurderesProps { + periode: Period; +} + +const PeriodeSomSkalVurderes = ({ periode }: PeriodeSomSkalVurderesProps): JSX.Element => { + const period = new Period(periode.fom, periode.tom); + return ( +
+ Type + + + +
+
+

+ {period.prettifyPeriod()} +

+
+
+
+ ); +}; + +export default PeriodeSomSkalVurderes; diff --git a/packages/fakta-omsorgen-for/src/ui/components/periode-som-skal-vurderes/periodeSomSkalVurderes.css b/packages/fakta-omsorgen-for/src/ui/components/periode-som-skal-vurderes/periodeSomSkalVurderes.css new file mode 100644 index 0000000000..993d388d10 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/periode-som-skal-vurderes/periodeSomSkalVurderes.css @@ -0,0 +1,28 @@ +.periodeSomSkalVurderes { + display: flex; + align-items: center; + cursor: pointer; +} +.periodeSomSkalVurderes__texts { + margin-left: 1.625rem; + display: flex; + align-items: center; +} +.periodeSomSkalVurderes__texts__period { + margin: 0; + color: #0067c5; + text-decoration: underline; +} +.periodeSomSkalVurderes__etikett { + margin-left: 1.375rem; +} +.periodeSomSkalVurderes .visuallyHidden { + position: absolute; + overflow: hidden; + clip: rect(0 0 0 0); + height: 1px; + width: 1px; + margin: -1px; + padding: 0; + border: 0; +} diff --git a/packages/fakta-omsorgen-for/src/ui/components/periodenavigasjon/Periodenavigasjon.tsx b/packages/fakta-omsorgen-for/src/ui/components/periodenavigasjon/Periodenavigasjon.tsx new file mode 100644 index 0000000000..fd020401df --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/periodenavigasjon/Periodenavigasjon.tsx @@ -0,0 +1,80 @@ +import { Period } from '@navikt/k9-fe-period-utils'; +import { Box, Margin, InteractiveList } from '@navikt/ft-plattform-komponenter'; +import { Undertittel } from 'nav-frontend-typografi'; +import React, { useEffect } from 'react'; +import Omsorgsperiode from '../../../types/Omsorgsperiode'; +import { usePrevious } from '../../../util/hooks'; +import { sortPeriodsByFomDate } from '../../../util/periodUtils'; +import PeriodeSomSkalVurderes from '../periode-som-skal-vurderes/PeriodeSomSkalVurderes'; +import VurderingsperiodeElement from '../vurderingsperiode/VurderingsperiodeElement'; +import styles from './periodenavigasjon.css'; + +interface PeriodenavigasjonProps { + perioderTilVurdering: Omsorgsperiode[]; + vurdertePerioder: Omsorgsperiode[]; + onPeriodeValgt: (periode: Omsorgsperiode) => void; + harValgtPeriode?: boolean; +} + +const Periodenavigasjon = ({ + perioderTilVurdering, + vurdertePerioder, + onPeriodeValgt, + harValgtPeriode, +}: PeriodenavigasjonProps): JSX.Element => { + const harPerioderSomSkalVurderes = perioderTilVurdering?.length > 0; + const [activeIndex, setActiveIndex] = React.useState(harPerioderSomSkalVurderes ? 0 : -1); + const previousHarValgtPeriode = usePrevious(harValgtPeriode); + + useEffect(() => { + if (harValgtPeriode === false && previousHarValgtPeriode === true) { + setActiveIndex(-1); + } + }, [harValgtPeriode]); + + const vurdertePerioderElements = vurdertePerioder + .sort((op1, op2) => { + const omsorgsperiode1 = new Period(op1.periode.fom, op1.periode.tom); + const omsorgsperiode2 = new Period(op2.periode.fom, op2.periode.tom); + return sortPeriodsByFomDate(omsorgsperiode1, omsorgsperiode2); + }) + .map(omsorgsperiode => { + const { periode } = omsorgsperiode; + return ; + }); + + const periodeTilVurderingElements = perioderTilVurdering.map(({ periode }) => ( + + )); + + const perioder = [...perioderTilVurdering, ...vurdertePerioder]; + const elements = [...periodeTilVurderingElements, ...vurdertePerioderElements]; + const antallPerioder = elements.length; + + return ( +
+ + Alle perioder + + {antallPerioder === 0 &&

Ingen vurderinger å vise

} + {antallPerioder > 0 && ( +
+ ({ + content: element, + active: activeIndex === currentIndex, + key: `${currentIndex}`, + onClick: () => { + setActiveIndex(currentIndex); + const periodeIndex = elements.indexOf(element); + onPeriodeValgt(perioder[periodeIndex]); + }, + }))} + /> +
+ )} +
+ ); +}; + +export default Periodenavigasjon; diff --git a/packages/fakta-omsorgen-for/src/ui/components/periodenavigasjon/periodenavigasjon.css b/packages/fakta-omsorgen-for/src/ui/components/periodenavigasjon/periodenavigasjon.css new file mode 100644 index 0000000000..88d64ea200 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/periodenavigasjon/periodenavigasjon.css @@ -0,0 +1,26 @@ +.nyVurderingKnapp { + flex-basis: 40%; + margin-left: auto; +} +.vurderingsvelgerContainer { + flex-grow: 1; + margin-top: 1rem; +} +.vurderingsperiode__postElementContainer { + margin-left: 1.375rem; + display: flex; +} +.vurderingsperiode__postElementContainer :nth-child(2) { + margin-left: 1rem; +} +.vurderingsnavigasjon { + position: relative; +} +.vurderingsnavigasjon__opprettVurderingKnapp { + position: absolute; + right: 0; + top: 4px; +} +.vurderingsnavigasjon__heading { + padding: 1.25rem 0.9375rem 0 1.375rem; +} diff --git a/packages/fakta-omsorgen-for/src/ui/components/vurdering-av-omsorgsperioder-form/VurderingAvOmsorgsperioderForm.tsx b/packages/fakta-omsorgen-for/src/ui/components/vurdering-av-omsorgsperioder-form/VurderingAvOmsorgsperioderForm.tsx new file mode 100644 index 0000000000..f37aac2801 --- /dev/null +++ b/packages/fakta-omsorgen-for/src/ui/components/vurdering-av-omsorgsperioder-form/VurderingAvOmsorgsperioderForm.tsx @@ -0,0 +1,236 @@ +import React from 'react'; +import { useIntl } from 'react-intl'; +import { FormProvider, useForm, useWatch } from 'react-hook-form'; + +import { getPeriodDifference, Period } from '@navikt/k9-fe-period-utils'; +import { Box, Margin, DetailView, Form, LabelledContent } from '@navikt/ft-plattform-komponenter'; +import { PeriodpickerList, RadioGroupPanel, TextArea } from '@navikt/k9-fe-form-utils'; +import { Label } from '@navikt/ds-react'; +import { AlertStripeInfo } from 'nav-frontend-alertstriper'; + +import Omsorgsperiode from '../../../types/Omsorgsperiode'; +import Relasjon from '../../../types/Relasjon'; +import Vurderingsresultat from '../../../types/Vurderingsresultat'; +import ContainerContext from '../../context/ContainerContext'; +import { required } from '../../form/validators/index'; +import AddButton from '../add-button/AddButton'; +import DeleteButton from '../delete-button/DeleteButton'; +import styles from './vurderingAvOmsorgsperioderForm.css'; +import Ytelsestype from '../../../types/Ytelsestype'; + +export enum FieldName { + BEGRUNNELSE = 'begrunnelse', + HAR_SØKER_OMSORGEN_FOR_I_PERIODE = 'harSøkerOmsorgenForIPeriode', + PERIODER = 'perioder', +} + +enum RadioOptions { + HELE = 'hele', + DELER = 'deler', + NEI = 'nei', +} + +interface FormPeriod { + period: Period; +} + +const finnResterendePerioder = (perioderFraForm: FormPeriod[], periodeTilVurdering: Period) => { + const formatertePerioderFraForm = perioderFraForm.map(periode => new Period(periode.period.fom, periode.period.tom)); + const resterendePerioder = + formatertePerioderFraForm.length > 0 && getPeriodDifference([periodeTilVurdering], formatertePerioderFraForm); + + return resterendePerioder; +}; + +interface VurderingAvOmsorgsperioderFormProps { + omsorgsperiode: Omsorgsperiode; + onAvbryt: () => void; + fosterbarn: string[]; +} + +interface VurderingAvOmsorgsperioderFormState { + [FieldName.BEGRUNNELSE]: string; + [FieldName.PERIODER]: FormPeriod[]; + [FieldName.HAR_SØKER_OMSORGEN_FOR_I_PERIODE]: RadioOptions; +} + +const VurderingAvOmsorgsperioderForm = ({ + omsorgsperiode, + onAvbryt, + fosterbarn, +}: VurderingAvOmsorgsperioderFormProps): JSX.Element => { + const { onFinished, readOnly, sakstype } = React.useContext(ContainerContext); + const erOMP = sakstype === Ytelsestype.OMP; + const intl = useIntl(); + const formMethods = useForm({ + defaultValues: { + [FieldName.PERIODER]: [{ period: omsorgsperiode.periode }], + [FieldName.BEGRUNNELSE]: omsorgsperiode.begrunnelse || '', + [FieldName.HAR_SØKER_OMSORGEN_FOR_I_PERIODE]: undefined, + }, + }); + + const handleSubmit = (formState: VurderingAvOmsorgsperioderFormState) => { + const { begrunnelse, perioder, harSøkerOmsorgenForIPeriode } = formState; + + let vurdertePerioder; + const fosterbarnForOmsorgspenger = erOMP ? fosterbarn : undefined; + if (harSøkerOmsorgenForIPeriode === RadioOptions.DELER) { + vurdertePerioder = perioder.map(({ period }) => ({ + periode: period, + resultat: Vurderingsresultat.OPPFYLT, + begrunnelse, + })); + + const resterendePerioder = finnResterendePerioder(perioder, omsorgsperiode.periode); + const perioderUtenOmsorg = resterendePerioder.map(periode => ({ + periode, + resultat: Vurderingsresultat.IKKE_OPPFYLT, + begrunnelse, + })); + vurdertePerioder = vurdertePerioder.concat(perioderUtenOmsorg); + } else { + vurdertePerioder = [ + { + periode: omsorgsperiode.periode, + resultat: + harSøkerOmsorgenForIPeriode === RadioOptions.HELE + ? Vurderingsresultat.OPPFYLT + : Vurderingsresultat.IKKE_OPPFYLT, + begrunnelse, + }, + ]; + } + onFinished(vurdertePerioder, fosterbarnForOmsorgspenger); + }; + + const perioder = useWatch({ control: formMethods.control, name: FieldName.PERIODER }); + const harSøkerOmsorgenFor = useWatch({ + control: formMethods.control, + name: FieldName.HAR_SØKER_OMSORGEN_FOR_I_PERIODE, + }); + const resterendePerioder = finnResterendePerioder(perioder, omsorgsperiode.periode); + const skalViseRelasjonsbeskrivelse = + omsorgsperiode.relasjon?.toUpperCase() === Relasjon.ANNET.toUpperCase() && omsorgsperiode.relasjonsbeskrivelse; + + return ( +
+ + {/* eslint-disable-next-line react/jsx-props-no-spreading */} + + {omsorgsperiode.relasjon && ( + + + + )} + {skalViseRelasjonsbeskrivelse && ( + + + + )} +
+ + + {erOMP &&

{intl.formatMessage({ id: 'vurdering.hjemmel.hjelpetekst' })}

} +