add edit page and widgets

This commit is contained in:
atseirjo
2026-01-15 13:44:48 +01:00
parent b9f379ad53
commit 6df0da2776
11 changed files with 915 additions and 16 deletions

View File

@@ -0,0 +1,103 @@
import 'package:flutter/material.dart';
class ColorSelector extends StatelessWidget {
final String selectedColor;
final List<String> colors;
final void Function(String) onColorSelected;
const ColorSelector({
super.key,
required this.selectedColor,
required this.colors,
required this.onColorSelected,
});
Color _getColorFromString(String colorName) {
final colorMap = {
'red': Colors.red,
'blue': Colors.blue,
'green': Colors.green,
'yellow': Colors.yellow,
'black': Colors.black,
'white': Colors.white,
'orange': Colors.orange,
'purple': Colors.purple,
'pink': Colors.pink,
'grey': Colors.grey,
'brown': Colors.brown,
};
return colorMap[colorName.toLowerCase()] ?? Colors.grey;
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Farbe',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.grey.shade700,
),
),
SizedBox(height: 12),
Wrap(
spacing: 12,
runSpacing: 12,
children: colors.map((colorName) {
final isSelected = selectedColor.toLowerCase() == colorName.toLowerCase();
final color = _getColorFromString(colorName);
return GestureDetector(
onTap: () => onColorSelected(colorName),
child: AnimatedContainer(
duration: Duration(milliseconds: 200),
width: isSelected ? 60 : 50,
height: isSelected ? 60 : 50,
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
border: Border.all(
color: isSelected ? Colors.blue : Colors.grey.shade300,
width: isSelected ? 3 : 2,
),
boxShadow: [
if (isSelected)
BoxShadow(
color: color.withAlpha(102),
blurRadius: 12,
spreadRadius: 2,
),
],
),
child: isSelected
? Icon(
Icons.check,
color: _isLightColor(color) ? Colors.black : Colors.white,
size: 28,
)
: null,
),
);
}).toList(),
),
SizedBox(height: 8),
Text(
'Ausgewählt: $selectedColor',
style: TextStyle(
fontSize: 12,
color: Colors.grey.shade600,
fontStyle: FontStyle.italic,
),
),
],
);
}
bool _isLightColor(Color color) {
final luminance = color.computeLuminance();
return luminance > 0.5;
}
}

View File

@@ -0,0 +1,79 @@
import 'package:flutter/material.dart';
class CustomDropdown extends StatelessWidget {
final String value;
final String label;
final IconData? icon;
final List<String> items;
final void Function(String?) onChanged;
final String? Function(String?)? validator;
const CustomDropdown({
super.key,
required this.value,
required this.label,
required this.items,
required this.onChanged,
this.icon,
this.validator,
});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.grey.shade700,
),
),
SizedBox(height: 8),
DropdownButtonFormField<String>(
initialValue: items.contains(value) ? value : null,
decoration: InputDecoration(
prefixIcon: icon != null
? Icon(icon, color: Colors.blue.shade400, size: 22)
: null,
filled: true,
fillColor: Colors.white,
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 14),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.grey.shade300),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.blue, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.red.shade300),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.red, width: 2),
),
),
items: items.map((String item) {
return DropdownMenuItem<String>(
value: item,
child: Text(item),
);
}).toList(),
onChanged: onChanged,
validator: validator,
dropdownColor: Colors.white,
icon: Icon(Icons.arrow_drop_down, color: Colors.blue.shade400),
),
],
);
}
}

View File

@@ -0,0 +1,87 @@
import 'package:flutter/material.dart';
class CustomTextField extends StatelessWidget {
final TextEditingController controller;
final String label;
final String? hint;
final IconData? icon;
final TextInputType keyboardType;
final String? Function(String?)? validator;
final int maxLines;
final bool readOnly;
final VoidCallback? onTap;
final Widget? suffix;
const CustomTextField({
super.key,
required this.controller,
required this.label,
this.hint,
this.icon,
this.keyboardType = TextInputType.text,
this.validator,
this.maxLines = 1,
this.readOnly = false,
this.onTap,
this.suffix,
});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.grey.shade700,
),
),
SizedBox(height: 8),
TextFormField(
controller: controller,
keyboardType: keyboardType,
validator: validator,
maxLines: maxLines,
readOnly: readOnly,
onTap: onTap,
decoration: InputDecoration(
hintText: hint,
prefixIcon: icon != null
? Icon(icon, color: Colors.blue.shade400, size: 22)
: null,
suffixIcon: suffix,
filled: true,
fillColor: Colors.white,
contentPadding: EdgeInsets.symmetric(
horizontal: 16,
vertical: maxLines > 1 ? 16 : 14,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.grey.shade300),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.blue, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.red.shade300),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.red, width: 2),
),
),
),
],
);
}
}

View File

@@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
class SectionHeader extends StatelessWidget {
final String title;
final IconData icon;
final Color color;
const SectionHeader({
super.key,
required this.title,
required this.icon,
this.color = Colors.blue,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 8),
child: Row(
children: [
Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: color.withAlpha(26),
borderRadius: BorderRadius.circular(10),
),
child: Icon(icon, color: color, size: 20),
),
SizedBox(width: 12),
Text(
title,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.grey.shade800,
),
),
Expanded(
child: Container(
margin: EdgeInsets.only(left: 12),
height: 2,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
color.withAlpha(77),
Colors.transparent,
],
),
),
),
),
],
),
);
}
}