import 'package:flutter/material.dart'; import 'package:pantry/i18n.dart'; import 'package:pantry/models/category.dart'; import 'package:pantry/services/category_service.dart'; import 'package:pantry/utils/category_icons.dart'; const categoryColors = [ '#ef4444', '#f97316', '#eab308', '#22c55e', '#14b8a6', '#0ea5e9', '#6366f1', '#a855f7', '#ec4899', '#78716c', ]; class CreateCategoryDialog extends StatefulWidget { final int houseId; /// If non-null, we're editing this category instead of creating a new one. final Category? existing; const CreateCategoryDialog({super.key, required this.houseId, this.existing}); @override State createState() => _CreateCategoryDialogState(); } class _CreateCategoryDialogState extends State { late final TextEditingController _nameController; late String _selectedIcon; late String _selectedColor; bool _saving = false; bool get _isEditing => widget.existing != null; @override void initState() { super.initState(); final e = widget.existing; _nameController = TextEditingController(text: e?.name ?? ''); _selectedIcon = e?.icon ?? 'tag'; _selectedColor = e?.color ?? categoryColors.first; } @override void dispose() { _nameController.dispose(); super.dispose(); } Future _save() async { final name = _nameController.text.trim(); if (name.isEmpty) return; setState(() => _saving = true); try { final category = _isEditing ? await CategoryService.instance.updateCategory( widget.houseId, widget.existing!.id, name: name, icon: _selectedIcon, color: _selectedColor, ) : await CategoryService.instance.createCategory( widget.houseId, name: name, icon: _selectedIcon, color: _selectedColor, ); if (mounted) Navigator.of(context).pop(category); } catch (e) { if (mounted) { ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text(m.categories.saveFailed))); } } finally { if (mounted) setState(() => _saving = false); } } Color _parseHex(String hex) { hex = hex.replaceFirst('#', ''); if (hex.length == 6) hex = 'FF$hex'; return Color(int.parse(hex, radix: 16)); } @override Widget build(BuildContext context) { final theme = Theme.of(context); final f = m.checklists.itemForm; return AlertDialog( title: Text(_isEditing ? m.categories.editTitle : m.categories.addTitle), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ TextField( controller: _nameController, autofocus: true, textCapitalization: TextCapitalization.sentences, decoration: InputDecoration( labelText: f.categoryName, border: const OutlineInputBorder(), ), ), const SizedBox(height: 16), Text(f.categoryIcon, style: theme.textTheme.bodyMedium), const SizedBox(height: 8), Wrap( spacing: 4, runSpacing: 4, children: categoryIconMap.entries.map((entry) { final isSelected = _selectedIcon == entry.key; return GestureDetector( onTap: () => setState(() => _selectedIcon = entry.key), child: Container( width: 40, height: 40, decoration: BoxDecoration( color: isSelected ? theme.colorScheme.primaryContainer : null, borderRadius: BorderRadius.circular(8), border: isSelected ? Border.all( color: theme.colorScheme.primary, width: 2, ) : null, ), child: Icon( entry.value, size: 20, color: isSelected ? theme.colorScheme.primary : theme.colorScheme.onSurfaceVariant, ), ), ); }).toList(), ), const SizedBox(height: 16), Text(f.categoryColor, style: theme.textTheme.bodyMedium), const SizedBox(height: 8), Wrap( spacing: 8, runSpacing: 8, children: categoryColors.map((hex) { final color = _parseHex(hex); final isSelected = _selectedColor == hex; return GestureDetector( onTap: () => setState(() => _selectedColor = hex), child: Container( width: 36, height: 36, decoration: BoxDecoration( color: color, shape: BoxShape.circle, border: isSelected ? Border.all( color: theme.colorScheme.primary, width: 3, ) : Border.all(color: theme.colorScheme.outlineVariant), ), child: isSelected ? const Icon(Icons.check, size: 18, color: Colors.white) : null, ), ); }).toList(), ), ], ), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: Text(m.common.cancel), ), FilledButton( onPressed: _saving ? null : _save, child: _saving ? const SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2), ) : Text(m.common.save), ), ], ); } }