@innspel/react-native 0.10.1 → 0.11.1

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