Files
ertl_filament_verwaltung/lib/widgets/bauteil_filament_auswahl.dart
T
2026-10-27 15:00:16 +01:00

128 lines
4.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controller/bauteil_controller.dart';
import '../helper/display_formats.dart';
import '../helper/input_validators.dart';
import '../theme/app_theme.dart';
import 'entry_panel.dart';
class BauteilFilamentAuswahl extends StatelessWidget {
const BauteilFilamentAuswahl({super.key, required this.controller});
final BauteilController controller;
@override
Widget build(BuildContext context) => Obx(() {
final ids = {
...controller.filamente.map((item) => item.filamentId),
...controller.selectedFilamente.keys,
};
if (ids.isEmpty) {
return const Text(
'Erfasse zuerst ein Filament in der Einkaufsverwaltung.',
);
}
return Column(
children: ids.map((id) {
final selected = controller.selectedFilamente.containsKey(id);
final profiles = controller.profilesFor(id);
final available = controller.verfuegbarGramm(id);
final checkbox = CheckboxListTile(
key: ValueKey('filament-$id'),
title: Text(controller.filamentLabel(id)),
subtitle: Text(
available == null
? 'Startgewicht unbekannt'
: '${DisplayFormats.number(available)} g verfügbar',
),
value: selected,
controlAffinity: ListTileControlAffinity.leading,
onChanged: (value) => controller.toggleFilament(id, value ?? false),
);
final consumption = selected
? Padding(
padding: const EdgeInsets.all(16),
child: EntryNumberField(
controller: controller.verbrauchController(id),
label: 'Verbrauch',
unit: 'g',
validator: InputValidators.positive,
),
)
: const SizedBox.shrink();
return Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Material(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
clipBehavior: Clip.antiAlias,
child: Column(
children: [
LayoutBuilder(
builder: (context, constraints) =>
constraints.maxWidth >= 500 && selected
? Row(
children: [
Expanded(child: checkbox),
SizedBox(width: 190, child: consumption),
],
)
: Column(children: [checkbox, if (selected) consumption]),
),
if (selected && profiles.isNotEmpty)
Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
child: DropdownButtonFormField<String>(
key: ValueKey(
'profile-$id-${controller.selectedFilamente[id]}',
),
initialValue:
profiles.any(
(item) =>
item.anwendungId ==
controller.selectedFilamente[id],
)
? controller.selectedFilamente[id]
: '',
isExpanded: true,
decoration: const InputDecoration(
labelText: 'Verarbeitungsprofil',
),
items: [
const DropdownMenuItem(
value: '',
child: Text('Ohne Profil'),
),
...profiles.map(
(profile) => DropdownMenuItem(
value: profile.anwendungId,
child: Text(
'${DisplayFormats.number(profile.druckTemperatur)} °C · Bett ${DisplayFormats.number(profile.druckbettTemperatur)} °C · ${DisplayFormats.date(profile.erstelltAm)}',
overflow: TextOverflow.ellipsis,
),
),
),
],
onChanged: (value) => controller.selectProfile(
id,
value == '' ? null : value,
),
),
),
if (selected && profiles.isEmpty)
const Padding(
padding: EdgeInsets.fromLTRB(16, 0, 16, 16),
child: Text(
'Noch kein Profil. Einstellungen kannst du über das Filament in der Einkaufsübersicht erfassen.',
style: TextStyle(color: AppTheme.muted),
),
),
],
),
),
);
}).toList(),
);
});
}