@innspel/react-native 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -40,8 +40,8 @@ __export(index_exports, {
40
40
  module.exports = __toCommonJS(index_exports);
41
41
 
42
42
  // src/InnspelProvider.tsx
43
- var import_react12 = require("react");
44
- var import_react_native10 = require("react-native");
43
+ var import_react13 = require("react");
44
+ var import_react_native11 = require("react-native");
45
45
 
46
46
  // src/skjermbilde.ts
47
47
  var import_react = require("react");
@@ -393,8 +393,8 @@ function useTema() {
393
393
 
394
394
  // src/widget/Widget.tsx
395
395
  var import_core3 = require("@innspel/core");
396
- var import_react11 = require("react");
397
- var import_react_native9 = require("react-native");
396
+ var import_react12 = require("react");
397
+ var import_react_native10 = require("react-native");
398
398
  var import_react_native_safe_area_context = require("react-native-safe-area-context");
399
399
 
400
400
  // src/Ikon.tsx
@@ -425,12 +425,21 @@ var calendar_outline_default = '<svg xmlns="http://www.w3.org/2000/svg" viewBox=
425
425
  // ../../node_modules/ionicons/dist/svg/camera-outline.svg
426
426
  var camera_outline_default = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="ionicon"><path d="m350.54 148.68-26.62-42.06C318.31 100.08 310.62 96 302 96h-92c-8.62 0-16.31 4.08-21.92 10.62l-26.62 42.06C155.85 155.23 148.62 160 140 160H80a32 32 0 0 0-32 32v192a32 32 0 0 0 32 32h352a32 32 0 0 0 32-32V192a32 32 0 0 0-32-32h-59c-8.65 0-16.85-4.77-22.46-11.32" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32px"/><circle cx="256" cy="272" r="80" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32px"/><path d="M124 158v-22h-24v22" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32px"/></svg>';
427
427
 
428
+ // ../../node_modules/ionicons/dist/svg/chatbox-outline.svg
429
+ var chatbox_outline_default = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="ionicon"><path d="M408 64H104a56.16 56.16 0 0 0-56 56v192a56.16 56.16 0 0 0 56 56h40v80l93.72-78.14a8 8 0 0 1 5.13-1.86H408a56.16 56.16 0 0 0 56-56V120a56.16 56.16 0 0 0-56-56Z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32px"/></svg>';
430
+
428
431
  // ../../node_modules/ionicons/dist/svg/checkmark-circle-outline.svg
429
432
  var checkmark_circle_outline_default = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="ionicon"><path d="M448 256c0-106-86-192-192-192S64 150 64 256s86 192 192 192 192-86 192-192Z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32px"/><path d="M352 176 217.6 336 160 272" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32px"/></svg>';
430
433
 
434
+ // ../../node_modules/ionicons/dist/svg/checkmark-outline.svg
435
+ var checkmark_outline_default = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="ionicon"><path d="M416 128 192 384l-96-96" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32px"/></svg>';
436
+
431
437
  // ../../node_modules/ionicons/dist/svg/chevron-down-outline.svg
432
438
  var chevron_down_outline_default = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="ionicon"><path d="m112 184 144 144 144-144" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48px"/></svg>';
433
439
 
440
+ // ../../node_modules/ionicons/dist/svg/chevron-forward-outline.svg
441
+ var chevron_forward_outline_default = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="ionicon"><path d="m184 112 144 144-144 144" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48px"/></svg>';
442
+
434
443
  // ../../node_modules/ionicons/dist/svg/chevron-up-outline.svg
435
444
  var chevron_up_outline_default = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="ionicon"><path d="m112 328 144-144 144 144" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48px"/></svg>';
436
445
 
@@ -508,8 +517,14 @@ var IKONER = Object.fromEntries(
508
517
  "bug-outline": bug_outline_default,
509
518
  "calendar-outline": calendar_outline_default,
510
519
  "camera-outline": camera_outline_default,
520
+ // «Send» og «Send nytt innspill» — ikonkartet i wireframen (R8.3).
521
+ "chatbox-outline": chatbox_outline_default,
511
522
  "checkmark-circle-outline": checkmark_circle_outline_default,
523
+ // Haken ALENE: sporingslinjens passerte ledd er allerede en sirkel (R8.3).
524
+ "checkmark-outline": checkmark_outline_default,
512
525
  "chevron-down-outline": chevron_down_outline_default,
526
+ // Sporvalgets rader peker videre (R8.3, DD-63) — dekorativ, etiketten bærer meningen.
527
+ "chevron-forward-outline": chevron_forward_outline_default,
513
528
  "chevron-up-outline": chevron_up_outline_default,
514
529
  "close-circle-outline": close_circle_outline_default,
515
530
  "close-outline": close_outline_default,
@@ -582,9 +597,9 @@ function Btn({
582
597
  const tema = useTema();
583
598
  const c = tema.color;
584
599
  const forbi = useTrykkForbiForelder(onPress, !!disabled, tema.touch / 2);
585
- const bakgrunn = variant === "primary" ? c.actionPrimary : variant === "secondary" ? c.surfaceRaised : "transparent";
586
- const tekstfarge = variant === "primary" ? c.onActionPrimary : variant === "danger" ? c.danger : c.actionSecondaryText;
587
- const kant = variant === "ghost" ? "transparent" : variant === "primary" ? c.actionPrimary : c.actionSecondaryBorder;
600
+ const bakgrunn = variant === "primary" ? c.actionPrimary : variant === "tonet" ? c.brandBg : variant === "secondary" ? c.surfaceRaised : "transparent";
601
+ const tekstfarge = variant === "primary" ? c.onActionPrimary : variant === "tonet" ? c.brand : variant === "danger" ? c.danger : c.actionSecondaryText;
602
+ const kant = variant === "ghost" || variant === "tonet" ? "transparent" : variant === "primary" ? c.actionPrimary : c.actionSecondaryBorder;
588
603
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native2.View, { style: grow ? { flex: 1 } : void 0, children: [
589
604
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
590
605
  import_react_native2.Pressable,
@@ -659,35 +674,142 @@ function useTrykkForbiForelder(onPress, laast, slingring) {
659
674
  [slingring]
660
675
  );
661
676
  }
662
- function H({ children, sub }) {
677
+ function H({
678
+ children,
679
+ sub,
680
+ meta,
681
+ nivaa = 2,
682
+ testID
683
+ }) {
663
684
  const tema = useTema();
664
685
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react_native2.View, { style: { gap: tema.space.xs }, children: [
665
686
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
666
687
  import_react_native2.Text,
667
688
  {
689
+ testID,
668
690
  accessibilityRole: "header",
669
691
  style: {
670
692
  color: tema.color.textPrimary,
671
- fontSize: tema.font.h2,
672
- lineHeight: tema.lineHeight.h2,
673
- fontWeight: tema.weight.semibold
693
+ fontSize: nivaa === 2 ? tema.font.h2 : tema.font.h3,
694
+ lineHeight: nivaa === 2 ? tema.lineHeight.h2 : tema.lineHeight.h3,
695
+ fontWeight: tema.weight.bold
674
696
  },
675
697
  children
676
698
  }
677
699
  ),
678
- sub ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
679
- import_react_native2.Text,
680
- {
681
- style: {
682
- color: tema.color.textSecondary,
683
- fontSize: tema.font.small,
684
- lineHeight: tema.lineHeight.small
685
- },
686
- children: sub
687
- }
688
- ) : null
700
+ sub ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Sek, { children: sub }) : null,
701
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Meta, { children: meta }) : null
689
702
  ] });
690
703
  }
704
+ function Brodtekst({ children, testID }) {
705
+ const tema = useTema();
706
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
707
+ import_react_native2.Text,
708
+ {
709
+ testID,
710
+ style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body },
711
+ children
712
+ }
713
+ );
714
+ }
715
+ function Sek({ children, testID }) {
716
+ const tema = useTema();
717
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
718
+ import_react_native2.Text,
719
+ {
720
+ testID,
721
+ style: { color: tema.color.textSecondary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body },
722
+ children
723
+ }
724
+ );
725
+ }
726
+ function Helt({
727
+ children,
728
+ testID,
729
+ farge,
730
+ live
731
+ }) {
732
+ const tema = useTema();
733
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
734
+ import_react_native2.Text,
735
+ {
736
+ testID,
737
+ ...live ? { accessibilityRole: "alert", accessibilityLiveRegion: "polite" } : {},
738
+ style: {
739
+ color: farge ?? tema.color.textPrimary,
740
+ fontSize: tema.font.h1,
741
+ lineHeight: tema.lineHeight.h1,
742
+ fontWeight: tema.weight.bold
743
+ },
744
+ children
745
+ }
746
+ );
747
+ }
748
+ function Meta({ children, testID, farge }) {
749
+ const tema = useTema();
750
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
751
+ import_react_native2.Text,
752
+ {
753
+ testID,
754
+ style: { color: farge ?? tema.color.textMuted, fontSize: tema.font.small, lineHeight: tema.lineHeight.small },
755
+ children
756
+ }
757
+ );
758
+ }
759
+ function Tekstknapp({
760
+ label,
761
+ ikon,
762
+ onPress,
763
+ noytral,
764
+ disabled,
765
+ testID,
766
+ accessibilityLabel
767
+ }) {
768
+ const tema = useTema();
769
+ const farge = disabled ? tema.color.textDisabled : noytral ? tema.color.textPrimary : tema.color.actionSecondaryText;
770
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
771
+ import_react_native2.Pressable,
772
+ {
773
+ testID,
774
+ accessibilityRole: "button",
775
+ accessibilityLabel: accessibilityLabel ?? label,
776
+ accessibilityState: { disabled: !!disabled },
777
+ disabled,
778
+ onPress,
779
+ style: {
780
+ alignSelf: "flex-start",
781
+ minHeight: tema.touch,
782
+ flexDirection: "row",
783
+ alignItems: "center",
784
+ gap: tema.space.sm
785
+ },
786
+ children: [
787
+ ikon ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Ikon, { navn: ikon, storrelse: "minste", farge }) : null,
788
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native2.Text, { style: { color: farge, fontSize: tema.font.body, fontWeight: tema.weight.semibold }, children: label })
789
+ ]
790
+ }
791
+ );
792
+ }
793
+ function Pille({ children, testID }) {
794
+ const tema = useTema();
795
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
796
+ import_react_native2.Text,
797
+ {
798
+ testID,
799
+ style: {
800
+ color: tema.color.info,
801
+ backgroundColor: tema.color.infoBg,
802
+ fontSize: tema.font.small,
803
+ lineHeight: tema.lineHeight.small,
804
+ fontWeight: tema.weight.semibold,
805
+ borderRadius: tema.radius.pill,
806
+ paddingHorizontal: tema.space.sm,
807
+ overflow: "hidden"
808
+ },
809
+ children
810
+ }
811
+ );
812
+ }
691
813
  function Hint({ children }) {
692
814
  const tema = useTema();
693
815
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -705,12 +827,16 @@ function Hint({ children }) {
705
827
  function Card({
706
828
  children,
707
829
  dashed,
708
- style
830
+ style,
831
+ testID,
832
+ accessibilityLabel
709
833
  }) {
710
834
  const tema = useTema();
711
835
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
712
836
  import_react_native2.View,
713
837
  {
838
+ testID,
839
+ ...accessibilityLabel ? { accessibilityLabel } : {},
714
840
  style: [
715
841
  {
716
842
  backgroundColor: tema.color.surface,
@@ -727,12 +853,19 @@ function Card({
727
853
  }
728
854
  );
729
855
  }
730
- function StatusPill({ ikon, etikett, fg, bg }) {
856
+ function StatusPill({
857
+ ikon,
858
+ etikett,
859
+ fg,
860
+ bg,
861
+ testID
862
+ }) {
731
863
  const tema = useTema();
732
864
  const farge = (navn, reserve) => tema.color[navn] ?? reserve;
733
865
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
734
866
  import_react_native2.View,
735
867
  {
868
+ testID,
736
869
  style: {
737
870
  flexDirection: "row",
738
871
  alignItems: "center",
@@ -779,8 +912,8 @@ function Banner({
779
912
  style: {
780
913
  flex: 1,
781
914
  color: tema.color[tone],
782
- fontSize: tema.font.small,
783
- lineHeight: tema.lineHeight.small
915
+ fontSize: tema.font.body,
916
+ lineHeight: tema.lineHeight.body
784
917
  },
785
918
  children
786
919
  }
@@ -797,30 +930,82 @@ function saksnr(id) {
797
930
  return rest.length > 8 ? rest.slice(-4) : rest;
798
931
  }
799
932
  var stor = (s) => s ? s.charAt(0).toUpperCase() + s.slice(1) : s;
933
+ var PLATTFORM_ORD = {
934
+ android: "Android",
935
+ ios: "iOS",
936
+ web: "Web",
937
+ tvos: "TV"
938
+ };
939
+ var SPRAAK_ORD = {
940
+ nb: "Norsk (bokm\xE5l)",
941
+ nn: "Norsk (nynorsk)",
942
+ no: "Norsk",
943
+ se: "Nordsamisk",
944
+ en: "Engelsk",
945
+ sv: "Svensk",
946
+ da: "Dansk",
947
+ fi: "Finsk",
948
+ is: "Islandsk",
949
+ de: "Tysk",
950
+ nl: "Nederlandsk",
951
+ fr: "Fransk",
952
+ es: "Spansk",
953
+ it: "Italiensk",
954
+ pt: "Portugisisk",
955
+ pl: "Polsk",
956
+ lt: "Litauisk",
957
+ ru: "Russisk",
958
+ uk: "Ukrainsk",
959
+ ar: "Arabisk",
960
+ so: "Somali",
961
+ ti: "Tigrinja",
962
+ tr: "Tyrkisk",
963
+ ur: "Urdu",
964
+ fa: "Persisk",
965
+ th: "Thai",
966
+ vi: "Vietnamesisk",
967
+ zh: "Kinesisk",
968
+ ja: "Japansk",
969
+ ko: "Koreansk"
970
+ };
971
+ function plattformOrd(verdi) {
972
+ return PLATTFORM_ORD[verdi.toLowerCase()] ?? stor(verdi);
973
+ }
974
+ function spraakOrd(verdi) {
975
+ const hoved = verdi.toLowerCase().split(/[-_]/)[0] ?? verdi;
976
+ return SPRAAK_ORD[hoved] ?? stor(hoved);
977
+ }
978
+ var TALLORD = ["null", "\xE9n", "to", "tre"];
979
+ var tallord = (n) => TALLORD[n] ?? String(n);
800
980
  var tekst = {
801
981
  // 2b — første valg
802
982
  valgTittel: "Hva gjelder det?",
803
983
  sporFeil: "Noe virker ikke",
984
+ /** DD-67, produkteier 2026-09-20: dette er VALGETS tekst, ikke en hjelpetekst. */
804
985
  sporFeilUnder: "Noe er galt eller virker rart",
805
986
  sporOnske: "Jeg \xF8nsker meg noe",
806
987
  sporOnskeUnder: "Noe du savner eller vil ha annerledes",
807
- // 2c — kjente feil (DD-29, DD-30)
988
+ /**
989
+ * Anonym modus (DD-62 (3)). Portalens ordlyd, med widgetens ord. ALDRI «du er ikke logget
990
+ * inn»: anonym modus er leietakerens valg ved `init()`, og widgeten vet ikke om
991
+ * innsenderen er logget inn i vertsappen.
992
+ */
993
+ sendAnonymtHint: "Innspillet kobles ikke til deg, og du kan ikke f\xF8lge det etterp\xE5.",
994
+ // 2c — kjente feil (DD-29, DD-30). Ingen undertittel: overskriften stiller spørsmålet.
808
995
  kjenteFeilTittelFeil: "Er det dette du ser?",
809
- kjenteFeilUnderFeil: "Kjenner du igjen en av disse?",
810
996
  kjenteFeilTittelOnske: "Har noen \xF8nsket dette?",
811
- kjenteFeilUnderOnske: "Ett trykk legger deg til p\xE5 \xF8nsket \u2014 ingen ny sak.",
812
997
  svarJa: "Ja, jeg ogs\xE5",
813
998
  svarLigner: "Ligner, men ikke helt",
814
999
  svarNei: "Nei, det er noe annet",
815
1000
  omvei: "Omvei:",
816
1001
  rettesI: (versjon) => `Rettes i ${versjon}`,
817
1002
  rettetI: (versjon) => `Rettet i ${versjon}`,
1003
+ /** Hvert kort er ÉN gruppe med samlet navn; de tre svarene er knapper i den. */
1004
+ kjentFeilGruppe: (tittel, status, versjon) => versjon ? `Kjent feil: ${tittel}, ${status}, ${versjon}` : `Kjent feil: ${tittel}, ${status}`,
818
1005
  // 2d + 2e — feltet og kontekstlinja
819
1006
  /**
820
- * «Ditt innspill», ikke «Din feil» (DD-54). «Din» festet saken til personen, og
821
- * «feil» karakteriserte den før noen hadde lest den — innsenderen leste det som
822
- * skyld. Ønskesporet beholder «Ditt ønske»: et ønske er ingen feil, og der finnes
823
- * ikke problemet. De to står aldri ved siden av hverandre; sporet velges før dette.
1007
+ * «Ditt innspill», ikke «Din feil» (DD-54). «Din» festet saken til personen, og «feil»
1008
+ * karakteriserte den før noen hadde lest den — innsenderen leste det som skyld.
824
1009
  */
825
1010
  feltLabelFeil: "Ditt innspill",
826
1011
  feltLabelOnske: "Ditt \xF8nske",
@@ -832,10 +1017,30 @@ var tekst = {
832
1017
  /** DD-44: minimum tegn er det ENESTE kravet. */
833
1018
  forKort: (min) => `Minst ${min} tegn. Ingenting annet er obligatorisk.`,
834
1019
  tellerFull: " \u2014 kort og konkret holder",
835
- kontekstLinje: "Legges ved: skjerm, appversjon, plattform, OS",
836
- kontekstVis: " \u2014 Vis",
1020
+ /**
1021
+ * DD-05 ordrett: «Én linje «Vis» under feltet ekspanderer». Lukket er linja en
1022
+ * OPPSUMMERING — den navngir det innsenderen kjenner igjen; lista er hele sannheten.
1023
+ */
1024
+ kontekstLinjeLukket: "Skjerm og enhet legges ved",
1025
+ kontekstLinjeApen: "Dette legges ved",
1026
+ kontekstVis: "Vis",
1027
+ kontekstSkjul: "Skjul",
837
1028
  kontekstFjern: "Fjern",
838
- kontekstAldri: "Aldri: navn, e-post, telefon, posisjon eller det som st\xE5r p\xE5 skjermen.",
1029
+ kontekstFjernA11y: (etikett) => `Fjern ${etikett.toLowerCase()} fra innsendingen`,
1030
+ /** K5 — skjermens ene hjelpesetning, og bare når lista står. */
1031
+ kontekstAldri: "Aldri navn, e-post, telefon, posisjon eller det som st\xE5r p\xE5 skjermen.",
1032
+ /**
1033
+ * Etikettene er portalens: samme felt, samme ord i begge flater (DD-50, presisert
1034
+ * 2026-09-20). Fram til R8.3 sto det «Plattform» og «OS» her.
1035
+ */
1036
+ kontekstEtiketter: {
1037
+ screen: "Skjerm",
1038
+ appVersion: "Appversjon",
1039
+ platform: "Enhet",
1040
+ os: "System",
1041
+ build: "Bygg",
1042
+ locale: "Spr\xE5k"
1043
+ },
839
1044
  lenketTil: (tittel) => `Lenket til: \xAB${tittel}\xBB`,
840
1045
  fjernLenke: "Fjern lenken til den kjente feilen",
841
1046
  // 2f — skjermbilde (K4, DD-39, DD-40, DD-42)
@@ -873,11 +1078,15 @@ var tekst = {
873
1078
  monsterFjern: "Fjern",
874
1079
  monsterBehold: "Behold",
875
1080
  monsterForklaring: "Teksten endres bare hvis du trykker Fjern. Vi fjerner aldri noe stille.",
876
- // 2g — kvittering
877
- kvitteringSendt: "Sendt",
878
- kvitteringRegistrert: "Registrert",
1081
+ /* 2g — kvitteringen som KORT (DD-07, P1 (a) 2026-09-20).
1082
+ Etiketten sier hva som skjedde; HELTEN er løftets setning. */
1083
+ kvitteringSendtDato: (dato) => `Sendt ${dato}`,
1084
+ kvitteringSendtAnonymtDato: (dato) => `Sendt anonymt ${dato}`,
1085
+ kvitteringRegistrertDato: (dato) => `Registrert ${dato}`,
1086
+ kvitteringLagretDato: (dato) => `Lagret ${dato}`,
879
1087
  kvitteringFeil: "Du f\xE5r beskjed n\xE5r den er rettet, eller hvis vi trenger mer.",
880
1088
  kvitteringJaOgsa: "Du f\xE5r beskjed n\xE5r den er rettet.",
1089
+ kvitteringUnder: "Ligger under \xABMine innspill\xBB og oppdaterer seg selv.",
881
1090
  saksnummer: (nr) => `Sak ${saksnr(nr)}`,
882
1091
  tilbakeTilAppen: "Tilbake til appen",
883
1092
  /** DD-42: saken er sendt, bildet kom ikke med — aldri en blokkert innsending. */
@@ -885,9 +1094,12 @@ var tekst = {
885
1094
  tekstenErLagret: "Teksten din er lagret.",
886
1095
  vedleggFeiletBanner: "Bildet ble ikke lastet opp. Saken er sendt uten det \u2014 vil du, kan du sende et nytt innspill med bilde.",
887
1096
  saksnummerUtenVedlegg: (nr) => `Sak ${saksnr(nr)} \xB7 uten vedlegg`,
888
- // 2i — tilstander
889
- koKvitteringTittel: "Lagret \u2014 sendes n\xE5r du er p\xE5 nett",
890
- offlineBanner: "Ingen nett. Lagres og sendes automatisk \u2014 du ser det under \xABMine innspill\xBB til det er sendt.",
1097
+ /* 2i — køet uten nett (DD-41, presisert 2026-09-20). Kortet lover ikke svar, og det er
1098
+ derfor ikke kvitteringen: kvitteringen kommer når køen tømmes. */
1099
+ koIngenNett: "Ingen nett",
1100
+ koHelt: "Sendes n\xE5r du er p\xE5 nett.",
1101
+ koUnder: "Du ser den under \xABMine innspill\xBB til den er sendt.",
1102
+ offlineBanner: "Ingen nett. Lagres og sendes automatisk.",
891
1103
  offlineLagre: "Lagre \u2014 sendes n\xE5r du er p\xE5 nett",
892
1104
  /** DD-41: et skjermbilde køes aldri. */
893
1105
  offlineUtenBilde: "Skjermbilde kan ikke legges ved uten nett. Teksten sendes; bildet ble ikke lagret.",
@@ -898,18 +1110,23 @@ var tekst = {
898
1110
  /** Knappen på første steg med innspill fra før (DD-62): tallet er det som gjør den til en inngang. */
899
1111
  mineMedAntall: (n) => `Mine innspill \xB7 ${n}`,
900
1112
  mineEtikett: (n) => `Mine innspill, ${n} innspill`,
901
- mineUnder: "Status og hva du kan vente deg.",
902
- mineTom: "Du har ikke sendt noe enn\xE5.",
903
- mineIkkeSendt: "Ikke sendt enn\xE5",
904
- mineSak: (nr) => `Sak ${saksnr(nr)}`,
1113
+ mineLaster: "Henter innspillene dine",
1114
+ /** DD-19: tomheten er OVERSKRIFTEN, ikke en grå linje under tittelen. */
1115
+ mineTomTittel: "Du har ikke sendt noe enn\xE5",
1116
+ /** Ordrett portalens `mineTomHint` — én innsender, to flater, samme setning. */
1117
+ mineTomHint: (leietaker) => `Det f\xF8rste innspillet tar under et minutt. Feil eller \xF8nske \u2014 ${leietaker} svarer p\xE5 begge.`,
1118
+ mineTomHintGenerisk: "Det f\xF8rste innspillet tar under et minutt. Feil eller \xF8nske \u2014 du f\xE5r svar p\xE5 begge.",
1119
+ /** Køraden har ingen saksnummer å vise — hodet sier hva den er i stedet (DD-41). */
1120
+ mineIkkeSendtHode: (spor) => `${stor(spor)} \xB7 ikke sendt enn\xE5`,
1121
+ mineFeil: "Innspillene dine kunne ikke hentes n\xE5.",
905
1122
  /** «Feil · sak 2041» — sporet først, aldri rå id og aldri kontraktens type (DD-50). */
906
1123
  sakHode: (spor, nr) => `${stor(spor)} \xB7 sak ${saksnr(nr)}`,
907
1124
  /** F14: svaret kom siden forrige gang denne enheten viste lista. */
908
1125
  nyttSvar: "Nytt svar",
909
1126
  // Leietakeren fjernet vedlegget. Bare AT — aldri hvorfor, av hvem eller når.
910
1127
  bildeFjernet: "Bildet er fjernet.",
911
- svarFra: (leietaker) => `Svar fra ${leietaker}`,
912
- svarFraGenerisk: "Svar",
1128
+ svarFra: (leietaker, dato) => `Svar fra ${leietaker} \xB7 ${dato}`,
1129
+ svarFraGenerisk: (dato) => `Svar \xB7 ${dato}`,
913
1130
  // DD-69 — «Legg til mer»: innsenderens egne ord, ikke et svar på svaret.
914
1131
  leggTilMer: "Legg til mer",
915
1132
  leggTilMerLabel: "Legg til mer p\xE5 denne saken",
@@ -920,80 +1137,115 @@ var tekst = {
920
1137
  lagtTil: "Lagt til",
921
1138
  tilleggTak: "Du har lagt til tre ganger. Har du mer, send et nytt innspill.",
922
1139
  tilleggLukket: "Saken er avsluttet \u2014 send et nytt innspill.",
1140
+ /** F34: serverens egen setning (InnspelApiError) — aldri en rå feil. */
923
1141
  tilleggFeil: (arsak) => `Kunne ikke legge til: ${arsak} Teksten din er beholdt.`,
1142
+ tilleggIngenNett: "Ingen nett. Teksten din er beholdt \u2014 pr\xF8v igjen n\xE5r du er p\xE5 nett.",
1143
+ tilleggFeilGenerisk: "Kunne ikke legge til. Teksten din er beholdt \u2014 pr\xF8v igjen.",
924
1144
  sendNytt: "Send nytt innspill",
925
1145
  /** Tom tilstand: det finnes ikke noe «nytt» å sende når ingenting er sendt. */
926
1146
  sendForste: "Send innspill",
927
- // 3a — invitasjonsbanneret (DD-12)
1147
+ /* Sporingslinjen (DD-08/DD-28 presisert 2026-09-20). Ordene er innsenderens, aldri
1148
+ kontraktens: ingen status-enum, ingen «deadline». Samme ord som portalen. */
1149
+ sporEtikett: "Sakens gang",
1150
+ sporSvarInnen: "Svar innen",
1151
+ /** Mottatt: fristen finnes ikke ennå, og vi lover ingen dato på en sak ingen har åpnet. */
1152
+ sporDatoenSettes: "dato kommer",
1153
+ /** Planlagt/Bygges: kontrakten har ingen leveringsdato, og DD-28 forbyr en ETA. */
1154
+ sporIngenDato: "ingen dato lovet",
1155
+ sporNaarTenantTarDen: (leietaker) => `n\xE5r ${leietaker} tar den`,
1156
+ sporNaarDenTasOpp: "n\xE5r de tar den",
1157
+ /** P3 (a), produkteier 2026-09-20. Klientregel på `deadlineAt` — ingen ny status. */
1158
+ sporFristenErGatt: "Fristen er g\xE5tt",
1159
+ // 3a — invitasjonsbanneret (DD-12). Kontakttaket står IKKE her (DD-14).
928
1160
  invitasjonRegion: "Invitasjon til betaprogram",
929
1161
  invitasjonHva: (navn) => `Vil du teste \xAB${navn}\xBB?`,
930
- invitasjonKontakter: (maks) => `Vi tar kontakt maks ${maks} ganger. Du kan g\xE5 ut n\xE5r som helst.`,
1162
+ /** Én meta-linje med det kontrakten har: antall oppgaver og perioden. */
1163
+ invitasjonMeta: (oppgaver, periode2) => `${oppgaver} oppgaver \xB7 ${periode2}`,
931
1164
  lesMer: "Les mer og bli med",
932
1165
  avvisInvitasjon: "Avvis invitasjonen",
933
1166
  // 3b — aksepten (DD-13, DD-32, DD-37)
934
- akseptHva: "Hva testes",
935
- /** DD-32: tallene på én linje, FØR forklaringen — N oppgaver · ca. M min hver · dato–dato · maks K kontakter. */
936
- akseptTall: (oppgaver, minutter, periode2, kontakter) => `${oppgaver} oppgaver \xB7 ca. ${minutter} min hver \xB7 ${periode2} \xB7 maks ${kontakter} kontakter`,
1167
+ /**
1168
+ * DD-32, presisert 2026-09-20: tallene skal være SANNE. Summen når anslagene er ulike —
1169
+ * et snitt av 5, 3 og 2 er ikke sant for noen av oppgavene.
1170
+ */
1171
+ akseptTallSum: (oppgaver, minutter, periode2) => `${oppgaver} oppgaver \xB7 ca. ${minutter} min i alt \xB7 ${periode2}`,
1172
+ akseptTallHver: (oppgaver, minutter, periode2) => `${oppgaver} oppgaver \xB7 ca. ${minutter} min hver \xB7 ${periode2}`,
937
1173
  akseptOppgaver: "Hva vi ber om",
938
1174
  akseptOppgaveTid: (minutter) => `ca. ${minutter} min`,
939
- akseptKjenteFeil: (antall) => `Kjente feil (${antall})`,
940
- akseptKjenteFeilUnder: "Disse trenger du ikke melde \u2014 vi vet om dem.",
1175
+ akseptKjenteFeil: "Kjente feil vi vet om",
941
1176
  akseptInnsamling: "Hva som samles inn",
942
- akseptInnsamlingTekst: "Skjerm, appversjon, plattform, OS og hva du svarer. Aldri navn, e-post, telefon eller posisjon.",
943
- akseptVilkar: "Les vilk\xE5rene (\xE5pnes i nettleser)",
944
- akseptVilkarHint: "Bare en lenke. Ingen avkryssing, ingen signatur \u2014 \xABBli med\xBB binder deg ikke til noe.",
945
- akseptIngenVilkar: "Ingen vilk\xE5r, ingen avtale \u2014 plattformen kjenner ikke navnet ditt og kan ikke inng\xE5 \xE9n.",
946
- akseptUtgang: "Du kan g\xE5 ut n\xE5r som helst \u2014 herfra.",
1177
+ /** Samme ord som kontekstlista (DD-50): «enhet», ikke «plattform». */
1178
+ akseptInnsamlingTekst: "Skjerm, appversjon, enhet og det du svarer. Aldri navn, e-post, telefon eller posisjon.",
1179
+ akseptVilkar: "Les vilk\xE5rene",
1180
+ /**
1181
+ * Skjermens ENE hjelpesetning: taket og utgangen i én (DD-67). «høyst N» — tallet er
1182
+ * `maxContacts`, et TAK som kan senkes og aldri heves, og antall oppfølginger er malene,
1183
+ * som kan være færre. «Vi spør tre ganger» lover noe som ikke er sant (DD-14).
1184
+ */
1185
+ akseptTakOgUtgang: (maks) => `Vi sp\xF8r h\xF8yst ${tallord(maks)} ${maks === 1 ? "gang" : "ganger"} underveis. Du kan g\xE5 ut n\xE5r som helst \u2014 ingen vilk\xE5r, ingen avtale.`,
1186
+ akseptTakOgUtgangVilkar: (maks) => `Vi sp\xF8r h\xF8yst ${tallord(maks)} ${maks === 1 ? "gang" : "ganger"} underveis. Du kan g\xE5 ut n\xE5r som helst.`,
947
1187
  bliMed: "Bli med",
948
1188
  bliMedHint: "Samtykket gjelder bare dette programmet.",
949
1189
  /** DD-12: tokenet er engangs og kom i leietakerens egen kanal — plattformen sender aldri. */
950
1190
  bliMedUtenToken: "\xC5pne lenken vi sendte deg for \xE5 bli med.",
951
1191
  akseptFeil: (arsak) => `Kunne ikke bli med: ${arsak}`,
952
- // 3c (M3.1-delen) — deltakelsen og «Gå ut» (DD-36)
1192
+ // 3c — deltakelsen og «Gå ut» (DD-36). Kontakttaket står IKKE her (DD-14).
953
1193
  deltakelseRegion: "Ditt betaprogram",
954
- deltakelsePeriode: (periode2, brukt, maks) => `${periode2} \xB7 Vi tar kontakt maks ${maks} ganger \u2014 ${brukt} brukt`,
955
- deltakelseOppgaverKommer: "Oppgavene kan gj\xF8res n\xE5r det passer deg.",
956
1194
  gaaUt: "G\xE5 ut av programmet",
957
1195
  gaaUtTittel: "G\xE5 ut av programmet?",
958
1196
  gaaUtTekst: (navn) => `Du tas ut av testgruppen med en gang. \xAB${navn}\xBB sl\xE5s av for deg, og vi tar ikke kontakt igjen. Det du allerede har svart, beholdes.`,
959
1197
  bliVaerende: "Bli v\xE6rende",
960
1198
  gaaUtBekreft: "G\xE5 ut",
961
- // 3c (M3.2) — oppgavene og «Hvordan gikk det?»: tre lukkede valg, aldri en skala
1199
+ /* Programmets sporingslinje (P1 (a), produkteier 2026-09-20): deltakelsen bæres av
1200
+ linjen, ikke av et kvitteringskort — merkefargen er for det som er SENDT (DD-41). */
1201
+ programSporEtikett: "Programmets gang",
1202
+ programBleMed: "Du ble med",
1203
+ programGjort: (gjort, av) => `${gjort} av ${av} gjort`,
1204
+ programOver: "Programmet er over",
1205
+ /** Under nå-leddet, ÉN linje. Aldri «to igjen»: «1 av 3» sier alt tallet sier (DD-08). */
1206
+ programNaarDetPasser: "n\xE5r det passer",
1207
+ // 3c — oppgavene
962
1208
  oppgaverTittel: "Oppgavene",
963
- oppgaveIkkeBegynt: "Ikke begynt",
964
1209
  oppgaveGjort: "Gjort",
965
1210
  oppgaveGjortLabel: (tittel) => `Gjort: ${tittel}`,
966
- oppgaveGjortMed: (utfall) => `Pr\xF8vd \xB7 ${utfall}`,
1211
+ /** Oppgavens ENE meta-linje i `small` (DD-67). Setningen hennes står i `body` under. */
1212
+ oppgaveGjortMeta: (dato, utfall) => `Gjort ${dato} \xB7 ${utfall.toLowerCase()}`,
1213
+ oppgaveTid: (minutter, skjerm) => `ca. ${minutter} min${skjerm ? ` \xB7 ${skjerm}` : ""}`,
1214
+ oppgaveUbekreftet: "Svaret ble ikke bekreftet \u2014 merk den p\xE5 nytt",
1215
+ oppgaveRadA11y: (nr, tittel, status) => `Oppgave ${nr}: ${tittel}, ${status}`,
1216
+ oppgaveIkkeGjort: "ikke gjort",
1217
+ // 3e — «Hvordan gikk det?»: tre lukkede valg, aldri en skala (DD-15)
967
1218
  hvordanGikkDet: "Hvordan gikk det?",
968
1219
  utfallFungerte: "Fungerte",
969
1220
  utfallDelvis: "Fungerte delvis",
970
1221
  utfallIkke: "Fungerte ikke",
971
- setningLabel: "Vil du si \xE9n setning om det? (valgfritt)",
972
- setningPlaceholder: "Kopien kom, men rullesjefen manglet p\xE5 torsdag.",
1222
+ setningLabel: "Vil du si \xE9n setning om det?",
1223
+ setningValgfritt: "Valgfritt",
973
1224
  lagre: "Lagre",
974
- lagreHint: "Ferdig \u2014 ingen flere sp\xF8rsm\xE5l n\xE5.",
975
1225
  /** Etter «Ikke»: feilsporet er vertens — plattformen navigerer aldri selv. */
976
1226
  meldFeil: "Meld det som feil",
977
- meldFeilHint: "Gikk det ikke? Et innspill hjelper oss \xE5 finne ut hvorfor.",
978
1227
  svarFeil: (arsak) => `Kunne ikke lagre svaret: ${arsak}`,
979
- // 3d (M3.2) — oppfølgingskortene (DD-34): arten avgjør knappene
1228
+ // 3d — oppfølgingskortene (DD-34): arten avgjør knappene. Ingen kontaktnummer (DD-14).
980
1229
  oppfolgingRegion: "Oppf\xF8lging fra betaprogrammet",
981
- oppfolgingKontakt: (nr, maks) => `Kontakt ${nr} av ${maks} \xB7 tar under ett minutt`,
982
- oppfolgingPaaminnelseHint: (nr, maks) => `Kontakt ${nr} av ${maks} \xB7 planlagt p\xE5minnelse`,
983
- oppfolgingUtgangHint: (nr, maks) => `Kontakt ${nr} av ${maks} \xB7 den siste vi sender`,
1230
+ oppfolgingKost: "Ett sp\xF8rsm\xE5l \xB7 tar under ett minutt",
984
1231
  senere: "Senere",
985
1232
  svarNaa: "Svar n\xE5",
986
1233
  aapneOppgavene: "\xC5pne oppgavene",
987
1234
  // Felles
988
1235
  tilbake: "Tilbake",
989
1236
  lukk: "Lukk",
990
- venterPaaNett: "Venter p\xE5 nett \u2014 sendes automatisk",
1237
+ venterPaaNett: "Venter p\xE5 nett",
991
1238
  feil: "feil",
992
1239
  onske: "\xF8nske"
993
1240
  };
994
1241
  var lofte = {
995
- venterNett: "Sendes automatisk n\xE5r du er p\xE5 nett \u2014 kvitteringen kommer da."
1242
+ venterNett: "Sendes automatisk n\xE5r du er p\xE5 nett."
996
1243
  };
1244
+ function kontekstVerdi(felt, verdi) {
1245
+ if (felt === "platform") return plattformOrd(verdi);
1246
+ if (felt === "locale") return spraakOrd(verdi);
1247
+ return verdi;
1248
+ }
997
1249
 
998
1250
  // src/widget/Felt.tsx
999
1251
  var import_jsx_runtime3 = require("react/jsx-runtime");
@@ -1027,20 +1279,13 @@ function Felt({
1027
1279
  const full = brukt >= textMaxLength;
1028
1280
  const visTeller = brukt >= textMaxLength * 0.8;
1029
1281
  const uavklart = funn.find((f) => !beholdt.includes(f.match));
1030
- const linjer = (0, import_react5.useMemo)(() => {
1031
- const etiketter = {
1032
- screen: "Skjerm",
1033
- appVersion: "Appversjon",
1034
- platform: "Plattform",
1035
- os: "OS",
1036
- build: "Bygg",
1037
- locale: "Spr\xE5k"
1038
- };
1039
- return Object.entries(etiketter).map(([felt, etikett]) => {
1040
- const verdi2 = kontekst[felt];
1041
- return verdi2 && !fjernedeFelter.includes(felt) ? { felt, etikett, verdi: verdi2 } : null;
1042
- }).filter((x) => x !== null);
1043
- }, [kontekst, fjernedeFelter]);
1282
+ const linjer = (0, import_react5.useMemo)(
1283
+ () => Object.entries(tekst.kontekstEtiketter).map(([felt, etikett]) => {
1284
+ const r\u00E5 = kontekst[felt];
1285
+ return r\u00E5 && !fjernedeFelter.includes(felt) ? { felt, etikett, verdi: kontekstVerdi(felt, r\u00E5) } : null;
1286
+ }).filter((x) => x !== null),
1287
+ [kontekst, fjernedeFelter]
1288
+ );
1044
1289
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { testID: "skjema", style: { flexGrow: 1, flexShrink: 1, gap: tema.space.md }, children: [
1045
1290
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1046
1291
  import_react_native3.ScrollView,
@@ -1097,8 +1342,8 @@ function Felt({
1097
1342
  accessibilityLiveRegion: "polite",
1098
1343
  style: {
1099
1344
  color: tema.color.warning,
1100
- fontSize: tema.font.small,
1101
- lineHeight: tema.lineHeight.small,
1345
+ fontSize: tema.font.body,
1346
+ lineHeight: tema.lineHeight.body,
1102
1347
  fontWeight: tema.weight.medium
1103
1348
  },
1104
1349
  children: tekst.monsterSpm[uavklart.kind]
@@ -1235,17 +1480,16 @@ function Felt({
1235
1480
  bildeNotat ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { testID: "bilde-notat", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Hint, { children: bildeNotat }) }) : null
1236
1481
  ] })
1237
1482
  ) : null,
1238
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: { borderTopWidth: tema.hairline, borderTopColor: tema.color.border, paddingTop: tema.space.sm }, children: [
1239
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1483
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: { borderTopWidth: tema.hairline, borderTopColor: tema.color.border, paddingTop: tema.space.xs }, children: [
1484
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1240
1485
  import_react_native3.Pressable,
1241
1486
  {
1242
1487
  testID: "kontekst-bryter",
1243
1488
  accessibilityRole: "button",
1244
1489
  accessibilityState: { expanded: apen },
1245
- accessibilityLabel: `${tekst.kontekstLinje}${apen ? "" : tekst.kontekstVis}`,
1246
1490
  onPress: () => setApen((a) => !a),
1247
- style: { minHeight: tema.touch, justifyContent: "center" },
1248
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
1491
+ style: { minHeight: tema.touch, flexDirection: "row", alignItems: "center", gap: tema.space.sm },
1492
+ children: [
1249
1493
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1250
1494
  Ikon,
1251
1495
  {
@@ -1254,11 +1498,9 @@ function Felt({
1254
1498
  farge: tema.color.textSecondary
1255
1499
  }
1256
1500
  ),
1257
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.Text, { style: { flex: 1, color: tema.color.textSecondary, fontSize: tema.font.small }, children: [
1258
- tekst.kontekstLinje,
1259
- apen ? "" : tekst.kontekstVis
1260
- ] })
1261
- ] })
1501
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: { flex: 1, color: tema.color.textSecondary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: apen ? tekst.kontekstLinjeApen : tekst.kontekstLinjeLukket }),
1502
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: { color: tema.color.actionSecondaryText, fontSize: tema.font.body, fontWeight: tema.weight.semibold }, children: apen ? tekst.kontekstSkjul : tekst.kontekstVis })
1503
+ ]
1262
1504
  }
1263
1505
  ),
1264
1506
  apen ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { children: [
@@ -1268,26 +1510,29 @@ function Felt({
1268
1510
  style: {
1269
1511
  flexDirection: "row",
1270
1512
  alignItems: "center",
1271
- gap: tema.space.sm,
1513
+ gap: tema.space.md,
1272
1514
  minHeight: tema.touch,
1273
- borderBottomWidth: tema.hairline,
1274
- borderBottomColor: tema.color.border
1515
+ borderTopWidth: tema.hairline,
1516
+ borderTopColor: tema.color.border
1275
1517
  },
1276
1518
  children: [
1277
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: { color: tema.color.textMuted, fontSize: tema.font.small, minWidth: tema.touch * 2 }, children: l.etikett }),
1278
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: { flex: 1, color: tema.color.textPrimary, fontSize: tema.font.small }, children: l.verdi }),
1519
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Meta, { testID: `kontekst-etikett-${l.felt}`, children: l.etikett }),
1520
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1521
+ import_react_native3.Text,
1522
+ {
1523
+ testID: `kontekst-verdi-${l.felt}`,
1524
+ style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body, fontWeight: tema.weight.semibold },
1525
+ children: l.verdi
1526
+ }
1527
+ ) }),
1279
1528
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1280
- import_react_native3.Pressable,
1529
+ Tekstknapp,
1281
1530
  {
1282
1531
  testID: `fjern-${l.felt}`,
1283
- accessibilityRole: "button",
1284
- accessibilityLabel: `${tekst.kontekstFjern} ${l.etikett.toLowerCase()} fra innsendingen`,
1285
- onPress: () => onFjernKontekst(l.felt),
1286
- style: { minWidth: tema.touch, minHeight: tema.touch, alignItems: "center", justifyContent: "center" },
1287
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native3.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
1288
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Ikon, { navn: "close-outline", storrelse: "minste", farge: tema.color.textSecondary }),
1289
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.small }, children: tekst.kontekstFjern })
1290
- ] })
1532
+ ikon: "close-outline",
1533
+ label: tekst.kontekstFjern,
1534
+ accessibilityLabel: tekst.kontekstFjernA11y(l.etikett),
1535
+ onPress: () => onFjernKontekst(l.felt)
1291
1536
  }
1292
1537
  )
