From 9c8afe739d18d3c3ab8f82345c52396d33725ed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Gonz=C3=A1lez?= Date: Thu, 26 Feb 2026 21:49:32 +0100 Subject: [PATCH 1/2] save formula, not tested --- lib/ai/formula_editor.dart | 42 ++++++++++++++++++----- lib/ai/formula_list.dart | 6 ++++ lib/ai/formula_screen.dart | 6 ++++ lib/corpus.dart | 21 ++++++++++++ lib/database/database_service.dart | 55 ++++++++++++++++++++++++++++++ 5 files changed, 121 insertions(+), 9 deletions(-) diff --git a/lib/ai/formula_editor.dart b/lib/ai/formula_editor.dart index ff7805e..159306d 100644 --- a/lib/ai/formula_editor.dart +++ b/lib/ai/formula_editor.dart @@ -5,6 +5,8 @@ import 'package:flutter_markdown_plus/flutter_markdown_plus.dart'; import 'package:markdown/markdown.dart' as markdown; import '../formula_models.dart'; import '../corpus.dart'; +import '../database/database_service.dart'; +import '../service_locator.dart'; import 'formula_screen.dart'; import 'unit_dropdown.dart'; @@ -13,11 +15,13 @@ import 'unit_dropdown.dart'; class FormulaEditor extends StatefulWidget { final Formula formula; final Corpus corpus; + final Function(Formula)? onSave; // Callback when formula is saved const FormulaEditor({ super.key, required this.formula, required this.corpus, + this.onSave, }); @override @@ -181,7 +185,7 @@ class _FormulaEditorState extends State { } } - void _saveFormula() { + Future _saveFormula() async { if (!_validateFormula()) { return; } @@ -189,14 +193,34 @@ class _FormulaEditorState extends State { final formula = _buildFormula(); if (formula == null) return; - // For now, just show a success message - // In a real implementation, this would save to database - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Formula "${formula.name}" saved successfully!'), - backgroundColor: Theme.of(context).colorScheme.primary, - ), - ); + try { + final database = getDatabase(); + + // Update corpus in memory + widget.corpus.updateFormula(formula); + + // Update database + final updated = await database.updateFormula(formula); + + if (!updated) { + // If formula wasn't found (e.g., name changed), add it as new + await database.addFormula(formula); + } + + // Call the onSave callback if provided + widget.onSave?.call(formula); + + // Show success message + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Formula "${formula.name}" saved successfully!'), + backgroundColor: Theme.of(context).colorScheme.primary, + ), + ); + } catch (e, stack) { + print('Error saving formula: $e\n$stack'); + _showErrorDialog('Error saving formula: $e'); + } } void _showErrorDialog(String message) { diff --git a/lib/ai/formula_list.dart b/lib/ai/formula_list.dart index a6b2129..a7041c0 100644 --- a/lib/ai/formula_list.dart +++ b/lib/ai/formula_list.dart @@ -80,6 +80,12 @@ class _FormulaListState extends State { builder: (context) => FormulaEditor( formula: formula, corpus: widget.corpus, + onSave: (updatedFormula) { + // Refresh the formula list after saving + setState(() { + // The corpus has been updated, so we just need to rebuild + }); + }, ), ), ); diff --git a/lib/ai/formula_screen.dart b/lib/ai/formula_screen.dart index 5395598..8b1c94b 100644 --- a/lib/ai/formula_screen.dart +++ b/lib/ai/formula_screen.dart @@ -184,6 +184,12 @@ class _FormulaScreenState extends State { builder: (context) => FormulaEditor( formula: widget.formula, corpus: widget.corpus, + onSave: (updatedFormula) { + // Refresh the screen after saving + setState(() { + // The corpus has been updated, refresh the displayed formula + }); + }, ), ), ); diff --git a/lib/corpus.dart b/lib/corpus.dart index 74c2146..1b28c40 100644 --- a/lib/corpus.dart +++ b/lib/corpus.dart @@ -63,6 +63,27 @@ class Corpus{ return _allFormulas.get(name); } + /// Updates a formula in the corpus + void updateFormula(Formula formula) { + if (!_allFormulas.containsKey(formula.name)) { + throw ArgumentError("Formula not found: ${formula.name}"); + } + + // Remove old tags + final oldFormula = _allFormulas[formula.name]!; + for (final tag in oldFormula.tags) { + _tags[tag]?.removeWhere((f) => f.name == formula.name); + } + + // Update the formula + _allFormulas[formula.name] = formula; + + // Add new tags + for (final tag in formula.tags) { + _tags[tag]?.add(formula); + } + } + final Multimap _baseToUnits = Multimap.create(); final Map _allUnits = {}; diff --git a/lib/database/database_service.dart b/lib/database/database_service.dart index 06dc034..4ccf2de 100644 --- a/lib/database/database_service.dart +++ b/lib/database/database_service.dart @@ -35,4 +35,59 @@ extension CorpusDatabaseExtension on FormulasDatabase { await insertFormulaElement(element.toStringLiteral()); } } + + // Method to update a formula in the database by name + Future updateFormula(models.Formula formula) async { + final elements = await getAllFormulaElements(); + + for (final element in elements) { + try { + final parsed = models.parseCorpusElements('[${element.elementText}]'); + if (parsed.isNotEmpty && parsed.first is models.Formula) { + final existingFormula = parsed.first as models.Formula; + if (existingFormula.name == formula.name) { + // Update this element + await updateFormulaElement( + element.id, + formula.toStringLiteral() + ); + return true; + } + } + } catch (e) { + print('Error parsing database element during update: $e'); + continue; + } + } + + return false; // Formula not found + } + + // Method to add a new formula to the database + Future addFormula(models.Formula formula) async { + await insertFormulaElement(formula.toStringLiteral()); + } + + // Method to delete a formula from the database by name + Future deleteFormula(String formulaName) async { + final elements = await getAllFormulaElements(); + + for (final element in elements) { + try { + final parsed = models.parseCorpusElements('[${element.elementText}]'); + if (parsed.isNotEmpty && parsed.first is models.Formula) { + final existingFormula = parsed.first as models.Formula; + if (existingFormula.name == formulaName) { + await deleteFormulaElement(element.id); + return true; + } + } + } catch (e) { + print('Error parsing database element during delete: $e'); + continue; + } + } + + return false; // Formula not found + } } From db83c6ecc2e92debf0968a4b784b31b70946ef93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Gonz=C3=A1lez?= Date: Sat, 28 Feb 2026 19:35:47 +0100 Subject: [PATCH 2/2] saved formulas --- TODO.md | 2 ++ lib/ai/formula_list.dart | 16 ++++------------ lib/main.dart | 1 - 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/TODO.md b/TODO.md index 8b6f6af..4a4ce85 100644 --- a/TODO.md +++ b/TODO.md @@ -47,3 +47,5 @@ - [R] There is one row for the ouput variable, similar to the row for the input variable - [R] d4rtCode is a text area with dart syntax highligthing - [R] At the botton, a button allows to test the edited Formula, launching a FormulaScreen +- [R] When FormulaEditor._save formula, ensure formula is updated in the initial FormulaList +- [ ] Refresh FormulaList each time it gets focus, so formulas are updated from corpus diff --git a/lib/ai/formula_list.dart b/lib/ai/formula_list.dart index a7041c0..42abf8a 100644 --- a/lib/ai/formula_list.dart +++ b/lib/ai/formula_list.dart @@ -8,12 +8,10 @@ import 'package:share_plus/share_plus.dart'; class FormulaList extends StatefulWidget { final Corpus corpus; - final List formulas; const FormulaList({ super.key, required this.corpus, - required this.formulas, }); @override @@ -43,9 +41,9 @@ class _FormulaListState extends State { } List get _filteredFormulas { - if (_searchQuery.isEmpty) return widget.formulas; + if (_searchQuery.isEmpty) return widget.corpus.getFormulas(); - return widget.formulas.where((formula) { + return widget.corpus.getFormulas().where((formula) { final nameMatch = formula.name.toLowerCase().contains(_searchQuery); final tagMatch = formula.tags.any((tag) => tag.toLowerCase().contains(_searchQuery)); return nameMatch || tagMatch; @@ -80,12 +78,6 @@ class _FormulaListState extends State { builder: (context) => FormulaEditor( formula: formula, corpus: widget.corpus, - onSave: (updatedFormula) { - // Refresh the formula list after saving - setState(() { - // The corpus has been updated, so we just need to rebuild - }); - }, ), ), ); @@ -122,14 +114,14 @@ class _FormulaListState extends State { context: context, builder: (BuildContext context) { return AlertDialog( - title: Text('Error'), + title: const Text('Error'), content: Text(message), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); }, - child: Text('OK'), + child: const Text('OK'), ), ], ); diff --git a/lib/main.dart b/lib/main.dart index da4781c..9455143 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -58,7 +58,6 @@ class _CorpusLoaderState extends State { appBar: AppBar(title: const Text('Formulas')), body: FormulaList( corpus: snapshot.data!, - formulas: snapshot.data!.getFormulas(), ), ); }