add edit page and widgets
This commit is contained in:
103
lib/widgets/color_selector.dart
Normal file
103
lib/widgets/color_selector.dart
Normal 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;
|
||||
}
|
||||
}
|
||||
79
lib/widgets/custom_dropdown.dart
Normal file
79
lib/widgets/custom_dropdown.dart
Normal 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),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
87
lib/widgets/custom_text_field.dart
Normal file
87
lib/widgets/custom_text_field.dart
Normal 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),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
56
lib/widgets/section_header.dart
Normal file
56
lib/widgets/section_header.dart
Normal 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,
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user