Files
2026-10-29 15:03:48 +01:00

190 lines
7.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controller/abfall_controller.dart';
import '../helper/display_formats.dart';
import '../models/abfall_model.dart';
import '../theme/app_theme.dart';
import 'entry_panel.dart';
class AbfallInventory extends StatelessWidget {
const AbfallInventory({super.key, required this.controller});
final AbfallController controller;
@override
Widget build(BuildContext context) => DecoratedSliver(
decoration: BoxDecoration(
color: AppTheme.inventorySurface,
borderRadius: BorderRadius.circular(24),
),
sliver: SliverPadding(
padding: const EdgeInsets.all(24),
sliver: Obx(() {
final entries = controller.abfaelle.toList();
final busy = controller.isSaving.value;
return SliverMainAxisGroup(
slivers: [
SliverToBoxAdapter(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Abfallübersicht',
style: TextStyle(
color: Colors.white,
fontSize: 25,
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 6),
Text(
'${entries.length} Einträge · die neuesten zuerst.',
style: const TextStyle(color: Color(0xFFB9CCD9)),
),
const SizedBox(height: 20),
Wrap(
spacing: 12,
runSpacing: 12,
children: [
_AbfallStat(
label: 'Summe Abfall',
value:
'${DisplayFormats.number(controller.summeAbfall)} g',
),
_AbfallStat(
label: 'Summe Abfallkosten',
value: DisplayFormats.currency(controller.summeKosten),
),
],
),
if (entries.any((entry) => entry.kostenUnbekannt)) ...[
const SizedBox(height: 12),
const Text(
'Bei einigen älteren Bauteilen fehlen Filamentdaten. Ihr Gewicht ist enthalten; ihre unbekannten Kosten fehlen in der Kostensumme.',
style: TextStyle(color: Color(0xFFB9CCD9), height: 1.5),
),
],
const SizedBox(height: 24),
],
),
),
if (entries.isEmpty)
const SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 24),
child: Text(
'Noch kein Abfall gespeichert. Erfasse deinen ersten Eintrag.',
style: TextStyle(color: Color(0xFFB9CCD9), height: 1.5),
),
),
)
else
SliverList.separated(
itemCount: entries.length,
separatorBuilder: (context, index) =>
const SizedBox(height: 12),
itemBuilder: (context, index) {
final entry = entries[index];
return SavedEntryCard(
key: ValueKey(entry.abfallId),
title:
'${DisplayFormats.number(entry.gewichtGramm)} g Abfall',
subtitle: DisplayFormats.date(entry.datumZeit),
notes: entry.ausBauteil
? 'Aus Bauteil „${entry.bauteilName}“. Änderungen und Löschen über die Bauteilverwaltung.${entry.kostenNachtraeglich ? ' Kosten nachträglich aus den aktuellen Rollenpreisen und Startgewichten berechnet.' : ''}'
: '',
details: [
entry.kostenUnbekannt
? 'Abfallkosten: nicht ermittelbar'
: 'Abfallkosten: ${DisplayFormats.currency(entry.kosten)}',
],
trailing: entry.ausBauteil
? null
: PopupMenuButton<String>(
tooltip: 'Abfalleintrag verwalten',
enabled: !busy,
iconColor: AppTheme.ink,
onSelected: (action) {
if (action == 'edit') {
controller.editAbfall(entry);
} else if (action == 'delete') {
_confirmDelete(context, entry);
}
},
itemBuilder: (context) => const [
PopupMenuItem(
value: 'edit',
child: Text('Bearbeiten'),
),
PopupMenuItem(
value: 'delete',
child: Text('Löschen'),
),
],
),
);
},
),
],
);
}),
),
);
Future<void> _confirmDelete(BuildContext context, AbfallModel entry) async {
final confirmed = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Abfall löschen?'),
content: Text(
'${DisplayFormats.number(entry.gewichtGramm)} g Abfall vom ${DisplayFormats.date(entry.datumZeit)} löschen?',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('Abbrechen'),
),
FilledButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('Löschen'),
),
],
),
);
if (confirmed == true) await controller.deleteAbfall(entry.abfallId);
}
}
class _AbfallStat extends StatelessWidget {
const _AbfallStat({required this.label, required this.value});
final String label;
final String value;
@override
Widget build(BuildContext context) => Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: const Color(0xFF243E50),
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: const TextStyle(color: Color(0xFFB9CCD9), fontSize: 12),
),
const SizedBox(height: 4),
Text(
value,
style: const TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w700,
),
),
],
),
);
}