一键导入
sif-soknad-add-step
Legg til et nytt steg i en søknadsapp som bruker @sif/soknad og @sif/rhf — oppretter alle filer og oppdaterer config/routing/i18n.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Legg til et nytt steg i en søknadsapp som bruker @sif/soknad og @sif/rhf — oppretter alle filer og oppdaterer config/routing/i18n.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | sif-soknad-add-step |
| type | action |
| description | Legg til et nytt steg i en søknadsapp som bruker @sif/soknad og @sif/rhf — oppretter alle filer og oppdaterer config/routing/i18n. |
src/app/steps/<steg>/types.ts — FormFields og FormValuessrc/app/steps/<steg>/<Prefix>Form.tsx — skjemakomponentsrc/app/steps/<steg>/<prefix>StegUtils.ts — mapping mellom FormValues og søknadsdatasrc/app/steps/<steg>/i18n/nb.ts og nn.ts — tekster og valideringsmeldingersrc/app/steps/<steg>/index.ts — barrel-eksportSoknadStepId, soknadStepConfig, Soknadsdata, formValuesToSoknadsdata, steps/index.ts og i18n-aggregeringsif-soknad-setup.Soknad.tsx, VelkommenPage, KvitteringPage og steps/index.ts → bruk sif-soknad-setup (seksjonen "Routing shell og pages").sif-intl.Agenten skal ikke utforske kodebasen bredt. Les kun filene som er nødvendige for å plassere steget riktig i den aktuelle appen:
src/app/types/SoknadStepId.ts — eksisterende steg-IDersrc/app/setup/soknadStepConfig.ts — stepConfig og stepOrdersrc/app/i18n/nb.ts — eksisterende i18n-nøkler og aggregeringsrc/app/types/Soknadsdata.ts — eksisterende søknadsdatatypesrc/app/utils/formValuesToSoknadsdata.ts — mapping fra form values til søknadsdatasrc/app/steps/index.ts og src/app/Soknad.tsx — eksporterer steg og ruter dem herIkke les andre steg-mapper eller gjør generell utforsking utover dette med mindre appen faktisk avviker fra standardoppsettet.
Utled navnene fra brukerens beskrivelse. Alle navn er konsekvente:
<Prefix> = PascalCase (f.eks. Periode)<prefix> = lowerCamelCase (f.eks. periode)| Konsept | Eksempel (for «Periode») |
|---|---|
StepId enum-verdi | PERIODE |
StepId string-verdi | 'periode' |
| Mappename | periode |
| Route | 'periode' |
| Komponentprefix | Periode |
| Utils-filnavn | periodeStegUtils.ts |
| i18n-prefix | 'periodeSteg' |
| i18n steg-tittel nøkkel | 'step.periode.title' |
I malene under brukes <felt> som plassholder for det konkrete feltnavnet du velger (f.eks. harPeriode, harArbeid). Det er lowerCamelCase og velges basert på hva spørsmålet handler om. Erstatt alle forekomster av <felt> med dette navnet, akkurat som <Prefix>/<prefix> erstattes med stegnavnet.
Posisjon i stepOrder: Plasser steget der brukeren ber om det. Hvis brukeren sier «førstesteg», legg det først. Hvis ingen posisjon er angitt, legg det sist før OPPSUMMERING.
Før du bygger UI fra bunnen: sjekk om steget handler om noe @sif/soknad-forms allerede dekker.
| Steg handler om | Bruk panel |
|---|---|
| Valg av registrert barn (radiogruppe med fødselsdato + kildeinfo) | VelgRegistrertBarnPanel |
Hvis et panel passer: importer det og bruk ANNET_BARN-konstanten fra samme pakke i stedet for å definere den lokalt.
import { ANNET_BARN, VelgRegistrertBarnPanel } from '@sif/soknad-forms';
Eksporter ANNET_BARN fra types.ts via re-eksport hvis andre filer i steget trenger den:
import { ANNET_BARN } from '@sif/soknad-forms';
export { ANNET_BARN };
Hvis steget porteres fra en eksisterende app: les v1-skjemakomponenten FØR du skriver kode. Finn filen som heter <Prefix>Form.tsx eller tilsvarende i kildeappen.
Kartlegg eksplisitt:
felt A → alltid synlig
felt B → synlig når felt A === YES
felt C → synlig når felt B === NO
melding X → synlig når felt A === NO
Sjekk spesielt inversjonsfeil — det er den vanligste feilen ved portering:
| v1-kode | Feil v2-kode | Riktig v2-kode |
|---|---|---|
kronisk === YES | kronisk === NO | kronisk === YES |
harBarn === false | harBarn === true | harBarn === false |
Skriv ned kartleggingen som kommentarer øverst i <Prefix>Form.tsx eller som lokale variabler med selvforklarende navn, og verifiser mot v1 før du leverer.
Pakken @navikt/k9-brukerdialog-prosessering-api re-eksporterer typer fra mange ytelser. Bruk alltid ytelse-spesifikk subpath — ikke flat import fra rot.
// ✅ Riktig — omsorgspenger-spesifikk Barn og søknadstype
import { omsorgspenger } from '@navikt/k9-brukerdialog-prosessering-api';
export type SøknadApiData = omsorgspenger.OmsorgspengerKroniskSyktBarnSøknad;
// ❌ Feil — henter fra legacy client/types.gen.ts som har andre (feil) typer
import { OmsorgspengerKroniskSyktBarnSøknad } from '@navikt/k9-brukerdialog-prosessering-api';
Tilgjengelige subpaths: omsorgspenger, aktivitetspenger, ungdomsytelse, ettersendelse, omsorgspenger-aleneomsorg, o.l. — se src/index.ts i pakken.
Samme prinsipp gjelder controllers i sendSoknad.ts:
// ✅
await omsorgspenger.OmsorgspengerUtvidetRettController.innsendingOmsorgspengerKroniskSyktBarnSøknad(...)
Opprett 5 filer under src/app/steps/<mappename>/:
types.tsimport { YesOrNo } from '@sif/rhf';
export enum <Prefix>FormFields {
<felt> = '<felt>',
}
export type <Prefix>FormValues = {
[<Prefix>FormFields.<felt>]?: YesOrNo;
};
For andre felttyper enn YesOrNo, bruk
string,boolean, osv. etter behov.
<prefix>StegUtils.tsimport { <Prefix>Søknadsdata } from '@app/types/Soknadsdata';
import { YesOrNo } from '@sif/rhf';
import { <Prefix>FormValues } from './types';
export const to<Prefix>FormValues = (
søknadsdata: <Prefix>Søknadsdata | undefined,
): Partial<<Prefix>FormValues> => {
if (søknadsdata?.<felt> === undefined) return {};
return {
<felt>: søknadsdata.<felt> ? YesOrNo.YES : YesOrNo.NO,
};
};
export const to<Prefix>Søknadsdata = (data: <Prefix>FormValues): <Prefix>Søknadsdata => ({
<felt>: data.<felt> === YesOrNo.YES,
});
i18n/nb.tsexport const <prefix>StegMessages_nb = {
'<prefix>Steg.spørsmål.<felt>': '<spørsmålstekst>',
'<prefix>Form.validation.<felt>.yesOrNoIsUnanswered': '<valideringstekst>',
};
Valideringsnøkkel-format:
{scope}.validation.{felt}.{errorCode}— derscopeer strengen sendt tiluseSifValidate('oppsummeringForm')ogerrorCodeer enum-verdien fra validatoren (f.eks.notChecked,yesOrNoIsUnanswered). Nøkkelen må finnes i i18n-filene, ellers vises raw key i UI.
i18n/nn.tsStart med å spre nb. Nynorsk-oversettelse gjøres manuelt av utvikler i etterkant:
import { <prefix>StegMessages_nb } from './nb';
export const <prefix>StegMessages_nn: Record<keyof typeof <prefix>StegMessages_nb, string> = {
...<prefix>StegMessages_nb,
};
For nøkkelstruktur-konvensjoner, ICU-parametre og
<AppText>vs.text()-hook → sesif-intl.
<Prefix>Form.tsximport { useAppIntl } from '@app/i18n';
import { SøknadStepId } from '@app/types/SoknadStepId';
import { <Prefix>Søknadsdata } from '@app/types/Soknadsdata';
import { getYesOrNoValidator } from '@navikt/sif-validation';
import { createSifFormComponents, useSifValidate } from '@sif/rhf';
import { SøknadStep, SøknadStepForm, useSaveSøknadFormValues, useStepData } from '@sif/soknad-app';
import { useForm } from 'react-hook-form';
import { to<Prefix>FormValues, to<Prefix>Søknadsdata } from './<prefix>StegUtils';
import { <Prefix>FormFields, <Prefix>FormValues } from './types';
const { YesOrNoQuestion } = createSifFormComponents<<Prefix>FormValues>();
const stepId = SøknadStepId.<STEP_ID>;
export const <Prefix>Form = () => {
const { validateField } = useSifValidate('<prefix>Form');
const { text } = useAppIntl();
const { lagretData, commit, draftFormValues } = useStepData<<Prefix>Søknadsdata, <Prefix>FormValues>(stepId);
const methods = useForm<<Prefix>FormValues>({ defaultValues: draftFormValues ?? to<Prefix>FormValues(lagretData) });
useSaveSøknadFormValues(stepId, methods.getValues);
const onSubmit = (data: <Prefix>FormValues) => commit(to<Prefix>Søknadsdata(data));
return (
<SøknadStep stepId={stepId}>
<SøknadStepForm stepId={stepId} methods={methods} onSubmit={onSubmit} isPending={false}>
<YesOrNoQuestion
name={<Prefix>FormFields.<felt>}
legend={text('<prefix>Steg.spørsmål.<felt>')}
validate={validateField(<Prefix>FormFields.<felt>, getYesOrNoValidator())}
/>
</SøknadStepForm>
</SøknadStep>
);
};
Ingen separat <Prefix>Steg.tsx — SøknadStep er nå wrapperkomponenten direkte i <Prefix>Form.tsx.
Disse endringene er mekaniske og følger samme mønster for hvert steg:
src/app/types/SoknadStepId.tsLegg til ny enum-verdi. Plasser den i riktig rekkefølge (f.eks. først = førstesteg).
src/app/setup/soknadStepConfig.tsLegg til i søknadStepConfig:
[SøknadStepId.<STEP_ID>]: {
route: '<mappename>',
isCompleted: (s) => s.<camelCase> !== undefined,
},
Route-strenger må ikke inneholde norske bokstaver (æ, ø, å). Bruk ASCII-ekvivalenter:
legeerklaring(ikkelegeerklæring),delt-bostedosv. Norske tegn i URL-path bryter routing i nettlesere.
Betingede steg som bare skal vises for noen brukere bruker isIncluded:
[SøknadStepId.DELT_BOSTED]: {
route: 'delt-bosted',
isIncluded: (s) => s[SøknadStepId.OM_BARNET]?.sammeAdresse === BarnSammeAdresse.JA_DELT_BOSTED,
isCompleted: (s) => s[SøknadStepId.DELT_BOSTED] !== undefined,
},
søknadStepOrder skal alltid inneholde alle steg inkl. betingede — isIncluded filtrerer dynamisk basert på søknadsdata. Ikke bruk manuell getSøknadStepOrder-funksjon.
Legg til i søknadStepOrder på riktig posisjon.
src/app/types/Soknadsdata.tsLegg til type:
export type <Prefix>Søknadsdata = {
<felt>: boolean;
};
Legg til i Søknadsdata-interface:
[SøknadStepId.<STEP_ID>]?: <Prefix>Søknadsdata;
src/app/utils/formValuesToSoknadsdata.tsLegg til import av utils og types fra det nye steget, og ny case i switch:
case SøknadStepId.<STEP_ID>:
return to<Prefix>Søknadsdata(formValues as <Prefix>FormValues);
src/app/i18n/nb.ts<prefix>StegMessages_nb fra stegets i18n/nb.tsappMessages_nb'step.<camelCase>.title': '<Stegtittel>'src/app/steps/index.tsLegg til eksport:
export { <Prefix>Form } from './<mappename>/<Prefix>Form';
src/app/Soknad.tsx<Prefix>Form fra './steps'/soknad-gruppen:<Route path={søknadStepConfig[SøknadStepId.<STEP_ID>].route} element={<<Prefix>Form />} />
Kjør npx tsc --noEmit i app-mappen. Ingen feil = ferdig.
types.ts, *StegUtils.ts, i18n/nb.ts, *Form.tsx)SoknadStepId.ts — ny enum-verdisoknadStepConfig.ts — config + stepOrderSoknadsdata.ts — type + interface-feltformValuesToSoknadsdata.ts — import + casenb.ts — import + spread + steg-tittelsteps/index.ts — eksportSoknad.tsx — import + Routetsc --noEmit passererMønster for å kombinere flere API-hooks til én asynkron laster (useInitialData + InitialDataLoader) i sif-soknad-apper.
Arkitekturreferanse og beslutningslogg for @sif/soknad-app — rammeverket for søknadsapper i sif-brukerdialog.
Sett opp OppsummeringSteg i en v2-app — DTO-basert oppsummering med FormSummary, bekreftelsescheckbox og i18n-nøkler.
Veiledning for oppsett av en ny søknadsapp med @sif/soknad-app — SøknadRouter, SøknadAppProvider, AppContext og routing shell.
Implementer et vedleggssteg i en v2-app — VedleggPanel, PersistedVedlegg, hydration og MSW-handlere.
Bruk denne skillen for å fange opp og rette feilaktig datoparsing fra backend i v2-apper — tidssoneproblemer, feil bruk av Date/dayjs og blandede ISODate/ISODateTime-verdier i frontend.