Skip to content

Commit 8e5477a

Browse files
authored
fix: show error when description is empty
PR #514 * fix: show error when description is empty * refactor: move description validation to GetX controller
1 parent 36facee commit 8e5477a

2 files changed

Lines changed: 82 additions & 50 deletions

File tree

lib/app/modules/detailRoute/controllers/detail_route_controller.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@ import 'package:taskwarrior/app/utils/taskfunctions/modify.dart';
1010
import 'package:taskwarrior/app/utils/taskfunctions/urgency.dart';
1111
import 'package:taskwarrior/app/utils/app_settings/app_settings.dart';
1212
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
13+
import 'package:taskwarrior/app/utils/language/sentence_manager.dart';
1314

1415
class DetailRouteController extends GetxController {
1516
late String uuid;
1617
late Modify modify;
1718
var onEdit = false.obs;
1819
var isReadOnly = false.obs;
1920

21+
// Description Edit State
22+
final descriptionController = TextEditingController();
23+
var descriptionErrorText = Rxn<String>();
2024
// Track whether user explicitly selected a start date
2125
bool startEdited = false;
2226

@@ -59,6 +63,24 @@ class DetailRouteController extends GetxController {
5963
initValues();
6064
}
6165

66+
// Validation Logic for Description
67+
bool validateDescription() {
68+
if (descriptionController.text.trim().isEmpty) {
69+
descriptionErrorText.value =
70+
SentenceManager(currentLanguage: AppSettings.selectedLanguage)
71+
.sentences
72+
.descriprtionCannotBeEmpty;
73+
return false;
74+
}
75+
descriptionErrorText.value = null;
76+
return true;
77+
}
78+
79+
void prepareDescriptionEdit(String initialValue) {
80+
descriptionController.text = initialValue;
81+
descriptionErrorText.value = null;
82+
}
83+
6284
Future<void> saveChanges() async {
6385
// If start was never edited AND backend auto-generated it (start == entry)
6486
if (!startEdited &&
@@ -175,4 +197,10 @@ class DetailRouteController extends GetxController {
175197
},
176198
);
177199
}
200+
201+
@override
202+
void onClose() {
203+
descriptionController.dispose();
204+
super.onClose();
205+
}
178206
}

lib/app/modules/detailRoute/views/description_widget.dart

Lines changed: 54 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:taskwarrior/app/utils/constants/utilites.dart';
88
import 'package:taskwarrior/app/utils/gen/fonts.gen.dart';
99
import 'package:taskwarrior/app/utils/themes/theme_extension.dart';
1010
import 'package:taskwarrior/app/utils/language/sentence_manager.dart';
11+
import 'package:taskwarrior/app/modules/detailRoute/controllers/detail_route_controller.dart';
1112

1213
class DescriptionWidget extends StatelessWidget {
1314
const DescriptionWidget({
@@ -25,6 +26,7 @@ class DescriptionWidget extends StatelessWidget {
2526

2627
@override
2728
Widget build(BuildContext context) {
29+
final controller = Get.find<DetailRouteController>();
2830
TaskwarriorColorTheme tColors =
2931
Theme.of(context).extension<TaskwarriorColorTheme>()!;
3032
return Card(
@@ -86,64 +88,66 @@ class DescriptionWidget extends StatelessWidget {
8688
),
8789
),
8890
onTap: () {
89-
var controller = TextEditingController(
90-
text: value,
91-
);
91+
controller.prepareDescriptionEdit(value ?? '');
9292
showDialog(
9393
context: context,
94-
builder: (context) => Utils.showAlertDialog(
95-
scrollable: true,
96-
title: Text(
97-
SentenceManager(currentLanguage: AppSettings.selectedLanguage)
98-
.sentences
99-
.editDescription,
100-
style: TextStyle(
101-
color: tColors.primaryTextColor,
102-
),
103-
),
104-
content: TextField(
105-
style: TextStyle(
106-
color: tColors.primaryTextColor,
94+
builder: (context) => Obx(
95+
() => Utils.showAlertDialog(
96+
scrollable: true,
97+
title: Text(
98+
SentenceManager(currentLanguage: AppSettings.selectedLanguage)
99+
.sentences
100+
.editDescription,
101+
style: TextStyle(
102+
color: tColors.primaryTextColor,
103+
),
107104
),
108-
autofocus: true,
109-
maxLines: null,
110-
controller: controller,
111-
),
112-
actions: [
113-
TextButton(
114-
onPressed: () {
115-
Get.back();
116-
},
117-
child: Text(
118-
SentenceManager(
119-
currentLanguage: AppSettings.selectedLanguage)
120-
.sentences
121-
.cancel,
122-
style: TextStyle(
123-
color: tColors.primaryTextColor,
105+
content: TextField(
106+
style: TextStyle(
107+
color: tColors.primaryTextColor,
108+
),
109+
decoration: InputDecoration(
110+
errorText: controller.descriptionErrorText.value,
111+
errorStyle: const TextStyle(
112+
color: Colors.red,
124113
),
125114
),
115+
autofocus: true,
116+
maxLines: null,
117+
controller: controller.descriptionController,
126118
),
127-
TextButton(
128-
onPressed: () {
129-
try {
130-
callback(controller.text);
131-
Get.back();
132-
} on FormatException catch (e, trace) {
133-
logError(e, trace);
134-
}
135-
},
136-
child: Text(
137-
SentenceManager(
138-
currentLanguage: AppSettings.selectedLanguage)
139-
.sentences
140-
.submit,
141-
style: TextStyle(
142-
color: tColors.primaryTextColor,
119+
actions: [
120+
TextButton(
121+
onPressed: () => Get.back(),
122+
child: Text(
123+
SentenceManager(
124+
currentLanguage: AppSettings.selectedLanguage)
125+
.sentences
126+
.cancel,
127+
style: TextStyle(
128+
color: tColors.primaryTextColor,
129+
),
143130
),
144131
),
145-
),
146-
],
132+
TextButton(
133+
onPressed: () {
134+
if (controller.validateDescription()) {
135+
callback(controller.descriptionController.text);
136+
Get.back();
137+
}
138+
},
139+
child: Text(
140+
SentenceManager(
141+
currentLanguage: AppSettings.selectedLanguage)
142+
.sentences
143+
.submit,
144+
style: TextStyle(
145+
color: tColors.primaryTextColor,
146+
),
147+
),
148+
),
149+
],
150+
),
147151
),
148152
);
149153
},

0 commit comments

Comments
 (0)