1293
1538
  ]
@@ -1319,26 +1564,23 @@ function Felt({
1319
1564
  var import_react6 = require("react");
1320
1565
  var import_react_native4 = require("react-native");
1321
1566
  var import_jsx_runtime4 = require("react/jsx-runtime");
1322
- function Valg({ onVelg }) {
1567
+ function Valg({ onVelg, anonym }) {
1323
1568
  const tema = useTema();
1324
- const flate = (spor, ikon, label, under) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1569
+ const rad = (spor, ikon, label, under, forst) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1325
1570
  import_react_native4.Pressable,
1326
1571
  {
1327
1572
  testID: `spor-${spor}`,
1328
1573
  accessibilityRole: "button",
1329
- accessibilityLabel: `${label}. ${under}`,
1574
+ accessibilityLabel: `${label}, ${under}`,
1330
1575
  onPress: () => onVelg(spor),
1331
1576
  style: {
1332
- flex: 1,
1333
- minHeight: tema.touch * 3,
1334
- backgroundColor: tema.color.surface,
1335
- borderWidth: tema.hairline,
1336
- borderColor: tema.color.borderStrong,
1337
- borderRadius: tema.radius.lg,
1577
+ flexDirection: "row",
1338
1578
  alignItems: "center",
1339
- justifyContent: "center",
1340
- gap: tema.space.sm,
1341
- padding: tema.space.md
1579
+ gap: tema.space.md,
1580
+ minHeight: tema.touch + tema.space.lg,
1581
+ paddingVertical: tema.space.sm,
1582
+ borderTopWidth: forst ? 0 : tema.hairline,
1583
+ borderTopColor: tema.color.border
1342
1584
  },
1343
1585
  children: [
1344
1586
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
@@ -1346,8 +1588,8 @@ function Valg({ onVelg }) {
1346
1588
  {
1347
1589
  testID: `spor-${spor}-ikonflate`,
1348
1590
  style: {
1349
- width: 2 * tema.icon.inline + 2 * tema.space.md,
1350
- height: 2 * tema.icon.inline + 2 * tema.space.md,
1591
+ width: tema.touch + tema.space.sm,
1592
+ height: tema.touch + tema.space.sm,
1351
1593
  borderRadius: tema.radius.pill,
1352
1594
  backgroundColor: tema.color.brandBg,
1353
1595
  alignItems: "center",
@@ -1356,28 +1598,21 @@ function Valg({ onVelg }) {
1356
1598
  children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Ikon, { navn: ikon, storrelse: "stor", farge: tema.color.brand })
1357
1599
  }
1358
1600
  ),
1359
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1360
- import_react_native4.Text,
1361
- {
1362
- style: {
1363
- color: tema.color.textPrimary,
1364
- fontSize: tema.font.h3,
1365
- fontWeight: tema.weight.semibold,
1366
- textAlign: "center"
1367
- },
1368
- children: label
1369
- }
1370
- ),
1371
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native4.Text, { style: { color: tema.color.textMuted, fontSize: tema.font.small, textAlign: "center" }, children: under })
1601
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native4.View, { style: { flex: 1, minWidth: 0 }, children: [
1602
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native4.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body, fontWeight: tema.weight.semibold }, children: label }),
1603
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native4.Text, { style: { color: tema.color.textMuted, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: under })
1604
+ ] }),
1605
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Ikon, { navn: "chevron-forward-outline", storrelse: "minste", farge: tema.color.textMuted })
1372
1606
  ]
