diff --git "a/apps/ungdomsytelse-deltaker/mock/msw/mocks/soker1/deltakelser/harS\303\270kt.ts" "b/apps/ungdomsytelse-deltaker/mock/msw/mocks/soker1/deltakelser/harS\303\270kt.ts" index 0cd3cb55d2..854f782fd5 100644 --- "a/apps/ungdomsytelse-deltaker/mock/msw/mocks/soker1/deltakelser/harS\303\270kt.ts" +++ "b/apps/ungdomsytelse-deltaker/mock/msw/mocks/soker1/deltakelser/harS\303\270kt.ts" @@ -7,61 +7,61 @@ export const deltakelserHarSøkt: DeltakelsePeriodInfo[] = [ tilOgMed: undefined, harSøkt: true, oppgaver: [ + // { + // id: 'fc2c6f01-8746-4ca0-b77a-40cc48bba216', + // oppgavetype: Oppgavetype.BEKREFT_ENDRET_SLUTTDATO, + // eksternReferanse: '3b2d6764-1ea1-4b5d-9a07-d4d5e254b595', + // oppgavetypeData: { + // type: 'BEKREFT_ENDRET_STARTDATO', + // nySluttdato: '2026-01-01', + // veilederRef: 'Pål Hønesen, Andeby', + // meldingFraVeileder: 'Jeg endrer sluttdatoen som vi avtalte på møtet forrige uke.', + // }, + // status: OppgaveStatus.ULØST, + // opprettetDato: '2025-02-22T11:43:29.048157Z', + // løstDato: '2025-02-23T05:00:12.048157Z', + // }, + // { + // id: 'fc2c6f01-8746-4ca0-b77a-40cc48bba216', + // eksternReferanse: '3b2d6764-1ea1-4b5d-9a07-d4d5e254b595', + // oppgavetype: Oppgavetype.BEKREFT_ENDRET_SLUTTDATO, + // oppgavetypeData: { + // type: 'BEKREFT_ENDRET_STARTDATO', + // nySluttdato: '2026-01-01', + // veilederRef: 'Pål Hønesen, Andeby', + // meldingFraVeileder: 'Jeg endrer sluttdatoen som vi avtalte på møtet forrige uke.', + // }, + // status: OppgaveStatus.UTLØPT, + // opprettetDato: '2025-02-22T11:43:29.048157Z', + // løstDato: '2025-02-23T05:00:12.048157Z', + // }, { id: 'fc2c6f01-8746-4ca0-b77a-40cc48bba216', - oppgavetype: Oppgavetype.BEKREFT_ENDRET_SLUTTDATO, + oppgavetype: Oppgavetype.BEKREFT_AVVIK_REGISTERINNTEKT, + eksternReferanse: '3b2d6764-1ea1-4b5d-9a07-d4d5e254b595', oppgavetypeData: { - type: 'BEKREFT_ENDRET_STARTDATO', - nySluttdato: '2026-01-01', - veilederRef: 'Pål Hønesen, Andeby', - meldingFraVeileder: 'Jeg endrer sluttdatoen som vi avtalte på møtet forrige uke.', - }, - status: OppgaveStatus.ULØST, - opprettetDato: '2025-02-22T11:43:29.048157Z', - løstDato: '2025-02-23T05:00:12.048157Z', - }, - { - id: 'fc2c6f01-8746-4ca0-b77a-40cc48bba216', - oppgavetype: Oppgavetype.BEKREFT_ENDRET_SLUTTDATO, - oppgavetypeData: { - type: 'BEKREFT_ENDRET_STARTDATO', - nySluttdato: '2026-01-01', - veilederRef: 'Pål Hønesen, Andeby', - meldingFraVeileder: 'Jeg endrer sluttdatoen som vi avtalte på møtet forrige uke.', - }, - status: OppgaveStatus.UTLØPT, - opprettetDato: '2025-02-22T11:43:29.048157Z', - løstDato: '2025-02-23T05:00:12.048157Z', - }, - { - id: 'fc2c6f01-8746-4ca0-b77a-40cc48bba216', - oppgavetype: Oppgavetype.BEKREFT_KORRIGERT_INNTEKT, - oppgavetypeData: { - periodeForInntekt: { - fraOgMed: '2026-01-01', - tilOgMed: '2026-01-31', - }, - inntektFraAinntekt: { - arbeidsgivere: [ + fraOgMed: '2026-01-01', + tilOgMed: '2026-01-31', + registerinntekt: { + arbeidOgFrilansInntekter: [ { - navn: 'Flåklypa barteservice', - beløp: 1232, + arbeidsgiver: 'Flåklypa barteservice', + inntekt: 1200, }, { - navn: 'Hopen klyp og klem', - beløp: 50, + arbeidsgiver: 'Hopen klyp og klem', + inntekt: 50, }, ], - ytelser: [ + ytelseInntekter: [ { - navn: 'Sykepenger', - beløp: 4200, + ytelsetype: 'Sykepenger', + inntekt: 4000, }, ], - }, - inntektFraDeltaker: { - arbeidstakerOgFrilansInntekt: undefined, - inntektFraYtelse: undefined, + totalInntektArbeidOgFrilans: 1250, + totalInntektYtelse: 5000, + totalInntekt: 5250, }, }, status: OppgaveStatus.ULØST, @@ -76,6 +76,7 @@ export const deltakelserHarSøkt: DeltakelsePeriodInfo[] = [ harRapportert: false, arbeidstakerOgFrilansInntekt: undefined, inntektFraYtelse: undefined, + summertInntekt: 0, }, { fraOgMed: '2025-01-01', @@ -83,6 +84,7 @@ export const deltakelserHarSøkt: DeltakelsePeriodInfo[] = [ harRapportert: false, arbeidstakerOgFrilansInntekt: undefined, inntektFraYtelse: undefined, + summertInntekt: 0, }, { fraOgMed: '2025-02-01', @@ -90,6 +92,7 @@ export const deltakelserHarSøkt: DeltakelsePeriodInfo[] = [ harRapportert: false, arbeidstakerOgFrilansInntekt: undefined, inntektFraYtelse: undefined, + summertInntekt: 0, }, { fraOgMed: '2025-03-01', @@ -97,6 +100,7 @@ export const deltakelserHarSøkt: DeltakelsePeriodInfo[] = [ harRapportert: false, arbeidstakerOgFrilansInntekt: undefined, inntektFraYtelse: undefined, + summertInntekt: 0, }, { fraOgMed: '2025-04-01', @@ -104,6 +108,7 @@ export const deltakelserHarSøkt: DeltakelsePeriodInfo[] = [ harRapportert: false, arbeidstakerOgFrilansInntekt: undefined, inntektFraYtelse: undefined, + summertInntekt: 0, }, ], }, diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/Deltakelse.stories.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/Deltakelse.stories.tsx index 25304b0569..e89bb7d567 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/Deltakelse.stories.tsx +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/Deltakelse.stories.tsx @@ -1,41 +1,11 @@ -import { ISODateToDate } from '@navikt/sif-common-utils'; -import { - DeltakelsePeriode, - deltakelsePeriodeSchema, - EndreSluttdatoOppgave, - EndreStartdatoOppgave, - OppgaveStatus, - Oppgavetype, -} from '@navikt/ung-common'; +import { DeltakelsePeriode, deltakelsePeriodeSchema } from '@navikt/ung-common'; import { deltakelserHarSøkt } from '../../../../mock/msw/mocks/soker1/deltakelser/harSøkt'; import { withIntl } from '../../../../storybook/decorators/withIntl'; import { withPageWidth } from '../../../../storybook/decorators/withPageWidth'; - -import type { Meta, StoryObj } from '@storybook/react'; import DeltakelseContent from './DeltakelseContent'; -const endretStartdatoOppgave: EndreStartdatoOppgave = { - oppgavetype: Oppgavetype.BEKREFT_ENDRET_STARTDATO, - id: '123', - opprettetDato: ISODateToDate('2024-07-01'), - status: OppgaveStatus.ULØST, - oppgavetypeData: { - veilederRef: 'Ref', - nyStartdato: ISODateToDate('2024-07-01'), - }, - svarfrist: ISODateToDate('2024-07-31'), -}; -const endretSluttdatoOppgave: EndreSluttdatoOppgave = { - id: '123', - opprettetDato: ISODateToDate('2024-07-01'), - status: OppgaveStatus.ULØST, - oppgavetype: Oppgavetype.BEKREFT_ENDRET_SLUTTDATO, - oppgavetypeData: { - veilederRef: 'Ref', - nySluttdato: ISODateToDate('2024-07-01'), - }, - svarfrist: ISODateToDate('2024-07-31'), -}; +import type { Meta, StoryObj } from '@storybook/react'; +import dayjs from 'dayjs'; const meta: Meta = { component: DeltakelseContent, @@ -49,32 +19,29 @@ type Story = StoryObj; const deltakelse: DeltakelsePeriode = deltakelsePeriodeSchema.parse(deltakelserHarSøkt[0]); -export const DeltakelseUtenOppgaver: Story = { - name: 'Åpen timerapportering', +export const DeltakelseIkkeStartet: Story = { + name: 'Deltakelse ikke startet', args: { deltakelse: { ...deltakelse, + programPeriode: { + from: dayjs().add(2, 'days').toDate(), + to: undefined, + }, oppgaver: [], }, }, }; - -export const DeltakelseMedEndretStartdato: Story = { - name: 'Endret startdato', - args: { - deltakelse: { - ...deltakelse, - oppgaver: [endretStartdatoOppgave], - }, - }, -}; - -export const DeltakelseMedEndretSluttdato: Story = { - name: 'Endret sluttdato', +export const DeltakelseAvsluttet: Story = { + name: 'Deltakelse er avsluttet', args: { deltakelse: { ...deltakelse, - oppgaver: [endretSluttdatoOppgave], + programPeriode: { + from: dayjs().subtract(1, 'year').toDate(), + to: dayjs().subtract(1, 'day').toDate(), + }, + oppgaver: [], }, }, }; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/DeltakelseContent.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/DeltakelseContent.tsx index 66e16fc9d3..07b0464c2c 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/DeltakelseContent.tsx +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/DeltakelseContent.tsx @@ -1,47 +1,66 @@ -import { Box, Heading, VStack } from '@navikt/ds-react'; +import { Heading, Switch, VStack } from '@navikt/ds-react'; import { Deltakelse as DeltakelseContent, OppgaveStatus } from '@navikt/ung-common'; -import { getPeriodeÅpenForInntektsrapportering } from '../utils/deltakelseUtils'; -import OppgavePanel from './oppgaver/OppgavePanel'; -import LøsteOppgaver from './løste-oppgaver/LøsteOppgaver'; import { DeltakelsePeriode } from '@navikt/ung-common/src/types/DeltakelsePeriode'; import RapporterInntekt from './rapporter-inntekt/RapporterInntekt'; +import UløsteOppgaverList from './oppgaver/UløsteOppgaverList'; +import { + erDeltakelseAvsluttet, + erDeltakelseStartet, + getPeriodeÅpenForInntektsrapportering, +} from '../utils/deltakelseUtils'; +import DeltakelseIkkeStartetInfo from './deltakelse-ikke-startet-info/DeltakelseIkkeStartetInfo'; +import DeltakelseAvsluttetInfo from './deltakelse-avsluttet-info/DeltakelseAvsluttetInfo'; +import RapporterInntektIkkeTilgjengeligInfo from './rapporter-inntekt/RapporterInntektIkkeTilgjengeligInfo'; +import { dateRangeToISODateRange, getDateToday, sortDateRange } from '@navikt/sif-common-utils'; +import { useState } from 'react'; interface Props { deltakelse: DeltakelsePeriode; } const DeltakelseContent = ({ deltakelse }: Props) => { - const { rapporteringsPerioder, oppgaver, programPeriode, id } = deltakelse; - // const tidligerePerioder = getTidligereRapporteringsperioder(rapporteringsPerioder || []); - const rapporterInntektPeriode = getPeriodeÅpenForInntektsrapportering(rapporteringsPerioder || []); + const [visTest, setVisTest] = useState(false); + + if (erDeltakelseStartet(deltakelse) === false) { + return ; + } + + if (erDeltakelseAvsluttet(deltakelse)) { + return ; + } + const { rapporteringsPerioder, oppgaver, programPeriode, id } = deltakelse; const uløsteOppgaver = oppgaver.filter((oppgave) => oppgave.status === OppgaveStatus.ULØST); - const løsteOppgaver = oppgaver.filter((oppgave) => oppgave.status !== OppgaveStatus.ULØST); + const åpenInntektsperiode = getPeriodeÅpenForInntektsrapportering(rapporteringsPerioder); return ( - {uløsteOppgaver.map((oppgave, index) => ( - - ))} - {rapporterInntektPeriode ? : null} - - {/* - - Perioder og inntekt - - - */} - {løsteOppgaver.length > 0 ? ( - - - Historikk + {uløsteOppgaver.length === 0 ? null : ( + + )} + {åpenInntektsperiode ? ( + + ) : ( + + )} + setVisTest(e.target.checked)}> + Testfunksjonalitet + + {visTest ? ( + + + Kun for testing - - + + {rapporteringsPerioder + .sort((p1, p2) => sortDateRange(p1.periode, p2.periode)) + .reverse() + .filter((p) => p.harRapportert === false) + .map((p) => ( + + ))} + + ) : null} ); diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/Periodeliste.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/Periodeliste.tsx deleted file mode 100644 index 9a9e84ec7a..0000000000 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/Periodeliste.tsx +++ /dev/null @@ -1,169 +0,0 @@ -import { BodyShort, Box, Button, ExpansionCard, Heading, HStack, VStack } from '@navikt/ds-react'; -import { useEffect, useMemo, useRef, useState } from 'react'; -import { FormattedNumber } from 'react-intl'; -import { Add } from '@navikt/ds-icons'; -import { dateFormatter, dateRangeFormatter } from '@navikt/sif-common-utils'; -import { Rapporteringsperiode } from '@navikt/ung-common'; -import { useAppIntl } from '../../../i18n'; -import { erDatoIFørsteMånedIProgrammet } from '../utils/deltakelseUtils'; -import EndreInntektDialog from './endre-inntekt-dialog/EndreInntektDialog'; - -interface Props { - perioder: Rapporteringsperiode[]; - programperiodeStartDato: Date; - erLåstForEndring?: boolean; -} - -const Periodeliste = ({ perioder, programperiodeStartDato, erLåstForEndring }: Props) => { - const { locale } = useAppIntl(); - const [antall, setAntall] = useState(2); - const [focusIndex, setFocusIndex] = useState(); - const ref = useRef(null); - const [periodeForEndring, setPeriodeForEndring] = useState(); - - useEffect(() => { - if (focusIndex && ref.current) { - ref.current.focus(); - setFocusIndex(undefined); - } - }, [antall, focusIndex]); - - if (perioder.length === 0) { - return null; - } - - const totalt = useMemo(() => perioder.length, perioder); - - const visFlere = () => { - setFocusIndex(antall); - setAntall(Math.min(perioder.length, antall + 3)); - }; - - const visEndreDialog = (periode: Rapporteringsperiode) => { - setPeriodeForEndring(periode); - }; - - return ( - - {perioder.slice(0, antall).map((rapporteringsperiode, index) => { - const { periode, inntekt, kanRapportere = true } = rapporteringsperiode; - const måned = dateFormatter.MonthFullYear(periode.from, locale); - const datoperiode = dateRangeFormatter.getDateRangeText(periode, locale); - const periodeNavn = `${måned} - ${datoperiode}`; - const erFørsteMåned = erDatoIFørsteMånedIProgrammet(periode.from, programperiodeStartDato); - return ( - - - - {måned} - - - - - {datoperiode} - - - {erFørsteMåned ? null : ( - <> - | - - Registrert inntekt:{' '} - - - - ,- - - - )} - - - - - - {erFørsteMåned ? ( - <> - Dette er den første måneden din i programmet. Du trenger ikke rapportere inntekt for - denne måneden. - - ) : ( - <> - {kanRapportere ? ( - - - - Arbeidstaker/frilanser:{' '} - - ,- - - - Ytelse fra Nav:{' '} - - ,- - - - - - Endre inntekt - - - Hvis inntekten har endret seg, kan du korrigere den her. - - - {erLåstForEndring ? null : ( - - )} - - - - ) : ( - - - Evt. informasjon som er relevant for deltaker på denne perioden. Hvis - inntekten kan endres, vises knapp for det. - - - {erFørsteMåned - ? 'Du skal ikke rapportere inntekt for den første måneden i programmet.' - : 'Inntekten kan ikke endres på dette tidspunktet.'} - - - )} - - )} - - - ); - })} - {antall < totalt ? ( - - - - ) : null} - setPeriodeForEndring(undefined)} - /> - - ); -}; - -export default Periodeliste; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/SnarveierSak.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/SnarveierSak.tsx deleted file mode 100644 index ebad55c72c..0000000000 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/SnarveierSak.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Heading, HGrid, LinkPanel } from '@navikt/ds-react'; - -const SnarveierSak = () => ( - <> - - Mer informasjon om ungdomsytelsen - - - - - Om ungdomsytelsen - - - - - Om inntekt - - - - - Om oppfølging fra veileder - - - - -); - -export default SnarveierSak; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/deltakelse-avsluttet-info/DeltakelseAvsluttetInfo.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/deltakelse-avsluttet-info/DeltakelseAvsluttetInfo.tsx new file mode 100644 index 0000000000..207a5287e0 --- /dev/null +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/deltakelse-avsluttet-info/DeltakelseAvsluttetInfo.tsx @@ -0,0 +1,11 @@ +import { Alert, VStack } from '@navikt/ds-react'; + +const DeltakelseAvsluttetInfo = () => { + return ( + + Informasjon når deltakelse er avsluttet + + ); +}; + +export default DeltakelseAvsluttetInfo; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/deltakelse-ikke-startet-info/DeltakelseIkkeStartetInfo.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/deltakelse-ikke-startet-info/DeltakelseIkkeStartetInfo.tsx new file mode 100644 index 0000000000..25a719ecae --- /dev/null +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/deltakelse-ikke-startet-info/DeltakelseIkkeStartetInfo.tsx @@ -0,0 +1,11 @@ +import { Alert, VStack } from '@navikt/ds-react'; + +const DeltakelseIkkeStartetInfo = () => { + return ( + + Informasjon når deltakelse ikke er startet + + ); +}; + +export default DeltakelseIkkeStartetInfo; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/endre-inntekt-dialog/EndreInntektDialog.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/endre-inntekt-dialog/EndreInntektDialog.tsx deleted file mode 100644 index 33ef35da32..0000000000 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/endre-inntekt-dialog/EndreInntektDialog.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Heading, Modal } from '@navikt/ds-react'; -import { dateFormatter } from '@navikt/sif-common-utils'; -import { Rapporteringsperiode } from '@navikt/ung-common'; -import InntektForm from '../inntekt-form/InntektForm'; - -interface Props { - rapporteringsperiode?: Rapporteringsperiode; - onCancel: () => void; -} - -const EndreInntektDialog = ({ rapporteringsperiode, onCancel }: Props) => { - if (!rapporteringsperiode) { - return null; - } - const { periode } = rapporteringsperiode; - return ( - - - - Endre inntekt for {dateFormatter.monthFullYear(periode.from)} - - - - - - - ); -}; - -export default EndreInntektDialog; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/InntektForm.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/InntektForm.tsx index 2a281c3274..fd70b20eab 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/InntektForm.tsx +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/InntektForm.tsx @@ -1,138 +1,94 @@ -import { Alert, BodyShort, Box, Button, Heading, ReadMore, Switch, VStack } from '@navikt/ds-react'; -import { useState } from 'react'; +import { Alert, Box, Button, VStack } from '@navikt/ds-react'; import { getIntlFormErrorHandler, YesOrNo } from '@navikt/sif-common-formik-ds'; -import { DateRange, dateRangeFormatter, dateToISODate } from '@navikt/sif-common-utils'; +import { DateRange, dateToISODate } from '@navikt/sif-common-utils'; import { Inntekt } from '@navikt/ung-common'; import { useAppIntl } from '../../../../i18n'; import { useRapporterInntekt } from '../../hooks/useRapporterInntekt'; import { getInntektFromFormValues, inntektFormComponents } from './inntektFormUtils'; import { InntektFormValues } from './types'; import InntektDefaultForm from './varianter/InntektDefaultForm'; -import InntektTableForm from './varianter/InntektTableForm'; import { UngdomsytelseInntektsrapportering, zUngdomsytelseInntektsrapportering, } from '@navikt/k9-brukerdialog-prosessering-api'; +import { useEffect, useRef } from 'react'; interface Props { inntekt?: Inntekt; periode: DateRange; - gjelderEndring?: boolean; - variant?: 'kompakt' | 'vanlig'; - kanEndreVariant?: boolean; onCancel: () => void; } -const InntektForm = ({ - periode, - inntekt, - gjelderEndring, - variant = 'vanlig', - kanEndreVariant = true, - onCancel, -}: Props) => { +const InntektForm = ({ periode, inntekt, onCancel }: Props) => { const { intl } = useAppIntl(); const { error, inntektSendt, pending, rapporterInntekt } = useRapporterInntekt(); - const [kompakt, setKompakt] = useState(variant === 'kompakt'); const { FormikWrapper, Form } = inntektFormComponents; + const okButtonRef = useRef(null); + const handleSubmit = (values: InntektFormValues) => { - const inntekt = getInntektFromFormValues(values, kompakt); + const inntekt = getInntektFromFormValues(values, false); const data: UngdomsytelseInntektsrapportering = zUngdomsytelseInntektsrapportering.parse({ oppgittInntektForPeriode: { periodeForInntekt: { fraOgMed: dateToISODate(periode.from), tilOgMed: dateToISODate(periode.to), }, - arbeidstakerOgFrilansInntekt: inntekt.arbeidstakerOgFrilansInntekt, - inntektFraYtelse: inntekt.inntektFraYtelse, + arbeidOgFrilansInntekter: inntekt.arbeidOgFrilansInntekter, + ytelseInntekter: inntekt.ytelseInntekter, }, harBekreftetInntekt: values.bekrefterInntekt === true, }); rapporterInntekt(data); }; + useEffect(() => { + // Sett fokus på okButton når inntektSendt er true + if (inntektSendt && okButtonRef.current) { + okButtonRef.current.focus(); + } + }, [inntektSendt]); + const initialValues: Partial = inntekt ? { - harArbeidstakerOgFrilansInntekt: inntekt.arbeidstakerOgFrilansInntekt || 0 > 0 ? YesOrNo.YES : YesOrNo.NO, - harInntektFraYtelse: inntekt.inntektFraYtelse || 0 > 0 ? YesOrNo.YES : YesOrNo.NO, - ansattInntekt: `${inntekt.arbeidstakerOgFrilansInntekt}`, - ytelseInntekt: `${inntekt.inntektFraYtelse}`, + harArbeidstakerOgFrilansInntekt: inntekt.arbeidOgFrilansInntekter || 0 > 0 ? YesOrNo.YES : YesOrNo.NO, + harInntektFraYtelse: inntekt.ytelseInntekter || 0 > 0 ? YesOrNo.YES : YesOrNo.NO, + ansattInntekt: `${inntekt.arbeidOgFrilansInntekter}`, + ytelseInntekt: `${inntekt.ytelseInntekter}`, } : {}; return ( - <> - - {/* {kompakt ? null : ( */} - - Inntektskjema {gjelderEndring ? '(endring)' : null} - - {/* )} */} - - {kanEndreVariant ? ( - { - setKompakt(evt.target.checked); - }} - checked={kompakt}> - Vis kompakt skjema - + + + {inntektSendt ? ( + <> + Inntekt for perioden er sendt + + + + ) : null} - {inntektSendt ? ( + {inntektSendt ? null : ( - Inntekt for perioden er sendt - - - - - ) : ( - - {!kompakt ? ( - - - Spørsmålene nedenfor gjelder for perioden{' '} - {dateRangeFormatter.getDateRangeText(periode, intl.locale)}. - - - Inntekten du skal oppgi er hva du har tjent i perioden. Dette er ikke det samme som hva - du har fått utbetalt. Hvis du er usikker på hva du skal oppgi, kan du se på lønnsslippen - din eller kontakte arbeidsgiveren din. - - - ) : null} - { return (
- {kompakt ? ( - - ) : ( - - )} - - {inntekt ? ( - - Når du endrer inntekt på tidligere perioder, vil Lorem ipsum dolor sit - amet consectetur adipisicing elit. Voluptas cumque quo sunt. - - ) : null} - + {error ? {error} : null}
@@ -141,7 +97,7 @@ const InntektForm = ({ />
)} - +
); }; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/InntektFormKompakt.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/InntektFormKompakt.tsx index 996a4b5ba5..7c1e8516b0 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/InntektFormKompakt.tsx +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/InntektFormKompakt.tsx @@ -16,12 +16,11 @@ import { interface Props { periode: DateRange; - gjelderEndring?: boolean; variant?: 'kompakt' | 'vanlig'; onCancel: () => void; } -const InntektFormKompakt = ({ periode, gjelderEndring, variant = 'kompakt', onCancel }: Props) => { +const InntektFormKompakt = ({ periode, variant = 'kompakt', onCancel }: Props) => { const { intl } = useAppIntl(); const { error, inntektSendt, pending, rapporterInntekt } = useRapporterInntekt(); const [kompakt, setKompakt] = useState(variant === 'kompakt'); @@ -35,8 +34,8 @@ const InntektFormKompakt = ({ periode, gjelderEndring, variant = 'kompakt', onCa fraOgMed: dateToISODate(periode.from), tilOgMed: dateToISODate(periode.to), }, - arbeidstakerOgFrilansInntekt: inntekt.arbeidstakerOgFrilansInntekt, - inntektFraYtelse: inntekt.inntektFraYtelse, + arbeidOgFrilansInntekter: inntekt.arbeidOgFrilansInntekter, + ytelseInntekter: inntekt.ytelseInntekter, }, harBekreftetInntekt: values.bekrefterInntekt === true, }); @@ -48,7 +47,7 @@ const InntektFormKompakt = ({ periode, gjelderEndring, variant = 'kompakt', onCa - Inntektskjema {gjelderEndring ? '(endring)' : null} + Inntektskjema { name={InntektFormFields.harInntektFraYtelse} legend="Har du hatt mottatt ytelser fra Nav i denne perioden?" description={ - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Obcaecati nam quisquam eum enim cum. - Consequuntur aspernatur itaque quasi porro! Optio tempora a, id ipsa incidunt aliquid sequi aut - non deserunt? - + <> + + + sykepenger + omsorgspenger + pleiepenger sykt barn + pleiepenger i livets sluttfase + opplæringspenger + + + } validate={getYesOrNoValidator()} /> diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/types.ts b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/types.ts index 888fb185e1..798e77a895 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/types.ts +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/types.ts @@ -1,6 +1,7 @@ import { YesOrNo } from '@navikt/sif-common-formik-ds'; export enum InntektFormFields { + harHattInntekt = 'harHattInntekt', harArbeidstakerOgFrilansInntekt = 'harArbeidstakerOgFrilansInntekt', harInntektFraYtelse = 'harInntektFraYtelse', ansattInntekt = 'ansattInntekt', @@ -9,6 +10,7 @@ export enum InntektFormFields { } export interface InntektFormValues { + [InntektFormFields.harHattInntekt]?: YesOrNo; [InntektFormFields.harArbeidstakerOgFrilansInntekt]?: YesOrNo; [InntektFormFields.harInntektFraYtelse]?: YesOrNo; [InntektFormFields.ansattInntekt]?: string; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/varianter/InntektDefaultForm.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/varianter/InntektDefaultForm.tsx index 6168a6eb54..a12d365351 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/varianter/InntektDefaultForm.tsx +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-form/varianter/InntektDefaultForm.tsx @@ -7,35 +7,55 @@ import { getInntektFromFormValues, inntektFormComponents, } from '../inntektFormUtils'; -import { getCheckedValidator } from '@navikt/sif-validation'; +import { getCheckedValidator, getYesOrNoValidator } from '@navikt/sif-validation'; import InntektOppsummering from '../../inntekt-oppsummering/InntektOppsummering'; -import { DateRange } from '@navikt/sif-common-utils'; +import { DateRange, dateRangeFormatter } from '@navikt/sif-common-utils'; import { YesOrNo } from '@navikt/sif-common-formik-ds'; +import { useAppIntl } from '../../../../../i18n'; interface Props { periode: DateRange; values: InntektFormValues; } +const { YesOrNoQuestion } = inntektFormComponents; + const InntektDefaultForm = ({ periode, values }: Props) => { + const { intl } = useAppIntl(); const { ConfirmationCheckbox } = inntektFormComponents; const harArbeidstakerOgFrilansInntekt = values[InntektFormFields.harArbeidstakerOgFrilansInntekt] === YesOrNo.YES; const harInntektFraYtelse = values[InntektFormFields.harInntektFraYtelse] === YesOrNo.YES; const inntekt = erAlleInntektSpørsmålBesvartOgGyldig(values) ? getInntektFromFormValues(values) : undefined; + const harHattInntektSvar = values[InntektFormFields.harHattInntekt]; + const harHattInntekt = harHattInntektSvar === YesOrNo.YES; + const harIkkeHattInntekt = harHattInntektSvar === YesOrNo.NO; + const periodetekst = dateRangeFormatter.getDateRangeText(periode, intl.locale); + return ( - + + {harHattInntekt ? ( + <> + - + + + ) : null} - {inntekt ? ( + {inntekt || harIkkeHattInntekt ? ( - + {inntekt ? ( + + ) : null} ) : null} diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-oppsummering/InntektOppsummering.stories.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-oppsummering/InntektOppsummering.stories.tsx index 3028451e0d..9d81101903 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-oppsummering/InntektOppsummering.stories.tsx +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-oppsummering/InntektOppsummering.stories.tsx @@ -12,8 +12,8 @@ const meta: Meta = { args: { periode: ISODateRangeToDateRange('2024-01-01/2024-12-31'), inntekt: { - arbeidstakerOgFrilansInntekt: 123, - inntektFraYtelse: 0, + arbeidOgFrilansInntekter: 123, + ytelseInntekter: 0, summertInntekt: 0, }, }, diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-oppsummering/InntektOppsummering.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-oppsummering/InntektOppsummering.tsx index a0a120c6e5..40e3f4677f 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-oppsummering/InntektOppsummering.tsx +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/inntekt-oppsummering/InntektOppsummering.tsx @@ -25,13 +25,13 @@ const InntektOppsummering = ({ periode, inntekt }: Props) => { Arbeidsgiver/­frilanser - + Ytelse fra Nav - + { const { intl } = useAppIntl(); const { sendSvar, setVisSkjema, error, pending } = useOppgaveContext(); + const [parseError, setParseError] = useState(); const handleSubmit = async (values: FormValues) => { const godkjennerOppgave = values[FormFields.godkjenner] === YesOrNo.YES; - - const dto: UngdomsytelseOppgavebekreftelse = { - deltakelseId, - oppgave: { - oppgaveId: oppgave.id, - bekreftelseSvar: godkjennerOppgave ? 'GODTAR' : 'AVSLÅR', - ikkeGodkjentResponse: godkjennerOppgave - ? undefined - : { - meldingFraDeltaker: values[FormFields.begrunnelse]!, - }, - type: Oppgavetype.BEKREFT_KORRIGERT_INNTEKT, - }, - }; - await sendSvar(dto); + const parsedOppgaveDto = zBekreftKorrigertInntektOppgaveDto.safeParse({ + oppgaveId: oppgave.id, + bekreftelseSvar: godkjennerOppgave ? 'GODTAR' : 'AVSLÅR', + ikkeGodkjentResponse: godkjennerOppgave + ? undefined + : { + meldingFraDeltaker: values[FormFields.begrunnelse]!, + }, + type: Oppgavetype.BEKREFT_AVVIK_REGISTERINNTEKT, + }); + + if (parsedOppgaveDto.success === true) { + const dto: UngdomsytelseOppgavebekreftelse = { + deltakelseId, + oppgave: parsedOppgaveDto.data, + }; + await sendSvar(dto); + } else { + console.error(parsedOppgaveDto.error); + setParseError('Det oppstod en feil da vi skulle sende svaret ditt.'); + } }; - const { periodeForInntekt } = oppgave.oppgavetypeData; + const { fraOgMed, tilOgMed } = oppgave.oppgavetypeData; const periodetekst = dateRangeFormatter.getDateRangeText( { - from: periodeForInntekt.fraOgMed, - to: periodeForInntekt.tilOgMed, + from: fraOgMed, + to: tilOgMed, }, intl.locale, ); const svarfristTekst = dateFormatter.compact(dayjs(oppgave.svarfrist).add(1, 'day').toDate()); - const { inntektFraAinntekt, inntektFraDeltaker } = oppgave.oppgavetypeData; + const { + registerinntekt: { arbeidOgFrilansInntekter, ytelseInntekter }, + } = oppgave.oppgavetypeData; - const harOppgittInntekt = - inntektFraDeltaker?.arbeidstakerOgFrilansInntekt !== undefined || - inntektFraDeltaker?.inntektFraYtelse !== undefined; + const harOppgittInntekt = false; // TODO + // inntektFraDeltaker?.arbeidOgFrilansInntekter !== undefined || + // inntektFraDeltaker?.ytelseInntekter !== undefined; const summertInntektFraAinntekt = - inntektFraAinntekt.arbeidsgivere.reduce((acc, arbeidsgiver) => acc + arbeidsgiver.beløp, 0) + - inntektFraAinntekt.ytelser.reduce((acc, yelse) => acc + yelse.beløp, 0); + arbeidOgFrilansInntekter.reduce((acc, arbeidsgiver) => acc + arbeidsgiver.inntekt, 0) + + ytelseInntekter.reduce((acc, yelse) => acc + yelse.inntekt, 0); - const summertInntektFraDeltaker = inntektFraDeltaker - ? (inntektFraDeltaker.arbeidstakerOgFrilansInntekt || 0) + (inntektFraDeltaker.inntektFraYtelse || 0) - : 0; + const summertInntektFraDeltaker = 0; return ( { formErrorHandler={getIntlFormErrorHandler(intl, 'inntektForm.validation')}> - {inntektFraAinntekt.arbeidsgivere.length > 0 ? ( + {arbeidOgFrilansInntekter.length > 0 ? ( <> ({ + beløp: inntekt, + navn: arbeidsgiver, + }), + )} /> ) : null} - {inntektFraAinntekt.ytelser.length > 0 ? ( + {ytelseInntekter.length > 0 ? ( <> - + ({ + beløp: y.inntekt, + navn: y.ytelsetype, + }))} + /> ) : null} @@ -213,7 +235,9 @@ const KorrigertInntektOppgave = ({ deltakelseId, oppgave }: Props) => { ) : null} - {error ? {JSON.stringify(error)} : null} + {error || parseError ? ( + {error ? JSON.stringify(error) : parseError} + ) : null} ); diff --git "a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/l\303\270ste-oppgaver/L\303\270steOppgaver.tsx" "b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/L\303\270steOppgaver.tsx" similarity index 100% rename from "apps/ungdomsytelse-deltaker/src/apps/innsyn/components/l\303\270ste-oppgaver/L\303\270steOppgaver.tsx" rename to "apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/L\303\270steOppgaver.tsx" diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/Oppgave.stories.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/Oppgave.stories.tsx index 9e547f99a2..8eb2efbf72 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/Oppgave.stories.tsx +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/Oppgave.stories.tsx @@ -45,34 +45,28 @@ const korrigertInntekt: Oppgave = { id: '123', opprettetDato: ISODateToDate('2024-07-01'), status: OppgaveStatus.ULØST, - oppgavetype: Oppgavetype.BEKREFT_KORRIGERT_INNTEKT, + oppgavetype: Oppgavetype.BEKREFT_AVVIK_REGISTERINNTEKT, oppgavetypeData: { - periodeForInntekt: { - fraOgMed: ISODateToDate('2026-01-01'), - tilOgMed: ISODateToDate('2026-01-31'), - }, - inntektFraAinntekt: { - arbeidsgivere: [ + fraOgMed: ISODateToDate('2026-01-01'), + tilOgMed: ISODateToDate('2026-01-31'), + registerinntekt: { + arbeidOgFrilansInntekter: [ { - navn: 'Flåklypa barteservice', - beløp: 1232, + arbeidsgiver: 'Flåklypa barteservice', + inntekt: 1232, }, { - navn: 'Hopen klyp og klem', - beløp: 50, + arbeidsgiver: 'Hopen klyp og klem', + inntekt: 50, }, ], - ytelser: [ + ytelseInntekter: [ { - navn: 'Sykepenger', - beløp: 4200, + ytelsetype: 'Sykepenger', + inntekt: 4200, }, ], }, - inntektFraDeltaker: { - arbeidstakerOgFrilansInntekt: undefined, - inntektFraYtelse: undefined, - }, }, svarfrist: dayjs().add(1, 'day').toDate(), }; @@ -101,10 +95,6 @@ export const BekreftKorrigertInntektOppgittInntekt: Story = { ...korrigertInntekt, oppgavetypeData: { ...korrigertInntekt.oppgavetypeData, - inntektFraDeltaker: { - arbeidstakerOgFrilansInntekt: 1200, - inntektFraYtelse: 550, - }, }, }, programPeriode: { diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/OppgaveLayout.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/OppgaveLayout.tsx index 2af9584481..eb9b9aca6b 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/OppgaveLayout.tsx +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/OppgaveLayout.tsx @@ -1,4 +1,4 @@ -import { Alert, Bleed, Box, Button, Heading, Tag, VStack } from '@navikt/ds-react'; +import { Alert, Bleed, Box, ExpansionCard, Heading, Tag, VStack } from '@navikt/ds-react'; import { dateFormatter } from '@navikt/sif-common-utils'; import BlueBox from '../../../../components/blue-box/BlueBox'; import { useOppgaveContext } from '../oppgave/OppgaveContext'; @@ -53,33 +53,21 @@ const OppgaveLayout = ({ {erBesvart ? ( Besvart ) : ( - <> - {visSkjema ? ( - - - - - Svarskjema - - {children} - - - - ) : ( - - - - )} - + { + setVisSkjema(isOpen); + if (isOpen && onÅpneOppgave) { + onÅpneOppgave(); + } + }}> + + {visOppgaveTittel} + + {children} + )} diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/OppgavePanel.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/OppgavePanel.tsx index 1d9140fc11..ca87d32005 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/OppgavePanel.tsx +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/OppgavePanel.tsx @@ -33,7 +33,7 @@ const OppgavePanel = ({ oppgave, deltakelseId, programPeriode }: Props): React.R /> ); - case Oppgavetype.BEKREFT_KORRIGERT_INNTEKT: + case Oppgavetype.BEKREFT_AVVIK_REGISTERINNTEKT: return ( diff --git "a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/Ul\303\270steOppgaverList.tsx" "b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/Ul\303\270steOppgaverList.tsx" new file mode 100644 index 0000000000..b239fd315e --- /dev/null +++ "b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/oppgaver/Ul\303\270steOppgaverList.tsx" @@ -0,0 +1,27 @@ +import { VStack } from '@navikt/ds-react'; +import { OpenDateRange } from '@navikt/sif-common-utils'; +import { Oppgave } from '@navikt/ung-common'; +import OppgavePanel from './OppgavePanel'; + +interface Props { + uløsteOppgaver: Oppgave[]; + programPeriode: OpenDateRange; + deltakelseId: string; +} + +const UløsteOppgaverList = ({ deltakelseId, uløsteOppgaver, programPeriode }: Props) => { + return ( + + {uløsteOppgaver.map((oppgave, index) => ( + + ))} + + ); +}; + +export default UløsteOppgaverList; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/EndreInntektPart.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/EndreInntektPart.tsx deleted file mode 100644 index bfb5e3c353..0000000000 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/EndreInntektPart.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Alert, BodyShort, Box, Button, VStack } from '@navikt/ds-react'; -import { FormattedNumber } from 'react-intl'; -import { Inntekt } from '@navikt/ung-common'; - -interface Props { - månedNavn: string; - inntekt?: Inntekt; - fristForRapportering: Date; - kanRapportere?: boolean; - visSkjema: boolean; - onEndreInntekt: () => void; -} - -const EndreInntektPart = ({ månedNavn, inntekt, kanRapportere, onEndreInntekt, visSkjema }: Props) => { - return ( - - - For {månedNavn} har du rapportert{' '} - - kroner - {' '} - i inntekt. - - {kanRapportere ? ( - <> - {visSkjema !== true ? ( - - - - ) : null} - - ) : ( - - Du kan ikke endre inntekt for denne perioden nå. - - )} - - ); -}; - -export default EndreInntektPart; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/FremhevetInntektsperiode.stories.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntekt.stories.tsx similarity index 54% rename from apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/FremhevetInntektsperiode.stories.tsx rename to apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntekt.stories.tsx index 90f83d94c5..a0235dac02 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/FremhevetInntektsperiode.stories.tsx +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntekt.stories.tsx @@ -3,37 +3,34 @@ import { ISODateToDate } from '@navikt/sif-common-utils'; import { Rapporteringsperiode } from '@navikt/ung-common'; import { withIntl } from '../../../../../storybook/decorators/withIntl'; import { withPageWidth } from '../../../../../storybook/decorators/withPageWidth'; -import FremhevetInntektsperiode from './RapporterInntekt'; +import RapporterInntekt from './RapporterInntekt'; const rapporteringsperiode: Rapporteringsperiode = { - harRapportert: true, - kanRapportere: true, - fristForRapportering: ISODateToDate('2025-01-31'), + harRapportert: false, periode: { from: ISODateToDate('2025-01-01'), to: ISODateToDate('2025-01-31'), }, - inntekt: { - arbeidstakerOgFrilansInntekt: 0, - inntektFraYtelse: 0, - summertInntekt: 0, - }, + arbeidstakerOgFrilansInntekt: 0, + erÅpenRapporteringsperiode: false, + inntektFraYtelse: 0, + summertInntekt: 0, }; -const meta: Meta = { - title: 'Komponenter/Fremhevet inntektsperiode', - component: FremhevetInntektsperiode, +const meta: Meta = { + title: 'Komponenter/Rapporter inntekt', + component: RapporterInntekt, decorators: [withIntl, withPageWidth], args: { - rapporteringsperiode, + rapporteringsperiode: rapporteringsperiode, }, }; export default meta; -type Story = StoryObj; +type Story = StoryObj; export const IkkeRapportertPeriode: Story = { - name: 'Åpen - uten inntekt', + name: 'Inntekt ikke rapportert', args: { rapporteringsperiode: { ...rapporteringsperiode, @@ -43,17 +40,14 @@ export const IkkeRapportertPeriode: Story = { }; export const RapportertPeriode: Story = { - name: 'Åpen - med inntekt', + name: 'Inntekt rapportert', args: { rapporteringsperiode: { ...rapporteringsperiode, harRapportert: true, - kanRapportere: true, - inntekt: { - arbeidstakerOgFrilansInntekt: 1500, - inntektFraYtelse: 0, - summertInntekt: 1500, - }, + arbeidstakerOgFrilansInntekt: 1500, + inntektFraYtelse: 0, + summertInntekt: 1500, }, }, }; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntekt.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntekt.tsx index aef349cf59..7960801c1b 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntekt.tsx +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntekt.tsx @@ -1,25 +1,23 @@ -import { Bleed, BodyLong, Box, Heading, VStack } from '@navikt/ds-react'; +import { BodyLong, BodyShort, Box, ExpansionCard, Heading, VStack } from '@navikt/ds-react'; import { useState } from 'react'; import { dateFormatter } from '@navikt/sif-common-utils'; import { Rapporteringsperiode } from '@navikt/ung-common'; import InntektForm from '../inntekt-form/InntektForm'; -import RapporterInntektPart from './RapporterInntektPart'; +import { getFristForRapporteringsperiode } from '../../utils/deltakelseUtils'; interface Props { rapporteringsperiode: Rapporteringsperiode; } -const FremhevetInntektsperiode = ({ rapporteringsperiode }: Props) => { - const { periode, harRapportert, kanRapportere, fristForRapportering } = rapporteringsperiode; - - if (!fristForRapportering) { - return null; - } +const RapporterInntekt = ({ rapporteringsperiode }: Props) => { + const { periode, harRapportert } = rapporteringsperiode; const [visSkjema, setVisSkjema] = useState(false); const månedNavn = dateFormatter.month(periode.from); const månedÅrNavn = dateFormatter.monthFullYear(periode.from); + const fristForRapportering = getFristForRapporteringsperiode(periode); + return ( @@ -29,33 +27,36 @@ const FremhevetInntektsperiode = ({ rapporteringsperiode }: Props) => { {harRapportert ? ( Inntekt er rapportert for denne perioden ) : ( - setVisSkjema(true)} - /> - )} - - {visSkjema ? ( - - - + <> + + Hvis du har inntekt i {månedNavn}, må du oppgi denne innen utgangen av{' '} + {dateFormatter.dayDateMonth(fristForRapportering)}. Hvis du ikke har noe + inntekt denne måneden, trenger du ikke melde fra. + + { + setVisSkjema(isOpen); + }}> + + Vis skjema + + { setVisSkjema(false); }} /> - - - - ) : null} + + + + )} ); }; -export default FremhevetInntektsperiode; +export default RapporterInntekt; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntektIkkeTilgjengeligInfo.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntektIkkeTilgjengeligInfo.tsx new file mode 100644 index 0000000000..9894067afc --- /dev/null +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntektIkkeTilgjengeligInfo.tsx @@ -0,0 +1,23 @@ +import { Alert } from '@navikt/ds-react'; +import { dateFormatter, dateRangeFormatter } from '@navikt/sif-common-utils'; +import { useAppIntl } from '../../../../i18n'; +import { getTidsromForInntektsrapportering } from '../../utils/deltakelseUtils'; + +interface Props { + inntektsmåned: Date; +} + +const RapporterInntektIkkeTilgjengeligInfo = ({ inntektsmåned }: Props) => { + const { intl } = useAppIntl(); + const månedNavn = dateFormatter.month(inntektsmåned); + const åpenPeriode = getTidsromForInntektsrapportering(inntektsmåned); + return ( + + Hvis du har inntekt i {månedNavn}, vil du få mulighet til å melde fra om dette i tidsrommet{' '} + {dateRangeFormatter.getDateRangeText(åpenPeriode, intl.locale)}. Hvis du ikke har inntekt, trenger du ikke + melde fra. + + ); +}; + +export default RapporterInntektIkkeTilgjengeligInfo; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntektPart.tsx b/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntektPart.tsx deleted file mode 100644 index ea5c0dfb89..0000000000 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/components/rapporter-inntekt/RapporterInntektPart.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Alert, BodyShort, Box, Button, VStack } from '@navikt/ds-react'; -import { dateFormatter } from '@navikt/sif-common-utils'; - -interface Props { - månedNavn: string; - kanRapportere?: boolean; - fristForRapportering: Date; - visSkjema: boolean; - onRapporterInntekt: () => void; -} - -const RapporterInntektPart = ({ - månedNavn, - kanRapportere, - fristForRapportering, - onRapporterInntekt, - visSkjema, -}: Props) => { - return ( - - - Hvis du har inntekt i {månedNavn}, må du oppgi denne innen utgangen av{' '} - {dateFormatter.dayDateMonth(fristForRapportering)}. Hvis du ikke har noe inntekt denne - måneden, trenger du ikke melde fra. - - {kanRapportere ? ( - <> - {visSkjema !== true ? ( - - - - ) : null} - - ) : ( - - Du kan ikke melde inn inntekt for denne perioden nå. - - )} - - ); -}; - -export default RapporterInntektPart; diff --git a/apps/ungdomsytelse-deltaker/src/apps/innsyn/utils/deltakelseUtils.ts b/apps/ungdomsytelse-deltaker/src/apps/innsyn/utils/deltakelseUtils.ts index 16d8e9ba75..578dbcd0e5 100644 --- a/apps/ungdomsytelse-deltaker/src/apps/innsyn/utils/deltakelseUtils.ts +++ b/apps/ungdomsytelse-deltaker/src/apps/innsyn/utils/deltakelseUtils.ts @@ -1,26 +1,38 @@ -import { isDateInDateRange } from '@navikt/sif-common-utils'; -import { Rapporteringsperiode } from '@navikt/ung-common'; +import { DateRange, getDateToday } from '@navikt/sif-common-utils'; +import { DeltakelsePeriode, Rapporteringsperiode } from '@navikt/ung-common'; import dayjs from 'dayjs'; -const datoErIRapporteringsperiode = (dato: Date, periode: Rapporteringsperiode): boolean => { - return isDateInDateRange(dato, periode.periode); +/** + * Finner tidsrom hvor bruker kan rapportere inntekt for en måned. Dette er + * fom 1. tom 6. i påfølgende måned. + * @param inntektsmåned Måned det skal rapporteres inntekt for + * @returns DateRange + */ +export const getTidsromForInntektsrapportering = (inntektsmåned: Date): DateRange => { + const from = dayjs(inntektsmåned).startOf('month').add(1, 'month').startOf('day'); + return { + from: from.toDate(), + to: from.add(5, 'days').toDate(), + }; }; -export const rapporteringsperiodeErTidligerePeriode = (rapporteringsperiode: Rapporteringsperiode): boolean => { - const { periode } = rapporteringsperiode; - return dayjs(periode.to).isBefore(dayjs(), 'day'); +export const getFristForRapporteringsperiode = (periode: DateRange): Date => { + return dayjs.min(dayjs(periode.to), dayjs(periode.from).startOf('month').add(6, 'days')).toDate(); }; export const getPeriodeÅpenForInntektsrapportering = ( rapporteringsperioder: Rapporteringsperiode[], ): Rapporteringsperiode | undefined => { - return rapporteringsperioder.find((p) => datoErIRapporteringsperiode(new Date(), p) && p.harRapportert === false); -}; - -export const getTidligereRapporteringsperioder = ( - rapporteringsperioder: Rapporteringsperiode[], -): Rapporteringsperiode[] => { - return rapporteringsperioder.filter(rapporteringsperiodeErTidligerePeriode).sort(sorterRapporteringsperioderDesc); + const perioder = rapporteringsperioder.filter( + (p) => p.erÅpenRapporteringsperiode === true && p.harRapportert === false, + ); + if (perioder.length === 0) { + return undefined; + } + if (perioder.length === 1) { + return perioder[0]; + } + throw 'Det er flere åpne perioder for inntektsrapportering'; }; export const sorterRapporteringsperioderDesc = (r1: Rapporteringsperiode, r2: Rapporteringsperiode): number => { @@ -30,3 +42,45 @@ export const sorterRapporteringsperioderDesc = (r1: Rapporteringsperiode, r2: Ra export const erDatoIFørsteMånedIProgrammet = (dato: Date, programStartdato: Date): boolean => { return dayjs(dato).isSame(programStartdato, 'month'); }; + +/** + * Returnerer true hvis deltakelsen er aktiv, dvs. den er startet og er pågående + * @param deltakelse + * @returns + */ +export const erDeltakelseAktiv = (deltakelse: DeltakelsePeriode): boolean => { + const today = getDateToday(); + if (dayjs(today).isBefore(deltakelse.programPeriode.from)) { + return false; + } + if (deltakelse.programPeriode.to && dayjs(today).isAfter(deltakelse.programPeriode.to)) { + return false; + } + return true; +}; + +/** + * Returnerer true hvis deltakelsen er aktiv, dvs. den er startet og er pågående + * @param deltakelse + * @returns + */ +export const erDeltakelseAvsluttet = (deltakelse: DeltakelsePeriode): boolean => { + const today = getDateToday(); + if (deltakelse.programPeriode.to && dayjs(today).isAfter(deltakelse.programPeriode.to)) { + return true; + } + return false; +}; + +/** + * Returnerer true hvis deltakelsen er påbegynt, dvs. den er startet og er pågående + * @param deltakelse + * @returns + */ +export const erDeltakelseStartet = (deltakelse: DeltakelsePeriode): boolean => { + const today = getDateToday(); + if (dayjs(today).isBefore(deltakelse.programPeriode.from)) { + return false; + } + return true; +}; diff --git a/apps/ungdomsytelse-deltaker/src/components/snarvei-link-panel/SnarveiLinkPanel.stories.tsx b/apps/ungdomsytelse-deltaker/src/components/snarvei-link-panel/SnarveiLinkPanel.stories.tsx deleted file mode 100644 index f94ee4ee5c..0000000000 --- a/apps/ungdomsytelse-deltaker/src/components/snarvei-link-panel/SnarveiLinkPanel.stories.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { Edit } from '@navikt/ds-icons'; -import { withPageWidth } from '../../../storybook/decorators/withPageWidth'; -import SnarveiLinkPanel from './SnarveiLinkPanel'; - -import type { Meta, StoryObj } from '@storybook/react'; -const meta: Meta = { - component: SnarveiLinkPanel, - title: 'Komponenter/SnarveiLinkPanel', - parameters: { - layout: 'centered', - }, - decorators: [withPageWidth], -}; -export default meta; - -type Story = StoryObj; - -export const Default: Story = { - args: { - href: '#', - title: 'Tittel på snarvei', - description: <>Her kommer noe beskrivelse, - }, -}; -export const MedIkon: Story = { - name: 'Med ikon', - args: { - icon: , - href: '#', - title: 'Tittel på snarvei', - description: <>Her kommer noe beskrivelse, - }, -}; diff --git a/apps/ungdomsytelse-deltaker/src/components/snarvei-link-panel/SnarveiLinkPanel.tsx b/apps/ungdomsytelse-deltaker/src/components/snarvei-link-panel/SnarveiLinkPanel.tsx deleted file mode 100644 index 78405c6acd..0000000000 --- a/apps/ungdomsytelse-deltaker/src/components/snarvei-link-panel/SnarveiLinkPanel.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { BodyShort, Box, HStack, Heading, Hide, LinkPanel, LinkPanelProps } from '@navikt/ds-react'; -import React from 'react'; - -interface Props extends LinkPanelProps { - icon?: React.ReactNode; - title: string; - description: React.ReactNode; -} - -const SnarveiLinkPanel: React.FunctionComponent = ({ icon, title, description, ...rest }) => { - return ( - - - {icon ? {icon} : undefined} - - - {title} - - - {description} - - - - - ); -}; - -export default SnarveiLinkPanel; diff --git a/apps/ungdomsytelse-deltaker/src/components/snarveier/Snarveier.stories.tsx b/apps/ungdomsytelse-deltaker/src/components/snarveier/Snarveier.stories.tsx deleted file mode 100644 index e1d5062aae..0000000000 --- a/apps/ungdomsytelse-deltaker/src/components/snarveier/Snarveier.stories.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { withPageWidth } from '../../../storybook/decorators/withPageWidth'; -import Snarveier from './Snarveier'; -import type { Meta, StoryObj } from '@storybook/react'; - -const meta: Meta = { - component: Snarveier, - title: 'Komponenter/Snarveier', - parameters: { - layout: 'centered', - }, - decorators: [withPageWidth], -}; -export default meta; - -type Story = StoryObj; - -export const Default: Story = { - args: {}, -}; diff --git a/apps/ungdomsytelse-deltaker/src/components/snarveier/Snarveier.tsx b/apps/ungdomsytelse-deltaker/src/components/snarveier/Snarveier.tsx deleted file mode 100644 index 6230e90f75..0000000000 --- a/apps/ungdomsytelse-deltaker/src/components/snarveier/Snarveier.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Heading, HGrid, VStack } from '@navikt/ds-react'; -import React from 'react'; -import SnarveiLinkPanel from '../snarvei-link-panel/SnarveiLinkPanel'; -import { BookIcon } from '@navikt/aksel-icons'; -import { Dialog } from '@navikt/ds-icons'; -import PageBleedBox from '../page-bleed-box/PageBleedBox'; - -interface Props { - title?: string; -} - -const Snarveier: React.FunctionComponent = ({ title }) => { - return ( - -
- - {title ? ( - - {title} - - ) : null} - - - } - title={'Mer om ytelsen'} - description={'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'} - /> - } - title={'Kontakt oss'} - description={'Hvis du lurer på noe om saken din kan du kontakte oss her'} - /> - - -
-
- ); -}; - -export default Snarveier; diff --git a/apps/ungdomsytelse-deltaker/src/i18n/enums.ts b/apps/ungdomsytelse-deltaker/src/i18n/enums.ts index 128d01f20b..caec8ae8ff 100644 --- a/apps/ungdomsytelse-deltaker/src/i18n/enums.ts +++ b/apps/ungdomsytelse-deltaker/src/i18n/enums.ts @@ -5,7 +5,7 @@ const nb = { 'oppgavestatus.UTLØPT': 'Utløpt', 'oppgavetype.BEKREFT_ENDRET_STARTDATO': 'Endret startdato', 'oppgavetype.BEKREFT_ENDRET_SLUTTDATO': 'Endret sluttdato', - 'oppgavetype.BEKREFT_KORRIGERT_INNTEKT': 'Endret inntekt', + 'oppgavetype.BEKREFT_AVVIK_REGISTERINNTEKT': 'Endret inntekt', }; const nn: Record = { ...nb }; diff --git a/apps/ungdomsytelse-veileder/.storybook/main.ts b/apps/ungdomsytelse-veileder/.storybook/main.ts new file mode 100644 index 0000000000..0a5177b167 --- /dev/null +++ b/apps/ungdomsytelse-veileder/.storybook/main.ts @@ -0,0 +1,27 @@ +import { join, dirname } from 'path'; + +function getAbsolutePath(value) { + return dirname(require.resolve(join(value, 'package.json'))); +} + +const config = { + stories: ['../src/**/*.stories.tsx'], + addons: [ + getAbsolutePath('@storybook/addon-links'), + getAbsolutePath('@storybook/addon-essentials'), + getAbsolutePath('@storybook/addon-onboarding'), + getAbsolutePath('@storybook/addon-interactions'), + ], + framework: { + name: '@storybook/react-vite', + options: {}, + }, + docs: { + autodocs: false, + }, + typescript: { + reactDocgen: 'react-docgen-typescript-plugin', + }, +}; + +export default config; diff --git a/apps/ungdomsytelse-veileder/.storybook/preview-head.html b/apps/ungdomsytelse-veileder/.storybook/preview-head.html new file mode 100644 index 0000000000..f82615bb34 --- /dev/null +++ b/apps/ungdomsytelse-veileder/.storybook/preview-head.html @@ -0,0 +1,33 @@ + + \ No newline at end of file diff --git a/apps/ungdomsytelse-veileder/.storybook/preview.ts b/apps/ungdomsytelse-veileder/.storybook/preview.ts new file mode 100644 index 0000000000..8f26e2435a --- /dev/null +++ b/apps/ungdomsytelse-veileder/.storybook/preview.ts @@ -0,0 +1,29 @@ +import { Preview } from '@storybook/react'; +import { initK9BrukerdialogProsesseringApiClient, initUngDeltakelseOpplyserApiClient } from '@navikt/ung-common'; +import { initialize, mswLoader } from 'msw-storybook-addon'; +import '../src/app.css'; + +initialize(); + +initUngDeltakelseOpplyserApiClient(); +initK9BrukerdialogProsesseringApiClient(); + +const preview: Preview = { + loaders: [mswLoader], + parameters: { + actions: { argTypesRegex: '^on[A-Z].*' }, + options: { + storySort: { + method: 'alphabetical', + }, + }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + }, +}; + +export default preview; diff --git a/apps/ungdomsytelse-veileder/.storybook/vitest.setup.ts b/apps/ungdomsytelse-veileder/.storybook/vitest.setup.ts new file mode 100644 index 0000000000..273710cd05 --- /dev/null +++ b/apps/ungdomsytelse-veileder/.storybook/vitest.setup.ts @@ -0,0 +1,9 @@ +import { beforeAll } from 'vitest'; +import { setProjectAnnotations } from '@storybook/react'; +import * as projectAnnotations from './preview'; + +// This is an important step to apply the right configuration when testing your stories. +// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations +const project = setProjectAnnotations([projectAnnotations]); + +beforeAll(project.beforeAll); \ No newline at end of file diff --git a/apps/ungdomsytelse-veileder/api-mock/mock-server.cjs b/apps/ungdomsytelse-veileder/api-mock/mock-server.cjs deleted file mode 100644 index 18606ac9d6..0000000000 --- a/apps/ungdomsytelse-veileder/api-mock/mock-server.cjs +++ /dev/null @@ -1,240 +0,0 @@ -// /* eslint-disable no-console */ -// const express = require('express'); -// const helmet = require('helmet'); -// const cors = require('cors'); - -// const server = express(); - -// server.use(express.json()); -// server.use( -// helmet({ -// contentSecurityPolicy: true, -// crossOriginEmbedderPolicy: false, -// crossOriginResourcePolicy: false, -// }), -// ); - -// server.use( -// cors({ -// origin: 'http://localhost:8080', -// methods: ['GET', 'POST', 'DELETE', 'PUT', 'OPTIONS'], -// allowedHeaders: ['content-type', 'X-Brukerdialog-Git-Sha', 'x_correlation_id'], -// credentials: true, -// }), -// ); -// server.options('*', cors()); - -// const nyDeltaker = { -// id: null, -// deltakerIdent: '56857102105', -// navn: { -// fornavn: 'GLORETE', -// mellomnavn: null, -// etternavn: 'TØFFEL', -// }, -// }; - -// const nyDeltakerRegistrert = { -// ...nyDeltaker, -// id: 'd-n', -// }; - -// const registrertDeltaker = { -// id: 'd-r', -// deltakerIdent: '03867198392', -// navn: { -// fornavn: 'PRESENTABEL', -// mellomnavn: null, -// etternavn: 'HOFTE', -// }, -// }; - -// const deltakelse1 = { -// id: '3ebb8cb3-a2eb-45a5-aeee-22a2766aaab0-1', -// deltakerIdent: '03867198392', -// deltaker: { -// id: 'd-r', -// deltakerIdent: '03867198392', -// }, -// fraOgMed: '2025-01-01', -// tilOgMed: '2025-05-01', -// harSøkt: true, -// oppgaver: [ -// { -// id: '00054e20-e6c3-4b85-8f62-b269e1c15dc2', -// oppgavetype: 'BEKREFT_ENDRET_STARTDATO', -// status: 'ULØST', -// opprettetDato: '2025-02-19T13:29:14.553804Z', -// }, -// ], -// }; - -// const deltakelse3 = { -// id: 'a3bed73f-d5d7-4aac-9c3b-3134c8394dac', -// deltaker: { -// id: '6ab6cd9f-9589-46b2-b665-cfc7502e38db', -// deltakerIdent: '10457231682', -// }, -// harSøkt: true, -// fraOgMed: '2025-01-02', -// tilOgMed: null, -// oppgaver: [ -// { -// id: '00054e20-e6c3-4b85-8f62-b269e1c15dc2', -// oppgavetype: 'BEKREFT_ENDRET_STARTDATO', -// status: 'ULØST', -// opprettetDato: '2025-02-19T13:29:14.553804Z', -// }, -// ], -// }; - -// const deltakelse2 = { -// id: '3ebb8cb3-a2eb-45a5-aeee-22a2766aaab2', -// deltakerIdent: '03867198392', -// deltaker: { -// id: 'd-r', -// deltakerIdent: '03867198392', -// }, -// oppgaver: [{}], -// fraOgMed: '2025-01-02', -// tilOgMed: '2025-02-04', -// oppgaver: [], -// harSøkt: false, -// }; - -// const deltakelser = [deltakelse3]; - -// const getDeltaker = ({ deltakerIdent, deltakerId }) => { -// if (deltakerIdent) { -// console.log('henter deltaker med deltakerIdent', deltakerIdent); -// switch (deltakerIdent) { -// case nyDeltaker.deltakerIdent: -// return nyDeltaker; -// case registrertDeltaker.deltakerIdent: -// return registrertDeltaker; -// default: -// console.log('fant ikke deltaker med deltakerIdent', deltakerIdent); -// return null; -// } -// } -// if (deltakerId) { -// console.log('henter deltaker med id', deltakerId); -// switch (deltakerId) { -// case registrertDeltaker.id: -// return registrertDeltaker; -// case nyDeltakerRegistrert.id: -// return nyDeltakerRegistrert; -// default: -// console.log('fant ikke deltaker med id', deltakerId); -// return null; -// } -// } -// }; - -// const getDeltakelser = (id) => { -// console.log('getDeltakelser', id); -// return id === 'd-n' ? [] : deltakelser; -// }; - -// const startExpressServer = () => { -// const port = process.env.PORT || 8099; - -// server.get('/oppslag/deltaker/:id', (req, res) => { -// console.log('/oppslag/deltaker', req.params); -// const response = getDeltaker({ deltakerId: req.params.id }); -// setTimeout(() => { -// res.status(200).send(response); -// }, 350); -// }); - -// server.post('/oppslag/deltaker', (req, res) => { -// const response = getDeltaker({ deltakerIdent: req.body.deltakerIdent }); -// setTimeout(() => { -// res.status(200).send(response); -// }, 350); -// }); - -// server.post('/oppslag/deltaker-500', (req, res) => { -// const response = getDeltaker(req.body); -// setTimeout(() => { -// res.status(500).send(response); -// }, 350); -// }); - -// server.get('/veileder/register/deltaker/:deltakerId/deltakelser', (req, res) => { -// const response = getDeltakelser(req.params.deltakerId); -// console.log(response); -// setTimeout(() => { -// res.status(200).send(response); -// }, 250); -// }); - -// server.post('/veileder/register/deltaker/innmelding', (req, res) => { -// const body = req.body; -// console.log('[POST] body', body); -// const response = { -// id: 'd-n', -// deltakerIdent: req.body.deltakerIdent, -// deltaker: { -// id: 'd-n', -// deltakerIdent: req.body.deltakerIdent, -// }, -// harSøkt: false, -// fraOgMed: req.body.startdato, -// }; -// setTimeout(() => { -// res.status(200).send(response); -// }, 1500); -// }); - -// server.put('/veileder/register/deltakelse/:id/avslutt', (req, res) => { -// const response = { -// ...deltakelse1, -// tilOgMed: req.body.utmeldingsdato, -// }; -// setTimeout(() => { -// res.status(200).send(response); -// }, 1500); -// }); - -// server.put('/veileder/register/deltakelse/:id/oppdater', (req, res) => { -// const body = req.body; -// const response = { -// ...deltakelse1, -// ...body, -// }; -// setTimeout(() => { -// res.status(200).send(response); -// }, 50); -// }); -// server.put('/veileder/register/deltakelse/:id/endre/startdato', (req, res) => { -// const body = req.body; -// const response = { -// ...deltakelse1, -// ...body, -// }; -// setTimeout(() => { -// res.status(200).send(response); -// }, 50); -// }); -// server.put('/veileder/register/deltakelse/:id/endre/sluttdato', (req, res) => { -// const body = req.body; -// const response = { -// ...deltakelse1, -// ...body, -// }; -// setTimeout(() => { -// res.status(200).send(response); -// }, 50); -// }); - -// server.delete('/veileder/register/deltakelse/:id/fjern', (req, res) => { -// res.sendStatus(200); -// }); - -// server.listen(port, () => { -// console.log(`App listening on port: ${port}`); -// }); -// }; - -// startExpressServer(); diff --git a/apps/ungdomsytelse-veileder/mock/msw/mocks/mockUtils.ts b/apps/ungdomsytelse-veileder/mock/msw/mocks/mockUtils.ts index 03e874e5b3..6eabb59973 100644 --- a/apps/ungdomsytelse-veileder/mock/msw/mocks/mockUtils.ts +++ b/apps/ungdomsytelse-veileder/mock/msw/mocks/mockUtils.ts @@ -1,6 +1,8 @@ import { Søker } from '@navikt/sif-common-api'; import { ISODateToDate } from '@navikt/sif-common-utils'; +import { deltakelseSchema, registrertDeltakerSchema } from '@navikt/ung-common'; import { DeltakerPersonlia, OppgaveDto, OppgaveStatus, Oppgavetype } from '@navikt/ung-deltakelse-opplyser-api'; +import { Veileder } from '../../../src/types/Veileder'; const nyDeltakerId = '7c6a3e15-4f5b-4cab-badd-198fe0247111'; export const registrertDeltakerId = '699b9f97-b0d7-4b78-9b8e-8758feb9e0fd'; @@ -10,8 +12,8 @@ export const findDeltaker = (deltakerIdent: string) => { switch (deltakerIdent) { case nyDeltakerMock.deltakerIdent: return nyDeltakerMock; - case registrertDeltaker.deltakerIdent: - return registrertDeltaker; + case registrertDeltakerMock.deltakerIdent: + return registrertDeltakerMock; default: console.log('fant ikke deltaker med deltakerIdent', deltakerIdent); return null; @@ -23,8 +25,8 @@ export const getDeltakerByDeltakerId = (deltakerId: string) => { if (deltakerId) { console.log('henter deltaker med id', deltakerId); switch (deltakerId) { - case registrertDeltaker.id: - return registrertDeltaker; + case registrertDeltakerMock.id: + return registrertDeltakerMock; case nyDeltakerRegistrert.id: return nyDeltakerRegistrert; default: @@ -52,24 +54,26 @@ const nyDeltakerRegistrert = { id: nyDeltakerId, }; -const registrertDeltaker: DeltakerPersonlia = { +export const registrertDeltakerMock: DeltakerPersonlia = { id: registrertDeltakerId, deltakerIdent: '03867198392', navn: { fornavn: 'PRESENTABEL', - mellomnavn: null as any, + // mellomnavn: null as any, etternavn: 'HOFTE', }, fødselsdato: '1998-12-31', førsteMuligeInnmeldingsdato: '2024-01-01', sisteMuligeInnmeldingsdato: '2024-12-31', }; +export const parsedMockDeltaker = registrertDeltakerSchema.parse(registrertDeltakerMock); export const mockOppgave: OppgaveDto = { id: '00054e20-e6c3-4b85-8f62-b269e1c15dc2', oppgavetype: Oppgavetype.BEKREFT_ENDRET_STARTDATO, status: OppgaveStatus.ULØST, opprettetDato: '2025-02-19T13:29:14.553804Z', + eksternReferanse: '00054e20-e6c3-4b85-8f62-b269e1c15dc2', oppgavetypeData: { nyStartdato: '2025-01-10', veilederRef: 'Veil Veiledersen', @@ -77,9 +81,10 @@ export const mockOppgave: OppgaveDto = { }, }; -const oppgaver = [ +const oppgaver: OppgaveDto[] = [ { id: 'eedc9be0-5cd7-4eb8-8cde-1cf9375e6eb5', + eksternReferanse: 'eedc9be0-5cd7-4eb8-8cde-1cf9375e6eb5', oppgavetype: Oppgavetype.BEKREFT_ENDRET_STARTDATO, oppgavetypeData: { type: Oppgavetype.BEKREFT_ENDRET_STARTDATO, @@ -87,12 +92,13 @@ const oppgaver = [ veilederRef: 'Pål Veileder Hønesen', meldingFraVeileder: '2025sdf', }, - status: 'KANSELLERT', + status: OppgaveStatus.KANSELLERT, opprettetDato: '2025-03-18T12:46:08.782385Z', løstDato: '2025-03-18T13:31:05.656698Z', }, { id: '37bcca77-9df0-4454-a697-5ba14f87a0a1', + eksternReferanse: 'eedc9be0-5cd7-4eb8-8cde-1cf9375e6eb5', oppgavetype: Oppgavetype.BEKREFT_ENDRET_STARTDATO, oppgavetypeData: { type: Oppgavetype.BEKREFT_ENDRET_STARTDATO, @@ -100,12 +106,12 @@ const oppgaver = [ veilederRef: 'Pål Veileder Hønesen', meldingFraVeileder: 'asdfasdfasdf', }, - status: 'ULØST', + status: OppgaveStatus.ULØST, opprettetDato: '2025-03-18T13:31:05.668281Z', - løstDato: null, }, { id: 'ee45c5a3-95b9-4538-b6c1-3be1462c20ae', + eksternReferanse: 'eedc9be0-5cd7-4eb8-8cde-1cf9375e6eb5', oppgavetype: Oppgavetype.BEKREFT_ENDRET_STARTDATO, oppgavetypeData: { type: Oppgavetype.BEKREFT_ENDRET_STARTDATO, @@ -113,13 +119,13 @@ const oppgaver = [ veilederRef: 'Pål Veileder Hønesen', meldingFraVeileder: 'En del tekst', }, - status: 'KANSELLERT', + status: OppgaveStatus.KANSELLERT, opprettetDato: '2025-03-18T12:18:22.025109Z', løstDato: '2025-03-18T12:46:08.773477Z', }, ]; -const deltakelseDR = { +export const deltakelseDRMock = { id: '3ebb8cb3-a2eb-45a5-aeee-22a2766aaab0-1', deltaker: { id: registrertDeltakerId, @@ -130,6 +136,7 @@ const deltakelseDR = { harSøkt: true, oppgaver: [...oppgaver], }; +export const parsedMockDeltakelse = deltakelseSchema.parse(deltakelseDRMock); export const deltakelseDNMock = { id: '3ebb8cb3-a2eb-45a5-aeee-22a2766aaab0-1', @@ -144,7 +151,7 @@ export const deltakelseDNMock = { }; export const getDeltakelser = (id) => { - return id === nyDeltakerId ? [deltakelseDNMock] : [deltakelseDR]; + return id === nyDeltakerId ? [deltakelseDNMock] : [deltakelseDRMock]; }; export const veilederMock: Søker = { @@ -154,3 +161,8 @@ export const veilederMock: Søker = { fødselsdato: ISODateToDate('1990-01-01'), fødselsnummer: 'w34', }; + +export const parsedVeilederMock: Veileder = { + fornavn: 'Pål', + etternavn: 'Hønesen', +}; diff --git a/apps/ungdomsytelse-veileder/package.json b/apps/ungdomsytelse-veileder/package.json index ed04fd960f..30963d8061 100644 --- a/apps/ungdomsytelse-veileder/package.json +++ b/apps/ungdomsytelse-veileder/package.json @@ -14,7 +14,9 @@ "build": "vite build --base=/", "check:types": "tsc --noemit", "lint": "eslint", - "lint:fix": "eslint --fix" + "lint:fix": "eslint --fix", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" }, "dependencies": { "@navikt/aksel-icons": "7.17.4", @@ -42,15 +44,24 @@ "react": "19.0.0", "react-dom": "19.0.0", "react-hook-form": "7.54.2", + "react-intl": "7.1.10", "react-markdown": "10.1.0", "react-router-dom": "7.4.0", "remark-gfm": "4.0.1", "zod": "3.24.2" }, "devDependencies": { + "@chromatic-com/storybook": "^3", "@eslint/eslintrc": "3.3.1", "@eslint/js": "9.23.0", "@navikt/nav-dekoratoren-moduler": "3.2.2", + "@storybook/addon-essentials": "^8.6.9", + "@storybook/addon-onboarding": "^8.6.9", + "@storybook/blocks": "^8.6.9", + "@storybook/experimental-addon-test": "^8.6.9", + "@storybook/react": "^8.6.9", + "@storybook/react-vite": "^8.6.9", + "@storybook/test": "^8.6.9", "@tailwindcss/postcss": "4.0.16", "@tailwindcss/vite": "4.0.16", "@types/node": "22.13.13", @@ -58,28 +69,41 @@ "@types/react-dom": "19.0.4", "@typescript-eslint/parser": "8.28.0", "@vitejs/plugin-react": "4.3.4", + "@vitest/browser": "3.0.9", + "@vitest/coverage-v8": "3.0.9", "compression": "1.8.0", "eslint": "9.23.0", "eslint-plugin-prettier": "5.2.5", "eslint-plugin-react": "7.37.4", "eslint-plugin-simple-import-sort": "12.1.1", + "eslint-plugin-storybook": "^0.12.0", "eslint-plugin-unicorn": "58.0.0", "express": "4.21.2", "http-proxy-middleware": "3.0.3", + "msw": "^2.7.3", + "msw-storybook-addon": "^2.0.4", "mustache-express": "1.3.2", + "playwright": "^1.51.1", "postcss-import": "16.1.0", "postcss-styled-syntax": "0.7.1", "prettier": "3.5.3", + "storybook": "^8.6.9", "stylelint": "16.16.0", "tailwindcss": "4.0.16", "typescript": "5.8.2", "typescript-eslint": "8.28.0", "vite": "6.2.3", - "vite-plugin-checker": "0.9.1" + "vite-plugin-checker": "0.9.1", + "vitest": "3.0.9" }, "msw": { "workerDirectory": [ "dist" ] + }, + "eslintConfig": { + "extends": [ + "plugin:storybook/recommended" + ] } } diff --git a/apps/ungdomsytelse-veileder/src/App.tsx b/apps/ungdomsytelse-veileder/src/App.tsx index 6e5a5dfd50..27374c189b 100644 --- a/apps/ungdomsytelse-veileder/src/App.tsx +++ b/apps/ungdomsytelse-veileder/src/App.tsx @@ -17,7 +17,7 @@ const App = () => { - + }> } /> diff --git a/apps/ungdomsytelse-veileder/src/app.css b/apps/ungdomsytelse-veileder/src/app.css index aa772cea4e..81edfa8e4f 100644 --- a/apps/ungdomsytelse-veileder/src/app.css +++ b/apps/ungdomsytelse-veileder/src/app.css @@ -1,4 +1,4 @@ -@import 'tailwindcss'; +@import 'tailwindcss' layer(base); @import '@navikt/ds-css' layer(components); @import '@navikt/sif-common-core-ds/src/styles/sif-ds-theme.css' layer(utilities); @import 'react-loading-skeleton/dist/skeleton.css' layer(utilities); diff --git a/apps/ungdomsytelse-veileder/src/components/deltakelse-content/DeltakelseContent.tsx b/apps/ungdomsytelse-veileder/src/components/deltakelse-content/DeltakelseContent.tsx index 89fa1c285d..0b228b79ca 100644 --- a/apps/ungdomsytelse-veileder/src/components/deltakelse-content/DeltakelseContent.tsx +++ b/apps/ungdomsytelse-veileder/src/components/deltakelse-content/DeltakelseContent.tsx @@ -3,9 +3,11 @@ import DeltakelsePeriodeInfo from './parts/DeltakelsePeriodeInfo'; import DeltakelseHandlinger from './parts/DeltakelseHandlinger'; import DeltakelseEndringerOgVarsler from './parts/DeltakelseEndringerOgVarsler'; import { useDeltakelse } from '../../context/DeltakelseContext'; +import { useVeileder } from '../../context/VeilederContext'; const DeltakelseContent = () => { - const { deltakelse, deltaker } = useDeltakelse(); + const { deltakelse, deltaker, onDeltakelseChanged: onDeltakelseChange } = useDeltakelse(); + const { veileder } = useVeileder(); return ( @@ -15,7 +17,12 @@ const DeltakelseContent = () => { - + diff --git a/apps/ungdomsytelse-veileder/src/components/deltakelse-content/parts/DeltakelseEndringerOgVarsler.stories.tsx b/apps/ungdomsytelse-veileder/src/components/deltakelse-content/parts/DeltakelseEndringerOgVarsler.stories.tsx new file mode 100644 index 0000000000..dea5b3b288 --- /dev/null +++ b/apps/ungdomsytelse-veileder/src/components/deltakelse-content/parts/DeltakelseEndringerOgVarsler.stories.tsx @@ -0,0 +1,20 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { parsedMockDeltakelse } from '../../../../mock/msw/mocks/mockUtils'; +import { withIntl } from '../../../../storybook/decorators/withIntl'; +import { withPageWidth } from '../../../../storybook/decorators/withPageWidth'; +import DeltakelseEndringerOgVarsler from './DeltakelseEndringerOgVarsler'; +import { withVeilederContext } from '../../../../storybook/decorators/withVeilederContext'; + +const meta: Meta = { + component: DeltakelseEndringerOgVarsler, + title: 'Deltakelse/EndringerOgVarslinger', + parameters: {}, + decorators: [withPageWidth, withIntl, withVeilederContext], +}; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { deltakelse: parsedMockDeltakelse }, +}; diff --git a/apps/ungdomsytelse-veileder/src/components/deltakelse-content/parts/DeltakelseHandlinger.stories.tsx b/apps/ungdomsytelse-veileder/src/components/deltakelse-content/parts/DeltakelseHandlinger.stories.tsx new file mode 100644 index 0000000000..ec883507c9 --- /dev/null +++ b/apps/ungdomsytelse-veileder/src/components/deltakelse-content/parts/DeltakelseHandlinger.stories.tsx @@ -0,0 +1,20 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { parsedMockDeltakelse, parsedMockDeltaker, parsedVeilederMock } from '../../../../mock/msw/mocks/mockUtils'; +import { withIntl } from '../../../../storybook/decorators/withIntl'; +import { withPageWidth } from '../../../../storybook/decorators/withPageWidth'; +import DeltakelseHandlinger from './DeltakelseHandlinger'; +import { withVeilederContext } from '../../../../storybook/decorators/withVeilederContext'; + +const meta: Meta = { + component: DeltakelseHandlinger, + title: 'Deltakelse/Handlinger', + parameters: {}, + decorators: [withPageWidth, withIntl, withVeilederContext], +}; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { veileder: parsedVeilederMock, deltakelse: parsedMockDeltakelse, deltaker: parsedMockDeltaker }, +}; diff --git a/apps/ungdomsytelse-veileder/src/components/deltakelse-content/parts/DeltakelseHandlinger.tsx b/apps/ungdomsytelse-veileder/src/components/deltakelse-content/parts/DeltakelseHandlinger.tsx index 395c5997b4..2a14a6a6be 100644 --- a/apps/ungdomsytelse-veileder/src/components/deltakelse-content/parts/DeltakelseHandlinger.tsx +++ b/apps/ungdomsytelse-veileder/src/components/deltakelse-content/parts/DeltakelseHandlinger.tsx @@ -1,24 +1,36 @@ import { Button } from '@navikt/ds-react'; import { Deltakelse, Deltaker, Oppgavetype } from '@navikt/ung-common'; import { useState } from 'react'; -import EndreStartdatoModal from '../../endre-startdato-modal/EndreStartdatoModal'; import SectionContainer from '../../section-container/SectionContainer'; -import EndreSluttdatoModal from '../../endre-sluttdato-modal/EndreSluttdatoModal'; -import { useDeltaker } from '../../../context/DeltakerContext'; +import { Veileder } from '../../../types/Veileder'; +import EndreDeltakelseModal from '../../endre-deltakelse-modal/EndreDeltakelseModal'; +import EndreStartdatoForm from '../../../forms/endre-startdato-form/EndreStartdatoForm'; +import EndreSluttdatoForm from '../../../forms/endre-sluttdato-form/EndreSluttdatoForm'; interface Props { + veileder: Veileder; deltaker: Deltaker; deltakelse: Deltakelse; + onDeltakelseChanged: () => void; } -const DeltakelseHandlinger = ({ deltakelse, deltaker }: Props) => { - const [visOppgaveDialog, setVisOppgaveDialog] = useState(null); - const { refetchDeltakelser } = useDeltaker(); +const DeltakelseHandlinger = ({ veileder, deltakelse, deltaker, onDeltakelseChanged }: Props) => { + const [visOppgaveDialog, setVisOppgaveDialog] = useState(undefined); + const [endretDeltakelse, setEndretDeltakelse] = useState(); + const handleOnClose = () => { + setVisOppgaveDialog(undefined); + setEndretDeltakelse(undefined); + }; return ( <> - + + ) : null} + + ); +}; + +export default EndreDeltakelseModal; diff --git a/apps/ungdomsytelse-veileder/src/components/endre-sluttdato-modal/EndreSluttdatoModal.tsx b/apps/ungdomsytelse-veileder/src/components/endre-sluttdato-modal/EndreSluttdatoModal.tsx deleted file mode 100644 index 8640227181..0000000000 --- a/apps/ungdomsytelse-veileder/src/components/endre-sluttdato-modal/EndreSluttdatoModal.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { Alert, BodyShort, Button, Heading, List, Modal, VStack } from '@navikt/ds-react'; -import { Deltakelse, Deltaker } from '@navikt/ung-common'; -import { useState } from 'react'; -import { dateFormatter } from '@navikt/sif-common-utils'; -import EndreSluttdatoForm from '../../forms/endre-sluttdato-form/EndreSluttdatoForm'; - -interface Props { - deltaker: Deltaker; - deltakelse: Deltakelse; - onClose: () => void; - onChanged: () => void; -} - -const EndreSluttdatoModal = ({ deltakelse, deltaker, onClose, onChanged }: Props) => { - const [endretDeltakelse, setEndretDeltakelse] = useState(undefined); - return ( - onClose()} - aria-labelledby="oppgave-modal-heading" - width={endretDeltakelse ? 'medium' : '800px'}> - - - Endre sluttdato - - - - - {endretDeltakelse ? ( - - - Sluttdato for deltakelsen er endret til{' '} - - {dateFormatter.full(endretDeltakelse.fraOgMed)} - - . - - - - Hva skjer videre - - - Deltaker får et varsel om endringen på nav.no/minside - - Endringen blir gjeldende fra tidspunktet når deltaker bekrefter endringen, eller - senest 14 dager fra i dag. - - - Deltaker har mulighet til å ikke bekrefte endringen, men må da legge ved en - melding til saksbehandler. - - - - - ) : ( - setEndretDeltakelse(deltakelse)} - /> - )} - - - {endretDeltakelse ? ( - - - - ) : null} - - ); -}; - -export default EndreSluttdatoModal; diff --git a/apps/ungdomsytelse-veileder/src/components/endre-startdato-modal/EndreStartdatoModal.tsx b/apps/ungdomsytelse-veileder/src/components/endre-startdato-modal/EndreStartdatoModal.tsx deleted file mode 100644 index 5e309dfce0..0000000000 --- a/apps/ungdomsytelse-veileder/src/components/endre-startdato-modal/EndreStartdatoModal.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { Alert, BodyShort, Button, Heading, List, Modal, VStack } from '@navikt/ds-react'; -import { Deltakelse, Deltaker } from '@navikt/ung-common'; -import EndreStartdatoForm from '../../forms/endre-startdato-form/EndreStartdatoForm'; -import { useState } from 'react'; -import { dateFormatter } from '@navikt/sif-common-utils'; - -interface Props { - deltaker: Deltaker; - deltakelse: Deltakelse; - onClose: () => void; - onChanged: () => void; -} - -const EndreStartdatoModal = ({ deltakelse, deltaker, onClose, onChanged }: Props) => { - const [endretDeltakelse, setEndretDeltakelse] = useState(undefined); - return ( - onClose()} - aria-labelledby="oppgave-modal-heading" - width={endretDeltakelse ? 'medium' : '800px'}> - - - Endre startdato - - - - - {endretDeltakelse ? ( - - - Startdato for deltakelsen er endret til{' '} - - {dateFormatter.full(endretDeltakelse.fraOgMed)} - - . - - - - Hva skjer videre - - - Deltaker får et varsel om endringen på nav.no/minside - - Endringen blir gjeldende fra tidspunktet når deltaker bekrefter endringen, eller - senest 14 dager fra i dag. - - - Deltaker har mulighet til å ikke bekrefte endringen, men må da legge ved en - melding til saksbehandler. - - - - - ) : ( - onClose()} - onDeltakelseChanged={(deltakelse) => setEndretDeltakelse(deltakelse)} - /> - )} - - - {endretDeltakelse ? ( - - - - ) : null} - - ); -}; - -export default EndreStartdatoModal; diff --git a/apps/ungdomsytelse-veileder/src/context/DeltakelseContext.tsx b/apps/ungdomsytelse-veileder/src/context/DeltakelseContext.tsx index e745a3fba8..204e9ecc7f 100644 --- a/apps/ungdomsytelse-veileder/src/context/DeltakelseContext.tsx +++ b/apps/ungdomsytelse-veileder/src/context/DeltakelseContext.tsx @@ -5,7 +5,7 @@ import { useDeltaker } from './DeltakerContext'; interface DeltakelseContextProps { deltaker: Deltaker; deltakelse: Deltakelse; - onDeltakelseChange: () => void; + onDeltakelseChanged: () => void; } const DeltakelseContext = createContext(undefined); @@ -23,7 +23,7 @@ export const DeltakelseProvider = ({ children, deltaker, deltakelse }: Deltakels value={{ deltaker, deltakelse, - onDeltakelseChange: refetchDeltakelser, + onDeltakelseChanged: refetchDeltakelser, }}> {children} diff --git a/apps/ungdomsytelse-veileder/src/forms/endre-sluttdato-form/EndreSluttdatoForm.stories.tsx b/apps/ungdomsytelse-veileder/src/forms/endre-sluttdato-form/EndreSluttdatoForm.stories.tsx new file mode 100644 index 0000000000..9ecac7cef3 --- /dev/null +++ b/apps/ungdomsytelse-veileder/src/forms/endre-sluttdato-form/EndreSluttdatoForm.stories.tsx @@ -0,0 +1,20 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { parsedMockDeltakelse, parsedMockDeltaker, parsedVeilederMock } from '../../../mock/msw/mocks/mockUtils'; +import { withIntl } from '../../../storybook/decorators/withIntl'; +import { withModalWrapper } from '../../../storybook/decorators/withModalWrapper'; +import { withVeilederContext } from '../../../storybook/decorators/withVeilederContext'; +import EndreSluttdatoForm from './EndreSluttdatoForm'; + +const meta: Meta = { + component: EndreSluttdatoForm, + title: 'Forms/Endre sluttdato', + parameters: {}, + decorators: [withIntl, withVeilederContext, (Story) => withModalWrapper(Story, { header: 'Endre sluttdato' })], +}; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { veileder: parsedVeilederMock, deltakelse: parsedMockDeltakelse, deltaker: parsedMockDeltaker }, +}; diff --git a/apps/ungdomsytelse-veileder/src/forms/endre-sluttdato-form/EndreSluttdatoForm.tsx b/apps/ungdomsytelse-veileder/src/forms/endre-sluttdato-form/EndreSluttdatoForm.tsx index 0217c96cb4..1e5ee767a7 100644 --- a/apps/ungdomsytelse-veileder/src/forms/endre-sluttdato-form/EndreSluttdatoForm.tsx +++ b/apps/ungdomsytelse-veileder/src/forms/endre-sluttdato-form/EndreSluttdatoForm.tsx @@ -1,9 +1,9 @@ -import { Alert, BodyLong, Box, VStack } from '@navikt/ds-react'; +import { Alert, Box, VStack } from '@navikt/ds-react'; import { TypedFormikForm, TypedFormikWrapper } from '@navikt/sif-common-formik-ds'; import { ISODateToDate } from '@navikt/sif-common-utils'; import { Deltakelse, Deltaker, EndreSluttdatoOppgave, formaterNavn, Oppgavetype } from '@navikt/ung-common'; -import { useVeileder } from '../../context/VeilederContext'; import { useEndreDeltakelse } from '../../hooks/useEndreDeltakelse'; +import { Veileder } from '../../types/Veileder'; import PeriodeFormPart from '../periode-form-part/PeriodeFormPart'; export type EndreSluttdatoFormValues = { @@ -15,15 +15,14 @@ export type EndreSluttdatoFormValues = { }; interface Props { + veileder: Veileder; deltaker: Deltaker; deltakelse: Deltakelse; onCancel?: () => void; onDeltakelseChanged: (deltakelse: Deltakelse) => void; } -const EndreSluttdatoForm = ({ deltakelse, deltaker, onCancel, onDeltakelseChanged }: Props) => { - const { veileder } = useVeileder(); - +const EndreSluttdatoForm = ({ veileder, deltakelse, deltaker, onCancel, onDeltakelseChanged }: Props) => { const { endreSluttdato, pending, error } = useEndreDeltakelse(onDeltakelseChanged); const åpenOppgaver = deltakelse.oppgaver.filter( @@ -44,7 +43,7 @@ const EndreSluttdatoForm = ({ deltakelse, deltaker, onCancel, onDeltakelseChange renderForm={({ values }) => { const tomDate = values.tom ? ISODateToDate(values.tom) : undefined; return ( - + {åpenOppgave ? ( Det finnes allerede en endring av startdato som deltaker ikke har besvart enda. Hvis @@ -52,10 +51,10 @@ const EndreSluttdatoForm = ({ deltakelse, deltaker, onCancel, onDeltakelseChange ) : null} {deltakelse.harSøkt ? ( - + Når sluttdato endres, opprettes en oppgave til deltaker hvor hen må bekrefte den nye datoen. Oppgaven vil også bli synlig for deg under fanen "Oppgaver til deltaker". - + ) : null} { - return ( - - - Om å endre avslutte/endre sluttdato - - - - - Når sluttdato endres, opprettes en oppgave til deltaker hvor hen må bekrefte den nye - sluttdatoen. Oppgaven vil også bli synlig for deg under fanen "Oppgaver til deltaker". - - - - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere error, aliquam sint ipsa nulla - nesciunt doloribus iste est asperiores eaque laudantium iusto. Necessitatibus esse officia dolor - itaque, ipsum tenetur alias! - - - - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere error, aliquam sint ipsa nulla - nesciunt doloribus iste est asperiores eaque laudantium iusto. Necessitatibus esse officia dolor - itaque, ipsum tenetur alias! - - - - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere error, aliquam sint ipsa nulla - nesciunt doloribus iste est asperiores eaque laudantium iusto. Necessitatibus esse officia dolor - itaque, ipsum tenetur alias! - - - - - ); -}; - -export default EndreSluttdatoInfo; diff --git a/apps/ungdomsytelse-veileder/src/forms/endre-startdato-form/EndreStartdatoForm.stories.tsx b/apps/ungdomsytelse-veileder/src/forms/endre-startdato-form/EndreStartdatoForm.stories.tsx new file mode 100644 index 0000000000..37d81726ae --- /dev/null +++ b/apps/ungdomsytelse-veileder/src/forms/endre-startdato-form/EndreStartdatoForm.stories.tsx @@ -0,0 +1,20 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { parsedMockDeltakelse, parsedMockDeltaker, parsedVeilederMock } from '../../../mock/msw/mocks/mockUtils'; +import { withIntl } from '../../../storybook/decorators/withIntl'; +import { withVeilederContext } from '../../../storybook/decorators/withVeilederContext'; +import EndreStartdatoForm from './EndreStartdatoForm'; +import { withModalWrapper } from '../../../storybook/decorators/withModalWrapper'; + +const meta: Meta = { + component: EndreStartdatoForm, + title: 'Forms/Endre startdato', + parameters: {}, + decorators: [withIntl, withVeilederContext, (Story) => withModalWrapper(Story, { header: 'Endre startdato' })], +}; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { veileder: parsedVeilederMock, deltakelse: parsedMockDeltakelse, deltaker: parsedMockDeltaker }, +}; diff --git a/apps/ungdomsytelse-veileder/src/forms/endre-startdato-form/EndreStartdatoForm.tsx b/apps/ungdomsytelse-veileder/src/forms/endre-startdato-form/EndreStartdatoForm.tsx index a8a9920ecf..6774a2fa1c 100644 --- a/apps/ungdomsytelse-veileder/src/forms/endre-startdato-form/EndreStartdatoForm.tsx +++ b/apps/ungdomsytelse-veileder/src/forms/endre-startdato-form/EndreStartdatoForm.tsx @@ -1,10 +1,10 @@ -import { Alert, BodyLong, Box, VStack } from '@navikt/ds-react'; +import { Alert, Box, VStack } from '@navikt/ds-react'; import { TypedFormikForm, TypedFormikWrapper } from '@navikt/sif-common-formik-ds'; import { ISODateToDate } from '@navikt/sif-common-utils'; import { Deltakelse, Deltaker, EndreStartdatoOppgave, formaterNavn, Oppgavetype } from '@navikt/ung-common'; import { useEndreDeltakelse } from '../../hooks/useEndreDeltakelse'; import PeriodeFormPart from '../periode-form-part/PeriodeFormPart'; -import { useVeileder } from '../../context/VeilederContext'; +import { Veileder } from '../../types/Veileder'; export type EndreStartdatoFormValues = { id: string; @@ -14,15 +14,14 @@ export type EndreStartdatoFormValues = { }; interface Props { + veileder: Veileder; deltaker: Deltaker; deltakelse: Deltakelse; onCancel?: () => void; onDeltakelseChanged: (oppdatertDeltakelse: Deltakelse) => void; } -const EndreStartdatoForm = ({ deltakelse, deltaker, onCancel, onDeltakelseChanged }: Props) => { - const { veileder } = useVeileder(); - +const EndreStartdatoForm = ({ veileder, deltakelse, deltaker, onCancel, onDeltakelseChanged }: Props) => { const { endreStartdato, pending, error } = useEndreDeltakelse(onDeltakelseChanged); const åpenOppgaver = deltakelse.oppgaver.filter( @@ -43,27 +42,27 @@ const EndreStartdatoForm = ({ deltakelse, deltaker, onCancel, onDeltakelseChange renderForm={({ values }) => { const fomDate = values.fom ? ISODateToDate(values.fom) : undefined; return ( - + {åpenOppgave ? ( Det finnes allerede en endring av startdato som deltaker ikke har besvart enda. Hvis du registrerer en ny endring, vil den forrige endringen bli erstattet av denne. ) : null} - + {deltakelse.harSøkt ? ( - + <> Når startdato endres, opprettes en oppgave til deltaker hvor hen må bekrefte den nye startdatoen. Oppgaven vil også bli synlig for deg under fanen "Oppgaver til deltaker". - + ) : ( - + <> Deltaker har ikke søkt enda. Du kan endre startdatoen uten at det utløser blir noen oppgave til deltaker. - + )} - + { - return ( - - - Om å endre startdato - - - - - Når startdato endres, opprettes en oppgave til deltaker hvor hen må bekrefte den nye - startdatoen. Oppgaven vil også bli synlig for deg under fanen "Oppgaver til deltaker". - - - - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere error, aliquam sint ipsa nulla - nesciunt doloribus iste est asperiores eaque laudantium iusto. Necessitatibus esse officia dolor - itaque, ipsum tenetur alias! - - - - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere error, aliquam sint ipsa nulla - nesciunt doloribus iste est asperiores eaque laudantium iusto. Necessitatibus esse officia dolor - itaque, ipsum tenetur alias! - - - - - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere error, aliquam sint ipsa nulla - nesciunt doloribus iste est asperiores eaque laudantium iusto. Necessitatibus esse officia dolor - itaque, ipsum tenetur alias! - - - - - ); -}; - -export default EndreStartdatoInfo; diff --git a/apps/ungdomsytelse-veileder/src/forms/finn-deltaker-form/FinnDeltakerForm.tsx b/apps/ungdomsytelse-veileder/src/forms/finn-deltaker-form/FinnDeltakerForm.tsx index 5537fcc238..f863f7041a 100644 --- a/apps/ungdomsytelse-veileder/src/forms/finn-deltaker-form/FinnDeltakerForm.tsx +++ b/apps/ungdomsytelse-veileder/src/forms/finn-deltaker-form/FinnDeltakerForm.tsx @@ -90,70 +90,72 @@ const FinnDeltakerForm = ({ onDeltakerFetched, onDeltakelseRegistrert }: Props) }; return ( - -
{ - evt.stopPropagation(); - evt.preventDefault(); - fetchDeltaker(); - }}> -
- + + + { + evt.stopPropagation(); + evt.preventDefault(); + fetchDeltaker(); + }}> +
- { - setFnrValue(evt.target.value); - setKandidat(undefined); - }} - size="medium" - maxLength={11} - {...textFieldFormatterProps} - /> - - - + + { + setFnrValue(evt.target.value); + setKandidat(undefined); + }} + size="medium" + maxLength={11} + {...textFieldFormatterProps} + /> + + + + - -
- - {error ? {error} : null} - {nyDeltaker ? ( - - - +
+ + {error ? {error} : null} + {nyDeltaker ? ( + + + + + setRegistrerNy(evt.target.checked)}> + Registrer som ny deltaker + + + ) : ( + + )} + {registrerNy && nyDeltaker ? ( + + setRegistrerNy(false)} + onDeltakelseRegistrert={onDeltakelseRegistrert} + /> - setRegistrerNy(evt.target.checked)}> - Registrer som ny deltaker - -
- ) : ( - - )} - {registrerNy && nyDeltaker ? ( - - setRegistrerNy(false)} - onDeltakelseRegistrert={onDeltakelseRegistrert} - /> - - ) : null} - {getAppEnv().isLocal ? ( - - Testbrukere lokalt: - - 03867198392 - - - 56857102105 - - - ) : null} + ) : null} + {getAppEnv().isLocal ? ( + + Testbrukere lokalt: + + 03867198392 + + + 56857102105 + + + ) : null} +
); }; diff --git a/apps/ungdomsytelse-veileder/src/i18n/index.ts b/apps/ungdomsytelse-veileder/src/i18n/index.ts index f69e97c6cf..04674ce704 100644 --- a/apps/ungdomsytelse-veileder/src/i18n/index.ts +++ b/apps/ungdomsytelse-veileder/src/i18n/index.ts @@ -2,4 +2,5 @@ const nb = {}; export const appMessages = { nb, + nn: nb, }; diff --git a/apps/ungdomsytelse-veileder/src/pages/start-page/StartPage.stories.tsx b/apps/ungdomsytelse-veileder/src/pages/start-page/StartPage.stories.tsx new file mode 100644 index 0000000000..b262fef5ee --- /dev/null +++ b/apps/ungdomsytelse-veileder/src/pages/start-page/StartPage.stories.tsx @@ -0,0 +1,41 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { withIntl } from '../../../storybook/decorators/withIntl'; +import { withVeilederContext } from '../../../storybook/decorators/withVeilederContext'; +import { withPageWidth } from '../../../storybook/decorators/withPageWidth'; +import StartPage from './StartPage'; +import { BrowserRouter } from 'react-router-dom'; +import { withDarkBg } from '../../../storybook/decorators/withDarkBg'; +import { http, HttpResponse } from 'msw'; +import { nyDeltakerMock } from '../../../mock/msw/mocks/mockUtils'; + +const meta: Meta = { + component: StartPage, + title: 'Pages/Startside', + parameters: {}, + decorators: [withPageWidth, withDarkBg, withIntl, withVeilederContext], +}; +export default meta; + +type Story = StoryObj; + +function delay(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export const UregistrertDeltaker: Story = { + render: () => ( + + + + ), + parameters: { + msw: { + handlers: [ + http.post('http://localhost:6006/api/ung-deltakelse-opplyser/oppslag/deltaker', async () => { + await delay(1000); + return HttpResponse.json(nyDeltakerMock); + }), + ], + }, + }, +}; diff --git a/apps/ungdomsytelse-veileder/src/pages/start-page/StartPage.tsx b/apps/ungdomsytelse-veileder/src/pages/start-page/StartPage.tsx index ce4127f0a9..98f1080863 100644 --- a/apps/ungdomsytelse-veileder/src/pages/start-page/StartPage.tsx +++ b/apps/ungdomsytelse-veileder/src/pages/start-page/StartPage.tsx @@ -1,4 +1,4 @@ -import { HStack, VStack } from '@navikt/ds-react'; +import { HStack } from '@navikt/ds-react'; import { useNavigate } from 'react-router-dom'; import { Deltakelse, Deltaker } from '@navikt/ung-common'; import FinnDeltakerForm from '../../forms/finn-deltaker-form/FinnDeltakerForm'; @@ -17,14 +17,10 @@ const StartPage = () => { return ( <> - - - + ); diff --git a/apps/ungdomsytelse-veileder/storybook/components/AlertStoryWrapper.tsx b/apps/ungdomsytelse-veileder/storybook/components/AlertStoryWrapper.tsx new file mode 100644 index 0000000000..496949913e --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/components/AlertStoryWrapper.tsx @@ -0,0 +1,35 @@ +import { Heading, VStack } from '@navikt/ds-react'; +import { ReactNode } from 'react'; +import MessagesList from '@navikt/sif-common-core-ds/src/dev-utils/intl/messages-preview/MessagesList'; +import ShadowBox from './ShadowBox'; +import { storybookIntlUtils } from '../utils/intlUtils'; + +const AlertStoryWrapper = ({ + title, + children, + intlScope, +}: { + title: string; + children: ReactNode; + intlScope?: string; +}) => { + const messages = intlScope + ? storybookIntlUtils.getIntlMessagesFromKeys(storybookIntlUtils.getScopedIntlKeys(intlScope)) + : undefined; + return ( + <> + + + + {title} + +
{children}
+
+
+ + {messages && } + + ); +}; + +export default AlertStoryWrapper; diff --git a/apps/ungdomsytelse-veileder/storybook/components/ShadowBox.tsx b/apps/ungdomsytelse-veileder/storybook/components/ShadowBox.tsx new file mode 100644 index 0000000000..b8efa42721 --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/components/ShadowBox.tsx @@ -0,0 +1,11 @@ +import { Box } from '@navikt/ds-react'; + +const ShadowBox = ({ children }: { children: React.ReactNode }) => { + return ( + + {children} + + ); +}; + +export default ShadowBox; diff --git "a/apps/ungdomsytelse-veileder/storybook/components/Sp\303\270rsm\303\245lWrapper.tsx" "b/apps/ungdomsytelse-veileder/storybook/components/Sp\303\270rsm\303\245lWrapper.tsx" new file mode 100644 index 0000000000..f72ba4ee9d --- /dev/null +++ "b/apps/ungdomsytelse-veileder/storybook/components/Sp\303\270rsm\303\245lWrapper.tsx" @@ -0,0 +1,63 @@ +import { Box, Button, Tabs, VStack } from '@navikt/ds-react'; +import * as React from 'react'; +import { MessagesTable } from '@navikt/sif-common-core-ds/src/dev-utils/intl/messages-preview/MessagesList'; +import { storybookIntlUtils } from '../utils/intlUtils'; +import ShadowBox from './ShadowBox'; +import { StoryFormikWrapper } from './StoryFormikWrapper'; +import '@navikt/ds-css'; + +export interface SpørsmålWrapperProps { + formErrorHandlerIntlKey: string; + spørsmål: React.ReactNode; + messageIntlKeys?: string[]; + validationErrorIntlKeys?: string[]; +} + +const { getIntlMessagesFromKeys } = storybookIntlUtils; + +export const SpørsmålWrapper: React.FunctionComponent = (props) => { + const { spørsmål, messageIntlKeys = [], validationErrorIntlKeys = [], formErrorHandlerIntlKey } = props; + const infoMessages = getIntlMessagesFromKeys(messageIntlKeys); + const validationMessages = getIntlMessagesFromKeys(validationErrorIntlKeys); + const allMessages = getIntlMessagesFromKeys([...messageIntlKeys, ...validationErrorIntlKeys]); + + return ( + + + + + + {spørsmål} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/apps/ungdomsytelse-veileder/storybook/components/StoryFormWrapper.tsx b/apps/ungdomsytelse-veileder/storybook/components/StoryFormWrapper.tsx new file mode 100644 index 0000000000..10ba4d53db --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/components/StoryFormWrapper.tsx @@ -0,0 +1,17 @@ +import { Box, VStack } from '@navikt/ds-react'; + +interface Props { + children: React.ReactNode; + values?: any; + maxWidth?: string; +} + +const StoryFormWrapper = ({ children, maxWidth = '35rem' }: Props) => ( + + + {children} + + +); + +export default StoryFormWrapper; diff --git a/apps/ungdomsytelse-veileder/storybook/components/StoryFormikWrapper.tsx b/apps/ungdomsytelse-veileder/storybook/components/StoryFormikWrapper.tsx new file mode 100644 index 0000000000..3f7f465c0a --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/components/StoryFormikWrapper.tsx @@ -0,0 +1,61 @@ +import { Box } from '@navikt/ds-react'; +import * as React from 'react'; +import { TypedFormikForm, TypedFormikWrapper } from '@navikt/sif-common-formik-ds'; +import { getIntlFormErrorHandler } from '@navikt/sif-common-formik-ds'; +import '@navikt/ds-css'; +import { useIntl } from 'react-intl'; + +interface Props { + parameters?: { + formik?: any; + includeButtons?: boolean; + maxWidth?: string; + formErrorHandlerIntlKey: string; + }; + children: React.ReactNode; + useBorder?: boolean; +} + +export const StoryFormikWrapper: React.FunctionComponent = (props) => { + const intl = useIntl(); + const { children, parameters, useBorder } = props; + const { + formik, + maxWidth = '800px', + includeButtons = true, + formErrorHandlerIntlKey = 'formIntlKey', + } = parameters || {}; + const initialValues = formik?.initialValues || {}; + + return ( + { + // eslint-disable-next-line no-console + console.log('StoryFormikProvider', values); + }} + renderForm={() => { + return ( + null} + includeValidationSummary={true} + formErrorHandler={getIntlFormErrorHandler(intl, formErrorHandlerIntlKey)} + runDelayedFormValidation={true}> + + {children} + + + ); + }} + /> + ); +}; diff --git a/apps/ungdomsytelse-veileder/storybook/decorators/print.css b/apps/ungdomsytelse-veileder/storybook/decorators/print.css new file mode 100644 index 0000000000..1c94453379 --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/decorators/print.css @@ -0,0 +1,17 @@ +@media print { + .navds-progress-bar { + display: none; + } + .navds-form-progress__collapsible { + display: none !important; + } + #decorator-header { + display: none !important; + } + #decorator-footer { + display: none !important; + } + .navds-tabs__tablist-wrapper { + display: none !important; + } +} diff --git a/apps/ungdomsytelse-veileder/storybook/decorators/withDarkBg.tsx b/apps/ungdomsytelse-veileder/storybook/decorators/withDarkBg.tsx new file mode 100644 index 0000000000..6504d783e2 --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/decorators/withDarkBg.tsx @@ -0,0 +1,5 @@ +export const withDarkBg = (Story) => ( +
+ +
+); diff --git a/apps/ungdomsytelse-veileder/storybook/decorators/withDeltakerContext.tsx b/apps/ungdomsytelse-veileder/storybook/decorators/withDeltakerContext.tsx new file mode 100644 index 0000000000..c9445afae2 --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/decorators/withDeltakerContext.tsx @@ -0,0 +1,12 @@ +import { BrowserRouter } from 'react-router-dom'; +import { DeltakerProvider } from '../../src/context/DeltakerContext'; + +export const withDeltakerContext = (Story) => { + return ( + + + + + + ); +}; diff --git a/apps/ungdomsytelse-veileder/storybook/decorators/withEnvSettings.tsx b/apps/ungdomsytelse-veileder/storybook/decorators/withEnvSettings.tsx new file mode 100644 index 0000000000..c3d3afca93 --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/decorators/withEnvSettings.tsx @@ -0,0 +1,4 @@ +export const withEnvSettings = (Story) => { + (window as any).appSettings.APP_VERSION = 'production'; + return ; +}; diff --git a/apps/ungdomsytelse-veileder/storybook/decorators/withFormikWrapper.tsx b/apps/ungdomsytelse-veileder/storybook/decorators/withFormikWrapper.tsx new file mode 100644 index 0000000000..4dbdb6f16c --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/decorators/withFormikWrapper.tsx @@ -0,0 +1,7 @@ +import { StoryFormikWrapper } from '../components/StoryFormikWrapper'; + +export const withFormikWrapper = (Story, args) => ( + + + +); diff --git a/apps/ungdomsytelse-veileder/storybook/decorators/withIntl.tsx b/apps/ungdomsytelse-veileder/storybook/decorators/withIntl.tsx new file mode 100644 index 0000000000..b8835fc4fb --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/decorators/withIntl.tsx @@ -0,0 +1,16 @@ +import { IntlProvider } from 'react-intl'; +import { uiMessages } from '@navikt/sif-common-ui'; +import { appMessages } from '../../src/i18n'; +import './print.css'; + +export const withIntl = (Story, context) => { + const locale = context?.parameters?.locale || context?.globals.locale || 'nb'; + const messages = + locale === 'nb' ? { ...appMessages.nb, ...uiMessages.nb } : { ...appMessages.nn, ...uiMessages.nn }; + + return ( + + + + ); +}; diff --git a/apps/ungdomsytelse-veileder/storybook/decorators/withModalWrapper.tsx b/apps/ungdomsytelse-veileder/storybook/decorators/withModalWrapper.tsx new file mode 100644 index 0000000000..49d720429f --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/decorators/withModalWrapper.tsx @@ -0,0 +1,18 @@ +import { Heading, Modal } from '@navikt/ds-react'; + +export const withModalWrapper = (Story, args) => ( + + + +); + +export const ModalWrapper = ({ header, children }: { header: string; children: React.ReactNode }) => ( + {}}> + + + {header} + + + {children} + +); diff --git a/apps/ungdomsytelse-veileder/storybook/decorators/withPageWidth.tsx b/apps/ungdomsytelse-veileder/storybook/decorators/withPageWidth.tsx new file mode 100644 index 0000000000..8d415a21c0 --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/decorators/withPageWidth.tsx @@ -0,0 +1,7 @@ +export const withPageWidth = (Story) => ( +
+
+ +
+
+); diff --git a/apps/ungdomsytelse-veileder/storybook/decorators/withRouter.tsx b/apps/ungdomsytelse-veileder/storybook/decorators/withRouter.tsx new file mode 100644 index 0000000000..fe97ceeb23 --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/decorators/withRouter.tsx @@ -0,0 +1,5 @@ +import { BrowserRouter } from 'react-router-dom'; + +export const withRouter = (Story) => { + return {Story}; +}; diff --git a/apps/ungdomsytelse-veileder/storybook/decorators/withVeilederContext.tsx b/apps/ungdomsytelse-veileder/storybook/decorators/withVeilederContext.tsx new file mode 100644 index 0000000000..d5991f2763 --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/decorators/withVeilederContext.tsx @@ -0,0 +1,10 @@ +import { VeilederProvider } from '../../src/context/VeilederContext'; +import { parsedVeilederMock } from '../../mock/msw/mocks/mockUtils'; + +export const withVeilederContext = (Story) => { + return ( + + + + ); +}; diff --git a/apps/ungdomsytelse-veileder/storybook/mock-data/index.ts b/apps/ungdomsytelse-veileder/storybook/mock-data/index.ts new file mode 100644 index 0000000000..a5f68ede4c --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/mock-data/index.ts @@ -0,0 +1,26 @@ +import { RegistrertBarn, Søker } from '@navikt/sif-common-api'; +import { ISODateToDate } from '@navikt/sif-common-utils'; + +export const SøkerMock: Søker = { + fødselsnummer: '30086421581', + fornavn: 'GODSLIG', + aktørId: '132', + fødselsdato: ISODateToDate('1990-01-01'), + etternavn: 'KRONJUVEL', +}; + +export const RegistrerteBarnMock: RegistrertBarn[] = [ + { + fødselsdato: ISODateToDate('1990-01-01'), + fornavn: 'Barn', + mellomnavn: 'Barne', + etternavn: 'Barnesen', + aktørId: '1', + }, + { + fødselsdato: ISODateToDate('1990-01-02'), + fornavn: 'Mock', + etternavn: 'Mocknes', + aktørId: '2', + }, +]; diff --git a/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/arbeidsgiverMock.ts b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/arbeidsgiverMock.ts new file mode 100644 index 0000000000..1279cf6680 --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/arbeidsgiverMock.ts @@ -0,0 +1,10 @@ +export const arbeidsgiverMock = { + organisasjoner: [ + { + navn: 'HAUGEN AS', + organisasjonsnummer: '123451234', + ansattFom: '2019-09-25', + ansattTom: null, + }, + ], +}; diff --git a/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/barnMock.ts b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/barnMock.ts new file mode 100644 index 0000000000..59ed845cfa --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/barnMock.ts @@ -0,0 +1,11 @@ +export const barnMock = { + barn: [ + { + fornavn: 'ALFABETISK', + etternavn: 'TURLØYPE', + aktørId: '2811762539343', + fødselsdato: '2019-06-08', + fødselsnummer: '08861999573', + }, + ], +}; diff --git "a/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/deltakelser/harS\303\270kt.ts" "b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/deltakelser/harS\303\270kt.ts" new file mode 100644 index 0000000000..854f782fd5 --- /dev/null +++ "b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/deltakelser/harS\303\270kt.ts" @@ -0,0 +1,115 @@ +import { DeltakelsePeriodInfo, OppgaveStatus, Oppgavetype } from '@navikt/ung-deltakelse-opplyser-api'; + +export const deltakelserHarSøkt: DeltakelsePeriodInfo[] = [ + { + id: '3b2d6764-1ea1-4b5d-9a07-d4d5e254b595', + fraOgMed: '2024-12-02', + tilOgMed: undefined, + harSøkt: true, + oppgaver: [ + // { + // id: 'fc2c6f01-8746-4ca0-b77a-40cc48bba216', + // oppgavetype: Oppgavetype.BEKREFT_ENDRET_SLUTTDATO, + // eksternReferanse: '3b2d6764-1ea1-4b5d-9a07-d4d5e254b595', + // oppgavetypeData: { + // type: 'BEKREFT_ENDRET_STARTDATO', + // nySluttdato: '2026-01-01', + // veilederRef: 'Pål Hønesen, Andeby', + // meldingFraVeileder: 'Jeg endrer sluttdatoen som vi avtalte på møtet forrige uke.', + // }, + // status: OppgaveStatus.ULØST, + // opprettetDato: '2025-02-22T11:43:29.048157Z', + // løstDato: '2025-02-23T05:00:12.048157Z', + // }, + // { + // id: 'fc2c6f01-8746-4ca0-b77a-40cc48bba216', + // eksternReferanse: '3b2d6764-1ea1-4b5d-9a07-d4d5e254b595', + // oppgavetype: Oppgavetype.BEKREFT_ENDRET_SLUTTDATO, + // oppgavetypeData: { + // type: 'BEKREFT_ENDRET_STARTDATO', + // nySluttdato: '2026-01-01', + // veilederRef: 'Pål Hønesen, Andeby', + // meldingFraVeileder: 'Jeg endrer sluttdatoen som vi avtalte på møtet forrige uke.', + // }, + // status: OppgaveStatus.UTLØPT, + // opprettetDato: '2025-02-22T11:43:29.048157Z', + // løstDato: '2025-02-23T05:00:12.048157Z', + // }, + { + id: 'fc2c6f01-8746-4ca0-b77a-40cc48bba216', + oppgavetype: Oppgavetype.BEKREFT_AVVIK_REGISTERINNTEKT, + eksternReferanse: '3b2d6764-1ea1-4b5d-9a07-d4d5e254b595', + oppgavetypeData: { + fraOgMed: '2026-01-01', + tilOgMed: '2026-01-31', + registerinntekt: { + arbeidOgFrilansInntekter: [ + { + arbeidsgiver: 'Flåklypa barteservice', + inntekt: 1200, + }, + { + arbeidsgiver: 'Hopen klyp og klem', + inntekt: 50, + }, + ], + ytelseInntekter: [ + { + ytelsetype: 'Sykepenger', + inntekt: 4000, + }, + ], + totalInntektArbeidOgFrilans: 1250, + totalInntektYtelse: 5000, + totalInntekt: 5250, + }, + }, + status: OppgaveStatus.ULØST, + opprettetDato: '2025-02-22T11:43:29.048157Z', + løstDato: '2025-02-23T05:00:12.048157Z', + }, + ], + rapporteringsPerioder: [ + { + fraOgMed: '2024-12-02', + tilOgMed: '2024-12-31', + harRapportert: false, + arbeidstakerOgFrilansInntekt: undefined, + inntektFraYtelse: undefined, + summertInntekt: 0, + }, + { + fraOgMed: '2025-01-01', + tilOgMed: '2025-01-31', + harRapportert: false, + arbeidstakerOgFrilansInntekt: undefined, + inntektFraYtelse: undefined, + summertInntekt: 0, + }, + { + fraOgMed: '2025-02-01', + tilOgMed: '2025-02-26', + harRapportert: false, + arbeidstakerOgFrilansInntekt: undefined, + inntektFraYtelse: undefined, + summertInntekt: 0, + }, + { + fraOgMed: '2025-03-01', + tilOgMed: '2025-03-31', + harRapportert: false, + arbeidstakerOgFrilansInntekt: undefined, + inntektFraYtelse: undefined, + summertInntekt: 0, + }, + { + fraOgMed: '2025-04-01', + tilOgMed: '2025-04-30', + harRapportert: false, + arbeidstakerOgFrilansInntekt: undefined, + inntektFraYtelse: undefined, + summertInntekt: 0, + }, + ], + }, +]; diff --git "a/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/deltakelser/ikkeS\303\270kt.ts" "b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/deltakelser/ikkeS\303\270kt.ts" new file mode 100644 index 0000000000..3bf21c1804 --- /dev/null +++ "b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/deltakelser/ikkeS\303\270kt.ts" @@ -0,0 +1,83 @@ +export const deltakelserIkkeSøkt = [ + { + id: '123', + fraOgMed: '2024-07-01', + tilOgMed: '2025-06-30', + harSøkt: false, + oppgaver: [], + rapporteringsPerioder: [ + { + fraOgMed: '2024-07-01', + tilOgMed: '2024-07-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2024-08-01', + tilOgMed: '2024-08-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2024-09-01', + tilOgMed: '2024-09-30', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2024-10-01', + tilOgMed: '2024-10-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2024-11-01', + tilOgMed: '2024-11-30', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2024-12-01', + tilOgMed: '2024-12-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2025-01-01', + tilOgMed: '2025-01-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2025-02-01', + tilOgMed: '2025-02-28', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2025-03-01', + tilOgMed: '2025-03-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2025-04-01', + tilOgMed: '2025-04-30', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2025-05-01', + tilOgMed: '2025-05-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2025-06-01', + tilOgMed: '2025-06-30', + harRapportert: false, + inntekt: null, + }, + ], + }, +]; diff --git a/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/hentAlle.ts b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/hentAlle.ts new file mode 100644 index 0000000000..87cd820473 --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/hentAlle.ts @@ -0,0 +1,82 @@ +export const hentAlleResponse = [ + { + id: '123', + fraOgMed: '2024-07-01', + tilOgMed: '2025-06-30', + harSøkt: false, + rapporteringsPerioder: [ + { + fraOgMed: '2024-07-01', + tilOgMed: '2024-07-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2024-08-01', + tilOgMed: '2024-08-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2024-09-01', + tilOgMed: '2024-09-30', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2024-10-01', + tilOgMed: '2024-10-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2024-11-01', + tilOgMed: '2024-11-30', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2024-12-01', + tilOgMed: '2024-12-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2025-01-01', + tilOgMed: '2025-01-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2025-02-01', + tilOgMed: '2025-02-28', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2025-03-01', + tilOgMed: '2025-03-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2025-04-01', + tilOgMed: '2025-04-30', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2025-05-01', + tilOgMed: '2025-05-31', + harRapportert: false, + inntekt: null, + }, + { + fraOgMed: '2025-06-01', + tilOgMed: '2025-06-30', + harRapportert: false, + inntekt: null, + }, + ], + }, +]; diff --git a/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/index.ts b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/index.ts new file mode 100644 index 0000000000..47f50d01ed --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/index.ts @@ -0,0 +1,9 @@ +import { arbeidsgiverMock } from './arbeidsgiverMock'; +import { barnMock } from './barnMock'; +import { søkerMock } from './søkerMock'; + +export const søker1Mock = { + barn: barnMock, + søker: søkerMock, + arbeidsgiver: arbeidsgiverMock, +}; diff --git "a/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/s\303\270kerMock.ts" "b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/s\303\270kerMock.ts" new file mode 100644 index 0000000000..3b50e0b393 --- /dev/null +++ "b/apps/ungdomsytelse-veileder/storybook/mock-data/soker1/s\303\270kerMock.ts" @@ -0,0 +1,8 @@ +export const søkerMock = { + aktørId: '2320509955297', + fødselsdato: '2005-06-02', + fødselsnummer: '02869599258', + fornavn: 'Test', + mellomnavn: null, + etternavn: 'Brukeresen', +}; diff --git a/apps/ungdomsytelse-veileder/storybook/utils/intlUtils.ts b/apps/ungdomsytelse-veileder/storybook/utils/intlUtils.ts new file mode 100644 index 0000000000..73b8aa9c73 --- /dev/null +++ b/apps/ungdomsytelse-veileder/storybook/utils/intlUtils.ts @@ -0,0 +1,34 @@ +import { appMessages } from '../../src/i18n'; +import { MessageFileFormat } from '@navikt/sif-common-core-ds/src/types'; + +const getIntlMessagesFromKeys = (keys: string[]): MessageFileFormat => { + const messages: MessageFileFormat = { + nb: {}, + nn: {}, + }; + keys.map((k) => { + messages.nb[k] = appMessages.nb[k]; + messages.nn[k] = appMessages.nn[k]; + }); + + return messages; +}; + +const getValidationIntlKeys = (keys: string[], intlKeyPath: string) => { + return keys.map((key) => `${intlKeyPath}.${key}`); +}; + +const getScopedIntlKeys = (scope: string): string[] => { + return Object.keys(appMessages.nb).filter((key) => key.includes(scope)); +}; + +const getScopedMessages = (scope: string): MessageFileFormat => { + return getIntlMessagesFromKeys(getScopedIntlKeys(scope)); +}; + +export const storybookIntlUtils = { + getIntlMessagesFromKeys, + getScopedIntlKeys, + getScopedMessages, + getValidationIntlKeys, +}; diff --git a/apps/ungdomsytelse-veileder/tailwind.config.ts b/apps/ungdomsytelse-veileder/tailwind.config.ts index 6d3d9f249e..026ee68966 100644 --- a/apps/ungdomsytelse-veileder/tailwind.config.ts +++ b/apps/ungdomsytelse-veileder/tailwind.config.ts @@ -3,5 +3,5 @@ import type { Config } from 'tailwindcss'; export default { presets: [dsTailwind], - content: ['./src/**'], + content: ['./src/**', './storybook/**'], } satisfies Config; diff --git a/apps/ungdomsytelse-veileder/tsconfig.json b/apps/ungdomsytelse-veileder/tsconfig.json index 2736a2e732..7b05b76a7e 100644 --- a/apps/ungdomsytelse-veileder/tsconfig.json +++ b/apps/ungdomsytelse-veileder/tsconfig.json @@ -6,5 +6,5 @@ "typeRoots": ["../../node_modules/@types", "./node_modules/@types"] }, "exclude": ["node_modules", "src/build", "**.js", "dist"], - "include": ["./src/**/*", "./mock/msw/**/*", "./vite-env.d.ts"] + "include": ["./src/**/*", "./mock/msw/**/*", "./vite-env.d.ts", "./storybook/**/*"] } diff --git a/apps/ungdomsytelse-veileder/vitest.shims.d.ts b/apps/ungdomsytelse-veileder/vitest.shims.d.ts new file mode 100644 index 0000000000..f923d47d48 --- /dev/null +++ b/apps/ungdomsytelse-veileder/vitest.shims.d.ts @@ -0,0 +1 @@ +/// \ No newline at end of file diff --git a/packages/k9-brukerdialog-prosessering-api/src/client/types.gen.ts b/packages/k9-brukerdialog-prosessering-api/src/client/types.gen.ts index a78ed7c54c..f08bea1dad 100644 --- a/packages/k9-brukerdialog-prosessering-api/src/client/types.gen.ts +++ b/packages/k9-brukerdialog-prosessering-api/src/client/types.gen.ts @@ -34,7 +34,7 @@ export type EndretStartdatoUngdomsytelseOppgaveDto = UngdomsytelseOppgaveDto & { }; export type BekreftKorrigertInntektOppgaveDto = UngdomsytelseOppgaveDto & { - type: 'BEKREFT_KORRIGERT_INNTEKT'; + type: 'BEKREFT_AVVIK_REGISTERINNTEKT'; }; export type UngdomsytelseIkkeGodkjentResponse = { @@ -44,8 +44,8 @@ export type UngdomsytelseIkkeGodkjentResponse = { }; export type UngdomsytelseIkkeGodkjentInntektResponse = { - arbeidstakerOgFrilansInntekt?: number; - inntektFraYtelse?: number; + arbeidOgFrilansInntekter?: number; + ytelseInntekter?: number; meldingFraDeltaker: string; }; @@ -65,8 +65,8 @@ export type UngdomsytelseOppgavebekreftelse = { }; export type OppgittInntektForPeriode = { - arbeidstakerOgFrilansInntekt?: number; - inntektFraYtelse?: number; + arbeidOgFrilansInntekter?: number; + ytelseInntekter?: number; periodeForInntekt: UngPeriode; }; diff --git a/packages/k9-brukerdialog-prosessering-api/src/client/zod.gen.ts b/packages/k9-brukerdialog-prosessering-api/src/client/zod.gen.ts index 8056172358..9bb23d1edd 100644 --- a/packages/k9-brukerdialog-prosessering-api/src/client/zod.gen.ts +++ b/packages/k9-brukerdialog-prosessering-api/src/client/zod.gen.ts @@ -67,8 +67,8 @@ export const zBekreftKorrigertInntektOppgaveDto = z bekreftelseSvar: z.enum(['GODTAR', 'AVSLÅR']), ikkeGodkjentResponse: z .object({ - arbeidstakerOgFrilansInntekt: z.number().int().optional(), - inntektFraYtelse: z.number().int().optional(), + arbeidOgFrilansInntekter: z.number().int().optional(), + ytelseInntekter: z.number().int().optional(), meldingFraDeltaker: z.string(), }) .optional(), @@ -76,7 +76,7 @@ export const zBekreftKorrigertInntektOppgaveDto = z }) .merge( z.object({ - type: z.literal('BEKREFT_KORRIGERT_INNTEKT'), + type: z.literal('BEKREFT_AVVIK_REGISTERINNTEKT'), }), ); @@ -87,8 +87,8 @@ export const zUngdomsytelseIkkeGodkjentResponse = z.object({ }); export const zUngdomsytelseIkkeGodkjentInntektResponse = z.object({ - arbeidstakerOgFrilansInntekt: z.number().int().optional(), - inntektFraYtelse: z.number().int().optional(), + arbeidOgFrilansInntekter: z.number().int().optional(), + ytelseInntekter: z.number().int().optional(), meldingFraDeltaker: z.string(), }); @@ -111,8 +111,8 @@ export const zUngdomsytelseOppgavebekreftelse = z.object({ }); export const zOppgittInntektForPeriode = z.object({ - arbeidstakerOgFrilansInntekt: z.number().int().optional(), - inntektFraYtelse: z.number().int().optional(), + arbeidOgFrilansInntekter: z.number().int().optional(), + ytelseInntekter: z.number().int().optional(), periodeForInntekt: z.object({ fraOgMed: z.string().date(), tilOgMed: z.string().date(), diff --git a/packages/ung-common/src/api/parse-utils/parseOppgaverElement.ts b/packages/ung-common/src/api/parse-utils/parseOppgaverElement.ts index d87e762c1c..6c83bad84b 100644 --- a/packages/ung-common/src/api/parse-utils/parseOppgaverElement.ts +++ b/packages/ung-common/src/api/parse-utils/parseOppgaverElement.ts @@ -2,7 +2,7 @@ import { ISODateToDate } from '@navikt/sif-common-utils'; import { EndretSluttdatoOppgavetypeDataDto, EndretStartdatoOppgavetypeDataDto, - KorrigertInntektOppgavetypeDataDto, + KontrollerRegisterinntektOppgavetypeDataDto, OppgaveStatus, Oppgavetype, zDeltakelseOpplysningDto, @@ -22,8 +22,8 @@ const getOppgaveStatusEnum = (status: string): OppgaveStatus => { return OppgaveStatus.ULØST; case 'KANSELLERT': return OppgaveStatus.KANSELLERT; - case 'UTLØPT': - return OppgaveStatus.UTLØPT; + // case 'UTLØPT': + // return OppgaveStatus.UTLØPT; default: throw new Error(`Ukjent oppgavestatus: ${status}`); } @@ -71,25 +71,22 @@ export const parseOppgaverElement = (oppgaver: zOppgaveElement[]): Oppgave[] => }; parsedOppgaver.push(endretSluttdatoOppgave); return; - case Oppgavetype.BEKREFT_KORRIGERT_INNTEKT: - const korrigertInntektData = oppgave.oppgavetypeData as KorrigertInntektOppgavetypeDataDto; + case Oppgavetype.BEKREFT_AVVIK_REGISTERINNTEKT: + const korrigertInntektData = oppgave.oppgavetypeData as KontrollerRegisterinntektOppgavetypeDataDto; const korrigertInntektOppgave: KorrigertInntektOppgave = { id: oppgave.id, status: getOppgaveStatusEnum(oppgave.status), opprettetDato, svarfrist, løstDato, - oppgavetype: Oppgavetype.BEKREFT_KORRIGERT_INNTEKT, + oppgavetype: Oppgavetype.BEKREFT_AVVIK_REGISTERINNTEKT, oppgavetypeData: { - inntektFraAinntekt: { - arbeidsgivere: korrigertInntektData.inntektFraAinntekt.arbeidsgivere, - ytelser: korrigertInntektData.inntektFraAinntekt.ytelser, + fraOgMed: ISODateToDate(korrigertInntektData.fraOgMed), + tilOgMed: ISODateToDate(korrigertInntektData.tilOgMed), + registerinntekt: { + arbeidOgFrilansInntekter: korrigertInntektData.registerinntekt.arbeidOgFrilansInntekter, + ytelseInntekter: korrigertInntektData.registerinntekt.ytelseInntekter, }, - periodeForInntekt: { - fraOgMed: ISODateToDate(korrigertInntektData.periodeForInntekt.fraOgMed), - tilOgMed: ISODateToDate(korrigertInntektData.periodeForInntekt.tilOgMed), - }, - inntektFraDeltaker: korrigertInntektData.inntektFraDeltaker, }, }; parsedOppgaver.push(korrigertInntektOppgave); diff --git a/packages/ung-common/src/api/parse-utils/parseRapporteringsperioder.ts b/packages/ung-common/src/api/parse-utils/parseRapporteringsperioder.ts index 4efd0f4f6b..854172eb42 100644 --- a/packages/ung-common/src/api/parse-utils/parseRapporteringsperioder.ts +++ b/packages/ung-common/src/api/parse-utils/parseRapporteringsperioder.ts @@ -1,4 +1,4 @@ -import { DateRange, ISODateToDate, OpenDateRange } from '@navikt/sif-common-utils'; +import { DateRange, getDateToday, isDateInDateRange, ISODateToDate, OpenDateRange } from '@navikt/sif-common-utils'; import { RapportPeriodeinfoDto } from '@navikt/ung-deltakelse-opplyser-api'; import dayjs from 'dayjs'; import { Rapporteringsperiode } from '../../types'; @@ -7,8 +7,18 @@ const erDatoIFørsteMånedIProgrammet = (dato: Date, programStartdato: Date): bo return dayjs(dato).isSame(programStartdato, 'month'); }; -const kanBrukerRapportereInntektForPeriode = (periode: DateRange, programStartdato: Date): boolean => { - return erDatoIFørsteMånedIProgrammet(periode.from, programStartdato) === false; +const getTillattRapporteringsperiodeForMåned = (dato: Date): DateRange => { + return { from: dayjs(dato).startOf('month').toDate(), to: dayjs(dato).add(6, 'days').toDate() }; +}; + +const erPeriodeInnforTillattRapporteringstidsrom = (periode: DateRange, programStartdato: Date): boolean => { + /** Skal ikke rapportere for første måned */ + if (erDatoIFørsteMånedIProgrammet(periode.from, programStartdato)) { + return false; + } + /** Kan rapportere hvis dagens dato er innenfor tillatt rapporteringsperiode for måned */ + const rapporteringsperiodeIMåned = getTillattRapporteringsperiodeForMåned(periode.from); + return isDateInDateRange(getDateToday(), rapporteringsperiodeIMåned); }; export const parseRapporteringsperioder = ( @@ -16,22 +26,22 @@ export const parseRapporteringsperioder = ( rapporteringsperioder: RapportPeriodeinfoDto[], ): Rapporteringsperiode[] => { return rapporteringsperioder.map((data) => { - const { arbeidstakerOgFrilansInntekt = 0, inntektFraYtelse = 0 } = data; + const { arbeidstakerOgFrilansInntekt = 0, inntektFraYtelse = 0, summertInntekt } = data; const periode: DateRange = { from: ISODateToDate(data.fraOgMed), to: ISODateToDate(data.tilOgMed), }; - return { + const rapporteringsperiode: Rapporteringsperiode = { periode, harRapportert: data.harRapportert, - kanRapportere: kanBrukerRapportereInntektForPeriode(periode, programPeriode.from), - fristForRapportering: dayjs().endOf('month').toDate(), // TODO - inntekt: { - arbeidstakerOgFrilansInntekt, - inntektFraYtelse, - summertInntekt: arbeidstakerOgFrilansInntekt + inntektFraYtelse, - }, + arbeidstakerOgFrilansInntekt, + inntektFraYtelse, + summertInntekt, + erÅpenRapporteringsperiode: + erPeriodeInnforTillattRapporteringstidsrom(periode, programPeriode.from) && + data.harRapportert === false, }; + return rapporteringsperiode; }); }; diff --git a/packages/ung-common/src/types/DeltakelsePeriode.ts b/packages/ung-common/src/types/DeltakelsePeriode.ts index 23482a1fd1..ac7542416b 100644 --- a/packages/ung-common/src/types/DeltakelsePeriode.ts +++ b/packages/ung-common/src/types/DeltakelsePeriode.ts @@ -16,7 +16,14 @@ export const deltakelsePeriodeSchema = zDeltakelsePeriodInfo return { ...rest, programPeriode, - rapporteringsPerioder: parseRapporteringsperioder(programPeriode, data.rapporteringsPerioder), + rapporteringsPerioder: parseRapporteringsperioder( + programPeriode, + data.rapporteringsPerioder.map((periode) => ({ + ...periode, + ytelseInntekter: periode.inntektFraYtelse ?? 0, + arbeidOgFrilansInntekter: periode.arbeidstakerOgFrilansInntekt ?? 0, + })), + ), oppgaver: parseOppgaverElement(data.oppgaver), }; }); diff --git a/packages/ung-common/src/types/Inntekt.ts b/packages/ung-common/src/types/Inntekt.ts index c5f2864e78..911dd66ad1 100644 --- a/packages/ung-common/src/types/Inntekt.ts +++ b/packages/ung-common/src/types/Inntekt.ts @@ -1,5 +1,5 @@ export interface Inntekt { - arbeidstakerOgFrilansInntekt?: number; - inntektFraYtelse?: number; + arbeidOgFrilansInntekter?: number; + ytelseInntekter?: number; summertInntekt: number; } diff --git a/packages/ung-common/src/types/Oppgave.ts b/packages/ung-common/src/types/Oppgave.ts index 4b4e33fa13..b895279442 100644 --- a/packages/ung-common/src/types/Oppgave.ts +++ b/packages/ung-common/src/types/Oppgave.ts @@ -26,28 +26,22 @@ export interface EndreSluttdatoOppgave extends oppgaveBase { }; } -export interface InntektFraAInntekt { - arbeidsgivere: Array<{ - navn: string; - beløp: number; +export interface Registerinntekt { + arbeidOgFrilansInntekter: Array<{ + arbeidsgiver: string; + inntekt: number; }>; - ytelser: Array<{ - navn: string; - beløp: number; + ytelseInntekter: Array<{ + ytelsetype: string; + inntekt: number; }>; } export interface KorrigertInntektOppgave extends oppgaveBase { - oppgavetype: Oppgavetype.BEKREFT_KORRIGERT_INNTEKT; + oppgavetype: Oppgavetype.BEKREFT_AVVIK_REGISTERINNTEKT; oppgavetypeData: { - periodeForInntekt: { - fraOgMed: Date; - tilOgMed: Date; - }; - inntektFraAinntekt: InntektFraAInntekt; - inntektFraDeltaker?: { - arbeidstakerOgFrilansInntekt?: number; - inntektFraYtelse?: number; - }; + fraOgMed: Date; + tilOgMed: Date; + registerinntekt: Registerinntekt; }; } diff --git a/packages/ung-common/src/types/Rapporteringsperiode.ts b/packages/ung-common/src/types/Rapporteringsperiode.ts index c574499d62..118d4becfb 100644 --- a/packages/ung-common/src/types/Rapporteringsperiode.ts +++ b/packages/ung-common/src/types/Rapporteringsperiode.ts @@ -1,13 +1,10 @@ import { DateRange } from '@navikt/sif-common-utils'; +import { RapportPeriodeinfoDto } from '@navikt/ung-deltakelse-opplyser-api'; -export interface Rapporteringsperiode { +export interface Rapporteringsperiode extends Omit { periode: DateRange; - harRapportert: boolean; - kanRapportere: boolean; - fristForRapportering: Date; - inntekt: { - arbeidstakerOgFrilansInntekt: number; - inntektFraYtelse: number; - summertInntekt: number; - }; + erÅpenRapporteringsperiode: boolean; + arbeidstakerOgFrilansInntekt: number; + inntektFraYtelse: number; + summertInntekt: number; } diff --git a/packages/ung-deltakelse-opplyser-api/src/client/sdk.gen.ts b/packages/ung-deltakelse-opplyser-api/src/client/sdk.gen.ts index 5a75510490..5795ffa2a1 100644 --- a/packages/ung-deltakelse-opplyser-api/src/client/sdk.gen.ts +++ b/packages/ung-deltakelse-opplyser-api/src/client/sdk.gen.ts @@ -29,21 +29,24 @@ import type { HentDeltakerInfoGittDeltakerData, HentDeltakerInfoGittDeltakerResponse, HentDeltakerInfoGittDeltakerError, + OpprettOppgaveForKontrollAvRegisterinntektData, + OpprettOppgaveForKontrollAvRegisterinntektResponse, + OpprettOppgaveForKontrollAvRegisterinntektError, HentAlleDeltakelserGittDeltakerIdData, HentAlleDeltakelserGittDeltakerIdResponse, HentAlleDeltakelserGittDeltakerIdError, HentDeltakerInfoGittDeltakerIdData, HentDeltakerInfoGittDeltakerIdResponse, HentDeltakerInfoGittDeltakerIdError, + HentOppgaveForDeltakelseData, + HentOppgaveForDeltakelseResponse, + HentOppgaveForDeltakelseError, HentAlleMineDeltakelserData, HentAlleMineDeltakelserResponse, HentAlleMineDeltakelserError, FjernFraProgramData, FjernFraProgramResponse, FjernFraProgramError, - HentOppgaveForDeltakelseData, - HentOppgaveForDeltakelseResponse, - HentOppgaveForDeltakelseError, } from './types.gen'; import { zOppdaterFraProgramResponse, @@ -55,6 +58,7 @@ import { zMeldInnDeltakerResponse, zHentAlleDeltakelserGittDeltakerAktørResponse, zHentDeltakerInfoGittDeltakerResponse, + zOpprettOppgaveForKontrollAvRegisterinntektResponse, zHentAlleDeltakelserGittDeltakerIdResponse, zHentDeltakerInfoGittDeltakerIdResponse, zHentOppgaveForDeltakelseResponse, @@ -445,3 +449,34 @@ export class OppslagService { }); } } + +export class OppretterOgEndrerPåOppgaverService { + /** + * Oppretter oppgave + */ + public static opprettOppgaveForKontrollAvRegisterinntekt( + options: Options, + ) { + return (options.client ?? _heyApiClient).post< + OpprettOppgaveForKontrollAvRegisterinntektResponse, + OpprettOppgaveForKontrollAvRegisterinntektError, + ThrowOnError + >({ + security: [ + { + scheme: 'bearer', + type: 'http', + }, + ], + responseValidator: async (data) => { + return await zOpprettOppgaveForKontrollAvRegisterinntektResponse.parseAsync(data); + }, + url: '/oppgave/opprett', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + }, + }); + } +} diff --git a/packages/ung-deltakelse-opplyser-api/src/client/types.gen.ts b/packages/ung-deltakelse-opplyser-api/src/client/types.gen.ts index fae2f3ccf0..2234505b04 100644 --- a/packages/ung-deltakelse-opplyser-api/src/client/types.gen.ts +++ b/packages/ung-deltakelse-opplyser-api/src/client/types.gen.ts @@ -13,6 +13,11 @@ export type ProblemDetail = { }; }; +export type ArbeidOgFrilansRegisterInntektDto = { + inntekt: number; + arbeidsgiver: string; +}; + export type DeltakelseOpplysningDto = { id?: string; deltaker: DeltakerDto; @@ -39,34 +44,20 @@ export type EndretStartdatoOppgavetypeDataDto = OppgavetypeDataDto & { meldingFraVeileder?: string; }; -export type KorrigertInntektOppgavetypeDataDto = OppgavetypeDataDto & { - periodeForInntekt: { - fraOgMed: string; - tilOgMed: string; - }; - inntektFraAinntekt: { - arbeidsgivere: Array<{ - navn: string; - beløp: number; - }>; - ytelser: Array<{ - navn: string; - beløp: number; - }>; - }; - inntektFraDeltaker?: { - arbeidstakerOgFrilansInntekt?: number; - inntektFraYtelse?: number; - }; +export type KontrollerRegisterinntektOppgavetypeDataDto = OppgavetypeDataDto & { + fraOgMed: string; + tilOgMed: string; + registerinntekt: RegisterinntektDto; }; export type OppgaveDto = { id: string; + eksternReferanse: string; oppgavetype: Oppgavetype; oppgavetypeData: | EndretSluttdatoOppgavetypeDataDto | EndretStartdatoOppgavetypeDataDto - | KorrigertInntektOppgavetypeDataDto; + | KontrollerRegisterinntektOppgavetypeDataDto; status: OppgaveStatus; opprettetDato: string; løstDato?: string; @@ -76,19 +67,31 @@ export enum OppgaveStatus { LØST = 'LØST', ULØST = 'ULØST', KANSELLERT = 'KANSELLERT', - UTLØPT = 'UTLØPT', } export enum Oppgavetype { BEKREFT_ENDRET_STARTDATO = 'BEKREFT_ENDRET_STARTDATO', BEKREFT_ENDRET_SLUTTDATO = 'BEKREFT_ENDRET_SLUTTDATO', - BEKREFT_KORRIGERT_INNTEKT = 'BEKREFT_KORRIGERT_INNTEKT', + BEKREFT_AVVIK_REGISTERINNTEKT = 'BEKREFT_AVVIK_REGISTERINNTEKT', } export type OppgavetypeDataDto = { [key: string]: unknown; }; +export type RegisterinntektDto = { + arbeidOgFrilansInntekter: Array; + ytelseInntekter: Array; + totalInntektArbeidOgFrilans: number; + totalInntektYtelse: number; + totalInntekt: number; +}; + +export type YtelseRegisterInntektDto = { + inntekt: number; + ytelsetype: string; +}; + export type EndrePeriodeDatoDto = { dato: string; veilederRef: string; @@ -117,8 +120,8 @@ export type DeltakerPersonlia = { deltakerIdent: string; navn: Navn; fødselsdato: string; - sisteMuligeInnmeldingsdato: string; førsteMuligeInnmeldingsdato: string; + sisteMuligeInnmeldingsdato: string; }; export type Navn = { @@ -127,6 +130,30 @@ export type Navn = { etternavn: string; }; +export type RegisterInntektArbeidOgFrilansDto = { + beløp: number; + arbeidsgiverIdent: string; +}; + +export type RegisterInntektDto = { + registerinntekterForArbeidOgFrilans?: Array; + registerinntekterForYtelse?: Array; +}; + +export type RegisterInntektOppgaveDto = { + aktørId: string; + referanse: string; + frist: string; + fomDato: string; + tomDato: string; + registerInntekter: RegisterInntektDto; +}; + +export type RegisterInntektYtelseDto = { + beløp: number; + ytelseType: string; +}; + export type DeltakelsePeriodInfo = { id: string; fraOgMed: string; @@ -142,6 +169,7 @@ export type RapportPeriodeinfoDto = { harRapportert: boolean; arbeidstakerOgFrilansInntekt?: number; inntektFraYtelse?: number; + summertInntekt: number; }; export type OppdaterFraProgramData = { @@ -455,6 +483,41 @@ export type HentDeltakerInfoGittDeltakerResponses = { export type HentDeltakerInfoGittDeltakerResponse = HentDeltakerInfoGittDeltakerResponses[keyof HentDeltakerInfoGittDeltakerResponses]; +export type OpprettOppgaveForKontrollAvRegisterinntektData = { + body: RegisterInntektOppgaveDto; + path?: never; + query?: never; + url: '/oppgave/opprett'; +}; + +export type OpprettOppgaveForKontrollAvRegisterinntektErrors = { + /** + * Unauthorized + */ + 401: ProblemDetail; + /** + * Forbidden + */ + 403: ProblemDetail; + /** + * Internal Server Error + */ + 500: ProblemDetail; +}; + +export type OpprettOppgaveForKontrollAvRegisterinntektError = + OpprettOppgaveForKontrollAvRegisterinntektErrors[keyof OpprettOppgaveForKontrollAvRegisterinntektErrors]; + +export type OpprettOppgaveForKontrollAvRegisterinntektResponses = { + /** + * OK + */ + 200: DeltakelseOpplysningDto; +}; + +export type OpprettOppgaveForKontrollAvRegisterinntektResponse = + OpprettOppgaveForKontrollAvRegisterinntektResponses[keyof OpprettOppgaveForKontrollAvRegisterinntektResponses]; + export type HentAlleDeltakelserGittDeltakerIdData = { body?: never; path: { @@ -501,17 +564,7 @@ export type HentDeltakerInfoGittDeltakerIdData = { url: '/oppslag/deltaker/{id}'; }; -export type HentOppgaveForDeltakelseData = { - body?: never; - path: { - deltakelseId: string; - oppgaveId: string; - }; - query?: never; - url: '/deltakelse/register/{deltakelseId}/oppgave/{oppgaveId}'; -}; - -export type HentOppgaveForDeltakelseErrors = { +export type HentDeltakerInfoGittDeltakerIdErrors = { /** * Unauthorized */ @@ -526,19 +579,30 @@ export type HentOppgaveForDeltakelseErrors = { 500: ProblemDetail; }; -export type HentOppgaveForDeltakelseError = HentOppgaveForDeltakelseErrors[keyof HentOppgaveForDeltakelseErrors]; +export type HentDeltakerInfoGittDeltakerIdError = + HentDeltakerInfoGittDeltakerIdErrors[keyof HentDeltakerInfoGittDeltakerIdErrors]; -export type HentOppgaveForDeltakelseResponses = { +export type HentDeltakerInfoGittDeltakerIdResponses = { /** * OK */ - 200: OppgaveDto; + 200: DeltakerPersonlia; }; -export type HentOppgaveForDeltakelseResponse = - HentOppgaveForDeltakelseResponses[keyof HentOppgaveForDeltakelseResponses]; +export type HentDeltakerInfoGittDeltakerIdResponse = + HentDeltakerInfoGittDeltakerIdResponses[keyof HentDeltakerInfoGittDeltakerIdResponses]; -export type HentDeltakerInfoGittDeltakerIdErrors = { +export type HentOppgaveForDeltakelseData = { + body?: never; + path: { + deltakelseId: string; + oppgaveId: string; + }; + query?: never; + url: '/deltakelse/register/{deltakelseId}/oppgave/{oppgaveId}'; +}; + +export type HentOppgaveForDeltakelseErrors = { /** * Unauthorized */ @@ -553,18 +617,17 @@ export type HentDeltakerInfoGittDeltakerIdErrors = { 500: ProblemDetail; }; -export type HentDeltakerInfoGittDeltakerIdError = - HentDeltakerInfoGittDeltakerIdErrors[keyof HentDeltakerInfoGittDeltakerIdErrors]; +export type HentOppgaveForDeltakelseError = HentOppgaveForDeltakelseErrors[keyof HentOppgaveForDeltakelseErrors]; -export type HentDeltakerInfoGittDeltakerIdResponses = { +export type HentOppgaveForDeltakelseResponses = { /** * OK */ - 200: DeltakerPersonlia; + 200: OppgaveDto; }; -export type HentDeltakerInfoGittDeltakerIdResponse = - HentDeltakerInfoGittDeltakerIdResponses[keyof HentDeltakerInfoGittDeltakerIdResponses]; +export type HentOppgaveForDeltakelseResponse = + HentOppgaveForDeltakelseResponses[keyof HentOppgaveForDeltakelseResponses]; export type HentAlleMineDeltakelserData = { body?: never; diff --git a/packages/ung-deltakelse-opplyser-api/src/client/zod.gen.ts b/packages/ung-deltakelse-opplyser-api/src/client/zod.gen.ts index 6a211447b8..bd92d35f72 100644 --- a/packages/ung-deltakelse-opplyser-api/src/client/zod.gen.ts +++ b/packages/ung-deltakelse-opplyser-api/src/client/zod.gen.ts @@ -11,6 +11,11 @@ export const zProblemDetail = z.object({ properties: z.object({}).optional(), }); +export const zArbeidOgFrilansRegisterInntektDto = z.object({ + inntekt: z.number().int(), + arbeidsgiver: z.string(), +}); + export const zDeltakelseOpplysningDto = z.object({ id: z.string().uuid().optional(), deltaker: z.object({ @@ -23,7 +28,12 @@ export const zDeltakelseOpplysningDto = z.object({ oppgaver: z.array( z.object({ id: z.string().uuid(), - oppgavetype: z.enum(['BEKREFT_ENDRET_STARTDATO', 'BEKREFT_ENDRET_SLUTTDATO', 'BEKREFT_KORRIGERT_INNTEKT']), + eksternReferanse: z.string().uuid(), + oppgavetype: z.enum([ + 'BEKREFT_ENDRET_STARTDATO', + 'BEKREFT_ENDRET_SLUTTDATO', + 'BEKREFT_AVVIK_REGISTERINNTEKT', + ]), oppgavetypeData: z.union([ z.object({}).merge( z.object({ @@ -41,32 +51,24 @@ export const zDeltakelseOpplysningDto = z.object({ ), z.object({}).merge( z.object({ - inntektFraAinntekt: z.object({ - arbeidsgivere: z.array( + fraOgMed: z.string().date(), + tilOgMed: z.string().date(), + registerinntekt: z.object({ + arbeidOgFrilansInntekter: z.array(zArbeidOgFrilansRegisterInntektDto), + ytelseInntekter: z.array( z.object({ - navn: z.string(), - beløp: z.number(), + inntekt: z.number().int(), + ytelsetype: z.string(), }), ), - ytelser: z.array( - z.object({ - navn: z.string(), - beløp: z.number(), - }), - ), - }), - inntektFraDeltaker: z.object({ - arbeidstakerOgFrilansInntekt: z.number().optional(), - inntektFraYtelse: z.number().optional(), - }), - periodeForInntekt: z.object({ - fraOgMed: z.string().date(), - tilOgMed: z.string().date(), + totalInntektArbeidOgFrilans: z.number().int(), + totalInntektYtelse: z.number().int(), + totalInntekt: z.number().int(), }), }), ), ]), - status: z.enum(['LØST', 'ULØST', 'KANSELLERT', 'UTLØPT']), + status: z.enum(['LØST', 'ULØST', 'KANSELLERT']), opprettetDato: z.string().datetime(), løstDato: z.string().datetime().optional(), }), @@ -94,52 +96,67 @@ export const zEndretStartdatoOppgavetypeDataDto = z.object({}).merge( }), ); -export const zKorrigertOppgavetypeDataDto = z.object({}).merge( +export const zKontrollerRegisterinntektOppgavetypeDataDto = z.object({}).merge( z.object({ - inntektFraAinntekt: z.object({ - arbeidsgivere: z.array( - z.object({ - navn: z.string(), - beløp: z.number(), - }), - ), - ytelser: z.array( + fraOgMed: z.string().date(), + tilOgMed: z.string().date(), + registerinntekt: z.object({ + arbeidOgFrilansInntekter: z.array(zArbeidOgFrilansRegisterInntektDto), + ytelseInntekter: z.array( z.object({ - navn: z.string(), - beløp: z.number(), + inntekt: z.number().int(), + ytelsetype: z.string(), }), ), - }), - inntektFraDeltaker: z.object({ - arbeidstakerOgFrilansInntekt: z.number().optional(), - inntektFraYtelse: z.number().optional(), - }), - periodeForInntekt: z.object({ - fraOgMed: z.string().date(), - tilOgMed: z.string().date(), + totalInntektArbeidOgFrilans: z.number().int(), + totalInntektYtelse: z.number().int(), + totalInntekt: z.number().int(), }), }), ); export const zOppgaveDto = z.object({ id: z.string().uuid(), - oppgavetype: z.enum(['BEKREFT_ENDRET_STARTDATO', 'BEKREFT_ENDRET_SLUTTDATO', 'BEKREFT_KORRIGERT_INNTEKT']), + eksternReferanse: z.string().uuid(), + oppgavetype: z.enum(['BEKREFT_ENDRET_STARTDATO', 'BEKREFT_ENDRET_SLUTTDATO', 'BEKREFT_AVVIK_REGISTERINNTEKT']), oppgavetypeData: z.union([ zEndretSluttdatoOppgavetypeDataDto, zEndretStartdatoOppgavetypeDataDto, - zKorrigertOppgavetypeDataDto, + zKontrollerRegisterinntektOppgavetypeDataDto, ]), - status: z.enum(['LØST', 'ULØST', 'KANSELLERT', 'UTLØPT']), + status: z.enum(['LØST', 'ULØST', 'KANSELLERT']), opprettetDato: z.string().datetime(), løstDato: z.string().datetime().optional(), }); -export const zOppgaveStatus = z.enum(['LØST', 'ULØST', 'KANSELLERT', 'UTLØPT']); +export const zOppgaveStatus = z.enum(['LØST', 'ULØST', 'KANSELLERT']); -export const zOppgavetype = z.enum(['BEKREFT_ENDRET_STARTDATO', 'BEKREFT_ENDRET_SLUTTDATO']); +export const zOppgavetype = z.enum([ + 'BEKREFT_ENDRET_STARTDATO', + 'BEKREFT_ENDRET_SLUTTDATO', + 'BEKREFT_AVVIK_REGISTERINNTEKT', +]); export const zOppgavetypeDataDto = z.object({}); +export const zRegisterinntektDto = z.object({ + arbeidOgFrilansInntekter: z.array(zArbeidOgFrilansRegisterInntektDto), + ytelseInntekter: z.array( + z.object({ + inntekt: z.number().int(), + ytelsetype: z.string(), + }), + ), + totalInntektArbeidOgFrilans: z.number().int(), + totalInntektYtelse: z.number().int(), + totalInntekt: z.number().int(), +}); + +export const zYtelseRegisterInntektDto = z.object({ + inntekt: z.number().int(), + ytelsetype: z.string(), +}); + export const zEndrePeriodeDatoDto = z.object({ dato: z.string().date(), veilederRef: z.string(), @@ -172,8 +189,8 @@ export const zDeltakerPersonlia = z.object({ etternavn: z.string(), }), fødselsdato: z.string().date(), - sisteMuligeInnmeldingsdato: z.string().date(), førsteMuligeInnmeldingsdato: z.string().date(), + sisteMuligeInnmeldingsdato: z.string().date(), }); export const zNavn = z.object({ @@ -182,6 +199,37 @@ export const zNavn = z.object({ etternavn: z.string(), }); +export const zRegisterInntektArbeidOgFrilansDto = z.object({ + beløp: z.number().int(), + arbeidsgiverIdent: z.string(), +}); + +export const zRegisterInntektDto = z.object({ + registerinntekterForArbeidOgFrilans: z.array(zRegisterInntektArbeidOgFrilansDto).optional(), + registerinntekterForYtelse: z + .array( + z.object({ + beløp: z.number().int(), + ytelseType: z.string(), + }), + ) + .optional(), +}); + +export const zRegisterInntektOppgaveDto = z.object({ + aktørId: z.string(), + referanse: z.string().uuid(), + frist: z.string().datetime(), + fomDato: z.string().date(), + tomDato: z.string().date(), + registerInntekter: zRegisterInntektDto, +}); + +export const zRegisterInntektYtelseDto = z.object({ + beløp: z.number().int(), + ytelseType: z.string(), +}); + export const zDeltakelsePeriodInfo = z.object({ id: z.string().uuid(), fraOgMed: z.string().date(), @@ -195,6 +243,7 @@ export const zDeltakelsePeriodInfo = z.object({ harRapportert: z.boolean(), arbeidstakerOgFrilansInntekt: z.number().optional(), inntektFraYtelse: z.number().optional(), + summertInntekt: z.number(), }), ), }); @@ -205,6 +254,7 @@ export const zRapportPeriodeinfoDto = z.object({ harRapportert: z.boolean(), arbeidstakerOgFrilansInntekt: z.number().optional(), inntektFraYtelse: z.number().optional(), + summertInntekt: z.number(), }); export const zOppdaterFraProgramResponse = zDeltakelseOpplysningDto; @@ -225,6 +275,8 @@ export const zHentAlleDeltakelserGittDeltakerAktørResponse = zDeltakerOpplysnin export const zHentDeltakerInfoGittDeltakerResponse = zDeltakerPersonlia; +export const zOpprettOppgaveForKontrollAvRegisterinntektResponse = zDeltakelseOpplysningDto; + export const zHentAlleDeltakelserGittDeltakerIdResponse = z.array(zDeltakelseOpplysningDto); export const zHentDeltakerInfoGittDeltakerIdResponse = zDeltakerPersonlia; diff --git a/vitest.workspace.ts b/vitest.workspace.ts index 885ab80e9c..4eac8949b9 100644 --- a/vitest.workspace.ts +++ b/vitest.workspace.ts @@ -1,5 +1,10 @@ import { defineWorkspace } from 'vitest/config'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { storybookTest } from '@storybook/experimental-addon-test/vitest-plugin'; +const dirname = typeof __dirname !== 'undefined' ? __dirname : path.dirname(fileURLToPath(import.meta.url)); +// More info at: https://storybook.js.org/docs/writing-tests/test-addon export default defineWorkspace([ './apps/dine-pleiepenger/vitest.config.ts', './apps/ekstra-omsorgsdager-andre-forelder-ikke-tilsyn/vitest.config.ts', @@ -16,4 +21,28 @@ export default defineWorkspace([ './packages/sif-common-forms-ds/vitest.config.ts', './packages/sif-common-formik-ds/vitest.config.ts', './packages/sif-common-utils/vitest.config.ts', + { + extends: 'apps/ungdomsytelse-veileder/vite.config.ts', + plugins: [ + // The plugin will run tests for the stories defined in your Storybook config + // See options at: https://storybook.js.org/docs/writing-tests/test-addon#storybooktest + storybookTest({ + configDir: path.join(dirname, '.storybook'), + }), + ], + test: { + name: 'storybook', + browser: { + enabled: true, + headless: true, + provider: 'playwright', + instances: [ + { + browser: 'chromium', + }, + ], + }, + setupFiles: ['apps/ungdomsytelse-veileder/.storybook/vitest.setup.ts'], + }, + }, ]); diff --git a/yarn.lock b/yarn.lock index 5b34939bb2..70cc388096 100644 --- a/yarn.lock +++ b/yarn.lock @@ -168,7 +168,7 @@ __metadata: languageName: node linkType: hard -"@ampproject/remapping@npm:^2.2.0": +"@ampproject/remapping@npm:^2.2.0, @ampproject/remapping@npm:^2.3.0": version: 2.3.0 resolution: "@ampproject/remapping@npm:2.3.0" dependencies: @@ -502,7 +502,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.27.0": +"@babel/parser@npm:^7.25.4, @babel/parser@npm:^7.27.0": version: 7.27.0 resolution: "@babel/parser@npm:7.27.0" dependencies: @@ -1745,7 +1745,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.27.0": +"@babel/types@npm:^7.25.4, @babel/types@npm:^7.27.0": version: 7.27.0 resolution: "@babel/types@npm:7.27.0" dependencies: @@ -1762,6 +1762,13 @@ __metadata: languageName: node linkType: hard +"@bcoe/v8-coverage@npm:^1.0.2": + version: 1.0.2 + resolution: "@bcoe/v8-coverage@npm:1.0.2" + checksum: 10/46600b2dde460269b07a8e4f12b72e418eae1337b85c979f43af3336c9a1c65b04e42508ab6b245f1e0e3c64328e1c38d8cd733e4a7cebc4fbf9cf65c6e59937 + languageName: node + linkType: hard + "@bundled-es-modules/cookie@npm:^2.0.1": version: 2.0.1 resolution: "@bundled-es-modules/cookie@npm:2.0.1" @@ -2024,7 +2031,7 @@ __metadata: languageName: node linkType: hard -"@chromatic-com/storybook@npm:3.2.6": +"@chromatic-com/storybook@npm:3.2.6, @chromatic-com/storybook@npm:^3": version: 3.2.6 resolution: "@chromatic-com/storybook@npm:3.2.6" dependencies: @@ -4033,7 +4040,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" dependencies: @@ -5972,6 +5979,7 @@ __metadata: version: 0.0.0-use.local resolution: "@navikt/ungdomsytelse-veileder@workspace:apps/ungdomsytelse-veileder" dependencies: + "@chromatic-com/storybook": "npm:^3" "@eslint/eslintrc": "npm:3.3.1" "@eslint/js": "npm:9.23.0" "@navikt/aksel-icons": "npm:7.17.4" @@ -5986,6 +5994,13 @@ __metadata: "@navikt/sif-common-ui": "workspace:*" "@navikt/sif-validation": "workspace:*" "@navikt/ung-common": "workspace:*" + "@storybook/addon-essentials": "npm:^8.6.9" + "@storybook/addon-onboarding": "npm:^8.6.9" + "@storybook/blocks": "npm:^8.6.9" + "@storybook/experimental-addon-test": "npm:^8.6.9" + "@storybook/react": "npm:^8.6.9" + "@storybook/react-vite": "npm:^8.6.9" + "@storybook/test": "npm:^8.6.9" "@tailwindcss/postcss": "npm:4.0.16" "@tailwindcss/vite": "npm:4.0.16" "@tanstack/react-form": "npm:1.1.2" @@ -5994,6 +6009,8 @@ __metadata: "@types/react-dom": "npm:19.0.4" "@typescript-eslint/parser": "npm:8.28.0" "@vitejs/plugin-react": "npm:4.3.4" + "@vitest/browser": "npm:3.0.9" + "@vitest/coverage-v8": "npm:3.0.9" axios: "npm:1.8.4" clsx: "npm:2.1.1" compression: "npm:1.8.0" @@ -6004,13 +6021,17 @@ __metadata: eslint-plugin-prettier: "npm:5.2.5" eslint-plugin-react: "npm:7.37.4" eslint-plugin-simple-import-sort: "npm:12.1.1" + eslint-plugin-storybook: "npm:^0.12.0" eslint-plugin-unicorn: "npm:58.0.0" express: "npm:4.21.2" formik: "npm:2.4.6" html-react-parser: "npm:5.2.2" http-proxy-middleware: "npm:3.0.3" jsdom: "npm:26.0.0" + msw: "npm:^2.7.3" + msw-storybook-addon: "npm:^2.0.4" mustache-express: "npm:1.3.2" + playwright: "npm:^1.51.1" postcss: "npm:8.5.3" postcss-import: "npm:16.1.0" postcss-styled-syntax: "npm:0.7.1" @@ -6018,15 +6039,18 @@ __metadata: react: "npm:19.0.0" react-dom: "npm:19.0.0" react-hook-form: "npm:7.54.2" + react-intl: "npm:7.1.10" react-markdown: "npm:10.1.0" react-router-dom: "npm:7.4.0" remark-gfm: "npm:4.0.1" + storybook: "npm:^8.6.9" stylelint: "npm:16.16.0" tailwindcss: "npm:4.0.16" typescript: "npm:5.8.2" typescript-eslint: "npm:8.28.0" vite: "npm:6.2.3" vite-plugin-checker: "npm:0.9.1" + vitest: "npm:3.0.9" zod: "npm:3.24.2" languageName: unknown linkType: soft @@ -6946,6 +6970,13 @@ __metadata: languageName: node linkType: hard +"@polka/url@npm:^1.0.0-next.24": + version: 1.0.0-next.28 + resolution: "@polka/url@npm:1.0.0-next.28" + checksum: 10/7402aaf1de781d0eb0870d50cbcd394f949aee11b38a267a5c3b4e3cfee117e920693e6e93ce24c87ae2d477a59634f39d9edde8e86471cae756839b07c79af7 + languageName: node + linkType: hard + "@portabletext/block-tools@npm:1.1.15, @portabletext/block-tools@npm:^1.1.14": version: 1.1.15 resolution: "@portabletext/block-tools@npm:1.1.15" @@ -9152,7 +9183,7 @@ __metadata: languageName: node linkType: hard -"@storybook/addon-essentials@npm:8.6.9": +"@storybook/addon-essentials@npm:8.6.9, @storybook/addon-essentials@npm:^8.6.9": version: 8.6.9 resolution: "@storybook/addon-essentials@npm:8.6.9" dependencies: @@ -9226,7 +9257,7 @@ __metadata: languageName: node linkType: hard -"@storybook/addon-onboarding@npm:8.6.9": +"@storybook/addon-onboarding@npm:8.6.9, @storybook/addon-onboarding@npm:^8.6.9": version: 8.6.9 resolution: "@storybook/addon-onboarding@npm:8.6.9" peerDependencies: @@ -9322,7 +9353,7 @@ __metadata: languageName: node linkType: hard -"@storybook/blocks@npm:8.6.9": +"@storybook/blocks@npm:8.6.9, @storybook/blocks@npm:^8.6.9": version: 8.6.9 resolution: "@storybook/blocks@npm:8.6.9" dependencies: @@ -9619,6 +9650,33 @@ __metadata: languageName: node linkType: hard +"@storybook/experimental-addon-test@npm:^8.6.9": + version: 8.6.9 + resolution: "@storybook/experimental-addon-test@npm:8.6.9" + dependencies: + "@storybook/global": "npm:^5.0.0" + "@storybook/icons": "npm:^1.2.12" + "@storybook/instrumenter": "npm:8.6.9" + "@storybook/test": "npm:8.6.9" + polished: "npm:^4.2.2" + prompts: "npm:^2.4.0" + ts-dedent: "npm:^2.2.0" + peerDependencies: + "@vitest/browser": ^2.1.1 || ^3.0.0 + "@vitest/runner": ^2.1.1 || ^3.0.0 + storybook: ^8.6.9 + vitest: ^2.1.1 || ^3.0.0 + peerDependenciesMeta: + "@vitest/browser": + optional: true + "@vitest/runner": + optional: true + vitest: + optional: true + checksum: 10/a3dfc099c527e2ff6621d274122a0e9caead29a8ca17850d913cc778f570307fc20e0630e790c647747bb39b4c46f6824e0753da64f7f915e4f47a3bdc377d3f + languageName: node + linkType: hard + "@storybook/global@npm:^5.0.0": version: 5.0.0 resolution: "@storybook/global@npm:5.0.0" @@ -9882,7 +9940,7 @@ __metadata: languageName: node linkType: hard -"@storybook/react-vite@npm:8.6.9": +"@storybook/react-vite@npm:8.6.9, @storybook/react-vite@npm:^8.6.9": version: 8.6.9 resolution: "@storybook/react-vite@npm:8.6.9" dependencies: @@ -9908,7 +9966,7 @@ __metadata: languageName: node linkType: hard -"@storybook/react@npm:8.6.9": +"@storybook/react@npm:8.6.9, @storybook/react@npm:^8.6.9": version: 8.6.9 resolution: "@storybook/react@npm:8.6.9" dependencies: @@ -9975,7 +10033,7 @@ __metadata: languageName: node linkType: hard -"@storybook/test@npm:8.6.9": +"@storybook/test@npm:8.6.9, @storybook/test@npm:^8.6.9": version: 8.6.9 resolution: "@storybook/test@npm:8.6.9" dependencies: @@ -10466,7 +10524,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/dom@npm:10.4.0": +"@testing-library/dom@npm:10.4.0, @testing-library/dom@npm:^10.4.0": version: 10.4.0 resolution: "@testing-library/dom@npm:10.4.0" dependencies: @@ -10557,7 +10615,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/user-event@npm:14.6.1, @testing-library/user-event@npm:^14.4.0": +"@testing-library/user-event@npm:14.6.1, @testing-library/user-event@npm:^14.4.0, @testing-library/user-event@npm:^14.6.1": version: 14.6.1 resolution: "@testing-library/user-event@npm:14.6.1" peerDependencies: @@ -11821,6 +11879,60 @@ __metadata: languageName: node linkType: hard +"@vitest/browser@npm:3.0.9": + version: 3.0.9 + resolution: "@vitest/browser@npm:3.0.9" + dependencies: + "@testing-library/dom": "npm:^10.4.0" + "@testing-library/user-event": "npm:^14.6.1" + "@vitest/mocker": "npm:3.0.9" + "@vitest/utils": "npm:3.0.9" + magic-string: "npm:^0.30.17" + msw: "npm:^2.7.3" + sirv: "npm:^3.0.1" + tinyrainbow: "npm:^2.0.0" + ws: "npm:^8.18.1" + peerDependencies: + playwright: "*" + vitest: 3.0.9 + webdriverio: ^7.0.0 || ^8.0.0 || ^9.0.0 + peerDependenciesMeta: + playwright: + optional: true + safaridriver: + optional: true + webdriverio: + optional: true + checksum: 10/e952bf735008874a4848ab196c49685ef2a0841b4f6d841b79b29d645c3892104503429855379aca47503bfde54cb28d0141c805e7a23d5d083a30ecc9a7d6fd + languageName: node + linkType: hard + +"@vitest/coverage-v8@npm:3.0.9": + version: 3.0.9 + resolution: "@vitest/coverage-v8@npm:3.0.9" + dependencies: + "@ampproject/remapping": "npm:^2.3.0" + "@bcoe/v8-coverage": "npm:^1.0.2" + debug: "npm:^4.4.0" + istanbul-lib-coverage: "npm:^3.2.2" + istanbul-lib-report: "npm:^3.0.1" + istanbul-lib-source-maps: "npm:^5.0.6" + istanbul-reports: "npm:^3.1.7" + magic-string: "npm:^0.30.17" + magicast: "npm:^0.3.5" + std-env: "npm:^3.8.0" + test-exclude: "npm:^7.0.1" + tinyrainbow: "npm:^2.0.0" + peerDependencies: + "@vitest/browser": 3.0.9 + vitest: 3.0.9 + peerDependenciesMeta: + "@vitest/browser": + optional: true + checksum: 10/7eea1ffc6966a15e29024f601d99bad1d0179267072e33f6c4e2328ab26e579c51649dd3ac2a99fa326bc8934874a5a16ed429edfdda42ba0ed5c814701a97e7 + languageName: node + linkType: hard + "@vitest/expect@npm:2.0.5": version: 2.0.5 resolution: "@vitest/expect@npm:2.0.5" @@ -16913,7 +17025,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-storybook@npm:0.12.0": +"eslint-plugin-storybook@npm:0.12.0, eslint-plugin-storybook@npm:^0.12.0": version: 0.12.0 resolution: "eslint-plugin-storybook@npm:0.12.0" dependencies: @@ -18480,7 +18592,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7, glob@npm:^10.4.5": +"glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7, glob@npm:^10.4.1, glob@npm:^10.4.5": version: 10.4.5 resolution: "glob@npm:10.4.5" dependencies: @@ -20281,7 +20393,7 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": +"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0, istanbul-lib-coverage@npm:^3.2.2": version: 3.2.2 resolution: "istanbul-lib-coverage@npm:3.2.2" checksum: 10/40bbdd1e937dfd8c830fa286d0f665e81b7a78bdabcd4565f6d5667c99828bda3db7fb7ac6b96a3e2e8a2461ddbc5452d9f8bc7d00cb00075fa6a3e99f5b6a81 @@ -20349,7 +20461,7 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-report@npm:^3.0.0": +"istanbul-lib-report@npm:^3.0.0, istanbul-lib-report@npm:^3.0.1": version: 3.0.1 resolution: "istanbul-lib-report@npm:3.0.1" dependencies: @@ -20371,7 +20483,18 @@ __metadata: languageName: node linkType: hard -"istanbul-reports@npm:^3.0.2, istanbul-reports@npm:^3.1.3": +"istanbul-lib-source-maps@npm:^5.0.6": + version: 5.0.6 + resolution: "istanbul-lib-source-maps@npm:5.0.6" + dependencies: + "@jridgewell/trace-mapping": "npm:^0.3.23" + debug: "npm:^4.1.1" + istanbul-lib-coverage: "npm:^3.0.0" + checksum: 10/569dd0a392ee3464b1fe1accbaef5cc26de3479eacb5b91d8c67ebb7b425d39fd02247d85649c3a0e9c29b600809fa60b5af5a281a75a89c01f385b1e24823a2 + languageName: node + linkType: hard + +"istanbul-reports@npm:^3.0.2, istanbul-reports@npm:^3.1.3, istanbul-reports@npm:^3.1.7": version: 3.1.7 resolution: "istanbul-reports@npm:3.1.7" dependencies: @@ -22194,6 +22317,17 @@ __metadata: languageName: node linkType: hard +"magicast@npm:^0.3.5": + version: 0.3.5 + resolution: "magicast@npm:0.3.5" + dependencies: + "@babel/parser": "npm:^7.25.4" + "@babel/types": "npm:^7.25.4" + source-map-js: "npm:^1.2.0" + checksum: 10/3a2dba6b0bdde957797361d09c7931ebdc1b30231705360eeb40ed458d28e1c3112841c3ed4e1b87ceb28f741e333c7673cd961193aa9fdb4f4946b202e6205a + languageName: node + linkType: hard + "make-dir@npm:^1.0.0": version: 1.3.0 resolution: "make-dir@npm:1.3.0" @@ -23397,6 +23531,13 @@ __metadata: languageName: node linkType: hard +"mrmime@npm:^2.0.0": + version: 2.0.1 + resolution: "mrmime@npm:2.0.1" + checksum: 10/1f966e2c05b7264209c4149ae50e8e830908eb64dd903535196f6ad72681fa109b794007288a3c2814f7a1ecf9ca192769909c0c374d974d604a8de5fc095d4a + languageName: node + linkType: hard + "ms@npm:2.0.0": version: 2.0.0 resolution: "ms@npm:2.0.0" @@ -23411,7 +23552,7 @@ __metadata: languageName: node linkType: hard -"msw-storybook-addon@npm:2.0.4": +"msw-storybook-addon@npm:2.0.4, msw-storybook-addon@npm:^2.0.4": version: 2.0.4 resolution: "msw-storybook-addon@npm:2.0.4" dependencies: @@ -23422,7 +23563,7 @@ __metadata: languageName: node linkType: hard -"msw@npm:2.7.3, msw@npm:^2.0.8": +"msw@npm:2.7.3, msw@npm:^2.0.8, msw@npm:^2.7.3": version: 2.7.3 resolution: "msw@npm:2.7.3" dependencies: @@ -25231,7 +25372,7 @@ __metadata: languageName: node linkType: hard -"playwright@npm:1.51.1, playwright@npm:^1.14.0": +"playwright@npm:1.51.1, playwright@npm:^1.14.0, playwright@npm:^1.51.1": version: 1.51.1 resolution: "playwright@npm:1.51.1" dependencies: @@ -25702,7 +25843,7 @@ __metadata: languageName: node linkType: hard -"prompts@npm:^2.0.1, prompts@npm:^2.4.1": +"prompts@npm:^2.0.1, prompts@npm:^2.4.0, prompts@npm:^2.4.1": version: 2.4.2 resolution: "prompts@npm:2.4.2" dependencies: @@ -28113,6 +28254,17 @@ __metadata: languageName: node linkType: hard +"sirv@npm:^3.0.1": + version: 3.0.1 + resolution: "sirv@npm:3.0.1" + dependencies: + "@polka/url": "npm:^1.0.0-next.24" + mrmime: "npm:^2.0.0" + totalist: "npm:^3.0.0" + checksum: 10/b110ebe28eb1740772fbbfacb6c71c58d1ec8ec17a5ae2852a5418c3ef41d52d473663613de808f8a6337ec29dd446414d0d059e75bfd13fb9630d18651c99f2 + languageName: node + linkType: hard + "sisteransi@npm:^1.0.5": version: 1.0.5 resolution: "sisteransi@npm:1.0.5" @@ -28250,7 +28402,7 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.0.1, source-map-js@npm:^1.0.2, source-map-js@npm:^1.2.1": +"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.0.1, source-map-js@npm:^1.0.2, source-map-js@npm:^1.2.0, source-map-js@npm:^1.2.1": version: 1.2.1 resolution: "source-map-js@npm:1.2.1" checksum: 10/ff9d8c8bf096d534a5b7707e0382ef827b4dd360a577d3f34d2b9f48e12c9d230b5747974ee7c607f0df65113732711bb701fe9ece3c7edbd43cb2294d707df3 @@ -28526,7 +28678,7 @@ __metadata: languageName: node linkType: hard -"storybook@npm:8.6.9": +"storybook@npm:8.6.9, storybook@npm:^8.6.9": version: 8.6.9 resolution: "storybook@npm:8.6.9" dependencies: @@ -29322,6 +29474,17 @@ __metadata: languageName: node linkType: hard +"test-exclude@npm:^7.0.1": + version: 7.0.1 + resolution: "test-exclude@npm:7.0.1" + dependencies: + "@istanbuljs/schema": "npm:^0.1.2" + glob: "npm:^10.4.1" + minimatch: "npm:^9.0.4" + checksum: 10/e6f6f4e1df2e7810e082e8d7dfc53be51a931e6e87925f5e1c2ef92cc1165246ba3bf2dae6b5d86251c16925683dba906bd41e40169ebc77120a2d1b5a0dbbe0 + languageName: node + linkType: hard + "text-decoder@npm:^1.1.0": version: 1.2.3 resolution: "text-decoder@npm:1.2.3" @@ -29527,6 +29690,13 @@ __metadata: languageName: node linkType: hard +"totalist@npm:^3.0.0": + version: 3.0.1 + resolution: "totalist@npm:3.0.1" + checksum: 10/5132d562cf88ff93fd710770a92f31dbe67cc19b5c6ccae2efc0da327f0954d211bbfd9456389655d726c624f284b4a23112f56d1da931ca7cfabbe1f45e778a + languageName: node + linkType: hard + "tough-cookie@npm:^4.1.2, tough-cookie@npm:^4.1.3, tough-cookie@npm:^4.1.4": version: 4.1.4 resolution: "tough-cookie@npm:4.1.4" @@ -31443,7 +31613,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.11.0, ws@npm:^8.16.0, ws@npm:^8.18.0, ws@npm:^8.2.3": +"ws@npm:^8.11.0, ws@npm:^8.16.0, ws@npm:^8.18.0, ws@npm:^8.18.1, ws@npm:^8.2.3": version: 8.18.1 resolution: "ws@npm:8.18.1" peerDependencies: