Skip to content

Commit

Permalink
Added Habit contract
Browse files Browse the repository at this point in the history
  • Loading branch information
xpavle00 committed Apr 18, 2023
1 parent c26df60 commit 0f38abb
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 25 deletions.
81 changes: 77 additions & 4 deletions lib/habits/edit_habit_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ class _EditHabitScreenState extends State<EditHabitScreen> {
TextEditingController cue = TextEditingController();
TextEditingController routine = TextEditingController();
TextEditingController reward = TextEditingController();
TextEditingController sanction = TextEditingController();
TextEditingController accountant = TextEditingController();
TimeOfDay notTime = const TimeOfDay(hour: 12, minute: 0);
bool twoDayRule = false;
bool showReward = false;
bool advanced = false;
bool notification = false;
bool showSanction = false;

Future<void> setNotificationTime(context) async {
TimeOfDay? selectedTime;
Expand All @@ -61,6 +64,9 @@ class _EditHabitScreenState extends State<EditHabitScreen> {
advanced = widget.habitData!.advanced;
notification = widget.habitData!.notification;
notTime = widget.habitData!.notTime;
sanction.text = widget.habitData!.sanction;
showSanction = widget.habitData!.showSanction;
accountant.text = widget.habitData!.accountant;
}
}

Expand All @@ -70,6 +76,8 @@ class _EditHabitScreenState extends State<EditHabitScreen> {
cue.dispose();
routine.dispose();
reward.dispose();
sanction.dispose();
accountant.dispose();
super.dispose();
}

Expand Down Expand Up @@ -120,6 +128,9 @@ class _EditHabitScreenState extends State<EditHabitScreen> {
notTime: notTime,
position: widget.habitData!.position,
events: widget.habitData!.events,
sanction: sanction.text.toString(),
showSanction: showSanction,
accountant: accountant.text.toString(),
),
);
} else {
Expand All @@ -133,6 +144,9 @@ class _EditHabitScreenState extends State<EditHabitScreen> {
advanced,
notification,
notTime,
sanction.text.toString(),
showSanction,
accountant.text.toString(),
);
}
Navigator.of(context).pop();
Expand Down Expand Up @@ -184,7 +198,6 @@ class _EditHabitScreenState extends State<EditHabitScreen> {
const Padding(
padding: EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Tooltip(
triggerMode: TooltipTriggerMode.tap,
message:
"With two day rule, you can miss one day and do not lose a streak if the next day is successful.",
child: Icon(
Expand Down Expand Up @@ -218,7 +231,7 @@ class _EditHabitScreenState extends State<EditHabitScreen> {
child: const Center(
child: Text(
"This section helps you better define your habits. You should define cue, routine, and reward for every habit.",
textAlign: TextAlign.center,
textAlign: TextAlign.left,
),
),
),
Expand Down Expand Up @@ -285,7 +298,6 @@ class _EditHabitScreenState extends State<EditHabitScreen> {
const Padding(
padding: EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Tooltip(
triggerMode: TooltipTriggerMode.tap,
message:
"The remainder of the reward after a successful routine.",
child: Icon(
Expand All @@ -299,8 +311,69 @@ class _EditHabitScreenState extends State<EditHabitScreen> {
],
),
),
const ListTile(
title: Text(
"Habit contract",
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: const Center(
child: Text(
"While positive reinforcement is recommended, some people may opt for a habit contract. A habit contract allows you to specify a sanction that will be imposed if you miss your habit, and may involve an accountant who helps supervise your goals.",
textAlign: TextAlign.left,
),
),
),
const SizedBox(
height: 10,
),
TextContainer(
title: sanction,
hint: 'Donate 10\$ to charity',
label: 'Sanction',
),
Container(
margin: const EdgeInsets.symmetric(
vertical: 5, horizontal: 20),
child: Row(
children: <Widget>[
Checkbox(
onChanged: (bool? value) {
setState(() {
showSanction = value!;
});
},
value: showSanction,
),
const Text("Show sanction"),
const Padding(
padding: EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Tooltip(
message:
"The remainder of the sanction after a unsuccessful routine.",
child: Icon(
Icons.info,
semanticLabel: 'Tooltip',
color: Colors.grey,
size: 20,
),
),
),
],
),
),
TextContainer(
title: accountant,
hint: 'Dan',
label: 'Accountant',
),
const SizedBox(
height: 50,
height: 110,
),
],
)
Expand Down
46 changes: 39 additions & 7 deletions lib/habits/habit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class Habit extends StatefulWidget {
"advanced": habitData.advanced ? 1 : 0,
"notification": habitData.notification ? 1 : 0,
"notTime": "${habitData.notTime.hour}:${habitData.notTime.minute}",
"sanction": habitData.sanction,
"showSanction": habitData.showSanction ? 1 : 0,
"accountant": habitData.accountant,
};
}

Expand All @@ -54,6 +57,9 @@ class Habit extends StatefulWidget {
"events": habitData.events.map((key, value) {
return MapEntry(key.toString(), [value[0].toString(), value[1]]);
}),
"sanction": habitData.sanction,
"showSanction": habitData.showSanction ? 1 : 0,
"accountant": habitData.accountant,
};
}

Expand All @@ -71,25 +77,25 @@ class Habit extends StatefulWidget {
notification: json['notification'] != 0 ? true : false,
notTime: parseTimeOfDay(json['notTime']),
events: doEvents(json['events']),
sanction: json['sanction'] ?? "",
showSanction: (json['showSanction'] ?? 0) != 0 ? true : false,
accountant: json['accountant'] ?? "",
);

static SplayTreeMap<DateTime, List> doEvents(Map<String, dynamic> input) {
SplayTreeMap<DateTime, List> result = SplayTreeMap<DateTime, List>();

input.forEach((key, value) {
result[DateTime.parse(key)] = [
DayType.values.firstWhere((e) =>
e.toString() == reformatOld(value[0])
),
DayType.values.firstWhere((e) => e.toString() == reformatOld(value[0])),
value[1]
];
});
return result;
}

// To be compatible with older version backup
static String reformatOld(String value)
{
static String reformatOld(String value) {
var all = value.split('.');
return "${all[0]}.${all[1].toLowerCase()}";
}
Expand Down Expand Up @@ -155,6 +161,30 @@ class HabitState extends State<Habit> {
}
}

showSanctionNotification(date) {
if (isSameDay(date, DateTime.now()) &&
widget.habitData.showSanction &&
widget.habitData.sanction != "") {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
duration: const Duration(seconds: 2),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
content: Text(
"Oh no! Your sanction:\n${widget.habitData.sanction}",
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.white),
),
backgroundColor:
Provider.of<SettingsManager>(context, listen: false).failColor,
behavior: SnackBarBehavior.floating,
),
);
}
}