1373
1607
  }
1374
1608
  );
1375
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native4.View, { style: { flex: 1, gap: tema.space.lg }, children: [
1609
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native4.View, { style: { gap: tema.space.lg }, children: [
1376
1610
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(H, { children: tekst.valgTittel }),
1377
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native4.View, { style: { flex: 1, justifyContent: "flex-end" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native4.View, { style: { flexDirection: "row", gap: tema.space.md }, children: [
1378
- flate("feil", "bug", tekst.sporFeil, tekst.sporFeilUnder),
1379
- flate("onske", "bulb", tekst.sporOnske, tekst.sporOnskeUnder)
1380
- ] }) })
1611
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_native4.View, { children: [
1612
+ rad("feil", "bug", tekst.sporFeil, tekst.sporFeilUnder, true),
1613
+ rad("onske", "bulb", tekst.sporOnske, tekst.sporOnskeUnder, false)
1614
+ ] }),
1615
+ anonym ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Hint, { children: tekst.sendAnonymtHint }) : null
1381
1616
  ] });
1382
1617
  }
1383
1618
 
@@ -1396,84 +1631,102 @@ function KjenteFeil({
1396
1631
  onNei
1397
1632
  }) {
1398
1633
  const tema = useTema();
1634
+ const tittel = spor === "onske" ? tekst.kjenteFeilTittelOnske : tekst.kjenteFeilTittelFeil;
1399
1635
  if (laster) {
1400
1636
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { style: { flex: 1, gap: tema.space.md }, children: [
1401
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(H, { sub: spor === "onske" ? tekst.kjenteFeilUnderOnske : tekst.kjenteFeilUnderFeil, children: spor === "onske" ? tekst.kjenteFeilTittelOnske : tekst.kjenteFeilTittelFeil }),
1637
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(H, { children: tittel }),
1402
1638
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.ActivityIndicator, { accessibilityLabel: "Sjekker kjente feil", color: tema.color.textSecondary })
1403
1639
  ] });
1404
1640
  }
1405
1641
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { testID: "kjente-feil", style: { flexGrow: 1, flexShrink: 1, gap: tema.space.md }, children: [
1406
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(H, { sub: spor === "onske" ? tekst.kjenteFeilUnderOnske : tekst.kjenteFeilUnderFeil, children: spor === "onske" ? tekst.kjenteFeilTittelOnske : tekst.kjenteFeilTittelFeil }),
1642
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(H, { children: tittel }),
1407
1643
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1408
1644
  import_react_native5.ScrollView,
1409
1645
  {
1410
1646
  testID: "kjente-feil-liste",
1411
1647
  style: { flexGrow: 0, flexShrink: 1 },
1412
- contentContainerStyle: { gap: tema.space.md },
1413
1648
  keyboardShouldPersistTaps: "handled",
1414
- children: kort.slice(0, MAKS_KORT).map((k) => {
1649
+ children: kort.slice(0, MAKS_KORT).map((k, i) => {
1415
1650
  const o = knownIssueStatus[k.status] ?? knownIssueStatus.aktiv;
1416
- const versjon = k.fixedIn ? k.status === "fikset" ? tekst.rettetI(k.fixedIn) : tekst.rettesI(k.fixedIn) : void 0;
1417
- const kontekst = versjon ? `${k.title}. ${o.etikett}. ${versjon}` : `${k.title}. ${o.etikett}`;
1418
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Card, { children: [
1419
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1420
- import_react_native5.Text,
1421
- {
1422
- style: {
1423
- color: tema.color.textPrimary,
1424
- fontSize: tema.font.body,
1425
- lineHeight: tema.lineHeight.body,
1426
- fontWeight: tema.weight.medium
1427
- },
1428
- children: k.title
1429
- }
1430
- ),
1431
- k.workaround ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1432
- import_react_native5.Text,
1433
- {
1434
- style: {
1435
- color: tema.color.textSecondary,
1436
- fontSize: tema.font.small,
1437
- lineHeight: tema.lineHeight.small
1438
- },
1439
- children: [
1651
+ const rettet = k.status === "fikset";
1652
+ const statusOrd = rettet && k.fixedIn ? tekst.rettetI(k.fixedIn) : o.etikett;
1653
+ const tillegg = !rettet && k.fixedIn ? `\xB7 ${tekst.rettesI(k.fixedIn).toLowerCase()}` : void 0;
1654
+ const gruppe = tekst.kjentFeilGruppe(k.title, statusOrd, tillegg?.replace("\xB7 ", ""));
1655
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1656
+ import_react_native5.View,
1657
+ {
1658
+ testID: `kjent-feil-${k.id}`,
1659
+ style: {
1660
+ gap: tema.space.sm,
1661
+ paddingVertical: tema.space.md,
1662
+ borderTopWidth: i === 0 ? 0 : tema.hairline,
1663
+ borderTopColor: tema.color.border
1664
+ },
1665
+ children: [
1666
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1667
+ import_react_native5.Text,
1668
+ {
1669
+ testID: `kjent-feil-tittel-${k.id}`,
1670
+ style: {
1671
+ color: tema.color.textPrimary,
1672
+ fontSize: tema.font.body,
1673
+ lineHeight: tema.lineHeight.body,
1674
+ fontWeight: tema.weight.semibold
1675
+ },
1676
+ children: k.title
1677
+ }
1678
+ ),
1679
+ k.workaround ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Sek, { testID: `kjent-feil-omvei-${k.id}`, children: [
1440
1680
  tekst.omvei,
1441
1681
  " ",
1442
1682
  k.workaround
1443
- ]
1444
- }
1445
- ) : null,
1446
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.sm, flexWrap: "wrap" }, children: [
1447
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(StatusPill, { ikon: o.ikon, etikett: o.etikett, fg: o.fg, bg: o.bg }),
1448
- versjon ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.small }, children: versjon }) : null
1449
- ] }),
1450
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { style: { flexDirection: "row", gap: tema.space.sm }, children: [
1451
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1452
- Btn,
1453
- {
1454
- grow: true,
1455
- testID: `ja-ogsa-${k.id}`,
1456
- label: tekst.svarJa,
1457
- accessibilityLabel: `${tekst.svarJa}. ${kontekst}`,
1458
- disabled: sender,
1459
- busy: sender,
1460
- onPress: () => onJaOgsa(k)
1461
- }
1462
- ),
1463
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1464
- Btn,
1465
- {
1466
- grow: true,
1467
- variant: "secondary",
1468
- testID: `ligner-${k.id}`,
1469
- label: tekst.svarLigner,
1470
- accessibilityLabel: `${tekst.svarLigner}. ${kontekst}`,
1471
- disabled: sender,
1472
- onPress: () => onLigner(k)
1473
- }
1474
- )
1475
- ] })
1476
- ] }, k.id);
1683
+ ] }) : null,
1684
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.sm, flexWrap: "wrap" }, children: [
1685
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
1686
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Ikon, { navn: o.ikon, storrelse: "minste", farge: tema.color[o.fg] }),
1687
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1688
+ import_react_native5.Text,
1689
+ {
1690
+ style: {
1691
+ color: tema.color[o.fg],
1692
+ fontSize: tema.font.small,
1693
+ lineHeight: tema.lineHeight.small,
1694
+ fontWeight: tema.weight.semibold
1695
+ },
1696
+ children: statusOrd
1697
+ }
1698
+ )
1699
+ ] }),
1700
+ tillegg ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native5.Text, { style: { color: tema.color.textMuted, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: tillegg }) : null
1701
+ ] }),
1702
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react_native5.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.md }, children: [
1703
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1704
+ Btn,
1705
+ {
1706
+ variant: "tonet",
1707
+ testID: `ja-ogsa-${k.id}`,
1708
+ label: tekst.svarJa,
1709
+ accessibilityLabel: `${tekst.svarJa}. ${gruppe}`,
1710
+ disabled: sender,
1711
+ busy: sender,
1712
+ onPress: () => onJaOgsa(k)
1713
+ }
1714
+ ),
1715
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1716
+ Tekstknapp,
1717
+ {
1718
+ testID: `ligner-${k.id}`,
1719
+ label: tekst.svarLigner,
1720
+ accessibilityLabel: `${tekst.svarLigner}. ${gruppe}`,
1721
+ disabled: sender,
1722
+ onPress: () => onLigner(k)
1723
+ }
1724
+ )
1725
+ ] })
1726
+ ]
1727
+ },
1728
+ k.id
1729
+ );
1477
1730
  })
1478
1731
  }
1479
1732
  ),
@@ -1482,6 +1735,10 @@ function KjenteFeil({
1482
1735
  }
1483
1736
 
1484
1737
  // src/widget/Kvittering.tsx
1738
+ var import_react9 = require("react");
1739
+ var import_react_native7 = require("react-native");
1740
+
1741
+ // src/widget/Sporingslinje.tsx
1485
1742
  var import_react8 = require("react");
1486
1743
  var import_react_native6 = require("react-native");
1487
1744
 
@@ -1491,6 +1748,12 @@ function formaterFrist(iso) {
1491
1748
  if (Number.isNaN(d.getTime())) return iso;
1492
1749
  return new Intl.DateTimeFormat("nb-NO", { day: "numeric", month: "long" }).format(d);
1493
1750
  }
1751
+ var KORT_MANED = ["jan", "feb", "mar", "apr", "mai", "jun", "jul", "aug", "sep", "okt", "nov", "des"];
1752
+ function formaterKortFrist(iso) {
1753
+ const d = new Date(iso);
1754
+ if (Number.isNaN(d.getTime())) return iso;
1755
+ return `${d.getDate()}. ${KORT_MANED[d.getMonth()]}`;
1756
+ }
1494
1757
  function statusVisning(status, type, deadlineAt) {
1495
1758
  const o = submissionStatus[status];
1496
1759
  const spor = type === "onske" ? "onske" : "feil";
@@ -1514,66 +1777,265 @@ var venterVisning = {
1514
1777
  lofte: lofte.venterNett
1515
1778
  };
1516
1779
 
1517
- // src/widget/Kvittering.tsx
1780
+ // src/widget/Sporingslinje.tsx
1518
1781
  var import_jsx_runtime6 = require("react/jsx-runtime");
1782
+ var HOVEDLINJE = ["ny", "vurderes", "planlagt", "bygges", "levert"];
1783
+ function erApen(rad) {
1784
+ if (rad.pending === true) return false;
1785
+ return rad.statusType === "reviewing" || rad.statusType === "active";
1786
+ }
1787
+ function sporingsledd(rad, tenantName, naa = /* @__PURE__ */ new Date()) {
1788
+ if (rad.pending === true || !erApen(rad)) return [];
1789
+ const type = rad.type;
1790
+ const navn = (status) => statusVisning(status, type).etikett;
1791
+ const ikon = (status) => statusVisning(status, type).ikon;
1792
+ const ledd = [];
1793
+ if (rad.status === "kjent_feil") {
1794
+ ledd.push({ nokkel: "ny", etikett: navn("ny"), tilstand: "gjort", detalj: formaterFrist(rad.createdAt) });
1795
+ ledd.push({ nokkel: "kjent_feil", etikett: navn("kjent_feil"), tilstand: "naa", ikon: ikon("kjent_feil"), detalj: formaterFrist(rad.statusChangedAt) });
1796
+ ledd.push({ nokkel: "slutt", etikett: navn("levert"), tilstand: "kommer", detalj: tekst.sporIngenDato });
1797
+ return ledd;
1798
+ }
1799
+ const naaIndeks = HOVEDLINJE.indexOf(rad.status);
1800
+ if (naaIndeks < 0) return [];
1801
+ for (let i = 0; i <= naaIndeks; i++) {
1802
+ const status = HOVEDLINJE[i];
1803
+ const erNaa = i === naaIndeks;
1804
+ ledd.push({
1805
+ nokkel: status,
1806
+ etikett: navn(status),
1807
+ tilstand: erNaa ? "naa" : "gjort",
1808
+ ...erNaa ? { ikon: ikon(status) } : {},
1809
+ // Mottatt har `createdAt`, nå-leddet har `statusChangedAt`. Et passert ledd mellom dem
1810
+ // har ingen dato i kontrakten, og får derfor ingen.
1811
+ ...i === 0 ? { detalj: formaterFrist(rad.createdAt) } : erNaa ? { detalj: formaterFrist(rad.statusChangedAt) } : {}
1812
+ });
1813
+ }
1814
+ if (rad.status === "ny") {
1815
+ ledd.push({
1816
+ nokkel: "vurderes",
1817
+ etikett: navn("vurderes"),
1818
+ tilstand: "kommer",
1819
+ detalj: tenantName ? tekst.sporNaarTenantTarDen(tenantName) : tekst.sporNaarDenTasOpp
1820
+ });
1821
+ }
1822
+ if (rad.statusType === "reviewing") {
1823
+ const frist = rad.deadlineAt;
1824
+ const gatt = frist !== void 0 && rad.status === "vurderes" && new Date(frist).getTime() < naa.getTime();
1825
+ ledd.push(
1826
+ gatt ? { nokkel: "slutt", etikett: tekst.sporFristenErGatt, tilstand: "brutt", ikon: "warning-outline", tall: formaterKortFrist(frist) } : {
1827
+ nokkel: "slutt",
1828
+ etikett: tekst.sporSvarInnen,
1829
+ tilstand: "kommer",
1830
+ ...frist ? { tall: formaterKortFrist(frist) } : { detalj: tekst.sporDatoenSettes }
1831
+ }
1832
+ );
1833
+ } else {
1834
+ ledd.push({ nokkel: "slutt", etikett: navn("levert"), tilstand: "kommer", detalj: tekst.sporIngenDato });
1835
+ }
1836
+ return ledd;
1837
+ }
1838
+ function Sporingslinje({
1839
+ ledd,
1840
+ testID,
1841
+ etikett = tekst.sporEtikett
1842
+ }) {
1843
+ const tema = useTema();
1844
+ if (ledd.length === 0) return null;
1845
+ const farge = (l) => l.tilstand === "brutt" ? tema.color.warning : l.tilstand === "gjort" ? tema.color.success : l.tilstand === "naa" ? tema.color.brand : tema.color.borderStrong;
1846
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1847
+ import_react_native6.View,
1848
+ {
1849
+ testID,
1850
+ accessibilityRole: "list",
1851
+ accessibilityLabel: etikett,
1852
+ style: { flexDirection: "row", alignItems: "flex-start", gap: tema.space.xs },
1853
+ children: ledd.map((l, i) => {
1854
+ const siste = i === ledd.length - 1;
1855
+ const c = farge(l);
1856
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1857
+ import_react_native6.View,
1858
+ {
1859
+ testID: testID ? `${testID}-ledd-${l.nokkel}` : void 0,
1860
+ style: siste ? { flexShrink: 0, gap: tema.space.xs } : { flex: 1, minWidth: 0, gap: tema.space.xs },
1861
+ children: [
1862
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native6.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
1863
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1864
+ import_react_native6.View,
1865
+ {
1866
+ style: {
1867
+ width: tema.space.lg,
1868
+ height: tema.space.lg,
1869
+ borderRadius: tema.radius.pill,
1870
+ borderWidth: tema.hairline * 2,
1871
+ borderColor: c,
1872
+ borderStyle: l.tilstand === "kommer" ? "dashed" : "solid",
1873
+ backgroundColor: l.tilstand === "gjort" ? tema.color.success : "transparent",
1874
+ alignItems: "center",
1875
+ justifyContent: "center"
1876
+ },
1877
+ children: l.tilstand === "gjort" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Ikon, { navn: "checkmark-outline", storrelse: "minste", farge: tema.color.bg }) : l.ikon ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Ikon, { navn: l.ikon, storrelse: "minste", farge: c }) : null
1878
+ }
1879
+ ),
1880
+ !siste ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1881
+ import_react_native6.View,
1882
+ {
1883
+ style: {
1884
+ flex: 1,
1885
+ height: tema.hairline * 2,
1886
+ borderRadius: tema.radius.pill,
1887
+ backgroundColor: l.tilstand === "gjort" ? tema.color.success : tema.color.borderStrong
1888
+ }
1889
+ }
1890
+ ) : null
1891
+ ] }),
1892
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1893
+ import_react_native6.Text,
1894
+ {
1895
+ style: {
1896
+ color: l.tilstand === "brutt" ? tema.color.warning : l.tilstand === "kommer" ? tema.color.textMuted : tema.color.textPrimary,
1897
+ fontSize: tema.font.small,
1898
+ lineHeight: tema.lineHeight.small,
1899
+ fontWeight: l.tilstand === "naa" || l.tilstand === "brutt" ? tema.weight.semibold : tema.weight.regular
1900
+ },
1901
+ children: l.etikett
1902
+ }
1903
+ ),
1904
+ l.tall !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Helt, { testID: testID ? `${testID}-tall` : void 0, farge: l.tilstand === "brutt" ? tema.color.warning : tema.color.textPrimary, children: l.tall }) : l.detalj !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_react_native6.Text, { style: { color: tema.color.textMuted, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: l.detalj }) : null
1905
+ ]
1906
+ },
1907
+ l.nokkel
1908
+ );
1909
+ })
1910
+ }
1911
+ );
1912
+ }
1913
+
1914
+ // src/widget/Kvittering.tsx
1915
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1519
1916
  function Kvittering({
1520
1917
  art,
1521
1918
  saksnummer,
1522
1919
  vedlegg,
1523
1920
  frist,
1921
+ sak,
1922
+ anonym,
1923
+ tenantName,
1524
1924
  onLukk
1525
1925
  }) {
1526
1926
  const tema = useTema();
1527
- const innhold = {
1528
- feil: { h: tekst.kvitteringSendt, p: tekst.kvitteringFeil },
1529
- // Løftet er NØYAKTIG det «Mine innspill» og panelet viser for «Vurderes»:
1530
- // det leses fra temaet, så kvitteringen og statusen ikke kan si to ting.
1531
- onske: { h: tekst.kvitteringSendt, p: statusVisning("vurderes", "onske", frist).lofte },
1532
- jaOgsa: { h: tekst.kvitteringRegistrert, p: tekst.kvitteringJaOgsa },
1533
- // Køet offline: kvitteringen kan IKKE love svar på noe som ikke er sendt
1534
- // (DD-41 presiserer DD-07). Den lover bare at det sendes.
1535
- k\u00F8: { h: tekst.koKvitteringTittel, p: tekst.offlineBanner }
1927
+ const ko = art === "k\xF8";
1928
+ const helt = {
1929
+ feil: tekst.kvitteringFeil,
1930
+ // Løftet er NØYAKTIG det «Mine innspill» og panelet viser for «Vurderes»: det leses fra
1931
+ // temaet, så kvitteringen og statusen ikke kan si to ting.
1932
+ onske: statusVisning("vurderes", "onske", frist).lofte,
1933
+ jaOgsa: tekst.kvitteringJaOgsa,
1934
+ k\u00F8: tekst.koHelt
1536
1935
  }[art];
1537
- const overskrift = vedlegg === "feilet" ? tekst.kvitteringVedleggFeilet : innhold.h;
1538
- const brodtekst = vedlegg === "feilet" ? `${tekst.tekstenErLagret} ${innhold.p}` : innhold.p;
1539
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native6.View, { style: { flex: 1, justifyContent: "center", gap: tema.space.lg }, children: [
1540
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react_native6.View, { style: { alignItems: "center", gap: tema.space.md }, children: [
1541
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1542
- Ikon,
1543
- {
1544
- navn: art === "k\xF8" ? "swap-vertical-outline" : "checkmark-circle-outline",
1545
- storrelse: "stor",
1546
- farge: art === "k\xF8" ? tema.color.neutral : tema.color.success
1547
- }
1548
- ),
1549
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(H, { children: overskrift }),
1550
- vedlegg === "feilet" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Banner, { ikon: "warning-outline", tone: "warning", children: tekst.vedleggFeiletBanner }) : null,
1551
- vedlegg === "forkastet" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Banner, { ikon: "image-outline", tone: "info", children: tekst.offlineUtenBilde }) : null,
1552
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1553
- import_react_native6.Text,
1554
- {
1555
- testID: "kvittering-tekst",
1556
- accessibilityRole: "alert",
1557
- accessibilityLiveRegion: "polite",
1558
- style: {
1559
- color: tema.color.textPrimary,
1560
- fontSize: tema.font.body,
1561
- lineHeight: tema.lineHeight.body,
1562
- textAlign: "center"
1563
- },
1564
- children: brodtekst
1565
- }
1566
- ),
1567
- saksnummer ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Hint, { children: vedlegg === "feilet" ? tekst.saksnummerUtenVedlegg(saksnummer) : tekst.saksnummer(saksnummer) }) : null
1568
- ] }),
1569
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Btn, { testID: "tilbake-til-appen", label: tekst.tilbakeTilAppen, onPress: onLukk })
1936
+ const dato = formaterFrist(sak?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString());
1937
+ const etikett = vedlegg === "feilet" ? tekst.kvitteringVedleggFeilet : ko ? tekst.kvitteringLagretDato(dato) : art === "jaOgsa" ? tekst.kvitteringRegistrertDato(dato) : anonym ? tekst.kvitteringSendtAnonymtDato(dato) : tekst.kvitteringSendtDato(dato);
1938
+ const ledd = sak && !ko ? sporingsledd(sak, tenantName) : [];
1939
+ const under = anonym ? void 0 : ko ? tekst.koUnder : saksnummer ? tekst.kvitteringUnder : void 0;
1940
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { testID: "kvittering", style: { flex: 1, gap: tema.space.md }, children: [
1941
+ vedlegg === "feilet" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Banner, { ikon: "warning-outline", tone: "warning", children: tekst.vedleggFeiletBanner }) : null,
1942
+ vedlegg === "forkastet" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Banner, { ikon: "image-outline", tone: "info", children: tekst.offlineUtenBilde }) : null,
1943
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1944
+ import_react_native7.View,
1945
+ {
1946
+ testID: "kvittering-kort",
1947
+ style: {
1948
+ backgroundColor: ko ? tema.color.surface : tema.color.brandFill,
1949
+ borderRadius: tema.radius.lg,
1950
+ borderWidth: ko ? tema.hairline : 0,
1951
+ borderStyle: ko ? "dashed" : "solid",
1952
+ borderColor: tema.color.borderInteractive,
1953
+ padding: tema.space.md,
1954
+ gap: tema.space.md
1955
+ },
1956
+ children: [
1957
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", gap: tema.space.sm }, children: [
1958
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.sm, flexShrink: 1 }, children: [
1959
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1960
+ Ikon,
1961
+ {
1962
+ navn: ko ? "swap-vertical-outline" : "checkmark-circle-outline",
1963
+ farge: ko ? tema.color.textSecondary : tema.color.onBrandFill
1964
+ }
1965
+ ),
1966
+ tenantName ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1967
+ import_react_native7.Text,
1968
+ {
1969
+ style: {
1970
+ color: ko ? tema.color.textPrimary : tema.color.onBrandFill,
1971
+ fontSize: tema.font.body,
1972
+ fontWeight: tema.weight.bold
1973
+ },
1974
+ children: tenantName
1975
+ }
1976
+ ) : null
1977
+ ] }),
1978
+ ko ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
1979
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Ikon, { navn: "cloud-offline-outline", storrelse: "minste", farge: tema.color.textMuted }),
1980
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { style: { color: tema.color.textMuted, fontSize: tema.font.small, fontWeight: tema.weight.semibold }, children: tekst.koIngenNett })
1981
+ ] }) : saksnummer ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1982
+ import_react_native7.Text,
1983
+ {
1984
+ style: { color: tema.color.onBrandFill, fontSize: tema.font.small, fontWeight: tema.weight.semibold },
1985
+ children: vedlegg === "feilet" ? tekst.saksnummerUtenVedlegg(saksnummer) : tekst.saksnummer(saksnummer)
1986
+ }
1987
+ ) : null
1988
+ ] }),
1989
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { gap: tema.space.xs }, children: [
1990
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1991
+ import_react_native7.Text,
1992
+ {
1993
+ style: {
1994
+ color: ko ? tema.color.textMuted : tema.color.onBrandFill,
1995
+ fontSize: tema.font.small,
1996
+ lineHeight: tema.lineHeight.small
1997
+ },
1998
+ children: etikett
1999
+ }
2000
+ ),
2001
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Helt, { testID: "kvittering-tekst", live: true, farge: ko ? tema.color.textPrimary : tema.color.onBrandFill, children: vedlegg === "feilet" ? `${tekst.tekstenErLagret} ${helt}` : helt })
2002
+ ] }),
2003
+ under ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2004
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2005
+ import_react_native7.View,
2006
+ {
2007
+ style: {
2008
+ borderTopWidth: tema.hairline,
2009
+ borderTopColor: ko ? tema.color.borderStrong : tema.color.onBrandFill,
2010
+ borderStyle: "dashed"
2011
+ }
2012
+ }
2013
+ ),
2014
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2015
+ import_react_native7.Text,
2016
+ {
2017
+ testID: "kvittering-under",
2018
+ style: {
2019
+ color: ko ? tema.color.textPrimary : tema.color.onBrandFill,
2020
+ fontSize: tema.font.body,
2021
+ lineHeight: tema.lineHeight.body
2022
+ },
2023
+ children: under
2024
+ }
2025
+ )
2026
+ ] }) : null
2027
+ ]
2028
+ }
2029
+ ),
2030
+ ledd.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Sporingslinje, { ledd, testID: "kvittering-spor" }) : null,
2031
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.View, { style: { flex: 1, justifyContent: "flex-end", paddingTop: tema.space.sm }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { testID: "tilbake-til-appen", label: tekst.tilbakeTilAppen, onPress: onLukk }) })
1570
2032
  ] });
