filament_verwaltung/lib/pages/edit_view.dart
2026-01-15 13:44:48 +01:00

410 lines
14 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import '../controllers/edit_controller.dart';
import '../widgets/custom_text_field.dart';
import '../widgets/custom_dropdown.dart';
import '../widgets/section_header.dart';
import '../widgets/color_selector.dart';
import '../widgets/action_button.dart';
class EditPage extends GetView<EditController> {
static const String namedRoute = '/edit-page';
const EditPage({super.key});
@override
Widget build(BuildContext context) {
final isNewFilament = controller.originalFilament.value == null;
return Scaffold(
backgroundColor: Colors.grey.shade50,
appBar: AppBar(
title: Text(
isNewFilament ? 'Neues Filament' : 'Filament bearbeiten',
style: TextStyle(fontWeight: FontWeight.bold),
),
backgroundColor: Colors.white,
elevation: 0,
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.close),
onPressed: () => Get.back(),
),
),
body: Form(
key: controller.formKey,
child: SingleChildScrollView(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Header Card
Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue.shade400, Colors.blue.shade600],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.blue.withAlpha(77),
blurRadius: 15,
offset: Offset(0, 5),
),
],
),
child: Row(
children: [
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white.withAlpha(51),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
isNewFilament ? Icons.add_circle : Icons.edit,
color: Colors.white,
size: 32,
),
),
SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
isNewFilament ? 'Neues Filament anlegen' : 'Filament bearbeiten',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(height: 4),
Text(
isNewFilament
? 'Fülle die Felder aus, um ein neues Filament hinzuzufügen'
: 'Aktualisiere die Informationen deines Filaments',
style: TextStyle(
fontSize: 13,
color: Colors.white.withAlpha(230),
),
),
],
),
),
],
),
),
SizedBox(height: 24),
// Basic Information
SectionHeader(
title: 'Grundinformationen',
icon: Icons.info_outline,
color: Colors.blue,
),
SizedBox(height: 16),
CustomTextField(
controller: controller.nameController,
label: 'Name *',
hint: 'z.B. 3Djake ECO Filament',
icon: Icons.label,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Bitte einen Namen eingeben';
}
return null;
},
),
SizedBox(height: 16),
CustomDropdown(
value: controller.typeController.text,
label: 'Typ *',
icon: Icons.category,
items: controller.filamentTypes,
onChanged: (value) {
if (value != null) {
controller.typeController.text = value;
}
},
validator: (value) {
if (value == null || value.isEmpty) {
return 'Bitte einen Typ auswählen';
}
return null;
},
),
SizedBox(height: 16),
ColorSelector(
selectedColor: controller.colorController.text.isNotEmpty
? controller.colorController.text
: 'White',
colors: controller.availableColors,
onColorSelected: (color) {
controller.colorController.text = color;
},
),
SizedBox(height: 24),
// Weight & Price
SectionHeader(
title: 'Gewicht & Preis',
icon: Icons.shopping_cart,
color: Colors.green,
),
SizedBox(height: 16),
Row(
children: [
Expanded(
child: CustomTextField(
controller: controller.weightController,
label: 'Gesamtgewicht (g) *',
hint: '1000',
icon: Icons.scale,
keyboardType: TextInputType.number,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Erforderlich';
}
if (double.tryParse(value) == null) {
return 'Ungültige Zahl';
}
return null;
},
),
),
SizedBox(width: 12),
Expanded(
child: CustomTextField(
controller: controller.weightUsedController,
label: 'Verbraucht (g)',
hint: '0',
icon: Icons.trending_down,
keyboardType: TextInputType.number,
validator: (value) {
if (value != null && value.isNotEmpty) {
if (double.tryParse(value) == null) {
return 'Ungültig';
}
}
return null;
},
),
),
],
),
SizedBox(height: 16),
Row(
children: [
Expanded(
child: CustomTextField(
controller: controller.priceController,
label: 'Preis (€) *',
hint: '19.99',
icon: Icons.euro,
keyboardType: TextInputType.number,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Erforderlich';
}
if (double.tryParse(value) == null) {
return 'Ungültige Zahl';
}
return null;
},
),
),
SizedBox(width: 12),
Expanded(
child: CustomTextField(
controller: controller.piecesController,
label: 'Anzahl Rollen',
hint: '1',
icon: Icons.inventory_2,
keyboardType: TextInputType.number,
),
),
],
),
SizedBox(height: 24),
// Print Settings
SectionHeader(
title: 'Druckeinstellungen',
icon: Icons.print,
color: Colors.orange,
),
SizedBox(height: 16),
Row(
children: [
Expanded(
child: CustomTextField(
controller: controller.printingTempController,
label: 'Drucktemperatur (°C)',
hint: '200',
icon: Icons.thermostat,
keyboardType: TextInputType.number,
),
),
SizedBox(width: 12),
Expanded(
child: CustomTextField(
controller: controller.bedTempController,
label: 'Betttemperatur (°C)',
hint: '60',
icon: Icons.heat_pump,
keyboardType: TextInputType.number,
),
),
],
),
SizedBox(height: 24),
// Additional Info
SectionHeader(
title: 'Zusatzinformationen',
icon: Icons.more_horiz,
color: Colors.purple,
),
SizedBox(height: 16),
CustomTextField(
controller: controller.manufacturerController,
label: 'Hersteller',
hint: 'z.B. 3Djake.at',
icon: Icons.business,
),
SizedBox(height: 16),
CustomTextField(
controller: controller.purchaseDateController,
label: 'Kaufdatum',
hint: 'TT.MM.JJJJ',
icon: Icons.calendar_today,
readOnly: true,
onTap: () async {
final date = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2020),
lastDate: DateTime.now(),
builder: (context, child) {
return Theme(
data: Theme.of(context).copyWith(
colorScheme: ColorScheme.light(
primary: Colors.blue,
),
),
child: child!,
);
},
);
if (date != null) {
final formatter = DateFormat('dd.MM.yyyy');
controller.purchaseDateController.text = formatter.format(date);
}
},
suffix: Icon(Icons.arrow_drop_down, color: Colors.blue.shade400),
),
SizedBox(height: 16),
CustomTextField(
controller: controller.notesController,
label: 'Notizen',
hint: 'Zusätzliche Informationen...',
icon: Icons.notes,
maxLines: 4,
),
SizedBox(height: 32),
// Save Button
Obx(() => AnimatedContainer(
duration: Duration(milliseconds: 300),
height: 56,
child: controller.isSaving.value
? Container(
decoration: BoxDecoration(
color: Colors.blue.shade100,
borderRadius: BorderRadius.circular(12),
),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
Colors.blue,
),
),
),
SizedBox(width: 12),
Text(
'Wird gespeichert...',
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.w600,
),
),
],
),
),
)
: ActionButton(
icon: Icons.save,
label: isNewFilament ? 'Erstellen' : 'Speichern',
color: Colors.blue,
onPressed: controller.saveFilament,
),
)),
SizedBox(height: 16),
// Cancel Button
TextButton(
onPressed: () => Get.back(),
style: TextButton.styleFrom(
padding: EdgeInsets.symmetric(vertical: 14),
),
child: Text(
'Abbrechen',
style: TextStyle(
fontSize: 15,
color: Colors.grey.shade600,
fontWeight: FontWeight.w600,
),
),
),
SizedBox(height: 32),
],
),
),
),
);
}
}