List _getEventsForDay(DateTime day) {
return widget.habitData.events[transformDate(day)] ?? [];
}
Expand Down Expand Up @@ -298,9 +328,11 @@ class HabitState extends State<Habit> {
? Provider.of<SettingsManager>(context, listen: false)
.checkColor
: events[0] == DayType.fail
? Provider.of<SettingsManager>(context, listen: false)
? Provider.of<SettingsManager>(context,
listen: false)
.failColor
: Provider.of<SettingsManager>(context, listen: false)
: Provider.of<SettingsManager>(context,
listen: false)
.skipColor,
borderRadius: BorderRadius.circular(10.0),
),
Expand Down
11 changes: 10 additions & 1 deletion lib/habits/habits_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,10 @@ class HabitsManager extends ChangeNotifier {
bool showReward,
bool advanced,
bool notification,
TimeOfDay notTime) {
TimeOfDay notTime,
String sanction,
bool showSanction,
String accountant) {
Habit newHabit = Habit(
habitData: HabitData(
position: allHabits.length,
Expand All @@ -162,6 +165,9 @@ class HabitsManager extends ChangeNotifier {
events: SplayTreeMap<DateTime, List>(),
notification: notification,
notTime: notTime,
sanction: sanction,
showSanction: showSanction,
accountant: accountant,
),
);
_haboModel.insertHabit(newHabit).then(
Expand Down Expand Up @@ -191,6 +197,9 @@ class HabitsManager extends ChangeNotifier {
hab.habitData.advanced = habitData.advanced;
hab.habitData.notification = habitData.notification;
hab.habitData.notTime = habitData.notTime;
hab.habitData.sanction = habitData.sanction;
hab.habitData.showSanction = habitData.showSanction;
hab.habitData.accountant = habitData.accountant;
_haboModel.editHabit(hab);
if (habitData.notification) {
setHabitNotification(
Expand Down
7 changes: 5 additions & 2 deletions lib/habits/one_day_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ class OneDayButton extends StatelessWidget {
if (value.key == const Key('Check') ||
value.key == const Key('Fail') ||
value.key == const Key('Skip')) {
Provider.of<HabitsManager>(context, listen: false).addEvent(
id, date, [
Provider.of<HabitsManager>(context, listen: false)
.addEvent(id, date, [
DayType.values[icons
.indexWhere((element) => element.key == value.key)],
comment
Expand All @@ -144,6 +144,9 @@ class OneDayButton extends StatelessWidget {
} else {
Provider.of<SettingsManager>(context, listen: false)
.playClickSound();
if (value.key == const Key('Fail')) {
parent.showSanctionNotification(date);
}
}
} else if (value.key == const Key('Comment')) {
showCommentDialog(context, index, comment);
Expand Down
6 changes: 6 additions & 0 deletions lib/model/habit_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class HabitData {
required this.notification,
required this.notTime,
required this.events,
required this.sanction,
required this.showSanction,
required this.accountant,
});

SplayTreeMap<DateTime, List> events;
Expand All @@ -31,4 +34,7 @@ class HabitData {
bool advanced;
bool notification;
TimeOfDay notTime;
String sanction;
bool showSanction;
String accountant;
}
Loading

0 comments on commit 0f38abb

Please sign in to comment.