1571
2033
  }
1572
2034
 
1573
2035
  // src/widget/MineInnspill.tsx
1574
2036
  var import_core = require("@innspel/core");
1575
- var import_react9 = require("react");
1576
- var import_react_native7 = require("react-native");
2037
+ var import_react10 = require("react");
2038
+ var import_react_native8 = require("react-native");
1577
2039
 
1578
2040
  // src/widget/nyttSvar.ts
1579
2041
  var N\u00D8KKEL = "innspel:svar-sett";
@@ -1596,8 +2058,8 @@ async function markerSvarSett(storage, n\u00E5 = Date.now()) {
1596
2058
  }
1597
2059
 
1598
2060
  // src/widget/MineInnspill.tsx
1599
- var import_jsx_runtime7 = require("react/jsx-runtime");
1600
- function MineInnspill({
2061
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2062
+ var MineInnspill = (0, import_react10.forwardRef)(function MineInnspill2({
1601
2063
  rader,
1602
2064
  laster,
1603
2065
  tenantName,
@@ -1606,16 +2068,46 @@ function MineInnspill({
1606
2068
  leggTil,
1607
2069
  onOppdatert,
1608
2070
  minTextLength,
1609
- textMaxLength
1610
- }) {
2071
+ textMaxLength,
2072
+ utkastLager
2073
+ }, ref) {
1611
2074
  const tema = useTema();
1612
2075
  const min = minTextLength ?? 10;
1613
2076
  const maks = textMaxLength ?? 280;
1614
- const [apen, setApen] = (0, import_react9.useState)(null);
1615
- const [utkast, setUtkast] = (0, import_react9.useState)("");
1616
- const [sender, setSender] = (0, import_react9.useState)(false);
1617
- const [feil, setFeil] = (0, import_react9.useState)();
1618
- const [lagtTil, setLagtTil] = (0, import_react9.useState)();
2077
+ const [apen, setApen] = (0, import_react10.useState)(null);
2078
+ const [utkast, setUtkast] = (0, import_react10.useState)("");
2079
+ const [sender, setSender] = (0, import_react10.useState)(false);
2080
+ const [feil, setFeil] = (0, import_react10.useState)();
2081
+ const [lagtTil, setLagtTil] = (0, import_react10.useState)();
2082
+ const egetLager = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
2083
+ const lager = utkastLager ?? egetLager.current;
2084
+ const rulleRef = (0, import_react10.useRef)(null);
2085
+ const kortY = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
2086
+ const apneFelt = (id) => {
2087
+ setApen(id);
2088
+ setUtkast(lager.get(id) ?? "");
2089
+ setFeil(void 0);
2090
+ setLagtTil(void 0);
2091
+ const y = kortY.current.get(id);
2092
+ if (y !== void 0) rulleRef.current?.scrollTo({ y, animated: true });
2093
+ };
2094
+ const lukkFelt = () => {
2095
+ if (apen === null) return false;
2096
+ import_react_native8.Keyboard.dismiss();
2097
+ if (utkast.trim()) lager.set(apen, utkast);
2098
+ else lager.delete(apen);
2099
+ setApen(null);
2100
+ setUtkast("");
2101
+ setFeil(void 0);
2102
+ return true;
2103
+ };
2104
+ const avbryt = () => {
2105
+ if (apen !== null) lager.delete(apen);
2106
+ setApen(null);
2107
+ setUtkast("");
2108
+ setFeil(void 0);
2109
+ };
2110
+ (0, import_react10.useImperativeHandle)(ref, () => ({ lukkFelt }));
1619
2111
  const send = async (id) => {
1620
2112
  if (!leggTil) return;
1621
2113
  setSender(true);
@@ -1623,19 +2115,20 @@ function MineInnspill({
1623
2115
  try {
1624
2116
  const sak = await leggTil(id, utkast.trim());
1625
2117
  onOppdatert?.(sak);
2118
+ lager.delete(id);
1626
2119
  setApen(null);
1627
2120
  setUtkast("");
1628
2121
  setLagtTil(id);
1629
2122
  } catch (e) {
1630
2123
  const kode = e instanceof import_core.InnspelApiError ? e.code : void 0;
1631
- const tekstFeil = kode === "addendum_limit_reached" ? tekst.tilleggTak : kode === "submission_closed" ? tekst.tilleggLukket : tekst.tilleggFeil(e instanceof Error && e.message ? e.message : "ukjent feil.");
2124
+ const tekstFeil = kode === "addendum_limit_reached" ? tekst.tilleggTak : kode === "submission_closed" ? tekst.tilleggLukket : e instanceof import_core.InnspelApiError && e.message ? tekst.tilleggFeil(e.message) : e instanceof import_core.NettverksFeil ? tekst.tilleggIngenNett : tekst.tilleggFeilGenerisk;
1632
2125
  setFeil({ id, tekst: tekstFeil });
1633
2126
  } finally {
1634
2127
  setSender(false);
1635
2128
  }
1636
2129
  };
1637
- const [visning, setVisning] = (0, import_react9.useState)(() => rader.map((rad) => ({ rad, nytt: false })));
1638
- (0, import_react9.useEffect)(() => {
2130
+ const [visning, setVisning] = (0, import_react10.useState)(() => rader.map((rad) => ({ rad, nytt: false })));
2131
+ (0, import_react10.useEffect)(() => {
1639
2132
  let gjelder = true;
1640
2133
  void merkNyeSvar(rader, storage).then((m) => {
1641
2134
  if (gjelder) setVisning(m);
@@ -1646,12 +2139,13 @@ function MineInnspill({
1646
2139
  gjelder = false;
1647
2140
  };
1648
2141
  }, [storage, rader]);
1649
- (0, import_react9.useEffect)(() => {
2142
+ (0, import_react10.useEffect)(() => {
1650
2143
  if (!laster && rader.length) void markerSvarSett(storage).catch(() => void 0);
1651
2144
  }, [storage, laster, rader]);
1652
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { flex: 1, gap: tema.space.md }, children: [
1653
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(H, { sub: tekst.mineUnder, children: tekst.mineTittel }),
1654
- laster ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.ActivityIndicator, { accessibilityLabel: "Henter innspillene dine", color: tema.color.textSecondary }) : rader.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: tekst.mineTom }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.ScrollView, { style: { flex: 1 }, contentContainerStyle: { gap: tema.space.sm }, children: visning.map(({ rad, nytt }) => {
2145
+ const tom = !laster && rader.length === 0;
2146
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { style: { flex: 1, gap: tema.space.md }, children: [
2147
+ tom ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(H, { sub: tenantName ? tekst.mineTomHint(tenantName) : tekst.mineTomHintGenerisk, children: tekst.mineTomTittel }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(H, { children: tekst.mineTittel }),
2148
+ laster ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native8.ActivityIndicator, { accessibilityLabel: tekst.mineLaster, color: tema.color.textSecondary }) : tom ? null : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native8.ScrollView, { ref: rulleRef, style: { flex: 1 }, contentContainerStyle: { gap: tema.space.md }, keyboardShouldPersistTaps: "handled", children: visning.map(({ rad, nytt }) => {
1655
2149
  const venter = rad.pending === true;
1656
2150
  const v = venter ? venterVisning : statusVisning(rad.status, rad.type, rad.deadlineAt);
1657
2151
  const nokkel = venter ? rad.clientRef : rad.id;
@@ -1662,196 +2156,157 @@ function MineInnspill({
1662
2156
  const taketN\u00E5dd = !venter && rad.canAddAddendum === false && tillegg.length >= 3;
1663
2157
  const feltApent = sakId !== void 0 && apen === sakId;
1664
2158
  const brukt = utkast.length;
1665
- const forKort = brukt < min;
1666
2159
  const full = brukt >= maks;
1667
2160
  const visTeller = brukt >= maks * 0.8;
1668
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Card, { dashed: venter, children: [
1669
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs, flexWrap: "wrap" }, children: [
1670
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: venter ? `${tekst.mineIkkeSendt} \xB7 ${rad.type === "onske" ? tekst.onske : tekst.feil}` : tekst.sakHode(rad.type === "onske" ? tekst.onske : tekst.feil, rad.id) }),
1671
- nytt ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1672
- import_react_native7.Text,
1673
- {
1674
- testID: "nytt-svar",
1675
- style: {
1676
- color: tema.color.info,
1677
- backgroundColor: tema.color.infoBg,
1678
- fontSize: tema.font.tiny,
1679
- fontWeight: tema.weight.semibold,
1680
- borderRadius: tema.radius.pill,
1681
- paddingHorizontal: tema.space.sm
1682
- },
1683
- children: tekst.nyttSvar
1684
- }
1685
- ) : null
1686
- ] }),
1687
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1688
- import_react_native7.Text,
1689
- {
1690
- style: {
1691
- color: tema.color.textPrimary,
1692
- fontSize: tema.font.body,
1693
- lineHeight: tema.lineHeight.body
1694
- },
1695
- children: rad.text
1696
- }
1697
- ),
1698
- tillegg.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.View, { testID: `tillegg-${sakId}`, style: { gap: tema.space.xs }, children: tillegg.map((a) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1699
- import_react_native7.View,
1700
- {
1701
- style: {
1702
- borderLeftWidth: tema.hairline * 2,
1703
- borderLeftColor: tema.color.border,
1704
- paddingLeft: tema.space.sm,
1705
- gap: tema.space.xs
1706
- },
1707
- children: [
1708
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
1709
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Ikon, { navn: "add-outline", storrelse: "minste", farge: tema.color.textSecondary }),
1710
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.small }, children: tekst.duLaTil(formaterFrist(a.createdAt)) })
1711
- ] }),
1712
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: a.text })
1713
- ]
2161
+ const ledd = venter ? [] : sporingsledd(rad, tenantName);
2162
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2163
+ import_react_native8.View,
2164
+ {
2165
+ onLayout: (e) => {
2166
+ if (sakId !== void 0) kortY.current.set(sakId, e.nativeEvent.layout.y);
1714
2167
  },
1715
- a.id
1716
- )) }) : null,
1717
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { gap: tema.space.xs }, children: [
1718
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StatusPill, { ikon: v.ikon, etikett: v.etikett, fg: v.fg, bg: v.bg }),
1719
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: v.lofte })
1720
- ] }),
1721
- sakId !== void 0 && lagtTil === sakId ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { accessibilityLiveRegion: "polite", testID: `lagt-til-${sakId}`, style: { color: tema.color.success, fontSize: tema.font.small }, children: tekst.lagtTil }) : null,
1722
- feltApent ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { testID: `tillegg-felt-${sakId}`, style: { gap: tema.space.sm }, children: [
1723
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.small }, children: tekst.leggTilMerLabel }),
1724
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1725
- import_react_native7.TextInput,
1726
- {
1727
- testID: "tillegg-tekst",
1728
- accessibilityLabel: tekst.leggTilMerLabel,
1729
- value: utkast,
1730
- onChangeText: setUtkast,
1731
- maxLength: maks,
1732
- multiline: true,
1733
- numberOfLines: 3,
1734
- autoFocus: true,
1735
- placeholder: tekst.leggTilMerPlaceholder,
1736
- placeholderTextColor: tema.color.textMuted,
1737
- style: {
1738
- backgroundColor: tema.color.surfaceRaised,
1739
- borderWidth: tema.hairline,
1740
- borderColor: full ? tema.color.warning : tema.color.borderStrong,
1741
- borderRadius: tema.radius.md,
1742
- padding: tema.space.md,
1743
- color: tema.color.textPrimary,
1744
- fontSize: tema.font.body,
1745
- lineHeight: tema.lineHeight.body,
1746
- minHeight: tema.touch * 2,
1747
- textAlignVertical: "top"
1748
- }
1749
- }
1750
- ),
1751
- visTeller ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1752
- import_react_native7.Text,
1753
- {
1754
- testID: "tillegg-teller",
1755
- accessibilityLiveRegion: full ? "assertive" : "polite",
1756
- style: { alignSelf: "flex-end", color: full ? tema.color.warning : tema.color.textMuted, fontSize: tema.font.small },
1757
- children: [
1758
- brukt,
1759
- " / ",
1760
- maks,
1761
- full ? tekst.tellerFull : ""
1762
- ]
1763
- }
1764
- ) : null,
1765
- feil?.id === sakId ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { accessibilityLiveRegion: "assertive", testID: `tillegg-feil-${sakId}`, style: { color: tema.color.danger, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: feil.tekst }) : null,
1766
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { style: { flexDirection: "row", gap: tema.space.sm }, children: [
1767
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1768
- Btn,
2168
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Card, { dashed: venter, testID: `sakskort-${nokkel}`, children: [
2169
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.sm, flexWrap: "wrap" }, children: [
2170
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2171
+ Ikon,
2172
+ {
2173
+ navn: rad.type === "onske" ? "bulb" : "bug",
2174
+ storrelse: "minste",
2175
+ farge: tema.color.brand
2176
+ }
2177
+ ),
2178
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Meta, { children: venter ? tekst.mineIkkeSendtHode(rad.type === "onske" ? tekst.onske : tekst.feil) : tekst.sakHode(rad.type === "onske" ? tekst.onske : tekst.feil, rad.id) }),
2179
+ nytt ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Pille, { testID: "nytt-svar", children: tekst.nyttSvar }) : null
2180
+ ] }),
2181
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Brodtekst, { testID: `sakstekst-${nokkel}`, children: rad.text }),
2182
+ tillegg.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native8.View, { testID: `tillegg-${sakId}`, style: { gap: tema.space.sm }, children: tillegg.map((a) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2183
+ import_react_native8.View,
1769
2184
  {
1770
- testID: "tillegg-send",
1771
- label: sender ? tekst.sender : tekst.send,
1772
- disabled: forKort || sender,
1773
- busy: sender,
1774
- ...forKort ? { hint: tekst.forKort(min) } : {},
1775
- onPress: () => sakId !== void 0 && void send(sakId),
1776
- grow: true
1777
- }
1778
- ),
1779
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1780
- Btn,
2185
+ style: {
2186
+ borderLeftWidth: tema.hairline * 2,
2187
+ borderLeftColor: tema.color.border,
2188
+ paddingLeft: tema.space.md,
2189
+ gap: tema.space.xs
2190
+ },
2191
+ children: [
2192
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Meta, { children: tekst.duLaTil(formaterFrist(a.createdAt)) }),
2193
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Brodtekst, { testID: `tillegg-tekst-${a.id}`, children: a.text })
2194
+ ]
2195
+ },
2196
+ a.id
2197
+ )) }) : null,
2198
+ svar ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2199
+ import_react_native8.View,
1781
2200
  {
1782
- testID: "tillegg-avbryt",
1783
- label: tekst.avbryt,
1784
- variant: "secondary",
1785
- onPress: () => {
1786
- setApen(null);
1787
- setUtkast("");
1788
- setFeil(void 0);
2201
+ testID: `svar-${sakId}`,
2202
+ style: {
2203
+ borderLeftWidth: tema.hairline * 2,
2204
+ borderLeftColor: tema.color.brand,
2205
+ paddingLeft: tema.space.md,
2206
+ gap: tema.space.xs
1789
2207
  },
1790
- grow: true
2208
+ children: [
2209
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Meta, { children: tenantName ? tekst.svarFra(tenantName, formaterFrist(svar.at)) : tekst.svarFraGenerisk(formaterFrist(svar.at)) }),
2210
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Brodtekst, { testID: `svar-tekst-${sakId}`, children: svar.text })
2211
+ ]
1791
2212
  }
1792
- )
1793
- ] }),
1794
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: tekst.leggTilMerHint })
1795
- ] }) : kanLeggeTil ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1796
- import_react_native7.Pressable,
1797
- {
1798
- testID: `legg-til-mer-${sakId}`,
1799
- accessibilityRole: "button",
1800
- accessibilityLabel: tekst.leggTilMerLabel,
1801
- onPress: () => {
1802
- if (sakId === void 0) return;
1803
- setApen(sakId);
1804
- setUtkast("");
1805
- setFeil(void 0);
1806
- setLagtTil(void 0);
1807
- },
1808
- style: { alignSelf: "flex-start", minHeight: tema.touch, flexDirection: "row", alignItems: "center", gap: tema.space.xs, paddingHorizontal: tema.space.sm },
1809
- children: [
1810
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Ikon, { navn: "add-outline", storrelse: "minste", farge: tema.color.actionSecondaryText }),
1811
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { style: { color: tema.color.actionSecondaryText, fontSize: tema.font.body, fontWeight: tema.weight.semibold }, children: tekst.leggTilMer })
1812
- ]
1813
- }
1814
- ) : taketN\u00E5dd ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: tekst.tilleggTak }) : null,
1815
- !venter && rad.attachmentRemoved ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react_native7.View, { testID: `bilde-fjernet-${rad.id}`, style: { flexDirection: "row", gap: tema.space.xs, alignItems: "center" }, children: [
1816
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Ikon, { navn: "trash-outline", storrelse: "minste", farge: tema.color.textMuted }),
1817
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Hint, { children: tekst.bildeFjernet })
1818
- ] }) : null,
1819
- svar ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1820
- import_react_native7.View,
1821
- {
1822
- style: {
1823
- borderLeftWidth: tema.hairline * 2,
1824
- borderLeftColor: tema.color.brand,
1825
- paddingLeft: tema.space.sm,
1826
- gap: tema.space.xs
1827
- },
1828
- children: [
1829
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_native7.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.small }, children: tenantName ? tekst.svarFra(tenantName) : tekst.svarFraGenerisk }),
1830
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1831
- import_react_native7.Text,
2213
+ ) : null,
2214
+ ledd.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Sporingslinje, { ledd, testID: `spor-${sakId}` }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StatusPill, { testID: `status-pille-${nokkel}`, ikon: v.ikon, etikett: v.etikett, fg: v.fg, bg: v.bg }),
2215
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Sek, { testID: `lofte-${nokkel}`, children: v.lofte }),
2216
+ !venter && rad.attachmentRemoved ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { testID: `bilde-fjernet-${rad.id}`, style: { flexDirection: "row", gap: tema.space.xs, alignItems: "center" }, children: [
2217
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Ikon, { navn: "trash-outline", storrelse: "minste", farge: tema.color.textMuted }),
2218
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Hint, { children: tekst.bildeFjernet })
2219
+ ] }) : null,
2220
+ sakId !== void 0 && lagtTil === sakId ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native8.Text, { accessibilityLiveRegion: "polite", testID: `lagt-til-${sakId}`, style: { color: tema.color.success, fontSize: tema.font.small }, children: tekst.lagtTil }) : null,
2221
+ feltApent ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { testID: `tillegg-felt-${sakId}`, style: { gap: tema.space.sm }, children: [
2222
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Meta, { children: tekst.leggTilMerLabel }),
2223
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2224
+ import_react_native8.TextInput,
1832
2225
  {
2226
+ testID: "tillegg-tekst",
2227
+ accessibilityLabel: tekst.leggTilMerLabel,
2228
+ value: utkast,
2229
+ onChangeText: setUtkast,
2230
+ maxLength: maks,
2231
+ multiline: true,
2232
+ numberOfLines: 3,
2233
+ autoFocus: true,
2234
+ placeholder: tekst.leggTilMerPlaceholder,
2235
+ placeholderTextColor: tema.color.textMuted,
1833
2236
  style: {
2237
+ backgroundColor: tema.color.surfaceRaised,
2238
+ borderWidth: tema.hairline,
2239
+ borderColor: full ? tema.color.warning : tema.color.borderStrong,
2240
+ borderRadius: tema.radius.md,
2241
+ padding: tema.space.md,
1834
2242
  color: tema.color.textPrimary,
1835
- fontSize: tema.font.small,
1836
- lineHeight: tema.lineHeight.small
1837
- },
1838
- children: svar.text
2243
+ fontSize: tema.font.body,
2244
+ lineHeight: tema.lineHeight.body,
2245
+ minHeight: tema.touch * 2,
2246
+ textAlignVertical: "top"
2247
+ }
1839
2248
  }
