feat: Add category deletion functionality and enhance category dialog for editing

This commit is contained in:
2026-05-20 19:07:26 +02:00
parent 2ef9cf1dbb
commit b1ab4235bd
3 changed files with 73 additions and 11 deletions
+4
View File
@@ -85,6 +85,10 @@ class NoteRepository {
debugPrint('Category inserted to database'); debugPrint('Category inserted to database');
} }
Future<void> deleteCategory(String id) async {
await _database.deleteCategory(id);
}
Future<Note> createNote(Note note) async { Future<Note> createNote(Note note) async {
await _database.insertNoteAtTop( await _database.insertNoteAtTop(
NotesCompanion.insert( NotesCompanion.insert(
+54 -10
View File
@@ -291,9 +291,11 @@ class _HomeScreenState extends State<HomeScreen> {
} }
} }
Future<void> _showCreateCategoryDialog() async { Future<void> _showCreateCategoryDialog([Category? category]) async {
final TextEditingController controller = TextEditingController(); final TextEditingController controller = TextEditingController(text: category?.name ?? '');
Color? selectedColor; Color? selectedColor = category != null && category.colorValue != null
? Color(category.colorValue!)
: null;
IconData? selectedIcon; IconData? selectedIcon;
final List<Color> palette = [ final List<Color> palette = [
@@ -318,13 +320,20 @@ class _HomeScreenState extends State<HomeScreen> {
Icons.lightbulb, Icons.lightbulb,
]; ];
if (category != null && category.iconCodePoint != null) {
selectedIcon = icons.firstWhere(
(i) => i.codePoint == category.iconCodePoint,
orElse: () => icons.first,
);
}
final bool? result = await showDialog<bool>( final bool? result = await showDialog<bool>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return StatefulBuilder( return StatefulBuilder(
builder: (BuildContext ctx, StateSetter setState) { builder: (BuildContext ctx, StateSetter setState) {
return AlertDialog( return AlertDialog(
title: const Text('Crear categoría'), title: Text(category == null ? 'Crear categoría' : 'Editar categoría'),
content: SingleChildScrollView( content: SingleChildScrollView(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@@ -406,13 +415,46 @@ class _HomeScreenState extends State<HomeScreen> {
), ),
), ),
actions: [ actions: [
if (category != null)
TextButton(
onPressed: () async {
final bool? confirm = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Borrar categoría'),
content: const Text('¿Seguro que quieres borrar esta categoría?'),
actions: [
TextButton(onPressed: () => Navigator.pop(context, false), child: const Text('Cancelar')),
TextButton(onPressed: () => Navigator.pop(context, true), child: const Text('Borrar')),
],
),
);
if (confirm == true) {
try {
await widget.repository.deleteCategory(category.id);
await _loadCategories();
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Categoría borrada')));
}
try {
await widget.onRequestSync();
} catch (_) {}
} catch (e) {
if (mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Error al borrar categoría: $e')));
}
Navigator.pop(context, false);
}
},
child: const Text('Borrar', style: TextStyle(color: Colors.red)),
),
TextButton( TextButton(
onPressed: () => Navigator.pop(context, false), onPressed: () => Navigator.pop(context, false),
child: const Text('Cancelar'), child: const Text('Cancelar'),
), ),
TextButton( TextButton(
onPressed: () => Navigator.pop(context, true), onPressed: () => Navigator.pop(context, true),
child: const Text('Crear'), child: Text(category == null ? 'Crear' : 'Guardar'),
), ),
], ],
); );
@@ -428,19 +470,20 @@ class _HomeScreenState extends State<HomeScreen> {
try { try {
final Category newCategory = Category( final Category newCategory = Category(
id: category?.id,
name: controller.text.trim(), name: controller.text.trim(),
updatedAt: DateTime.now(), updatedAt: DateTime.now(),
colorValue: selectedColor?.toARGB32(), colorValue: selectedColor?.toARGB32(),
iconCodePoint: selectedIcon?.codePoint, iconCodePoint: selectedIcon?.codePoint,
); );
if (category == null) {
debugPrint('Creating category: ${newCategory.name}, color: ${newCategory.colorValue}, icon: ${newCategory.iconCodePoint}'); debugPrint('Creating category: ${newCategory.name}, color: ${newCategory.colorValue}, icon: ${newCategory.iconCodePoint}');
} else {
debugPrint('Updating category: ${newCategory.name}, color: ${newCategory.colorValue}, icon: ${newCategory.iconCodePoint}');
}
await widget.repository.createCategory(newCategory); await widget.repository.createCategory(newCategory);
await _loadCategories(); await _loadCategories();
if (mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('Categoría creada')));
}
try { try {
await widget.onRequestSync(); await widget.onRequestSync();
} catch (_) {} } catch (_) {}
@@ -876,6 +919,7 @@ class _HomeScreenState extends State<HomeScreen> {
? 'deleted_notes' ? 'deleted_notes'
: 'all_notes'), : 'all_notes'),
categories: _categories, categories: _categories,
onEditCategory: (Category c) => _showCreateCategoryDialog(c),
onCreateCategory: _showCreateCategoryDialog, onCreateCategory: _showCreateCategoryDialog,
), ),
), ),
+14
View File
@@ -8,12 +8,14 @@ class MenuDrawer extends StatelessWidget {
this.selectedItem, this.selectedItem,
this.categories = const [], this.categories = const [],
this.onCreateCategory, this.onCreateCategory,
this.onEditCategory,
}); });
final ValueChanged<String>? onMenuItemTapped; final ValueChanged<String>? onMenuItemTapped;
final String? selectedItem; final String? selectedItem;
final List<Category> categories; final List<Category> categories;
final VoidCallback? onCreateCategory; final VoidCallback? onCreateCategory;
final ValueChanged<Category>? onEditCategory;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -57,6 +59,15 @@ class MenuDrawer extends StatelessWidget {
onTap: () => onMenuItemTapped?.call(categoryId), onTap: () => onMenuItemTapped?.call(categoryId),
iconColor: Color(category.colorValue ?? 0xFFFFC107), iconColor: Color(category.colorValue ?? 0xFFFFC107),
textColor: Color(category.colorValue ?? 0xFFFFC107), textColor: Color(category.colorValue ?? 0xFFFFC107),
trailing: selectedItem == categoryId
? IconButton(
icon: const Icon(
Icons.more_vert,
color: Colors.white70,
),
onPressed: () => onEditCategory?.call(category),
)
: null,
); );
}).toList(), }).toList(),
), ),
@@ -99,6 +110,7 @@ class _MenuItemTile extends StatelessWidget {
this.onTap, this.onTap,
this.iconColor, this.iconColor,
this.textColor, this.textColor,
this.trailing,
}); });
final IconData icon; final IconData icon;
@@ -107,6 +119,7 @@ class _MenuItemTile extends StatelessWidget {
final VoidCallback? onTap; final VoidCallback? onTap;
final Color? iconColor; final Color? iconColor;
final Color? textColor; final Color? textColor;
final Widget? trailing;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -134,6 +147,7 @@ class _MenuItemTile extends StatelessWidget {
), ),
child: ListTile( child: ListTile(
leading: Icon(icon, color: iconColor ?? foregroundColor), leading: Icon(icon, color: iconColor ?? foregroundColor),
trailing: trailing,
title: Text( title: Text(
label, label,
style: TextStyle(color: textColor ?? foregroundColor, fontSize: 14), style: TextStyle(color: textColor ?? foregroundColor, fontSize: 14),