# Implementeringsplan: "Se kvitto"-Modal för Kvittoimporten **Mål**: MVP-vägen för split-view UX – lägg till modal som visar OCR-text från parsade kvittoraderna. **Scope**: 2-3 timmar **Status**: Planering --- ## 1. Ändringar i `receipt_import_tab.dart` ### 1.1 Lägg till knapp "Se kvitto" i header-raden (rad ~745-752) **Plats**: Höger om "Välj alla/Avmarkera alla"-knappen ```dart // Innan: Row med bara "Välj alla"-knapp Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('${items.length} rader — tryck för att redigera', style: theme.textTheme.titleSmall), TextButton(...), // "Välj alla/Avmarkera alla" ], ) // Efter: Lägg till "Se kvitto"-knapp Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('${items.length} rader — tryck för att redigera', style: theme.textTheme.titleSmall), Row( children: [ TextButton.icon( onPressed: items.isEmpty ? null : () => _showReceiptPreview(context, items), icon: const Icon(Icons.description_outlined), label: const Text('Se kvitto'), ), const SizedBox(width: 8), TextButton( onPressed: () => setState(...), // Befintlig "Välj alla" child: Text(...), ), ], ), ], ) ``` ### 1.2 Implementera `_showReceiptPreview`-metod Lägg till denna metod i `_ReceiptImportTabState`: ```dart Future _showReceiptPreview(BuildContext context, List items) async { if (!context.mounted) return; await showDialog( context: context, builder: (ctx) => _ReceiptPreviewDialog(items: items), ); } ``` --- ## 2. Ny widget: `_ReceiptPreviewDialog` Lägg till denna widget **i samma fil** (`receipt_import_tab.dart`), efter `_ReceiptImportResultRow`-klassen: ```dart class _ReceiptPreviewDialog extends StatelessWidget { final List items; const _ReceiptPreviewDialog({required this.items}); @override Widget build(BuildContext context) { final theme = Theme.of(context); return AlertDialog( title: const Text('Kvittotexten i sin helhet'), content: SizedBox( width: 600, // Responsiv bredd på desktop child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Här visas all OCR-parsad text från kvittot. En rad per artikel:', style: theme.textTheme.bodySmall?.copyWith( color: theme.colorScheme.onSurfaceVariant, ), ), const SizedBox(height: 12), Container( decoration: BoxDecoration( color: theme.colorScheme.surfaceContainerLowest, border: Border.all(color: theme.colorScheme.outlineVariant), borderRadius: BorderRadius.circular(8), ), padding: const EdgeInsets.all(12), child: SelectableText.rich( TextSpan( children: items.isEmpty ? [TextSpan(text: '(Inga rader)', style: theme.textTheme.bodySmall)] : items .asMap() .entries .map((entry) { final item = entry.value; final lineNumber = entry.key + 1; final lineText = _formatReceiptLine(item); return TextSpan( children: [ TextSpan( text: '$lineNumber. ', style: theme.textTheme.labelSmall?.copyWith( color: theme.colorScheme.outlineVariant, ), ), TextSpan( text: lineText, style: theme.textTheme.bodySmall?.copyWith( fontFamily: 'monospace', ), ), const TextSpan(text: '\n'), ], ); }) .toList(), ), style: theme.textTheme.bodySmall, ), ), ], ), ), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Stäng'), ), ], ); } String _formatReceiptLine(ParsedReceiptItem item) { final parts = []; if (item.quantity != null) { parts.add('${item.quantity}'); } if (item.unit != null) { parts.add(item.unit!); } parts.add(item.rawName); if (item.price != null) { parts.add('— ${item.price} kr'); } return parts.join(' '); } } ``` --- ## 3. Implementeringssteg (steg-för-steg) 1. **Läs receipt_import_tab.dart** och identifiera raden med "Välj alla/Avmarkera alla"-knappen 2. **Refaktorera Row**: Lägg "Se kvitto"-knapp bredvid befintliga knapp 3. **Lägg till `_showReceiptPreview()`-metod** i `_ReceiptImportTabState` 4. **Implementera `_ReceiptPreviewDialog`-widget** på slutet av filen 5. **Testa**: - Ladda ett kvitto - Klicka "Se kvitto"-knappen - Verifiera att texten är lesbar och formaterad - Testa responsive bredd (dialog behöver minska på mobil) --- ## 4. Responsiv förbättring (optional) Om dialogen behöver anpassas för mobil: ```dart // I _ReceiptPreviewDialog.build(): final isWide = MediaQuery.of(context).size.width > 600; return Dialog( insetPadding: const EdgeInsets.all(16), child: SizedBox( width: isWide ? 600 : double.maxFinite, // Full bredd på mobil // ... ), ); ``` --- ## 5. Långsiktiga förbättringar (Phase 2) Se `next_steps_flutter.md` för split-view roadmap: - Horisontell split-view på desktop - Scroll-synkronisering - Tab-fallback på mobil - AI-guiding labels --- ## Ärendemal **Titel**: "Se kvitto"-modal för kvittoimporten **Branch**: `feat/receipt-preview-modal` **Labels**: `enhancement`, `import-ux`, `phase-1-mvp` **Estimate**: 2-3h ## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR. ## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR. ## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR. ## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR. ## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR. ## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR. ## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR. ## 2026-05-10: Admin-inventarie (CRUD, merge, filter, sortering, preview, säkerhet), user-scope, IDOR-skydd, säkerhetshärdning, optimeringar och utökad testtäckning är nu genomförda och dokumenterade i README, TEKNISK_BESKRIVNING, SÄKERHETSHÄRDNINGSPLAN och SESSIONLOGGAR.