1840
- )
1841
- ]
1842
- }
1843
- ) : null
1844
- ] }, nokkel);
2249
+ ),
2250
+ visTeller ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2251
+ import_react_native8.Text,
2252
+ {
2253
+ testID: "tillegg-teller",
2254
+ accessibilityLiveRegion: full ? "assertive" : "polite",
2255
+ style: { alignSelf: "flex-end", color: full ? tema.color.warning : tema.color.textMuted, fontSize: tema.font.small },
2256
+ children: [
2257
+ brukt,
2258
+ " / ",
2259
+ maks,
2260
+ full ? tekst.tellerFull : ""
2261
+ ]
2262
+ }
2263
+ ) : null,
2264
+ feil?.id === sakId ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native8.Text, { accessibilityLiveRegion: "assertive", testID: `tillegg-feil-${sakId}`, style: { color: tema.color.danger, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: feil.tekst }) : null
2265
+ ] }) : kanLeggeTil ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2266
+ Tekstknapp,
2267
+ {
2268
+ testID: `legg-til-mer-${sakId}`,
2269
+ ikon: "add-outline",
2270
+ label: tekst.leggTilMer,
2271
+ accessibilityLabel: tekst.leggTilMerLabel,
2272
+ onPress: () => sakId !== void 0 && apneFelt(sakId)
2273
+ }
2274
+ ) : taketN\u00E5dd ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Hint, { children: tekst.tilleggTak }) : null
2275
+ ] })
2276
+ },
2277
+ nokkel
2278
+ );
1845
2279
  }) }),
1846
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { testID: "send-nytt", label: rader.length === 0 ? tekst.sendForste : tekst.sendNytt, onPress: onNytt })
2280
+ apen !== null ? (
2281
+ // F32: fotens plass — én primærhandling om gangen. «Send nytt innspill» er borte til
2282
+ // tillegget er sendt eller avbrutt, så første trykk aldri treffer feil knapp.
2283
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { testID: "tillegg-fot", style: { gap: tema.space.sm }, children: [
2284
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { style: { flexDirection: "row", gap: tema.space.sm }, children: [
2285
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2286
+ Btn,
2287
+ {
2288
+ testID: "tillegg-send",
2289
+ label: sender ? tekst.sender : tekst.send,
2290
+ disabled: utkast.length < min || sender,
2291
+ busy: sender,
2292
+ ...utkast.length < min ? { hint: tekst.forKort(min) } : {},
2293
+ onPress: () => void send(apen),
2294
+ grow: true
2295
+ }
2296
+ ),
2297
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Btn, { testID: "tillegg-avbryt", label: tekst.avbryt, variant: "secondary", onPress: avbryt, grow: true })
2298
+ ] }),
2299
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Hint, { children: tekst.leggTilMerHint })
2300
+ ] })
2301
+ ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Btn, { testID: "send-nytt", ikon: "chatbox-outline", label: tom ? tekst.sendForste : tekst.sendNytt, onPress: onNytt })
1847
2302
  ] });
1848
- }
2303
+ });
1849
2304
 
1850
2305
  // src/widget/Skjermbilde.tsx
1851
2306
  var import_core2 = require("@innspel/core");
1852
- var import_react10 = require("react");
1853
- var import_react_native8 = require("react-native");
1854
- var import_jsx_runtime8 = require("react/jsx-runtime");
2307
+ var import_react11 = require("react");
2308
+ var import_react_native9 = require("react-native");
2309
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1855
2310
  function Skjermbilde({
1856
2311
  bilde,
1857
2312
  automaskerRot,
@@ -1864,21 +2319,21 @@ function Skjermbilde({
1864
2319
  onLeggVed
1865
2320
  }) {
1866
2321
  const tema = useTema();
1867
- const [verktoy, setVerktoy] = (0, import_react10.useState)("pensel");
1868
- const [allTekst, setAllTekst] = (0, import_react10.useState)(false);
1869
- const [egne, setEgne] = (0, import_react10.useState)([]);
1870
- const [ramme, setRamme] = (0, import_react10.useState)(null);
1871
- const strok = (0, import_react10.useRef)([]);
1872
- const visning = (0, import_react10.useMemo)(() => {
2322
+ const [verktoy, setVerktoy] = (0, import_react11.useState)("pensel");
2323
+ const [allTekst, setAllTekst] = (0, import_react11.useState)(false);
2324
+ const [egne, setEgne] = (0, import_react11.useState)([]);
2325
+ const [ramme, setRamme] = (0, import_react11.useState)(null);
2326
+ const strok = (0, import_react11.useRef)([]);
2327
+ const visning = (0, import_react11.useMemo)(() => {
1873
2328
  if (!ramme) return null;
1874
2329
  const s = Math.min(ramme.width / bilde.width, ramme.height / bilde.height);
1875
2330
  return { width: Math.floor(bilde.width * s), height: Math.floor(bilde.height * s) };
1876
2331
  }, [ramme, bilde.width, bilde.height]);
1877
- const automasker = (0, import_react10.useMemo)(
2332
+ const automasker = (0, import_react11.useMemo)(
1878
2333
  () => visning ? automaskerRot.map((r) => (0, import_core2.skaler)(r, rotStorrelse, visning)) : [],
1879
2334
  [automaskerRot, rotStorrelse, visning]
1880
2335
  );
1881
- const onLayout = (0, import_react10.useCallback)((e) => {
2336
+ const onLayout = (0, import_react11.useCallback)((e) => {
1882
2337
  const { width, height } = e.nativeEvent.layout;
1883
2338
  setRamme({ width, height });
1884
2339
  }, []);
@@ -1910,8 +2365,8 @@ function Skjermbilde({
1910
2365
  };
1911
2366
  const knapp = (id, ikon, label) => {
1912
2367
  const valgt = id === "allTekst" ? allTekst : verktoy === id && !allTekst;
1913
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1914
- import_react_native8.Pressable,
2368
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2369
+ import_react_native9.Pressable,
1915
2370
  {
1916
2371
  testID: `verktoy-${id}`,
1917
2372
  accessibilityRole: "button",
@@ -1933,9 +2388,9 @@ function Skjermbilde({
1933
2388
  backgroundColor: valgt ? tema.color.surfaceRaised : "transparent"
1934
2389
  },
1935
2390
  children: [
1936
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Ikon, { navn: ikon, farge: tema.color.textPrimary }),
1937
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1938
- import_react_native8.Text,
2391
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Ikon, { navn: ikon, farge: tema.color.textPrimary }),
2392
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2393
+ import_react_native9.Text,
1939
2394
  {
1940
2395
  style: {
1941
2396
  color: tema.color.textPrimary,
@@ -1951,16 +2406,16 @@ function Skjermbilde({
1951
2406
  );
1952
2407
  };
1953
2408
  const a11y = tekst.skjermbildeA11y(automasker.length, egne.length, allTekst);
1954
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { testID: "skjermbilde-steg", style: { flexGrow: 1, flexShrink: 1, gap: tema.space.md }, children: [
1955
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(H, { sub: kilde === "galleri" ? tekst.skjermbildeUnderGalleri : tekst.skjermbildeUnder, children: tekst.skjermbildeTittel }),
1956
- notat ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native8.View, { testID: "bilde-notat", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Hint, { children: notat }) }) : null,
1957
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { accessibilityRole: "toolbar", accessibilityLabel: tekst.maskering, style: { flexDirection: "row", gap: tema.space.sm }, children: [
2409
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native9.View, { testID: "skjermbilde-steg", style: { flexGrow: 1, flexShrink: 1, gap: tema.space.md }, children: [
2410
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(H, { sub: kilde === "galleri" ? tekst.skjermbildeUnderGalleri : tekst.skjermbildeUnder, children: tekst.skjermbildeTittel }),
2411
+ notat ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native9.View, { testID: "bilde-notat", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Hint, { children: notat }) }) : null,
2412
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native9.View, { accessibilityRole: "toolbar", accessibilityLabel: tekst.maskering, style: { flexDirection: "row", gap: tema.space.sm }, children: [
1958
2413
  knapp("felt", "scan-outline", tekst.maskerFelt),
1959
2414
  knapp("pensel", "brush-outline", tekst.tegnOver),
1960
2415
  knapp("allTekst", "grid-outline", tekst.maskerAllTekst)
1961
2416
  ] }),
1962
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1963
- import_react_native8.View,
2417
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2418
+ import_react_native9.View,
1964
2419
  {
1965
2420
  testID: "skjermbilde-ramme",
1966
2421
  onLayout,
@@ -1973,8 +2428,8 @@ function Skjermbilde({
1973
2428
  borderRadius: tema.radius.md,
1974
2429
  overflow: "hidden"
1975
2430
  },
1976
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native8.View, { testID: "skjermbilde-flate", pointerEvents: "box-none", style: [import_react_native8.StyleSheet.absoluteFill, { alignItems: "center", justifyContent: "center" }], children: visning ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1977
- import_react_native8.View,
2431
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native9.View, { testID: "skjermbilde-flate", pointerEvents: "box-none", style: [import_react_native9.StyleSheet.absoluteFill, { alignItems: "center", justifyContent: "center" }], children: visning ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2432
+ import_react_native9.View,
1978
2433
  {
1979
2434
  ref: previewRef,
1980
2435
  collapsable: false,
@@ -1989,8 +2444,8 @@ function Skjermbilde({
1989
2444
  onResponderTerminate: onRelease,
1990
2445
  style: { width: visning.width, height: visning.height, backgroundColor: screenRules.previewBackdrop },
1991
2446
  children: [
1992
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1993
- import_react_native8.Image,
2447
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2448
+ import_react_native9.Image,
1994
2449
  {
1995
2450
  testID: "skjermbilde-bilde",
1996
2451
  source: { uri: bilde.uri },
@@ -1999,8 +2454,8 @@ function Skjermbilde({
1999
2454
  accessibilityIgnoresInvertColors: true
2000
2455
  }
2001
2456
  ),
2002
- automasker.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2003
- import_react_native8.View,
2457
+ automasker.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2458
+ import_react_native9.View,
2004
2459
  {
2005
2460
  testID: `automask-${i}`,
2006
2461
  pointerEvents: "none",
@@ -2021,16 +2476,16 @@ function Skjermbilde({
2021
2476
  // (skjermKontrastpar i theme.ts). textSecondary var 2,2:1 (C11a).
2022
2477
  // Ikonet arver samme farge: det er unntaket i «Styling» — maskeringen
2023
2478
  // tegnes i faste signalfarger, ikke i palettens.
2024
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
2025
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Ikon, { navn: "lock-closed-outline", storrelse: "minste", farge: screenRules.autoMaskText }),
2026
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_native8.Text, { style: { color: screenRules.autoMaskText, fontSize: tema.font.small }, numberOfLines: 1, children: tekst.maskertAvAppen })
2479
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native9.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
2480
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Ikon, { navn: "lock-closed-outline", storrelse: "minste", farge: screenRules.autoMaskText }),
2481
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native9.Text, { style: { color: screenRules.autoMaskText, fontSize: tema.font.small }, numberOfLines: 1, children: tekst.maskertAvAppen })
2027
2482
  ] })
2028
2483
  ) : null
2029
2484
  },
2030
2485
  `auto-${i}`
2031
2486
  )),
2032
- egne.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2033
- import_react_native8.View,
2487
+ egne.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2488
+ import_react_native9.View,
2034
2489
  {
2035
2490
  testID: `maske-${i}`,
2036
2491
  pointerEvents: "none",
@@ -2043,14 +2498,14 @@ function Skjermbilde({
2043
2498
  ) : null })
2044
2499
  }
2045
2500
  ),
2046
- automasker.length ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
2047
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Ikon, { navn: "lock-closed-outline", storrelse: "minste", farge: tema.color.textMuted }),
2048
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Hint, { children: tekst.maskertAvAppenHint })
2501
+ automasker.length ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native9.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
2502
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Ikon, { navn: "lock-closed-outline", storrelse: "minste", farge: tema.color.textMuted }),
2503
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Hint, { children: tekst.maskertAvAppenHint })
2049
2504
  ] }) : null,
2050
- egne.length ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Hint, { children: tekst.dittStrok }) : null,
2051
- allTekst ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Hint, { children: tekst.allTekstHint }) : null,
2052
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_native8.View, { testID: "skjermbilde-fot", style: { flexShrink: 0, gap: tema.space.sm }, children: [
2053
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2505
+ egne.length ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Hint, { children: tekst.dittStrok }) : null,
2506
+ allTekst ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Hint, { children: tekst.allTekstHint }) : null,
2507
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native9.View, { testID: "skjermbilde-fot", style: { flexShrink: 0, gap: tema.space.sm }, children: [
2508
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2054
2509
  Btn,
2055
2510
  {
2056
2511
  variant: "secondary",
@@ -2061,7 +2516,7 @@ function Skjermbilde({
2061
2516
  onPress: () => setEgne((x) => x.slice(0, -1))
2062
2517
  }
2063
2518
  ),
2064
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2519
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2065
2520
  Btn,
2066
2521
  {
2067
2522
  variant: "danger",
@@ -2072,13 +2527,13 @@ function Skjermbilde({
2072
2527
  disabled: komponerer
2073
2528
  }
2074
2529
  ),
2075
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Btn, { testID: "legg-ved", label: tekst.leggVed, onPress: onLeggVed, disabled: komponerer || !visning })
2530
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Btn, { testID: "legg-ved", label: tekst.leggVed, onPress: onLeggVed, disabled: komponerer || !visning })
2076
2531
  ] })
2077
2532
  ] });
2078
2533
  }
2079
2534
 
2080
2535
  // src/widget/Widget.tsx
2081
- var import_jsx_runtime9 = require("react/jsx-runtime");
2536
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2082
2537
  var FANGST = { format: "jpg", quality: 0.85 };
