multiple receipts in a trip

This commit is contained in:
davmar
2026-09-03 15:09:17 +02:00
parent ae42ba8193
commit 8b040e83c0
6 changed files with 409 additions and 52 deletions
+72 -4
View File
@@ -9,6 +9,7 @@ import 'models/line_item.dart';
import 'models/shop.dart';
import 'product_detail_screen.dart';
import 'services/product_repository.dart';
import 'services/receipt_capture.dart';
import 'utils/dates.dart';
import 'utils/money.dart';
import 'widgets/confirm_dialog.dart';
@@ -37,6 +38,7 @@ class _ShopDetailScreenState extends State<ShopDetailScreen> {
bool _editing = false;
List<String> _tagSuggestions = [];
int _loadToken = 0;
bool _addingReceipt = false;
@override
void initState() {
@@ -150,6 +152,42 @@ class _ShopDetailScreenState extends State<ShopDetailScreen> {
}
}
Future<void> _addFromReceipt() async {
final shop = _shop;
if (shop == null || _addingReceipt) return;
setState(() => _addingReceipt = true);
try {
final captured = await captureAndParseReceipt(context);
if (captured == null || !mounted) return;
var added = 0;
for (final item in captured.items) {
await widget.repository.addShopItem(shopId: shop.id, item: item);
added++;
}
if (!mounted) return;
await _load();
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
added == 1
? 'Added 1 item from receipt.'
: 'Added $added items from receipt.',
),
),
);
} catch (_) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Could not add items from this receipt.')),
);
_load();
} finally {
if (mounted) setState(() => _addingReceipt = false);
}
}
Future<void> _editItem(ShopItem item) async {
final result = await showItemEditSheet(
context,
@@ -299,11 +337,41 @@ class _ShopDetailScreenState extends State<ShopDetailScreen> {
),
],
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: _editing
? FloatingActionButton.extended(
onPressed: _addItem,
icon: const Icon(Icons.add),
label: const Text('Add product'),
? Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Expanded(
child: FilledButton.tonalIcon(
onPressed: _addingReceipt ? null : _addFromReceipt,
icon: _addingReceipt
? const SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.receipt_long_outlined),
label: const Text('Add receipt'),
style: FilledButton.styleFrom(
minimumSize: const Size.fromHeight(52),
),
),
),
const SizedBox(width: 12),
Expanded(
child: FilledButton.icon(
onPressed: _addingReceipt ? null : _addItem,
icon: const Icon(Icons.add),
label: const Text('Add product'),
style: FilledButton.styleFrom(
minimumSize: const Size.fromHeight(52),
),
),
),
],
),
)
: null,
body: Builder(