Files
ertl_filament_verwaltung/lib/widgets/bauteil_form.dart
T
2026-10-28 12:32:49 +01:00

131 lines
4.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controller/bauteil_controller.dart';
import '../helper/input_validators.dart';
import '../theme/app_theme.dart';
import 'bauteil_filament_auswahl.dart';
import 'bauteil_photo_picker.dart';
import 'entry_panel.dart';
class BauteilForm extends StatelessWidget {
const BauteilForm({super.key, required this.controller});
final BauteilController controller;
@override
Widget build(BuildContext context) => Obx(
() => EntryPanel(
title: controller.editingId.value == null
? 'Bauteil erfassen'
: 'Bauteil bearbeiten',
subtitle: 'Dokumentiere deinen Druck und den Verbrauch je Filament.',
child: Form(
key: controller.formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextFormField(
controller: controller.nameController,
decoration: const InputDecoration(labelText: 'Bauteilname'),
validator: InputValidators.requiredText,
),
const SizedBox(height: 16),
TextFormField(
controller: controller.verwendungController,
decoration: const InputDecoration(
labelText: 'Art der Verwendung',
),
validator: InputValidators.requiredText,
),
const SizedBox(height: 16),
EntryFieldGrid(
children: [
EntryNumberField(
controller: controller.stundenController,
label: 'Druckdauer: Stunden',
unit: 'h',
validator: InputValidators.hours,
),
EntryNumberField(
controller: controller.minutenController,
label: 'Druckdauer: Minuten',
unit: 'min',
validator: InputValidators.minutes,
),
EntryNumberField(
controller: controller.gewichtController,
label: 'Bauteilgewicht',
unit: 'g',
validator: InputValidators.positive,
),
EntryNumberField(
controller: controller.abfallController,
label: 'Abfallmenge',
unit: 'g',
validator: InputValidators.nonNegative,
),
EntryNumberField(
controller: controller.gesamtpreisController,
label: 'Gesamtpreis (optional)',
unit: '€',
validator: (value) =>
InputValidators.nonNegative(value, optional: true),
),
],
),
const SizedBox(height: 24),
BauteilPhotoPicker(controller: controller),
const SizedBox(height: 24),
const Text(
'Verwendete Filamente',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w700),
),
const SizedBox(height: 6),
const Text(
'Wähle für Mehrfarbdruck mehrere Filamente. Gib je Rolle den gesamten Verbrauch inklusive ihres Abfallanteils an. Die Summe muss Bauteilgewicht + Abfall ergeben.',
style: TextStyle(color: AppTheme.muted, height: 1.5),
),
const SizedBox(height: 12),
BauteilFilamentAuswahl(controller: controller),
const SizedBox(height: 12),
Obx(
() => FilledButton.icon(
onPressed:
controller.isSaving.value ||
controller.isPickingPhoto.value ||
controller.filamente.isEmpty
? null
: controller.saveBauteil,
icon: Icon(
controller.editingId.value == null ? Icons.add : Icons.check,
),
label: Text(
controller.isSaving.value
? 'Wird gespeichert …'
: controller.editingId.value == null
? 'Bauteil speichern'
: 'Änderungen speichern',
),
),
),
if (controller.editingId.value != null)
TextButton.icon(
onPressed: controller.isSaving.value
? null
: controller.resetForm,
icon: const Icon(Icons.close),
label: const Text('Bearbeitung abbrechen'),
),
Obx(
() => EntryMessage(
message: controller.message.value,
hasError: controller.hasError.value,
),
),
],
),
),
),
);
}