2083
2538
  function Widget({
2084
2539
  client,
@@ -2090,35 +2545,35 @@ function Widget({
2090
2545
  onSubmitted
2091
2546
  }) {
2092
2547
  const tema = useTema();
2093
- const insets = (0, import_react11.useContext)(import_react_native_safe_area_context.SafeAreaInsetsContext) ?? import_react_native_safe_area_context.initialWindowMetrics?.insets ?? { top: 0, bottom: 0, left: 0, right: 0 };
2548
+ const insets = (0, import_react12.useContext)(import_react_native_safe_area_context.SafeAreaInsetsContext) ?? import_react_native_safe_area_context.initialWindowMetrics?.insets ?? { top: 0, bottom: 0, left: 0, right: 0 };
2094
2549
  const skjermbilde = useSkjermbilde();
2095
- const previewRef = (0, import_react11.useRef)(null);
2096
- const [steg, setSteg] = (0, import_react11.useState)("valg");
2097
- const [spor, setSpor] = (0, import_react11.useState)("feil");
2098
- const [verdi, setVerdi] = (0, import_react11.useState)("");
2099
- const [kort, setKort] = (0, import_react11.useState)([]);
2100
- const [lasterKort, setLasterKort] = (0, import_react11.useState)(false);
2101
- const [lenketTil, setLenketTil] = (0, import_react11.useState)();
2102
- const [funn, setFunn] = (0, import_react11.useState)([]);
2103
- const [fjernede, setFjernede] = (0, import_react11.useState)([]);
2104
- const [sender, setSender] = (0, import_react11.useState)(false);
2550
+ const previewRef = (0, import_react12.useRef)(null);
2551
+ const [steg, setSteg] = (0, import_react12.useState)("valg");
2552
+ const [spor, setSpor] = (0, import_react12.useState)("feil");
2553
+ const [verdi, setVerdi] = (0, import_react12.useState)("");
2554
+ const [kort, setKort] = (0, import_react12.useState)([]);
2555
+ const [lasterKort, setLasterKort] = (0, import_react12.useState)(false);
2556
+ const [lenketTil, setLenketTil] = (0, import_react12.useState)();
2557
+ const [funn, setFunn] = (0, import_react12.useState)([]);
2558
+ const [fjernede, setFjernede] = (0, import_react12.useState)([]);
2559
+ const [sender, setSender] = (0, import_react12.useState)(false);
2105
2560
  const online = useNettstatus(client);
2106
- const [feil, setFeil] = (0, import_react11.useState)();
2107
- const [kvittering, setKvittering] = (0, import_react11.useState)();
2108
- const [mine, setMine] = (0, import_react11.useState)([]);
2109
- const [lasterMine, setLasterMine] = (0, import_react11.useState)(false);
2110
- const [bilde, setBilde] = (0, import_react11.useState)();
2111
- const [automasker, setAutomasker] = (0, import_react11.useState)([]);
2112
- const [rotStorrelse, setRotStorrelse] = (0, import_react11.useState)({ width: 1, height: 1 });
2113
- const [komponerer, setKomponerer] = (0, import_react11.useState)(false);
2114
- const [kilde, setKilde] = (0, import_react11.useState)("skjerm");
2115
- const [vedlegg, setVedlegg] = (0, import_react11.useState)();
2116
- const [innstillinger, setInnstillinger] = (0, import_react11.useState)({ ...client.settings });
2561
+ const [feil, setFeil] = (0, import_react12.useState)();
2562
+ const [kvittering, setKvittering] = (0, import_react12.useState)();
2563
+ const [mine, setMine] = (0, import_react12.useState)([]);
2564
+ const [lasterMine, setLasterMine] = (0, import_react12.useState)(false);
2565
+ const [bilde, setBilde] = (0, import_react12.useState)();
2566
+ const [automasker, setAutomasker] = (0, import_react12.useState)([]);
2567
+ const [rotStorrelse, setRotStorrelse] = (0, import_react12.useState)({ width: 1, height: 1 });
2568
+ const [komponerer, setKomponerer] = (0, import_react12.useState)(false);
2569
+ const [kilde, setKilde] = (0, import_react12.useState)("skjerm");
2570
+ const [vedlegg, setVedlegg] = (0, import_react12.useState)();
2571
+ const [innstillinger, setInnstillinger] = (0, import_react12.useState)({ ...client.settings });
2117
2572
  const skjermbildeMulig = innstillinger.screenshotsEnabled && skjermbilde?.adapter != null;
2118
2573
  const fangstMulig = skjermbildeMulig && skjermbilde?.adapter?.captureScreen !== false;
2119
2574
  const galleriMulig = skjermbildeMulig && typeof skjermbilde?.adapter?.pick === "function";
2120
2575
  const bildeNotat = typeof imageStepNote === "string" ? imageStepNote : imageStepNote?.[spor];
2121
- const nullstill = (0, import_react11.useCallback)(() => {
2576
+ const nullstill = (0, import_react12.useCallback)(() => {
2122
2577
  setSteg("valg");
2123
2578
  setSpor("feil");
2124
2579
  setVerdi("");
@@ -2133,25 +2588,25 @@ function Widget({
2133
2588
  setVedlegg(void 0);
2134
2589
  setKomponerer(false);
2135
2590
  }, []);
2136
- const [mineDirekte, setMineDirekte] = (0, import_react11.useState)(false);
2137
- const [stegForMine, setStegForMine] = (0, import_react11.useState)("valg");
2138
- const stegRef = (0, import_react11.useRef)(steg);
2591
+ const [mineDirekte, setMineDirekte] = (0, import_react12.useState)(false);
2592
+ const [stegForMine, setStegForMine] = (0, import_react12.useState)("valg");
2593
+ const stegRef = (0, import_react12.useRef)(steg);
2139
2594
  stegRef.current = steg;
2140
2595
  const harUtkast = verdi.trim().length > 0 || vedlegg !== void 0;
2141
- const lukk = (0, import_react11.useCallback)(() => {
2596
+ const lukk = (0, import_react12.useCallback)(() => {
2142
2597
  onLukk();
2143
2598
  if (stegRef.current === "mine" && mineDirekte) {
2144
2599
  setSteg(stegForMine);
2145
2600
  setMineDirekte(false);
2146
2601
  }
2147
2602
  }, [onLukk, mineDirekte, stegForMine]);
2148
- const lukkOgNullstill = (0, import_react11.useCallback)(() => {
2603
+ const lukkOgNullstill = (0, import_react12.useCallback)(() => {
2149
2604
  onLukk();
2150
2605
  nullstill();
2151
2606
  setMineDirekte(false);
2152
2607
  setStegForMine("valg");
2153
2608
  }, [onLukk, nullstill]);
2154
- (0, import_react11.useEffect)(() => {
2609
+ (0, import_react12.useEffect)(() => {
2155
2610
  if (!synlig) return;
2156
2611
  client.track({ name: "widget_opened" });
2157
2612
  void client.queue.flush().catch(() => void 0);
@@ -2162,7 +2617,7 @@ function Widget({
2162
2617
  if (apneOpsjoner?.view === "mine" && !client.isAnonymous) void visMine(true);
2163
2618
  else if (apneOpsjoner?.track && !harUtkast) void velgSpor(apneOpsjoner.track);
2164
2619
  }, [synlig]);
2165
- const hentKort = (0, import_react11.useCallback)(async () => {
2620
+ const hentKort = (0, import_react12.useCallback)(async () => {
2166
2621
  setLasterKort(true);
2167
2622
  try {
2168
2623
  const q = apneOpsjoner?.screen ? { screen: apneOpsjoner.screen } : {};
@@ -2171,7 +2626,7 @@ function Widget({
2171
2626
  setLasterKort(false);
2172
2627
  }
2173
2628
  }, [client, apneOpsjoner?.screen]);
2174
- const velgSpor = (0, import_react11.useCallback)(
2629
+ const velgSpor = (0, import_react12.useCallback)(
2175
2630
  async (valgt) => {
2176
2631
  setSpor(valgt);
2177
2632
  client.track({ name: "track_selected", type: valgt });
@@ -2184,17 +2639,17 @@ function Widget({
2184
2639
  },
2185
2640
  [client, hentKort]
2186
2641
  );
2187
- (0, import_react11.useEffect)(() => {
2642
+ (0, import_react12.useEffect)(() => {
2188
2643
  if (steg === "kjenteFeil" && !lasterKort && kort.length === 0) setSteg("felt");
2189
2644
  }, [steg, lasterKort, kort.length]);
2190
- const endreTekst = (0, import_react11.useCallback)(
2645
+ const endreTekst = (0, import_react12.useCallback)(
2191
2646
  (v) => {
2192
2647
  setVerdi(v);
2193
2648
  setFunn(client.scanText(v));
2194
2649
  },
2195
2650
  [client]
2196
2651
  );
2197
- const taSkjermbilde = (0, import_react11.useCallback)(async () => {
2652
+ const taSkjermbilde = (0, import_react12.useCallback)(async () => {
2198
2653
  if (!skjermbilde?.adapter) return;
2199
2654
  const { adapter, rootRef, privat } = skjermbilde;
2200
2655
  setFeil(void 0);
@@ -2218,7 +2673,7 @@ function Widget({
2218
2673
  setFeil(tekst.skjermbildeFeilet);
2219
2674
  }
2220
2675
  }, [skjermbilde]);
2221
- const velgBilde = (0, import_react11.useCallback)(async () => {
2676
+ const velgBilde = (0, import_react12.useCallback)(async () => {
2222
2677
  const pick = skjermbilde?.adapter?.pick;
2223
2678
  if (!pick) return;
2224
2679
  setFeil(void 0);
@@ -2234,7 +2689,7 @@ function Widget({
2234
2689
  setFeil(tekst.bildeFeilet);
2235
2690
  }
2236
2691
  }, [skjermbilde]);
2237
- const leggVedBilde = (0, import_react11.useCallback)(async () => {
2692
+ const leggVedBilde = (0, import_react12.useCallback)(async () => {
2238
2693
  if (!skjermbilde?.adapter) return;
2239
2694
  setKomponerer(true);
2240
2695
  try {
@@ -2250,15 +2705,18 @@ function Widget({
2250
2705
  setKomponerer(false);
2251
2706
  }
2252
2707
  }, [skjermbilde]);
2253
- const fjernBilde = (0, import_react11.useCallback)(() => {
2708
+ const fjernBilde = (0, import_react12.useCallback)(() => {
2254
2709
  setBilde(void 0);
2255
2710
  setAutomasker([]);
2256
2711
  setVedlegg(void 0);
2257
2712
  setSteg("felt");
2258
2713
  }, []);
2259
- const gaaTilbake = (0, import_react11.useCallback)(() => {
2714
+ const mineRef = (0, import_react12.useRef)(null);
2715
+ const tilleggUtkast = (0, import_react12.useRef)(/* @__PURE__ */ new Map());
2716
+ const gaaTilbake = (0, import_react12.useCallback)(() => {
2260
2717
  setFeil(void 0);
2261
2718
  if (steg === "mine") {
2719
+ if (mineRef.current?.lukkFelt()) return;
2262
2720
  if (mineDirekte) lukk();
2263
2721
  else setSteg("valg");
2264
2722
  return;
@@ -2275,12 +2733,12 @@ function Widget({
2275
2733
  }
2276
2734
  setSteg("valg");
2277
2735
  }, [steg, spor, kort.length, mineDirekte, lukk]);
2278
- const androidTilbake = (0, import_react11.useCallback)(() => {
2736
+ const androidTilbake = (0, import_react12.useCallback)(() => {
2279
2737
  if (steg === "valg") lukk();
2280
2738
  else if (steg === "kvittering") lukkOgNullstill();
2281
2739
  else gaaTilbake();
2282
2740
  }, [steg, lukk, lukkOgNullstill, gaaTilbake]);
2283
- const send = (0, import_react11.useCallback)(async () => {
2741
+ const send = (0, import_react12.useCallback)(async () => {
2284
2742
  setSender(true);
2285
2743
  setFeil(void 0);
2286
2744
  try {
@@ -2297,6 +2755,9 @@ function Widget({
2297
2755
  setKvittering({
2298
2756
  art: spor,
2299
2757
  nr: res.submission.id,
2758
+ // Kortet får HELE saken: sporingslinjen leser `status`, `createdAt` og
2759
+ // `statusChangedAt` derfra — ingen nye felter, ingen ny kontrakt (DD-28).
2760
+ sak: res.submission,
2300
2761
  // Tidsløftet i kvitteringen er DATOEN fra svaret, aldri «innen 90 dager» (DD-07, DD-28).
2301
2762
  ...res.submission.deadlineAt ? { frist: res.submission.deadlineAt } : {},
2302
2763
  ...res.attachment?.status === "failed" ? { vedlegg: "feilet" } : {}
@@ -2312,12 +2773,12 @@ function Widget({
2312
2773
  setSender(false);
2313
2774
  }
2314
2775
  }, [client, spor, verdi, vedlegg, lenketTil, fjernede, apneOpsjoner?.screen, onSubmitted]);
2315
- const jaOgsa = (0, import_react11.useCallback)(
2776
+ const jaOgsa = (0, import_react12.useCallback)(
2316
2777
  async (k) => {
2317
2778
  setSender(true);
2318
2779
  try {
2319
2780
  const res = await client.knownIssues.confirm(k.id);
2320
- setKvittering({ art: "jaOgsa", nr: res.id });
2781
+ setKvittering({ art: "jaOgsa", nr: res.id, sak: res });
2321
2782
  setSteg("kvittering");
2322
2783
  } catch (e) {
2323
2784
  setFeil(e instanceof import_core3.InnspelApiError ? e.message : "tjeneren svarte ikke.");
@@ -2327,7 +2788,7 @@ function Widget({
2327
2788
  },
2328
2789
  [client]
2329
2790
  );
2330
- const visMine = (0, import_react11.useCallback)(async (direkte = false) => {
2791
+ const visMine = (0, import_react12.useCallback)(async (direkte = false) => {
2331
2792
  if (direkte) {
2332
2793
  if (stegRef.current !== "mine") setStegForMine(stegRef.current);
2333
2794
  } else {
@@ -2344,27 +2805,27 @@ function Widget({
2344
2805
  setLasterMine(false);
2345
2806
  }
2346
2807
  }, [client]);
2347
- const nyttFraMine = (0, import_react11.useCallback)(() => {
2808
+ const nyttFraMine = (0, import_react12.useCallback)(() => {
2348
2809
  setMineDirekte(false);
2349
2810
  if (harUtkast) setSteg(stegForMine);
2350
2811
  else nullstill();
2351
2812
  }, [harUtkast, stegForMine, nullstill]);
2352
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2353
- import_react_native9.Modal,
2813
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2814
+ import_react_native10.Modal,
2354
2815
  {
2355
2816
  visible: synlig,
2356
2817
  transparent: true,
2357
2818
  animationType: "slide",
2358
2819
  onRequestClose: androidTilbake,
2359
2820
  accessibilityViewIsModal: true,
2360
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2361
- import_react_native9.KeyboardAvoidingView,
2821
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2822
+ import_react_native10.KeyboardAvoidingView,
2362
2823
  {
2363
2824
  behavior: "padding",
2364
2825
  keyboardVerticalOffset: -insets.bottom,
2365
2826
  style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end", paddingTop: insets.top },
2366
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2367
- import_react_native9.View,
2827
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2828
+ import_react_native10.View,
2368
2829
  {
2369
2830
  testID: "innspel-widget",
2370
2831
  accessibilityViewIsModal: true,
@@ -2385,37 +2846,37 @@ function Widget({
2385
2846
  ...steg === "skjermbilde" ? { height: "92%" } : {}
2386
2847
  },
2387
2848
  children: [
2388
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_react_native9.View, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, children: [
2389
- steg !== "valg" && steg !== "kvittering" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Btn, { variant: "ghost", testID: "tilbake", ikon: "arrow-back-outline", label: tekst.tilbake, onPress: gaaTilbake }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native9.View, {}),
2390
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2391
- import_react_native9.Pressable,
2849
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native10.View, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, children: [
2850
+ steg !== "valg" && steg !== "kvittering" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Btn, { variant: "ghost", testID: "tilbake", ikon: "arrow-back-outline", label: tekst.tilbake, onPress: gaaTilbake }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native10.View, {}),
2851
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2852
+ import_react_native10.Pressable,
2392
2853
  {
2393
2854
  testID: "lukk",
2394
2855
  accessibilityRole: "button",
2395
2856
  accessibilityLabel: tekst.lukk,
2396
2857
  onPress: steg === "kvittering" ? lukkOgNullstill : lukk,
2397
2858
  style: { minWidth: tema.touch, minHeight: tema.touch, alignItems: "center", justifyContent: "center" },
2398
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Ikon, { navn: "close-outline", farge: tema.color.textSecondary })
2859
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Ikon, { navn: "close-outline", farge: tema.color.textSecondary })
2399
2860
  }
2400
2861
  )
2401
2862
  ] }),
2402
- feil ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Banner, { live: true, ikon: "warning-outline", tone: "danger", children: tekst.sendefeilBanner(feil) }) : null,
2403
- !online && steg !== "kvittering" && steg !== "mine" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Banner, { ikon: "cloud-offline-outline", tone: "info", testID: "offline-banner", children: tekst.offlineBanner }) : null,
2404
- steg === "valg" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2405
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Valg, { onVelg: velgSpor }),
2406
- !client.isAnonymous ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2863
+ feil ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Banner, { live: true, ikon: "warning-outline", tone: "danger", children: tekst.sendefeilBanner(feil) }) : null,
2864
+ !online && steg !== "kvittering" && steg !== "mine" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Banner, { ikon: "cloud-offline-outline", tone: "info", testID: "offline-banner", children: tekst.offlineBanner }) : null,
2865
+ steg === "valg" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2866
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Valg, { onVelg: velgSpor, anonym: client.isAnonymous }),
2867
+ !client.isAnonymous ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native10.View, { style: { flex: 1, justifyContent: "flex-end" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2407
2868
  Btn,
2408
2869
  {
2409
- variant: mine.length > 0 ? "secondary" : "ghost",
2870
+ variant: "secondary",
2410
2871
  testID: "mine-innspill",
2411
2872
  ikon: "list-outline",
2412
2873
  label: mine.length > 0 ? tekst.mineMedAntall(mine.length) : tekst.mineTittel,
2413
2874
  accessibilityLabel: mine.length > 0 ? tekst.mineEtikett(mine.length) : tekst.mineTittel,
2414
2875
  onPress: () => void visMine()
2415
2876
  }
2416
- ) : null
2877
+ ) }) : null
2417
2878
  ] }) : null,
2418
- steg === "kjenteFeil" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2879
+ steg === "kjenteFeil" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2419
2880
  KjenteFeil,
2420
2881
  {
2421
2882
  kort,
@@ -2430,7 +2891,7 @@ function Widget({
2430
2891
  onNei: () => setSteg("felt")
2431
2892
  }
2432
2893
  ) : null,
2433
- steg === "felt" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2894
+ steg === "felt" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2434
2895
  Felt,
2435
2896
  {
2436
2897
  spor,
@@ -2454,7 +2915,7 @@ function Widget({
2454
2915
  onFjernVedlegg: fjernBilde
2455
2916
  }
2456
2917
  ) : null,
2457
- steg === "skjermbilde" && bilde ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2918
+ steg === "skjermbilde" && bilde ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2458
2919
  Skjermbilde,
2459
2920
  {
2460
2921
  bilde,
@@ -2468,19 +2929,24 @@ function Widget({
2468
2929
  onLeggVed: leggVedBilde
2469
2930
  }
2470
2931
  ) : null,
2471
- steg === "kvittering" && kvittering ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2932
+ steg === "kvittering" && kvittering ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2472
2933
  Kvittering,
2473
2934
  {
2474
2935
  art: kvittering.art,
2475
2936
  ...kvittering.nr ? { saksnummer: kvittering.nr } : {},
2476
2937
  ...kvittering.vedlegg ? { vedlegg: kvittering.vedlegg } : {},
2477
2938
  ...kvittering.frist ? { frist: kvittering.frist } : {},
2939
+ ...kvittering.sak && kvittering.sak.pending !== true ? { sak: kvittering.sak } : {},
2940
+ ...tenantName ? { tenantName } : {},
2941
+ anonym: client.isAnonymous,
2478
2942
  onLukk: lukkOgNullstill
2479
2943
  }
2480
2944
  ) : null,
2481
- steg === "mine" ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2945
+ steg === "mine" ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2482
2946
  MineInnspill,
2483
2947
  {
2948
+ ref: mineRef,
2949
+ utkastLager: tilleggUtkast.current,
2484
2950
  storage: client.storage,
2485
2951
  rader: mine,
2486
2952
  laster: lasterMine,
@@ -2502,8 +2968,8 @@ function Widget({
2502
2968
  }
2503
2969
  function useNettstatus(client) {
2504
2970
  const c = client.connectivity;
2505
- const [online, setOnline] = (0, import_react11.useState)(() => c?.isOnline() ?? true);
2506
- (0, import_react11.useEffect)(() => {
2971
+ const [online, setOnline] = (0, import_react12.useState)(() => c?.isOnline() ?? true);
2972
+ (0, import_react12.useEffect)(() => {
2507
2973
  if (!c) return void 0;
2508
2974
  setOnline(c.isOnline());
2509
2975
  return c.subscribe?.((v) => setOnline(v));
@@ -2520,8 +2986,8 @@ function fjernetKontekst(client, fjernede, skjerm) {
2520
2986
  }
2521
2987
 
2522
2988
  // src/InnspelProvider.tsx
2523
- var import_jsx_runtime10 = require("react/jsx-runtime");
2524
- var Kontekst = (0, import_react12.createContext)(null);
2989
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2990
+ var Kontekst = (0, import_react13.createContext)(null);
2525
2991
  function InnspelProvider({
2526
2992
  client,
2527
2993
  children,
@@ -2532,32 +2998,32 @@ function InnspelProvider({
2532
2998
  imageStepNote,
2533
2999
  onSubmitted
2534
3000
  }) {
2535
- const [synlig, setSynlig] = (0, import_react12.useState)(false);
2536
- const [apneOpsjoner, setApneOpsjoner] = (0, import_react12.useState)();
2537
- const registrert = (0, import_react12.useRef)(false);
2538
- const rootRef = (0, import_react12.useRef)(null);
2539
- const privat = (0, import_react12.useMemo)(createPrivateRegistry, []);
2540
- const open = (0, import_react12.useCallback)(
3001
+ const [synlig, setSynlig] = (0, import_react13.useState)(false);
3002
+ const [apneOpsjoner, setApneOpsjoner] = (0, import_react13.useState)();
3003
+ const registrert = (0, import_react13.useRef)(false);
3004
+ const rootRef = (0, import_react13.useRef)(null);
3005
+ const privat = (0, import_react13.useMemo)(createPrivateRegistry, []);
3006
+ const open = (0, import_react13.useCallback)(
2541
3007
  async (options) => {
2542
3008
  setApneOpsjoner(options);
2543
3009
  setSynlig(true);
2544
3010
  },
2545
3011
  []
2546
3012
  );
2547
- const close = (0, import_react12.useCallback)(() => setSynlig(false), []);
3013
+ const close = (0, import_react13.useCallback)(() => setSynlig(false), []);
2548
3014
  if (!registrert.current) {
2549
3015
  client.registerPresenter({ open });
2550
3016
  registrert.current = true;
2551
3017
  }
2552
- const tema = (0, import_react12.useMemo)(() => byggTema(theme, colorScheme), [theme, colorScheme]);
2553
- const verdi = (0, import_react12.useMemo)(() => ({ client, open, close }), [client, open, close]);
2554
- const skjermbilde = (0, import_react12.useMemo)(
3018
+ const tema = (0, import_react13.useMemo)(() => byggTema(theme, colorScheme), [theme, colorScheme]);
3019
+ const verdi = (0, import_react13.useMemo)(() => ({ client, open, close }), [client, open, close]);
3020
+ const skjermbilde = (0, import_react13.useMemo)(
2555
3021
  () => ({ adapter: screenshot ?? null, rootRef, privat }),
2556
3022
  [screenshot, privat]
2557
3023
  );
2558
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Kontekst.Provider, { value: verdi, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SkjermbildeContext.Provider, { value: skjermbilde, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(TemaProvider, { value: tema, children: [
2559
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native10.View, { ref: rootRef, collapsable: false, style: { flex: 1 }, testID: "innspel-rot", children }),
2560
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3024
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Kontekst.Provider, { value: verdi, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SkjermbildeContext.Provider, { value: skjermbilde, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(TemaProvider, { value: tema, children: [
3025
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native11.View, { ref: rootRef, collapsable: false, style: { flex: 1 }, testID: "innspel-rot", children }),
3026
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2561
3027
  Widget,
2562
3028
  {
2563
3029
  client,
@@ -2572,7 +3038,7 @@ function InnspelProvider({
2572
3038
  ] }) }) });
2573
3039
  }
2574
3040
  function useInnspel() {
2575
- const k = (0, import_react12.useContext)(Kontekst);
3041
+ const k = (0, import_react13.useContext)(Kontekst);
2576
3042
  if (!k) {
2577
3043
  throw new Error(
2578
3044
  "[innspel] useInnspel() ble kalt utenfor <InnspelProvider>. Pakk appen din i den \u2014 se README.md."
@@ -2582,28 +3048,24 @@ function useInnspel() {
2582
3048
  }
2583
3049
 
2584
3050
  // src/InnspelPrivate.tsx
2585
- var import_react13 = require("react");
2586
- var import_react_native11 = require("react-native");
2587
- var import_jsx_runtime11 = require("react/jsx-runtime");
3051
+ var import_react14 = require("react");
3052
+ var import_react_native12 = require("react-native");
3053
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2588
3054
  function InnspelPrivate({ children, style }) {
2589
- const ref = (0, import_react13.useRef)(null);
3055
+ const ref = (0, import_react14.useRef)(null);
2590
3056
  const kontekst = useSkjermbilde();
2591
3057
  const registrer = kontekst?.privat.register;
2592
- (0, import_react13.useEffect)(() => {
3058
+ (0, import_react14.useEffect)(() => {
2593
3059
  if (!registrer) return;
2594
3060
  return registrer(ref);
2595
3061
  }, [registrer]);
2596
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_native11.View, { ref, collapsable: false, style, testID: "innspel-privat", children });
3062
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native12.View, { ref, collapsable: false, style, testID: "innspel-privat", children });
2597
3063
  }
2598
3064
 
2599
3065
  // src/program/InnspelProgram.tsx
2600
3066
  var import_core4 = require("@innspel/core");
2601
- var import_react18 = require("react");
2602
- var import_react_native16 = require("react-native");
2603
-
2604
- // src/program/Aksept.tsx
2605
- var import_react14 = require("react");
2606
- var import_react_native12 = require("react-native");
3067
+ var import_react20 = require("react");
3068
+ var import_react_native17 = require("react-native");
2607
3069
 
2608
3070
  // src/program/periode.ts
2609
3071
  var MANEDER = [
@@ -2627,13 +3089,31 @@ function periode(opensAt, closesAt) {
2627
3089
  const sammeManed = fra.getMonth() === til.getMonth() && fra.getFullYear() === til.getFullYear();
2628
3090
  return sammeManed ? `${fra.getDate()}.\u2013${til.getDate()}. ${MANEDER[til.getMonth()]}` : `${fra.getDate()}. ${MANEDER[fra.getMonth()]} \u2013 ${til.getDate()}. ${MANEDER[til.getMonth()]}`;
2629
3091
  }
2630
- function minutterPerOppgave(tasks) {
2631
- if (tasks.length === 0) return 0;
2632
- return Math.round(tasks.reduce((sum, t2) => sum + t2.estimatedMinutes, 0) / tasks.length);
3092
+ function minutterLinje(tasks) {
3093
+ if (tasks.length === 0) return { minutter: 0, like: true };
3094
+ const forste = tasks[0].estimatedMinutes;
3095
+ const like = tasks.every((t2) => t2.estimatedMinutes === forste);
3096
+ return like ? { minutter: forste, like: true } : { minutter: tasks.reduce((sum, t2) => sum + t2.estimatedMinutes, 0), like: false };
2633
3097
  }
2634
3098
 
2635
3099
  // src/program/Aksept.tsx
2636
- var import_jsx_runtime12 = require("react/jsx-runtime");
3100
+ var import_react15 = require("react");
3101
+ var import_react_native13 = require("react-native");
3102
+ var import_jsx_runtime13 = require("react/jsx-runtime");
3103
+ function Seksjon({ tittel, children }) {
3104
+ const tema = useTema();
3105
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native13.View, { style: { gap: tema.space.sm }, children: [
3106
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3107
+ import_react_native13.Text,
3108
+ {
3109
+ accessibilityRole: "header",
3110
+ style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body, fontWeight: tema.weight.bold },
3111
+ children: tittel
3112
+ }
3113
+ ),
3114
+ children
3115
+ ] });
3116
+ }
2637
3117
  function Aksept({
2638
3118
  program,
2639
3119
  harToken,
@@ -2643,14 +3123,15 @@ function Aksept({
2643
3123
  onLukk
2644
3124
  }) {
2645
3125
  const tema = useTema();
2646
- const tall = tekst.akseptTall(
3126
+ const { minutter, like } = minutterLinje(program.tasks);
3127
+ const tall = (like ? tekst.akseptTallHver : tekst.akseptTallSum)(
2647
3128
  program.tasks.length,
2648
- minutterPerOppgave(program.tasks),
2649
- periode(program.opensAt, program.closesAt),
2650
- program.maxContacts
3129
+ minutter,
3130
+ periode(program.opensAt, program.closesAt)
2651
3131
  );
2652
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native12.Modal, { visible: true, transparent: true, animationType: "slide", onRequestClose: onLukk, accessibilityViewIsModal: true, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native12.View, { style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end" }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2653
- import_react_native12.View,
3132
+ const medVilkar = !!program.termsUrl && !program.commitmentFree;
3133
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.Modal, { visible: true, transparent: true, animationType: "slide", onRequestClose: onLukk, accessibilityViewIsModal: true, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.View, { style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end" }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3134
+ import_react_native13.View,
2654
3135
  {
2655
3136
  testID: "program-aksept",
2656
3137
  accessibilityViewIsModal: true,
@@ -2664,17 +3145,17 @@ function Aksept({
2664
3145
  minHeight: "60%"
2665
3146
  },
2666
3147
  children: [
2667
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native12.View, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, children: [
2668
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Btn, { variant: "ghost", testID: "aksept-tilbake", ikon: "arrow-back-outline", label: tekst.tilbake, onPress: onLukk }),
2669
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native12.View, {})
3148
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native13.View, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, children: [
3149
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Btn, { variant: "ghost", testID: "aksept-tilbake", ikon: "arrow-back-outline", label: tekst.tilbake, onPress: onLukk }),
3150
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.View, {})
2670
3151
  ] }),
2671
- feil ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Banner, { live: true, ikon: "warning-outline", tone: "danger", children: tekst.akseptFeil(feil) }) : null,
2672
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native12.ScrollView, { contentContainerStyle: { gap: tema.space.md }, children: [
2673
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(H, { sub: tekst.akseptHva, children: program.name }),
2674
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2675
- import_react_native12.Text,
3152
+ feil ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Banner, { live: true, ikon: "warning-outline", tone: "danger", children: tekst.akseptFeil(feil) }) : null,
3153
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native13.ScrollView, { contentContainerStyle: { gap: tema.space.lg }, children: [
3154
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(H, { testID: "aksept-tittel", sub: program.hypothesis, children: program.name }),
3155
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3156
+ import_react_native13.Text,
2676
3157
  {
2677
- accessibilityRole: "text",
3158
+ testID: "aksept-tall",
2678
3159
  style: {
2679
3160
  color: tema.color.textPrimary,
2680
3161
  fontSize: tema.font.body,
@@ -2684,79 +3165,116 @@ function Aksept({
2684
3165
  children: tall
2685
3166
  }
2686
3167
  ),
2687
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native12.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: program.hypothesis }),
2688
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Card, { children: [
2689
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(H, { children: tekst.akseptOppgaver }),
2690
- program.tasks.map((o) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native12.View, { style: { gap: tema.space.xs }, children: [
2691
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native12.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: o.title }),
2692
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Hint, { children: [
2693
- tekst.akseptOppgaveTid(o.estimatedMinutes),
2694
- o.screenHint ? ` \xB7 ${o.screenHint}` : ""
2695
- ] })
2696
- ] }, o.id))
2697
- ] }),
2698
- program.knownIssues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Card, { children: [
2699
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(H, { sub: tekst.akseptKjenteFeilUnder, children: tekst.akseptKjenteFeil(program.knownIssues.length) }),
2700
- program.knownIssues.map((k) => {
2701
- const o = knownIssueStatus[k.status] ?? knownIssueStatus.aktiv;
2702
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native12.View, { style: { gap: tema.space.xs }, children: [
2703
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native12.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: k.title }),
2704
- k.workaround ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native12.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.small, lineHeight: tema.lineHeight.small }, children: [
2705
- tekst.omvei,
2706
- " ",
2707
- k.workaround
2708
- ] }) : null,
2709
- k.fixedIn ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2710
- StatusPill,
3168
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Seksjon, { tittel: tekst.akseptOppgaver, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.View, { children: program.tasks.map((o, i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3169
+ import_react_native13.View,
3170
+ {
3171
+ style: {
3172
+ flexDirection: "row",
3173
+ alignItems: "center",
3174
+ gap: tema.space.sm,
3175
+ minHeight: tema.touch + tema.space.sm,
3176
+ paddingVertical: tema.space.sm,
3177
+ borderTopWidth: i === 0 ? 0 : tema.hairline,
3178
+ borderTopColor: tema.color.border
3179
+ },
3180
+ children: [
3181
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3182
+ import_react_native13.View,
2711
3183
  {
2712
- ikon: o.ikon,
2713
- etikett: k.status === "fikset" ? tekst.rettetI(k.fixedIn) : tekst.rettesI(k.fixedIn),
2714
- fg: o.fg,
2715
- bg: o.bg
3184
+ style: {
3185
+ width: tema.space.lg,
3186
+ height: tema.space.lg,
3187
+ borderRadius: tema.radius.pill,
3188
+ borderWidth: tema.hairline * 2,
3189
+ borderStyle: "dashed",
3190
+ borderColor: tema.color.borderStrong
3191
+ }
2716
3192
  }
2717
- ) : null
2718
- ] }, k.id);
2719
- })
2720
- ] }) : null,
2721
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Card, { children: [
2722
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(H, { sub: tekst.akseptInnsamlingTekst, children: tekst.akseptInnsamling }),
2723
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Hint, { children: tekst.kontekstAldri })
2724
- ] }),
2725
- program.termsUrl && !program.commitmentFree ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native12.View, { style: { gap: tema.space.xs }, children: [
2726
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2727
- import_react_native12.Pressable,
2728
- {
2729
- testID: "vilkar-lenke",
2730
- accessibilityRole: "link",
2731
- accessibilityLabel: tekst.akseptVilkar,
2732
- onPress: () => void import_react_native12.Linking.openURL(String(program.termsUrl)),
2733
- style: { minHeight: tema.touch, justifyContent: "center" },
2734
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native12.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
2735
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Ikon, { navn: "open-outline", farge: tema.color.textPrimary }),
2736
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2737
- import_react_native12.Text,
3193
+ ),
3194
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native13.View, { style: { flex: 1, minWidth: 0 }, children: [
3195
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3196
+ import_react_native13.Text,
2738
3197
  {
2739
- style: { color: tema.color.textPrimary, fontSize: tema.font.body, textDecorationLine: "underline" },
2740
- children: tekst.akseptVilkar
3198
+ style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body, fontWeight: tema.weight.semibold },
3199
+ children: o.title
2741
3200
  }
2742
- )
3201
+ ),
3202
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Meta, { children: tekst.oppgaveTid(o.estimatedMinutes, o.screenHint) })
2743
3203
  ] })
2744
- }
2745
- ),
2746
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Hint, { children: tekst.akseptVilkarHint })
2747
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Hint, { children: tekst.akseptIngenVilkar }),
2748
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native12.View, { style: { flexDirection: "row", alignItems: "flex-start", gap: tema.space.sm }, children: [
2749
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Ikon, { navn: "exit-outline", farge: tema.color.textPrimary }),
2750
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2751
- import_react_native12.Text,
3204
+ ]
3205
+ },
3206
+ o.id
3207
+ )) }) }),
3208
+ program.knownIssues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Seksjon, { tittel: tekst.akseptKjenteFeil, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.View, { children: program.knownIssues.map((k, i) => {
3209
+ const o = knownIssueStatus[k.status] ?? knownIssueStatus.aktiv;
3210
+ const rettet = k.status === "fikset";
3211
+ const statusOrd = rettet && k.fixedIn ? tekst.rettetI(k.fixedIn) : o.etikett;
3212
+ const tillegg = !rettet && k.fixedIn ? `\xB7 ${tekst.rettesI(k.fixedIn).toLowerCase()}` : void 0;
3213
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3214
+ import_react_native13.View,
2752
3215
  {
2753
- style: { flex: 1, color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body },
2754
- children: tekst.akseptUtgang
3216
+ style: {
3217
+ gap: tema.space.xs,
3218
+ paddingVertical: tema.space.sm,
3219
+ borderTopWidth: i === 0 ? 0 : tema.hairline,
3220
+ borderTopColor: tema.color.border
3221
+ },
3222
+ children: [
3223
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3224
+ import_react_native13.Text,
3225
+ {
3226
+ style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body, fontWeight: tema.weight.semibold },
3227
+ children: k.title
3228
+ }
3229
+ ),
3230
+ k.workaround ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Sek, { children: [
3231
+ tekst.omvei,
3232
+ " ",
3233
+ k.workaround
3234
+ ] }) : null,
3235
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native13.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.sm, flexWrap: "wrap" }, children: [
3236
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native13.View, { style: { flexDirection: "row", alignItems: "center", gap: tema.space.xs }, children: [
3237
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Ikon, { navn: o.ikon, storrelse: "minste", farge: tema.color[o.fg] }),
3238
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3239
+ import_react_native13.Text,
3240
+ {
3241
+ style: {
3242
+ color: tema.color[o.fg],
3243
+ fontSize: tema.font.small,
3244
+ lineHeight: tema.lineHeight.small,
3245
+ fontWeight: tema.weight.semibold
3246
+ },
3247
+ children: statusOrd
3248
+ }
3249
+ )
3250
+ ] }),
3251
+ tillegg ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Meta, { children: tillegg }) : null
3252
+ ] })
3253
+ ]
3254
+ },
3255
+ k.id
3256
+ );
3257
+ }) }) }) : null,
3258
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Seksjon, { tittel: tekst.akseptInnsamling, children: [
3259
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Sek, { children: tekst.akseptInnsamlingTekst }),
3260
+ medVilkar ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3261
+ import_react_native13.Pressable,
3262
+ {
3263
+ testID: "vilkar-lenke",
3264
+ accessibilityRole: "link",
3265
+ accessibilityLabel: tekst.akseptVilkar,
3266
+ onPress: () => void import_react_native13.Linking.openURL(String(program.termsUrl)),
3267
+ style: { minHeight: tema.touch, flexDirection: "row", alignItems: "center", gap: tema.space.sm },
3268
+ children: [
3269
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Ikon, { navn: "open-outline", storrelse: "minste", farge: tema.color.actionSecondaryText }),
3270
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.Text, { style: { color: tema.color.actionSecondaryText, fontSize: tema.font.body, fontWeight: tema.weight.semibold }, children: tekst.akseptVilkar })
3271
+ ]
2755
3272
  }
2756
- )
3273
+ ) : null,
3274
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Hint, { children: medVilkar ? tekst.akseptTakOgUtgangVilkar(program.maxContacts) : tekst.akseptTakOgUtgang(program.maxContacts) })
2757
3275
  ] })
2758
3276
  ] }),
2759
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3277
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2760
3278
  Btn,
2761
3279
  {
2762
3280
  testID: "bli-med",
@@ -2772,9 +3290,9 @@ function Aksept({
2772
3290
  }
2773
3291
 
2774
3292
  // src/program/HvordanGikkDet.tsx
2775
- var import_react15 = require("react");
2776
- var import_react_native13 = require("react-native");
2777
- var import_jsx_runtime13 = require("react/jsx-runtime");
3293
+ var import_react16 = require("react");
3294
+ var import_react_native14 = require("react-native");
3295
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2778
3296
  var UTFALL = [
2779
3297
  { verdi: "fungerte", ikon: "checkmark-circle-outline", etikett: tekst.utfallFungerte },
2780
3298
  { verdi: "delvis", ikon: "contrast-outline", etikett: tekst.utfallDelvis },
@@ -2786,65 +3304,114 @@ function utfallEtikett(verdi) {
2786
3304
  }
2787
3305
  function HvordanGikkDet({
2788
3306
  under,
3307
+ spoersmaal,
2789
3308
  sender,
2790
3309
  feil,
2791
3310
  onLagre,
3311
+ onMeldFeil,
2792
3312
  onLukk
2793
3313
  }) {
2794
3314
  const tema = useTema();
2795
- const [valgt, setValgt] = (0, import_react15.useState)();
2796
- const [setning, setSetning] = (0, import_react15.useState)("");
2797
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.Modal, { visible: true, transparent: true, animationType: "fade", onRequestClose: onLukk, accessibilityViewIsModal: true, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.View, { style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end", padding: tema.space.md }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2798
- import_react_native13.View,
3315
+ const [valgt, setValgt] = (0, import_react16.useState)();
3316
+ const [setning, setSetning] = (0, import_react16.useState)("");
3317
+ const tekstVerdi = () => {
3318
+ const trimmet = setning.trim();
3319
+ return trimmet.length > 0 ? trimmet : void 0;
3320
+ };
3321
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native14.Modal, { visible: true, transparent: true, animationType: "slide", onRequestClose: onLukk, accessibilityViewIsModal: true, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native14.View, { style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end" }, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3322
+ import_react_native14.View,
2799
3323
  {
2800
3324
  testID: "hvordan-gikk-det",
2801
3325
  accessibilityViewIsModal: true,
2802
3326
  style: {
2803
- backgroundColor: tema.color.surface,
2804
- borderRadius: tema.radius.lg,
2805
- borderWidth: tema.hairline,
2806
- borderColor: tema.color.borderStrong,
2807
- padding: tema.space.md,
2808
- gap: tema.space.md
3327
+ backgroundColor: tema.color.bg,
3328
+ borderTopLeftRadius: tema.radius.lg * 2,
3329
+ borderTopRightRadius: tema.radius.lg * 2,
3330
+ padding: tema.screenPadding,
3331
+ gap: tema.space.md,
3332
+ maxHeight: "92%"
2809
3333
  },
2810
3334
  children: [
2811
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Btn, { variant: "ghost", testID: "hvordan-tilbake", ikon: "arrow-back-outline", label: tekst.tilbake, onPress: onLukk }),
2812
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Hint, { children: under }),
2813
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(H, { children: tekst.hvordanGikkDet }),
2814
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.View, { testID: "utfall-gruppe", accessibilityRole: "radiogroup", accessibilityLabel: tekst.hvordanGikkDet, style: { flexDirection: "row", gap: tema.space.sm }, children: UTFALL.map((u) => {
2815
- const aktiv = valgt === u.verdi;
2816
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2817
- import_react_native13.Pressable,
2818
- {
2819
- testID: `utfall-${u.verdi}`,
2820
- accessibilityRole: "radio",
2821
- accessibilityLabel: u.etikett,
2822
- accessibilityState: { checked: aktiv },
2823
- onPress: () => setValgt(u.verdi),
2824
- style: {
2825
- flex: 1,
2826
- minHeight: tema.touch,
2827
- alignItems: "center",
2828
- justifyContent: "center",
2829
- gap: tema.space.xs,
2830
- padding: tema.space.sm,
2831
- borderRadius: tema.radius.md,
2832
- borderWidth: tema.hairline,
2833
- borderColor: aktiv ? tema.color.brand : tema.color.borderStrong,
2834
- backgroundColor: aktiv ? tema.color.brandBg : tema.color.surfaceRaised
2835
- },
2836
- children: [
2837
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Ikon, { navn: u.ikon, farge: tema.color.textPrimary }),
2838
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.small, fontWeight: aktiv ? tema.weight.semibold : tema.weight.regular }, children: u.etikett })
2839
- ]
2840
- },
2841
- u.verdi
2842
- );
2843
- }) }),
2844
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react_native13.View, { style: { gap: tema.space.xs }, children: [
2845
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_native13.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.small }, children: tekst.setningLabel }),
2846
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2847
- import_react_native13.TextInput,
3335
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native14.View, { style: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, children: [
3336
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Btn, { variant: "ghost", testID: "hvordan-tilbake", ikon: "arrow-back-outline", label: tekst.tilbake, onPress: onLukk }),
3337
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native14.View, {})
3338
+ ] }),
3339
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native14.View, { style: { gap: tema.space.xs }, children: [
3340
+ under ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Meta, { children: under }) : null,
3341
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(H, { children: spoersmaal ?? tekst.hvordanGikkDet })
3342
+ ] }),
3343
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3344
+ import_react_native14.View,
3345
+ {
3346
+ testID: "utfall-gruppe",
3347
+ accessibilityRole: "radiogroup",
3348
+ accessibilityLabel: spoersmaal ?? tekst.hvordanGikkDet,
3349
+ children: UTFALL.map((u, i) => {
3350
+ const aktiv = valgt === u.verdi;
3351
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3352
+ import_react_native14.Pressable,
3353
+ {
3354
+ testID: `utfall-${u.verdi}`,
3355
+ accessibilityRole: "radio",
3356
+ accessibilityLabel: u.etikett,
3357
+ accessibilityState: { checked: aktiv },
3358
+ onPress: () => setValgt(u.verdi),
3359
+ style: {
3360
+ flexDirection: "row",
3361
+ alignItems: "center",
3362
+ gap: tema.space.md,
3363
+ minHeight: tema.touch + tema.space.sm,
3364
+ borderTopWidth: i === 0 ? 0 : tema.hairline,
3365
+ borderTopColor: tema.color.border
3366
+ },
3367
+ children: [
3368
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3369
+ import_react_native14.View,
3370
+ {
3371
+ testID: aktiv ? `utfall-merke-${u.verdi}` : void 0,
3372
+ style: {
3373
+ width: tema.space.lg,
3374
+ height: tema.space.lg,
3375
+ borderRadius: tema.radius.pill,
3376
+ alignItems: "center",
3377
+ justifyContent: "center",
3378
+ backgroundColor: aktiv ? tema.color.brand : "transparent",
3379
+ borderWidth: tema.hairline * 2,
3380
+ borderColor: aktiv ? tema.color.brand : tema.color.borderInteractive
3381
+ },
3382
+ children: aktiv ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Ikon, { navn: "checkmark-outline", storrelse: "minste", farge: tema.color.onBrand }) : null
3383
+ }
3384
+ ),
3385
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Ikon, { navn: u.ikon, farge: tema.color.textSecondary }),
3386
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3387
+ import_react_native14.Text,
3388
+ {
3389
+ testID: `utfall-etikett-${u.verdi}`,
3390
+ style: {
3391
+ flex: 1,
3392
+ color: tema.color.textPrimary,
3393
+ fontSize: tema.font.body,
3394
+ lineHeight: tema.lineHeight.body,
3395
+ fontWeight: aktiv ? tema.weight.semibold : tema.weight.regular
3396
+ },
3397
+ children: u.etikett
3398
+ }
3399
+ )
3400
+ ]
3401
+ },
3402
+ u.verdi
3403
+ );
3404
+ })
3405
+ }
3406
+ ),
3407
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native14.View, { style: { gap: tema.space.sm }, children: [
3408
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native14.Text, { style: { color: tema.color.textSecondary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: [
3409
+ tekst.setningLabel,
3410
+ " ",
3411
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native14.Text, { style: { color: tema.color.textMuted }, children: tekst.setningValgfritt })
3412
+ ] }),
3413
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3414
+ import_react_native14.TextInput,
2848
3415
  {
2849
3416
  testID: "hvordan-setning",
2850
3417
  accessibilityLabel: tekst.setningLabel,
@@ -2852,9 +3419,7 @@ function HvordanGikkDet({
2852
3419
  onChangeText: setSetning,
2853
3420
  maxLength: SETNING_MAKS,
2854
3421
  multiline: true,
2855
- numberOfLines: 3,
2856
- placeholder: tekst.setningPlaceholder,
2857
- placeholderTextColor: tema.color.textMuted,
3422
+ numberOfLines: 2,
2858
3423
  style: {
2859
3424
  backgroundColor: tema.color.surfaceRaised,
2860
3425
  borderWidth: tema.hairline,
@@ -2864,24 +3429,33 @@ function HvordanGikkDet({
2864
3429
  color: tema.color.textPrimary,
2865
3430
  fontSize: tema.font.body,
2866
3431
  lineHeight: tema.lineHeight.body,
2867
- minHeight: tema.touch * 2,
3432
+ minHeight: tema.touch * 1.5,
2868
3433
  textAlignVertical: "top"
2869
3434
  }
2870
3435
  }
2871
3436
  )
2872
3437
  ] }),
2873
- feil ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Banner, { live: true, ikon: "warning-outline", tone: "danger", children: tekst.svarFeil(feil) }) : null,
2874
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3438
+ valgt === "ikke" && onMeldFeil ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3439
+ Tekstknapp,
3440
+ {
3441
+ testID: "meld-feil",
3442
+ ikon: "bug-outline",
3443
+ label: tekst.meldFeil,
3444
+ disabled: sender,
3445
+ onPress: () => onMeldFeil("ikke", tekstVerdi())
3446
+ }
3447
+ ) : null,
3448
+ feil ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Banner, { live: true, ikon: "warning-outline", tone: "danger", children: tekst.svarFeil(feil) }) : null,
3449
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2875
3450
  Btn,
2876
3451
  {
2877
3452
  testID: "hvordan-lagre",
2878
3453
  label: tekst.lagre,
2879
- hint: tekst.lagreHint,
2880
3454
  disabled: valgt === void 0 || sender,
3455
+ busy: sender,
2881
3456
  onPress: () => {
2882
3457
  if (valgt === void 0) return;
2883
- const trimmet = setning.trim();
2884
- onLagre(valgt, trimmet.length > 0 ? trimmet : void 0);
3458
+ onLagre(valgt, tekstVerdi());
2885
3459
  }
2886
3460
  }
2887
3461
  )
@@ -2891,16 +3465,14 @@ function HvordanGikkDet({
2891
3465
  }
2892
3466
 
2893
3467
  // src/program/Oppfolging.tsx
2894
- var import_react16 = require("react");
2895
- var import_react_native14 = require("react-native");
2896
- var import_jsx_runtime14 = require("react/jsx-runtime");
3468
+ var import_react17 = require("react");
3469
+ var import_react_native15 = require("react-native");
3470
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2897
3471
  function tarSvar(kind) {
2898
3472
  return kind === "hvordan_gikk_det" || kind === "sjekkpunkt";
2899
3473
  }
2900
3474
  function Oppfolging({
2901
3475
  oppfolging,
2902
- kontaktNr,
2903
- maksKontakter,
2904
3476
  onSenere,
2905
3477
  onSvar,
2906
3478
  onAapneOppgavene,
@@ -2908,45 +3480,28 @@ function Oppfolging({
2908
3480
  }) {
2909
3481
  const tema = useTema();
2910
3482
  const art = tarSvar(oppfolging.kind) ? "spoersmaal" : oppfolging.kind === "tilbud_om_utgang" ? "utgang" : "paaminnelse";
2911
- const ikon = art === "spoersmaal" ? "flask-outline" : art === "utgang" ? "exit-outline" : "calendar-outline";
2912
- const hint = art === "spoersmaal" ? tekst.oppfolgingKontakt(kontaktNr, maksKontakter) : art === "utgang" ? tekst.oppfolgingUtgangHint(kontaktNr, maksKontakter) : tekst.oppfolgingPaaminnelseHint(kontaktNr, maksKontakter);
2913
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2914
- import_react_native14.View,
3483
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
3484
+ import_react_native15.View,
2915
3485
  {
2916
3486
  testID: `oppfolging-${oppfolging.id}`,
2917
3487
  accessibilityLabel: tekst.oppfolgingRegion,
2918
3488
  style: {
2919
3489
  backgroundColor: tema.color.brandBg,
2920
- borderWidth: tema.hairline,
2921
- borderColor: tema.color.brand,
2922
3490
  borderRadius: tema.radius.lg,
2923
3491
  padding: tema.space.md,
2924
- gap: tema.space.sm
3492
+ gap: tema.space.md
2925
3493
  },
2926
3494
  children: [
2927
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native14.View, { style: { flexDirection: "row", gap: tema.space.sm, alignItems: "flex-start" }, children: [
2928
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Ikon, { navn: ikon, farge: tema.color.textPrimary }),
2929
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native14.View, { style: { flex: 1, gap: tema.space.xs }, children: [
2930
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native14.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: oppfolging.question }),
2931
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Hint, { children: hint })
2932
- ] })
3495
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native15.View, { style: { flexDirection: "row", gap: tema.space.sm, alignItems: "flex-start" }, children: [
3496
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native15.View, { style: { paddingTop: tema.space.xs }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Ikon, { navn: "flask-outline", farge: tema.color.brand }) }),
3497
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native15.View, { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(H, { nivaa: 3, meta: tekst.oppfolgingKost, children: oppfolging.question }) })
2933
3498
  ] }),
2934
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native14.View, { style: { flexDirection: "row", gap: tema.space.sm }, children: art === "utgang" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
2935
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Btn, { grow: true, variant: "secondary", testID: `bli-vaerende-${oppfolging.id}`, label: tekst.bliVaerende, onPress: onSenere }),
2936
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2937
- Btn,
2938
- {
2939
- grow: true,
2940
- variant: "danger",
2941
- testID: `gaa-ut-${oppfolging.id}`,
2942
- ikon: "exit-outline",
2943
- label: tekst.gaaUtBekreft,
2944
- onPress: onGaaUt
2945
- }
2946
- )
2947
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
2948
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Btn, { grow: true, variant: "secondary", testID: `senere-${oppfolging.id}`, label: tekst.senere, onPress: onSenere }),
2949
- art === "spoersmaal" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Btn, { grow: true, testID: `svar-naa-${oppfolging.id}`, label: tekst.svarNaa, onPress: onSvar }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Btn, { grow: true, testID: `aapne-oppgavene-${oppfolging.id}`, label: tekst.aapneOppgavene, onPress: onAapneOppgavene })
3499
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native15.View, { style: { flexDirection: "row", gap: tema.space.sm }, children: art === "utgang" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
3500
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Btn, { grow: true, variant: "secondary", testID: `bli-vaerende-${oppfolging.id}`, label: tekst.bliVaerende, onPress: onSenere }),
3501
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Btn, { grow: true, variant: "secondary", testID: `gaa-ut-${oppfolging.id}`, ikon: "exit-outline", label: tekst.gaaUtBekreft, onPress: onGaaUt })
3502
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
3503
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Btn, { grow: true, variant: "secondary", testID: `senere-${oppfolging.id}`, label: tekst.senere, onPress: onSenere }),
3504
+ art === "spoersmaal" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Btn, { grow: true, testID: `svar-naa-${oppfolging.id}`, label: tekst.svarNaa, onPress: onSvar }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Btn, { grow: true, testID: `aapne-oppgavene-${oppfolging.id}`, label: tekst.aapneOppgavene, onPress: onAapneOppgavene })
2950
3505
  ] }) })
2951
3506
  ]
2952
3507
  }
@@ -2954,53 +3509,74 @@ function Oppfolging({
2954
3509
  }
2955
3510
 
2956
3511
  // src/program/Oppgaver.tsx
2957
- var import_react17 = require("react");
2958
- var import_react_native15 = require("react-native");
2959
- var import_jsx_runtime15 = require("react/jsx-runtime");
3512
+ var import_react18 = require("react");
3513
+ var import_react_native16 = require("react-native");
3514
+ var import_jsx_runtime16 = require("react/jsx-runtime");
2960
3515
  function Oppgaver({
2961
3516
  tasks,
2962
3517
  completions,
3518
+ over,
2963
3519
  onGjort
2964
3520
  }) {
2965
3521
  const tema = useTema();
2966
3522
  const ferdig = new Map(completions.map((c) => [c.taskId, c]));
2967
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native15.View, { testID: "oppgaver", accessibilityLabel: tekst.oppgaverTittel, style: { gap: tema.space.sm }, children: [...tasks].sort((a, b) => a.order - b.order).map((o) => {
3523
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native16.View, { testID: "oppgaver", accessibilityLabel: tekst.oppgaverTittel, children: [...tasks].sort((a, b) => a.order - b.order).map((o, i) => {
2968
3524
  const c = ferdig.get(o.id);
2969
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2970
- import_react_native15.View,
3525
+ const meta = c ? tekst.oppgaveGjortMeta(formaterFrist(c.at), utfallEtikett(c.outcome)) : tekst.oppgaveTid(o.estimatedMinutes, o.screenHint);
3526
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3527
+ import_react_native16.View,
2971
3528
  {
2972
3529
  testID: `oppgave-${o.id}`,
3530
+ accessibilityLabel: tekst.oppgaveRadA11y(i + 1, o.title, c ? meta : tekst.oppgaveIkkeGjort),
2973
3531
  style: {
2974
3532
  flexDirection: "row",
2975
3533
  alignItems: "center",
2976
3534
  gap: tema.space.sm,
2977
- paddingVertical: tema.space.xs,
2978
- borderBottomWidth: tema.hairline,
2979
- borderBottomColor: tema.color.border
3535
+ minHeight: tema.touch + tema.space.sm,
3536
+ paddingVertical: tema.space.sm,
3537
+ borderTopWidth: i === 0 ? 0 : tema.hairline,
3538
+ borderTopColor: tema.color.border
2980
3539
  },
2981
3540
  children: [
2982
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react_native15.View, { style: { flex: 1, gap: tema.space.xs }, children: [
2983
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native15.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: o.title }),
2984
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Hint, { children: [
2985
- c ? tekst.oppgaveGjortMed(utfallEtikett(c.outcome)) : `${tekst.oppgaveIkkeBegynt} \xB7 ${tekst.akseptOppgaveTid(o.estimatedMinutes)}`,
2986
- c?.text ? ` \xB7 \xAB${c.text}\xBB` : ""
2987
- ] })
3541
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3542
+ import_react_native16.View,
3543
+ {
3544
+ style: {
3545
+ width: tema.space.lg,
3546
+ height: tema.space.lg,
3547
+ borderRadius: tema.radius.pill,
3548
+ alignItems: "center",
3549
+ justifyContent: "center",
3550
+ backgroundColor: c ? tema.color.success : "transparent",
3551
+ borderWidth: c ? 0 : tema.hairline * 2,
3552
+ borderStyle: "dashed",
3553
+ borderColor: tema.color.borderStrong
3554
+ },
3555
+ children: c ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Ikon, { navn: "checkmark-outline", storrelse: "minste", farge: tema.color.bg }) : null
3556
+ }
3557
+ ),
3558
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native16.View, { style: { flex: 1, minWidth: 0 }, children: [
3559
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3560
+ import_react_native16.Text,
3561
+ {
3562
+ testID: `oppgave-tittel-${o.id}`,
3563
+ style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body, fontWeight: tema.weight.semibold },
3564
+ children: o.title
3565
+ }
3566
+ ),
3567
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Meta, { testID: `oppgave-meta-${o.id}`, children: meta }),
3568
+ c?.text ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Sek, { testID: `oppgave-setning-${o.id}`, children: c.text }) : null
2988
3569
  ] }),
2989
- c ? (
2990
- // Merket er den eneste flaten der ikonet står alene, så etiketten
2991
- // ligger på containeren: skjermleseren hører utfallet, ikke «hake».
2992
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react_native15.View, { accessibilityLabel: tekst.oppgaveGjortMed(utfallEtikett(c.outcome)), accessible: true, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Ikon, { navn: "checkmark-circle-outline", farge: tema.color.success }) })
2993
- ) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3570
+ !c && !over ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2994
3571
  Btn,
2995
3572
  {
2996
- variant: "secondary",
3573
+ variant: "tonet",
2997
3574
  testID: `gjort-${o.id}`,
2998
- ikon: "checkmark-circle-outline",
2999
3575
  label: tekst.oppgaveGjort,
3000
3576
  accessibilityLabel: tekst.oppgaveGjortLabel(o.title),
3001
3577
  onPress: () => onGjort(o)
3002
3578
  }
3003
- )
3579
+ ) : null
3004
3580
  ]
