一键导入
sif-dialog-migration
Porter *ListAndDialog-komponenter fra sif-common-forms-ds (v1/Formik) til sif-soknad-forms (v2/RHF) via ModalFormAndList.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Porter *ListAndDialog-komponenter fra sif-common-forms-ds (v1/Formik) til sif-soknad-forms (v2/RHF) via ModalFormAndList.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Mønster for å kombinere flere API-hooks til én asynkron laster (useInitialData + InitialDataLoader) i sif-soknad-apper.
Legg til et nytt steg i en søknadsapp som bruker @sif/soknad og @sif/rhf — oppretter alle filer og oppdaterer config/routing/i18n.
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.
| name | sif-dialog-migration |
| type | action |
| description | Porter *ListAndDialog-komponenter fra sif-common-forms-ds (v1/Formik) til sif-soknad-forms (v2/RHF) via ModalFormAndList. |
sif-common-forms-ds til sif-soknad-forms.porter dialog, migrer ListAndDialog, flytt til sif-soknad-forms, ModalFormAndList, eller en spesifikk v1-dialog.src/dialogs/<navn>/index.tsXxxDialogForm — RHF-form med felter, validering og konverteringsfunksjonerXxxDialog — Aksel Dialog-shellXxxList — liste med ItemListDarksideXxxListAndDialog — kobler ModalFormAndList med domenekomponentene.stories.tsxnb.ts og nn.ts) under src/dialogs/<navn>/i18n/src/dialogs/<navn>/index.ts og src/dialogs/index.tssif-soknad-forms) → bruk sif-formik-to-rhf.sif-intl.Generisk komponent i packages/sif-soknad-forms/src/components/ModalFormAndList.tsx som håndterer:
maxItems-begrensning og emptyStateAlle *ListAndDialog-porter bruker denne som orkestreringskomponent. Domenelogikk holdes i egne filer.
src/dialogs/<navn>/
index.ts ← domenetype + barrel exports
XxxDialogForm.tsx ← useForm + createSifFormComponents + useSifValidate
XxxDialog.tsx ← Aksel Dialog shell rundt formen
XxxList.tsx ← ItemListDarkside fra @navikt/sif-common-ui
XxxListAndDialog.tsx ← tynn wrapper: mapper domeneprops til ModalFormAndList
XxxListAndDialog.stories.tsx
i18n/
nb.ts
nn.ts
| Fil | Ansvar |
|---|---|
XxxDialogForm | RHF-form: felter, validering, formValuesToXxx(), xxxToFormValues() |
XxxDialog | Aksel Dialog-shell: tittel, body (form), footer (knapper) |
XxxList | Render liste med ItemListDarkside, label-rendering, formattering |
XxxListAndDialog | Kobler ModalFormAndList med domenekomponentene via render-props |
For hver dialog som porteres:
src/dialogs/<navn>/index.ts.XxxDialogForm — RHF-form med useForm, createSifFormComponents, useSifValidate. Inkluder formValuesToXxx og xxxToFormValues.XxxDialog — Aksel Dialog-shell rundt formen.XxxList — bruker ItemListDarkside fra @navikt/sif-common-ui.XxxListAndDialog — tynn wrapper som kobler ModalFormAndList med domenekomponentene.XxxListAndDialog.stories.tsx med StoryFrame. Intl håndteres globalt.src/dialogs/<navn>/i18n/, aggregert i src/i18n/index.tsx.src/dialogs/<navn>/index.ts og src/dialogs/index.ts.get_errors på alle nye filer + lint:tsc.useSifValidate('@sifSoknadForms.<xxxForm>') — scope følger @sifSoknadForms-prefiksen.getDateValidator, getRequiredFieldValidator etc. fra @navikt/sif-validation.DateRangePicker: getDateValidator per felt + validate-prop på gruppen for cross-field validering.crypto.randomUUID() for nye elementer.sifIntl.locale (via useSifSoknadFormsIntl()) når displaydata bygges, f.eks. getCountryName(landkode, sifIntl.locale).'nb' i mapper-funksjoner som bygger brukervendt tekst.Dato-APIet er delt i to lag:
| Lag | Pakke | Funksjon | Bruksområde |
|---|---|---|---|
| Datepicker-parsing | @sif/rhf → datePickerUtils | parseDatePickerValue(value) | Konverterer brukerinput fra datepicker (ISO-streng eller norske datoformater) til Date | undefined |
| Generell ISO-konvertering | @navikt/sif-common-utils → dateUtils | dateToISODate(date), ISODateToDate(iso), isISODateString(value) | Konvertering mellom Date og ISODate-strenger |
Regler:
formValuesToXxx()-funksjoner der verdier kommer fra datepicker-felter, bruk datePickerUtils.parseDatePickerValue(value) for å parse til Date.xxxToFormValues()-funksjoner der Date skal til formverdi, bruk dateUtils.dateToISODate(date) for å konvertere til ISO-streng.dateUtils.isISODateString(value).new Date(...) er blokkert i portert runtime-kode for skjemaer med mindre bruker eksplisitt har godkjent det.ISODateToDate kan brukes i tester og mock-data, men ikke som erstatning for parseDatePickerValue i skjemaflyt.validationUtils.getDateFromDateString (fra @navikt/sif-validation) brukes fortsatt internt i validatorer — ikke bland den inn i dialog-mapping.@navikt/sif-common-env i packages/sif-soknad-forms uten at det er strengt nødvendig.sif-soknad-forms også kjøres i Storybook, hvor full appSettings ikke alltid finnes.Dialog med Dialog.Popup, Dialog.Header, Dialog.Body, Dialog.Footer.onOpenChange skal wrappe cancel: onOpenChange={(open) => { if (!open) onCancel(); }}.null når isOpen === false slik at innholdet unmountes mellom åpninger.useForm({ defaultValues }) ved ny mount, og er ofte enklere enn manuell reset(...)-logikk.form={formId} for å koble til formen i body.XxxDialogForm → XxxDialog → XxxListAndDialog), eksporter en egen delt config-type fra form-filen og gjenbruk den i wrapperne.XxxDialogFormConfig fremfor å repetere feltene eller bygge wrapper-API på Pick<Props, ...> fra hele form-komponenten.Når du lager stories i packages/sif-soknad-forms:
IntlProvider — intl er globalt satt opp i .storybook/preview.js via withIntl.StoryFrame fra src/storybook/components/StoryFrame.tsx for layout (maxWidth, minHeight).withRHFForm fra src/storybook/decorators/withRHFForm.tsx hvis storyen trenger RHF-kontekst, med parameters.rhf.defaultValues.useState for liste eller åpen dialog).disallowedFødselsnumre, placeholders, hjelpetekst og andre domeneprops som styrer validering eller visning.import { StoryFrame } from '../../storybook/components/StoryFrame';
function XxxListAndDialogStory({ items }: StoryProps) {
const [data, setData] = useState(items);
return <XxxListAndDialog items={data} onChange={setData} addButtonLabel="Legg til" />;
}
const meta = {
title: 'Dialogs/Xxx/ListAndDialog',
component: XxxListAndDialogStory,
decorators: [
(Story) => (
<StoryFrame maxWidth={720} minHeight={700}>
<Story />
</StoryFrame>
),
],
args: { items: exampleItems },
} satisfies Meta<typeof XxxListAndDialogStory>;
Etter porting av en dialog må alle renderbare komponenter verifiseres mot v1-originalen. Denne sjekken er blokkerende — dialogen regnes ikke som ferdig portert før den er bestått.
Alle brukersynlige tekster og valideringsmeldinger i v2 skal være identiske med v1, inkludert:
nb.ts og nn.ts{land}, {navn}, {dato}, {min}, {maks})Unntaket er strukturendringer: Hvis v2 slår sammen felter, endrer feltrekkefølge eller dropper felter av strukturelle årsaker, må tekstene tilpasses — men avviket skal dokumenteres eksplisitt og begrunnes. Hvis du er usikker på om noe er strukturendring, ta det opp med bruker.
Eksempel: v1 validerer
erSammenMedBarnetmed{ land: getCountryName(...) }som interpolasjonsparameter. v2 må sende samme parameter iextraValuesMapperog teksten må inneholde{land}.
Dette gjelder alle komponenttyper som rendrer brukersynlig innhold:
For hver komponenttype som finnes i v1:
sif-common-forms-ds/src/forms/<xxx>/Xxx*.tsx og list opp alt innhold som rendres.sif-soknad-forms/src/dialogs/<xxx>/Xxx*.tsx og list opp alt innhold som rendres.{land}, {navn}, {dato} etc.)extraValuesMapper i validateField sender alle parametere som teksten refererer tilerNyoppstartet, registrertINorge)YesOrNo-felt i FormValues typet som string i stedet for YesOrNo. RHF støtter enum-typer direkte — bruk YesOrNo-typen og unngå as YesOrNo-caster i konverteringsfunksjonene.=== YES der v1 bruker === NO eller omvendt.v1 bruker ofte en API-data-type (flat/nested DTO), mens v2 bruker en form-nær type med YesOrNo-felter. Sørg for at alle verdier fra DTO-en som v1 rendrer, også er tilgjengelig og rendret via v2-typen.
@sifSoknadForms.<xxx>. for tekster, @sifSoknadForms.<xxxForm>.validation. for feilmeldinger.nn.ts types mot nb.ts med Record<keyof typeof ..._nb, string>.src/i18n/index.tsx sammen med andre dialogs meldinger.XxxListAndDialog er ~30 linjer:
export const BostedUtlandListAndDialog = ({ minDate, maxDate, bosteder, addButtonLabel, onChange }: Props) => (
<ModalFormAndList
items={bosteder}
getItemId={(b) => b.id}
addButtonLabel={addButtonLabel}
onChange={onChange}
listRenderer={({ items, onEdit, onDelete }) => (
<BostedUtlandList bosteder={items} onEdit={onEdit} onDelete={onDelete} />
)}
dialogRenderer={({ item, allItems, isOpen, onSubmit, onCancel }) => (
<BostedUtlandFormDialog
minDate={minDate}
maxDate={maxDate}
bosted={item}
alleBosteder={allItems}
isOpen={isOpen}
onValidSubmit={onSubmit}
onCancel={onCancel}
/>
)}
/>
);
Fra packages/sif-common-forms-ds/src/forms/:
| v1-mappe | Porteringsstatus |
|---|---|
bosted-utland | Ferdig |
utenlandsopphold | Ikke startet |
tidsperiode | Ikke startet |
ferieuttak | Ikke startet |
opptjening-utland | Ikke startet |
enkeltdatoer | Ikke startet |
annet-barn | Ferdig |
utenlandsk-næring | Ikke startet |
fravær (perioder + dager) | Ikke startet |
fosterbarn | Ikke startet |