131 lines
4.8 KiB
Dart
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,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|