3005
3581
  },
3006
3582
  o.id
@@ -3008,8 +3584,33 @@ function Oppgaver({
3008
3584
  }) });
3009
3585
  }
3010
3586
 
3587
+ // src/program/ProgramSpor.tsx
3588
+ var import_react19 = require("react");
3589
+ var import_jsx_runtime17 = require("react/jsx-runtime");
3590
+ function programErOver(deltakelse, program, naa = /* @__PURE__ */ new Date()) {
3591
+ return deltakelse.status === "fullfoert" || new Date(program.closesAt).getTime() < naa.getTime();
3592
+ }
3593
+ function programledd(deltakelse, program, naa = /* @__PURE__ */ new Date()) {
3594
+ const over = programErOver(deltakelse, program, naa);
3595
+ const gjort = deltakelse.completions.length;
3596
+ const av = program.tasks.length;
3597
+ const alt = av > 0 && gjort >= av;
3598
+ return [
3599
+ { nokkel: "ble-med", etikett: tekst.programBleMed, tilstand: "gjort", detalj: formaterFrist(deltakelse.joinedAt) },
3600
+ {
3601
+ nokkel: "gjort",
3602
+ etikett: tekst.programGjort(gjort, av),
3603
+ ...over || alt ? { tilstand: "gjort" } : { tilstand: "naa", ikon: "flask-outline", detalj: tekst.programNaarDetPasser }
3604
+ },
3605
+ over ? { nokkel: "over", etikett: tekst.programOver, tilstand: "gjort", detalj: formaterFrist(program.closesAt) } : { nokkel: "over", etikett: tekst.programOver, tilstand: "kommer", tall: formaterKortFrist(program.closesAt) }
3606
+ ];
3607
+ }
3608
+ function ProgramSpor({ deltakelse, program }) {
3609
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Sporingslinje, { ledd: programledd(deltakelse, program), testID: "program-spor", etikett: tekst.programSporEtikett });
3610
+ }
3611
+
3011
3612
  // src/program/InnspelProgram.tsx
