feat: add receipt import session management with file handling and item editing support

This commit is contained in:
Nils-Johan Gynther
2026-05-01 08:57:34 +02:00
parent f983458ff0
commit 5c263a14df
3 changed files with 212 additions and 54 deletions
@@ -0,0 +1,95 @@
import 'dart:typed_data';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../domain/parsed_receipt_item.dart';
// ── Destination-enum ──────────────────────────────────────────────────────────
enum ImportDestination { inventory, pantry }
// ── Per-rad redigeringstillstånd ──────────────────────────────────────────────
class ItemEdit {
final int? productId;
final String? productName;
final double? quantity;
final String? unit;
final ImportDestination destination;
const ItemEdit({
this.productId,
this.productName,
this.quantity,
this.unit,
this.destination = ImportDestination.inventory,
});
}
// ── Session-state ─────────────────────────────────────────────────────────────
class ReceiptImportSession {
final Uint8List? fileBytes;
final String? fileExtension;
final List<ParsedReceiptItem>? items; // null = ej parsad än
final Map<int, ItemEdit> edits;
final Map<int, bool> selected;
const ReceiptImportSession({
this.fileBytes,
this.fileExtension,
this.items,
this.edits = const {},
this.selected = const {},
});
ReceiptImportSession copyWith({
Uint8List? fileBytes,
String? fileExtension,
List<ParsedReceiptItem>? items,
Map<int, ItemEdit>? edits,
Map<int, bool>? selected,
}) =>
ReceiptImportSession(
fileBytes: fileBytes ?? this.fileBytes,
fileExtension: fileExtension ?? this.fileExtension,
items: items ?? this.items,
edits: edits ?? this.edits,
selected: selected ?? this.selected,
);
}
// ── Notifier ──────────────────────────────────────────────────────────────────
class ReceiptImportSessionNotifier
extends Notifier<ReceiptImportSession?> {
@override
ReceiptImportSession? build() => null;
/// Ny fil vald — återställer items/edits/selected, behåller ingenting gammalt.
void setFile(Uint8List bytes, String extension) {
state = ReceiptImportSession(fileBytes: bytes, fileExtension: extension);
}
void setItems(List<ParsedReceiptItem> items) {
// Bevara filinformationen när items sätts
state = (state ?? const ReceiptImportSession()).copyWith(items: items);
}
void setEdit(int index, ItemEdit edit) {
if (state == null) return;
final edits = Map<int, ItemEdit>.from(state!.edits)..[index] = edit;
state = state!.copyWith(edits: edits);
}
void setSelected(int index, bool value) {
if (state == null) return;
final selected = Map<int, bool>.from(state!.selected)..[index] = value;
state = state!.copyWith(selected: selected);
}
void clear() => state = null;
}
final receiptImportSessionProvider =
NotifierProvider<ReceiptImportSessionNotifier, ReceiptImportSession?>(
ReceiptImportSessionNotifier.new,
);