refactor: remove ReceiptImportTab and its state management for cleaner code structure

This commit is contained in:
Nils-Johan Gynther
2026-05-01 01:37:35 +02:00
parent 73d653aef9
commit 997d62ade8
@@ -590,131 +590,3 @@ class _ReceiptImportTabState extends ConsumerState<ReceiptImportTab> {
}
}
class ReceiptImportTab extends ConsumerStatefulWidget {
const ReceiptImportTab({super.key});
@override
ConsumerState<ReceiptImportTab> createState() => _ReceiptImportTabState();
}
class _ReceiptImportTabState extends ConsumerState<ReceiptImportTab> {
bool _isLoading = false;
String? _error;
PlatformFile? _pickedFile;
List<ParsedReceiptItem>? _items;
Future<void> _pickFile() async {
final result = await FilePicker.pickFiles(
type: FileType.custom,
allowedExtensions: ['pdf', 'png', 'jpg', 'jpeg', 'webp', 'bmp'],
withData: true,
);
if (result == null || result.files.isEmpty) return;
setState(() {
_pickedFile = result.files.first;
_error = null;
_items = null;
});
}
Future<void> _submit() async {
if (_pickedFile == null) {
setState(() => _error = 'Vänligen välj en fil först');
return;
}
setState(() {
_isLoading = true;
_error = null;
_items = null;
});
try {
final token = await ref.read(authStateProvider.future);
final repo = ref.read(importRepositoryProvider);
final items = await repo.importReceiptFile(
bytes: _pickedFile!.bytes!,
filename: _pickedFile!.name,
token: token,
);
if (!mounted) return;
setState(() => _items = items);
} catch (e) {
showGlobalErrorDialog(context, 'Ett fel uppstod vid import: $e');
} finally {
if (mounted) {
setState(() => _isLoading = false);
}
}
}
bool get _canSubmit => !_isLoading && _pickedFile?.bytes != null;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Ladda upp ett kvitto (PDF eller bild) — raderna tolkas och kan läggas till i ditt inventarie.',
style: theme.textTheme.bodyMedium?.copyWith(color: theme.colorScheme.onSurfaceVariant)),
const SizedBox(height: 20),
OutlinedButton.icon(
onPressed: _isLoading ? null : _pickFile,
icon: const Icon(Icons.attach_file),
label: Text(_pickedFile == null ? 'Välj kvittofil' : _pickedFile!.name),
),
if (_pickedFile != null) ...[
const SizedBox(height: 8),
Text('${(_pickedFile!.size / 1024).round()} KB', style: theme.textTheme.bodySmall?.copyWith(color: theme.colorScheme.outline)),
],
const SizedBox(height: 24),
if (_isLoading) ...[
const LinearProgressIndicator(),
const SizedBox(height: 8),
Text('Tolkar kvittot — detta kan ta upp till en minut...', style: theme.textTheme.bodySmall?.copyWith(color: theme.colorScheme.onSurfaceVariant)),
const SizedBox(height: 16),
],
if (_error != null) ...[
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: theme.colorScheme.errorContainer,
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Icon(Icons.error_outline, color: theme.colorScheme.onErrorContainer, size: 18),
const SizedBox(width: 8),
Expanded(child: Text(_error!, style: theme.textTheme.bodySmall?.copyWith(color: theme.colorScheme.onErrorContainer))),
],
),
),
const SizedBox(height: 16),
],
FilledButton.icon(
onPressed: _canSubmit ? _submit : null,
icon: const Icon(Icons.receipt_long_outlined),
label: const Text('Importera kvitto'),
),
const SizedBox(height: 24),
if (_items != null) ...[
const Divider(),
const SizedBox(height: 12),
Text('Granska rader:', style: theme.textTheme.titleMedium),
const SizedBox(height: 8),
..._items!.map((item) => ListTile(
leading: const Icon(Icons.shopping_cart_outlined),
title: Text(item.rawName),
subtitle: Text('${item.quantity ?? ''} ${item.unit ?? ''}'),
trailing: Text(item.suggestedProductName ?? '', style: theme.textTheme.bodySmall),
)),
],
],
),
);
}
}