3012
- var import_jsx_runtime16 = require("react/jsx-runtime");
3613
+ var import_jsx_runtime18 = require("react/jsx-runtime");
3013
3614
  function InnspelProgram({
3014
3615
  invitationToken,
3015
3616
  onEndring,
@@ -3017,20 +3618,19 @@ function InnspelProgram({
3017
3618
  }) {
3018
3619
  const { client } = useInnspel();
3019
3620
  const tema = useTema();
3020
- const [mine, setMine] = (0, import_react18.useState)();
3021
- const [deltakelse, setDeltakelse] = (0, import_react18.useState)();
3022
- const [viserAksept, setViserAksept] = (0, import_react18.useState)(false);
3023
- const [viserGaaUt, setViserGaaUt] = (0, import_react18.useState)(false);
3024
- const [avvist, setAvvist] = (0, import_react18.useState)(false);
3025
- const [sender, setSender] = (0, import_react18.useState)(false);
3026
- const [feil, setFeil] = (0, import_react18.useState)();
3027
- const [dialog, setDialog] = (0, import_react18.useState)();
3028
- const [svarFeil, setSvarFeil] = (0, import_react18.useState)();
3029
- const [lagtBort, setLagtBort] = (0, import_react18.useState)(/* @__PURE__ */ new Set());
3030
- const [meldFeilFor, setMeldFeilFor] = (0, import_react18.useState)();
3031
- const leggBort = (0, import_react18.useCallback)((id) => setLagtBort((s) => /* @__PURE__ */ new Set([...s, id])), []);
3032
- const lagreSvar = (0, import_react18.useCallback)(
3033
- async (outcome, text) => {
3621
+ const [mine, setMine] = (0, import_react20.useState)();
3622
+ const [deltakelse, setDeltakelse] = (0, import_react20.useState)();
3623
+ const [viserAksept, setViserAksept] = (0, import_react20.useState)(false);
3624
+ const [viserGaaUt, setViserGaaUt] = (0, import_react20.useState)(false);
3625
+ const [avvist, setAvvist] = (0, import_react20.useState)(false);
3626
+ const [sender, setSender] = (0, import_react20.useState)(false);
3627
+ const [feil, setFeil] = (0, import_react20.useState)();
3628
+ const [dialog, setDialog] = (0, import_react20.useState)();
3629
+ const [svarFeil, setSvarFeil] = (0, import_react20.useState)();
3630
+ const [lagtBort, setLagtBort] = (0, import_react20.useState)(/* @__PURE__ */ new Set());
3631
+ const leggBort = (0, import_react20.useCallback)((id) => setLagtBort((s) => /* @__PURE__ */ new Set([...s, id])), []);
3632
+ const lagreSvar = (0, import_react20.useCallback)(
3633
+ async (outcome, text, meldEtterpaa = false) => {
3034
3634
  if (!dialog || !deltakelse) return;
3035
3635
  setSender(true);
3036
3636
  setSvarFeil(void 0);
@@ -3038,7 +3638,7 @@ function InnspelProgram({
3038
3638
  if (dialog.type === "oppgave") {
3039
3639
  const ny = await client.programs.completeTask(dialog.task.id, { outcome, ...text ? { text } : {} });
3040
3640
  setDeltakelse({ ...deltakelse, completions: [...deltakelse.completions, ny] });
3041
- if (outcome === "ikke" && onMeldFeil) setMeldFeilFor(dialog.task);
3641
+ if (meldEtterpaa && onMeldFeil) onMeldFeil(dialog.task);
3042
3642
  } else {
3043
3643
  await client.programs.respond(dialog.oppfolging.id, { outcome, ...text ? { text } : {} });
3044
3644
  setMine((m) => m ? { ...m, pendingFollowUps: m.pendingFollowUps.filter((f) => f.id !== dialog.oppfolging.id) } : m);
@@ -3052,7 +3652,7 @@ function InnspelProgram({
3052
3652
  },
3053
3653
  [client, deltakelse, dialog, onMeldFeil]
3054
3654
  );
3055
- (0, import_react18.useEffect)(() => {
3655
+ (0, import_react20.useEffect)(() => {
3056
3656
  if (client.isAnonymous) return;
3057
3657
  let levende = true;
3058
3658
  void client.programs.list().then((svar) => {
@@ -3064,7 +3664,7 @@ function InnspelProgram({
3064
3664
  levende = false;
3065
3665
  };
3066
3666
  }, [client]);
3067
- const bliMed = (0, import_react18.useCallback)(async () => {
3667
+ const bliMed = (0, import_react20.useCallback)(async () => {
3068
3668
  if (!invitationToken) return;
3069
3669
  setSender(true);
3070
3670
  setFeil(void 0);
@@ -3079,7 +3679,7 @@ function InnspelProgram({
3079
3679
  setSender(false);
3080
3680
  }
3081
3681
  }, [client, invitationToken, onEndring]);
3082
- const gaaUt = (0, import_react18.useCallback)(async () => {
3682
+ const gaaUt = (0, import_react20.useCallback)(async () => {
3083
3683
  if (!deltakelse) return;
3084
3684
  setSender(true);
3085
3685
  try {
@@ -3098,14 +3698,12 @@ function InnspelProgram({
3098
3698
  if (!program) return null;
3099
3699
  if (deltakelse) {
3100
3700
  const kort = (mine?.pendingFollowUps ?? []).filter((f) => f.programId === program.id && !lagtBort.has(f.id)).sort((a, b) => a.emittedAt.localeCompare(b.emittedAt));
3101
- const forsteKontaktNr = Math.max(1, deltakelse.contactsSent - kort.length + 1);
3102
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native16.View, { testID: "program-deltakelse", accessibilityLabel: tekst.deltakelseRegion, style: { gap: tema.space.sm }, children: [
3103
- kort.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3701
+ const over = programErOver(deltakelse, program);
3702
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native17.View, { testID: "program-deltakelse", accessibilityLabel: tekst.deltakelseRegion, style: { gap: tema.space.md }, children: [
3703
+ kort.map((f) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3104
3704
  Oppfolging,
3105
3705
  {
3106
3706
  oppfolging: f,
3107
- kontaktNr: forsteKontaktNr + i,
3108
- maksKontakter: program.maxContacts,
3109
3707
  onSenere: () => leggBort(f.id),
3110
3708
  onSvar: () => {
3111
3709
  setSvarFeil(void 0);
@@ -3116,50 +3714,37 @@ function InnspelProgram({
3116
3714
  },
3117
3715
  f.id
3118
3716
  )),
3119
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Card, { children: [
3120
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(H, { sub: tekst.deltakelsePeriode(periode(program.opensAt, program.closesAt), deltakelse.contactsSent, program.maxContacts), children: program.name }),
3121
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3717
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Card, { style: { gap: tema.space.md }, children: [
3718
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(H, { children: program.name }),
3719
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ProgramSpor, { deltakelse, program }),
3720
+ feil ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Banner, { live: true, ikon: "warning-outline", tone: "warning", children: feil }) : null,
3721
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3122
3722
  Oppgaver,
3123
3723
  {
3124
3724
  tasks: program.tasks,
3125
3725
  completions: deltakelse.completions,
3726
+ over,
3126
3727
  onGjort: (task) => {
3127
3728
  setSvarFeil(void 0);
3128
3729
  setDialog({ type: "oppgave", task });
3129
3730
  }
3130
3731
  }
3131
3732
  ),
3132
- meldFeilFor && onMeldFeil ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native16.View, { style: { gap: tema.space.xs }, children: [
3133
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Hint, { children: tekst.meldFeilHint }),
3134
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3135
- Btn,
3136
- {
3137
- variant: "secondary",
3138
- testID: "meld-feil",
3139
- ikon: "bug-outline",
3140
- label: tekst.meldFeil,
3141
- onPress: () => {
3142
- const task = meldFeilFor;
3143
- setMeldFeilFor(void 0);
3144
- onMeldFeil(task);
3145
- }
3146
- }
3147
- )
3148
- ] }) : null,
3149
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Btn, { variant: "ghost", testID: "gaa-ut", ikon: "exit-outline", label: tekst.gaaUt, onPress: () => setViserGaaUt(true) })
3733
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Tekstknapp, { noytral: true, testID: "gaa-ut", ikon: "exit-outline", label: tekst.gaaUt, onPress: () => setViserGaaUt(true) })
3150
3734
  ] }),
3151
- dialog ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3735
+ dialog ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3152
3736
  HvordanGikkDet,
3153
3737
  {
3154
- under: dialog.type === "oppgave" ? dialog.task.title : dialog.oppfolging.question,
3738
+ ...dialog.type === "oppgave" ? { under: dialog.task.title } : { spoersmaal: dialog.oppfolging.question },
3155
3739
  sender,
3156
3740
  ...svarFeil ? { feil: svarFeil } : {},
3741
+ ...dialog.type === "oppgave" && onMeldFeil ? { onMeldFeil: (outcome, text) => void lagreSvar(outcome, text, true) } : {},
3157
3742
  onLagre: (outcome, text) => void lagreSvar(outcome, text),
3158
3743
  onLukk: () => setDialog(void 0)
3159
3744
  }
3160
3745
  ) : null,
3161
- viserGaaUt ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native16.Modal, { visible: true, transparent: true, animationType: "fade", onRequestClose: () => setViserGaaUt(false), accessibilityViewIsModal: true, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native16.View, { style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end", padding: tema.space.md }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3162
- import_react_native16.View,
3746
+ viserGaaUt ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native17.Modal, { visible: true, transparent: true, animationType: "fade", onRequestClose: () => setViserGaaUt(false), accessibilityViewIsModal: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native17.View, { style: { flex: 1, backgroundColor: tema.color.scrim, justifyContent: "flex-end", padding: tema.space.md }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
3747
+ import_react_native17.View,
3163
3748
  {
3164
3749
  testID: "gaa-ut-dialog",
3165
3750
  accessibilityViewIsModal: true,
@@ -3172,11 +3757,11 @@ function InnspelProgram({
3172
3757
  gap: tema.space.md
3173
3758
  },
3174
3759
  children: [
3175
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(H, { children: tekst.gaaUtTittel }),
3176
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native16.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: tekst.gaaUtTekst(program.name) }),
3177
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native16.View, { style: { flexDirection: "row", gap: tema.space.sm }, children: [
3178
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Btn, { grow: true, variant: "secondary", testID: "bli-vaerende", label: tekst.bliVaerende, onPress: () => setViserGaaUt(false) }),
3179
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3760
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(H, { nivaa: 3, children: tekst.gaaUtTittel }),
3761
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Brodtekst, { children: tekst.gaaUtTekst(program.name) }),
3762
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native17.View, { style: { flexDirection: "row", gap: tema.space.sm }, children: [
3763
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Btn, { grow: true, variant: "secondary", testID: "bli-vaerende", label: tekst.bliVaerende, onPress: () => setViserGaaUt(false) }),
3764
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3180
3765
  Btn,
3181
3766
  {
3182
3767
  grow: true,
@@ -3195,45 +3780,40 @@ function InnspelProgram({
3195
3780
  ] });
3196
3781
  }
3197
3782
  if (!invitasjon || avvist) return null;
3198
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3199
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3200
- import_react_native16.View,
3783
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
3784
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
3785
+ import_react_native17.View,
3201
3786
  {
3202
3787
  testID: "program-banner",
3203
3788
  accessibilityLabel: tekst.invitasjonRegion,
3204
3789
  style: {
3205
3790
  backgroundColor: tema.color.brandBg,
3206
3791
  borderRadius: tema.radius.lg,
3207
- borderWidth: tema.hairline,
3208
- borderColor: tema.color.brand,
3209
3792
  padding: tema.space.md,
3210
- gap: tema.space.sm
3793
+ gap: tema.space.md
3211
3794
  },
3212
3795
  children: [
3213
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native16.View, { style: { flexDirection: "row", gap: tema.space.sm, alignItems: "flex-start" }, children: [
3214
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Ikon, { navn: "flask-outline", farge: tema.color.textPrimary }),
3215
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native16.View, { style: { flex: 1, gap: tema.space.xs }, children: [
3216
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native16.Text, { style: { color: tema.color.textPrimary, fontSize: tema.font.body, lineHeight: tema.lineHeight.body }, children: tekst.invitasjonHva(program.name) }),
3217
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Hint, { children: tekst.invitasjonKontakter(program.maxContacts) })
3218
- ] }),
3219
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3220
- import_react_native16.Pressable,
3796
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_react_native17.View, { style: { flexDirection: "row", gap: tema.space.sm, alignItems: "flex-start" }, children: [
3797
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native17.View, { style: { paddingTop: tema.space.xs }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Ikon, { navn: "flask-outline", farge: tema.color.brand }) }),
3798
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native17.View, { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(H, { nivaa: 3, meta: tekst.invitasjonMeta(program.tasks.length, periode(program.opensAt, program.closesAt)), children: tekst.invitasjonHva(program.name) }) }),
3799
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3800
+ import_react_native17.Pressable,
3221
3801
  {
3222
3802
  testID: "avvis-invitasjon",
3223
3803
  accessibilityRole: "button",
3224
3804
  accessibilityLabel: tekst.avvisInvitasjon,
3225
3805
  onPress: () => setAvvist(true),
3226
3806
  style: { minWidth: tema.touch, minHeight: tema.touch, alignItems: "center", justifyContent: "center" },
3227
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Ikon, { navn: "close-outline", farge: tema.color.textSecondary })
3807
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Ikon, { navn: "close-outline", farge: tema.color.textSecondary })
3228
3808
  }
3229
3809
  )
3230
3810
  ] }),
3231
- feil && !viserAksept ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Banner, { live: true, ikon: "warning-outline", tone: "danger", children: tekst.akseptFeil(feil) }) : null,
3232
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Btn, { variant: "secondary", testID: "les-mer", label: tekst.lesMer, onPress: () => setViserAksept(true) })
3811
+ feil && !viserAksept ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Banner, { live: true, ikon: "warning-outline", tone: "danger", children: tekst.akseptFeil(feil) }) : null,
3812
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Btn, { testID: "les-mer", label: tekst.lesMer, onPress: () => setViserAksept(true) })
3233
3813
  ]
3234
3814
  }
3235
3815
  ),
3236
- viserAksept ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3816
+ viserAksept ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3237
3817
  Aksept,
3238
3818
  {
3239
3819
  program,