Files
ertl_filament_verwaltung/lib/widgets/filament_form.dart
T
2026-10-29 15:03:48 +01:00

222 lines
7.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import '../controller/home_controller.dart';
import '../theme/app_theme.dart';
import '../helper/input_validators.dart';
import 'filament_material_field.dart';
class FilamentForm extends StatelessWidget {
const FilamentForm({super.key, required this.controller});
final HomeController controller;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: AppTheme.inputSurface,
borderRadius: BorderRadius.circular(24),
border: Border.all(color: const Color(0xFFCEE6DF)),
),
child: Form(
key: controller.formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Row(
children: [
Icon(Icons.add_circle_outline, color: AppTheme.teal),
SizedBox(width: 10),
Flexible(
child: Text(
'EINKAUF ERFASSEN',
style: TextStyle(
color: AppTheme.teal,
fontSize: 12,
fontWeight: FontWeight.w700,
letterSpacing: 1.4,
),
),
),
],
),
const SizedBox(height: 14),
Obx(
() => Text(
controller.editingId.value == null
? 'Neues Filament'
: 'Filament bearbeiten',
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.w700,
),
),
),
const SizedBox(height: 6),
const Text(
'Alle Details zu deinem Einkauf an einem Ort.',
style: TextStyle(color: AppTheme.muted, height: 1.5),
),
const SizedBox(height: 24),
Obx(
() => Material(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
side: const BorderSide(color: Color(0xFFCCDEDA)),
),
clipBehavior: Clip.antiAlias,
child: ListTile(
contentPadding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 3,
),
leading: const Icon(
Icons.calendar_today_outlined,
color: AppTheme.teal,
),
title: const Text(
'Kaufdatum',
style: TextStyle(fontSize: 12, color: AppTheme.muted),
),
subtitle: Text(
DateFormat('dd.MM.yyyy').format(controller.kaufdatum.value),
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppTheme.ink,
),
),
trailing: const Icon(
Icons.expand_more,
color: AppTheme.muted,
),
onTap: () async {
final date = await showDatePicker(
context: context,
initialDate: controller.kaufdatum.value,
firstDate: DateTime(2000),
lastDate: DateTime(2100),
);
if (date != null) controller.kaufdatum.value = date;
},
),
),
),
const SizedBox(height: 16),
TextFormField(
controller: controller.haendlerController,
textCapitalization: TextCapitalization.words,
decoration: const InputDecoration(
labelText: 'Händler',
prefixIcon: Icon(Icons.storefront_outlined),
),
validator: (value) => value == null || value.trim().isEmpty
? 'Händler eingeben'
: null,
),
const SizedBox(height: 16),
TextFormField(
controller: controller.markeController,
textCapitalization: TextCapitalization.words,
decoration: const InputDecoration(
labelText: 'Marke',
prefixIcon: Icon(Icons.sell_outlined),
),
validator: (value) => value == null || value.trim().isEmpty
? 'Marke eingeben'
: null,
),
const SizedBox(height: 16),
FilamentMaterialField(controller: controller),
const SizedBox(height: 16),
TextFormField(
controller: controller.farbeController,
textCapitalization: TextCapitalization.words,
decoration: const InputDecoration(
labelText: 'Farbe',
prefixIcon: Icon(Icons.palette_outlined),
),
validator: (value) => value == null || value.trim().isEmpty
? 'Farbe eingeben'
: null,
),
const SizedBox(height: 16),
TextFormField(
controller: controller.preisController,
keyboardType: const TextInputType.numberWithOptions(
decimal: true,
),
decoration: const InputDecoration(
labelText: 'Preis',
suffixText: '€',
),
validator: InputValidators.nonNegative,
),
const SizedBox(height: 16),
TextFormField(
controller: controller.gewichtController,
keyboardType: const TextInputType.numberWithOptions(
decimal: true,
),
decoration: const InputDecoration(
labelText: 'Nettogewicht',
suffixText: 'g',
helperText: 'Startgewicht ohne Spule, nur Material.',
helperMaxLines: 2,
),
validator: InputValidators.positive,
),
const SizedBox(height: 16),
TextFormField(
controller: controller.bruttoGewichtController,
keyboardType: const TextInputType.numberWithOptions(
decimal: true,
),
decoration: const InputDecoration(
labelText: 'Bruttogewicht (optional)',
suffixText: 'g',
helperText: 'Material und Spule zusammen.',
helperMaxLines: 2,
),
validator: controller.validateBruttogewicht,
),
const SizedBox(height: 24),
Obx(
() => Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
FilledButton.icon(
onPressed: controller.saveFilament,
icon: Icon(
controller.editingId.value == null
? Icons.add
: Icons.check,
),
label: Text(
controller.editingId.value == null
? 'Filament speichern'
: 'Änderungen speichern',
),
),
if (controller.editingId.value != null) ...[
const SizedBox(height: 8),
TextButton.icon(
onPressed: controller.resetForm,
icon: const Icon(Icons.close),
label: const Text('Bearbeitung abbrechen'),
),
],
],
),
),
],
),
),
);
}
}