Skip to content

Commit 2d73068

Browse files
feat: add confirmation dialog for task details
1 parent c190e1a commit 2d73068

File tree

1 file changed

+147
-87
lines changed

1 file changed

+147
-87
lines changed

lib/app/modules/home/views/show_details.dart

Lines changed: 147 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ignore_for_file: use_build_context_synchronously
1+
// ignore_for_file: deprecated_member_use, use_build_context_synchronously
22

33
import 'package:flutter/material.dart';
44
import 'package:google_fonts/google_fonts.dart';
@@ -50,83 +50,83 @@ class _TaskDetailsState extends State<TaskDetails> {
5050

5151
@override
5252
Widget build(BuildContext context) {
53-
return Scaffold(
54-
backgroundColor: AppSettings.isDarkMode
55-
? TaskWarriorColors.kprimaryBackgroundColor
56-
: TaskWarriorColors.kLightPrimaryBackgroundColor,
57-
appBar: AppBar(
58-
foregroundColor: TaskWarriorColors.lightGrey,
59-
backgroundColor: TaskWarriorColors.kprimaryBackgroundColor,
60-
title: Text(
61-
'Task: ${widget.task.description}',
62-
style: GoogleFonts.poppins(color: TaskWarriorColors.white),
63-
),
64-
),
65-
body: Padding(
66-
padding: const EdgeInsets.all(16.0),
67-
child: ListView(
68-
children: [
69-
_buildEditableDetail('Description:', description, (value) {
70-
setState(() {
71-
description = value;
72-
hasChanges = true;
73-
});
74-
}),
75-
_buildEditableDetail('Project:', project, (value) {
76-
setState(() {
77-
project = value;
78-
hasChanges = true;
79-
});
80-
}),
81-
_buildSelectableDetail('Status:', status, ['pending', 'completed'],
82-
(value) {
83-
setState(() {
84-
status = value;
85-
hasChanges = true;
86-
});
87-
}),
88-
_buildSelectableDetail('Priority:', priority, ['H', 'M', 'L'],
89-
(value) {
90-
setState(() {
91-
priority = value;
92-
hasChanges = true;
93-
});
94-
}),
95-
_buildDatePickerDetail('Due:', due, (value) {
96-
setState(() {
97-
due = value;
98-
hasChanges = true;
99-
});
100-
}),
101-
_buildDetail('UUID:', widget.task.uuid!),
102-
_buildDetail('Urgency:', widget.task.urgency.toString()),
103-
_buildDetail('End:', _buildDate(widget.task.end)),
104-
_buildDetail('Entry:', _buildDate(widget.task.entry)),
105-
_buildDetail('Modified:', _buildDate(widget.task.modified)),
106-
],
53+
return WillPopScope(
54+
onWillPop: () async {
55+
if (hasChanges) {
56+
final action = await _showUnsavedChangesDialog(context);
57+
if (action == UnsavedChangesAction.cancel) {
58+
return Future.value(false);
59+
} else if (action == UnsavedChangesAction.save) {
60+
await _saveTask();
61+
}
62+
}
63+
return Future.value(true);
64+
},
65+
child: Scaffold(
66+
backgroundColor: AppSettings.isDarkMode
67+
? TaskWarriorColors.kprimaryBackgroundColor
68+
: TaskWarriorColors.kLightPrimaryBackgroundColor,
69+
appBar: AppBar(
70+
foregroundColor: TaskWarriorColors.lightGrey,
71+
backgroundColor: TaskWarriorColors.kprimaryBackgroundColor,
72+
title: Text(
73+
'Task: ${widget.task.description}',
74+
style: GoogleFonts.poppins(color: TaskWarriorColors.white),
75+
),
10776
),
108-
),
109-
floatingActionButton: hasChanges
110-
? FloatingActionButton(
111-
onPressed: () async {
112-
await taskDatabase.saveEditedTaskInDB(widget.task.uuid!,
113-
description, project, status, priority, due);
77+
body: Padding(
78+
padding: const EdgeInsets.all(16.0),
79+
child: ListView(
80+
children: [
81+
_buildEditableDetail('Description:', description, (value) {
11482
setState(() {
115-
hasChanges = false;
83+
description = value;
84+
hasChanges = true;
11685
});
117-
modifyTaskOnTaskwarrior(
118-
description,
119-
project,
120-
due,
121-
priority,
122-
status,
123-
widget.task.uuid!,
124-
);
125-
// used this for testing
126-
},
127-
child: const Icon(Icons.save),
128-
)
129-
: null,
86+
}),
87+
_buildEditableDetail('Project:', project, (value) {
88+
setState(() {
89+
project = value;
90+
hasChanges = true;
91+
});
92+
}),
93+
_buildSelectableDetail(
94+
'Status:', status, ['pending', 'completed'], (value) {
95+
setState(() {
96+
status = value;
97+
hasChanges = true;
98+
});
99+
}),
100+
_buildSelectableDetail('Priority:', priority, ['H', 'M', 'L'],
101+
(value) {
102+
setState(() {
103+
priority = value;
104+
hasChanges = true;
105+
});
106+
}),
107+
_buildDatePickerDetail('Due:', due, (value) {
108+
setState(() {
109+
due = value;
110+
hasChanges = true;
111+
});
112+
}),
113+
_buildDetail('UUID:', widget.task.uuid!),
114+
_buildDetail('Urgency:', widget.task.urgency.toString()),
115+
_buildDetail('End:', _buildDate(widget.task.end)),
116+
_buildDetail('Entry:', _buildDate(widget.task.entry)),
117+
_buildDetail('Modified:', _buildDate(widget.task.modified)),
118+
],
119+
),
120+
),
121+
floatingActionButton: hasChanges
122+
? FloatingActionButton(
123+
onPressed: () async {
124+
await _saveTask();
125+
},
126+
child: const Icon(Icons.save),
127+
)
128+
: null,
129+
),
130130
);
131131
}
132132

@@ -169,25 +169,15 @@ class _TaskDetailsState extends State<TaskDetails> {
169169
return Theme(
170170
data: Theme.of(context).copyWith(
171171
colorScheme: AppSettings.isDarkMode
172-
? ColorScheme(
173-
brightness: Brightness.dark,
172+
? ColorScheme.dark(
174173
primary: TaskWarriorColors.white,
175174
onPrimary: TaskWarriorColors.black,
176-
secondary: TaskWarriorColors.black,
177-
onSecondary: TaskWarriorColors.white,
178-
error: TaskWarriorColors.red,
179-
onError: TaskWarriorColors.black,
180175
surface: TaskWarriorColors.black,
181176
onSurface: TaskWarriorColors.white,
182177
)
183-
: ColorScheme(
184-
brightness: Brightness.light,
178+
: ColorScheme.light(
185179
primary: TaskWarriorColors.black,
186180
onPrimary: TaskWarriorColors.white,
187-
secondary: TaskWarriorColors.white,
188-
onSecondary: TaskWarriorColors.black,
189-
error: TaskWarriorColors.red,
190-
onError: TaskWarriorColors.white,
191181
surface: TaskWarriorColors.white,
192182
onSurface: TaskWarriorColors.black,
193183
),
@@ -376,4 +366,74 @@ class _TaskDetailsState extends State<TaskDetails> {
376366
return '-';
377367
}
378368
}
369+
370+
Future<UnsavedChangesAction?> _showUnsavedChangesDialog(
371+
BuildContext context) async {
372+
return showDialog<UnsavedChangesAction>(
373+
context: context,
374+
barrierDismissible: false,
375+
builder: (BuildContext context) {
376+
return Utils.showAlertDialog(
377+
title: Text(
378+
'Unsaved Changes',
379+
style: TextStyle(
380+
color: AppSettings.isDarkMode
381+
? TaskWarriorColors.kprimaryTextColor
382+
: TaskWarriorColors.kLightPrimaryTextColor),
383+
),
384+
content: Text(
385+
'You have unsaved changes. What would you like to do?',
386+
style: TextStyle(
387+
color: AppSettings.isDarkMode
388+
? TaskWarriorColors.kprimaryTextColor
389+
: TaskWarriorColors.kLightPrimaryTextColor),
390+
),
391+
actions: <Widget>[
392+
TextButton(
393+
onPressed: () {
394+
Navigator.of(context).pop(UnsavedChangesAction.cancel);
395+
},
396+
child: const Text('Cancel'),
397+
),
398+
TextButton(
399+
onPressed: () {
400+
Navigator.of(context).pop(UnsavedChangesAction.discard);
401+
},
402+
child: const Text('Don\'t Save'),
403+
),
404+
TextButton(
405+
onPressed: () {
406+
Navigator.of(context).pop(UnsavedChangesAction.save);
407+
},
408+
child: const Text('Save'),
409+
),
410+
],
411+
);
412+
},
413+
);
414+
}
415+
416+
Future<void> _saveTask() async {
417+
await taskDatabase.saveEditedTaskInDB(
418+
widget.task.uuid!,
419+
description,
420+
project,
421+
status,
422+
priority,
423+
due,
424+
);
425+
setState(() {
426+
hasChanges = false;
427+
});
428+
modifyTaskOnTaskwarrior(
429+
description,
430+
project,
431+
due,
432+
priority,
433+
status,
434+
widget.task.uuid!,
435+
);
436+
}
379437
}
438+
439+
enum UnsavedChangesAction { save, discard, cancel }

0 commit comments

Comments
 (0)