From d524d452bddebd05a21a9e103d674505310f28ac Mon Sep 17 00:00:00 2001 From: Kima Date: Mon, 28 Aug 2023 18:25:20 +0200 Subject: [PATCH] some progress in goal planner (started goal state) --- .../images/subject_covers/math_light.png | Bin 0 -> 19672 bytes filcnaplo/lib/database/init.dart | 8 +- filcnaplo/lib/database/query.dart | 27 ++- filcnaplo/lib/database/store.dart | 16 ++ filcnaplo/pubspec.yaml | 1 + .../lib/common/round_border_icon.dart | 4 +- .../lib/pages/grades/grade_subject_view.dart | 6 +- .../goal_planner/goal_planner_screen.dart | 202 ++++++++------- .../goal_planner/goal_state_screen.dart | 229 ++++++++++++++++++ .../goal_planner/goal_state_screen.i18n.dart | 39 +++ 10 files changed, 440 insertions(+), 92 deletions(-) create mode 100644 filcnaplo/assets/images/subject_covers/math_light.png create mode 100644 filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.dart create mode 100644 filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.i18n.dart diff --git a/filcnaplo/assets/images/subject_covers/math_light.png b/filcnaplo/assets/images/subject_covers/math_light.png new file mode 100644 index 0000000000000000000000000000000000000000..eb3e2f518951b484985709a3292f0c0d3fc50c07 GIT binary patch literal 19672 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 literal 0 HcmV?d00001 diff --git a/filcnaplo/lib/database/init.dart b/filcnaplo/lib/database/init.dart index 8c01136f..1519f0a6 100644 --- a/filcnaplo/lib/database/init.dart +++ b/filcnaplo/lib/database/init.dart @@ -46,8 +46,10 @@ const userDataDB = DatabaseStruct("user_data", { "renamed_teachers": String, // "subject_lesson_count": String, // non kreta data "last_seen_grade": int, - // goal plans // non kreta data + // goal planning // non kreta data "goal_plans": String, + "goal_averages": String, + "goal_befores": String, }); Future createTable(Database db, DatabaseStruct struct) => @@ -99,8 +101,10 @@ Future initDB(DatabaseProvider database) async { "renamed_teachers": "{}", // "subject_lesson_count": "{}", // non kreta data "last_seen_grade": 0, - // goal plans // non kreta data + // goal planning // non kreta data "goal_plans": "{}", + "goal_averages": "{}", + "goal_befores": "{}", }); } catch (error) { print("ERROR: migrateDB: $error"); diff --git a/filcnaplo/lib/database/query.dart b/filcnaplo/lib/database/query.dart index 47066150..b3a6de85 100644 --- a/filcnaplo/lib/database/query.dart +++ b/filcnaplo/lib/database/query.dart @@ -192,6 +192,7 @@ class UserDatabaseQuery { return lastSeen; } + // renamed things Future> renamedSubjects({required String userId}) async { List userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]); @@ -214,14 +215,36 @@ class UserDatabaseQuery { .map((key, value) => MapEntry(key.toString(), value.toString())); } + // goal planner Future> subjectGoalPlans({required String userId}) async { List userData = await db.query("user_data", where: "id = ?", whereArgs: [userId]); if (userData.isEmpty) return {}; - String? goalPlansJson = - userData.elementAt(0)["goal_plans"] as String?; + String? goalPlansJson = userData.elementAt(0)["goal_plans"] as String?; if (goalPlansJson == null) return {}; return (jsonDecode(goalPlansJson) as Map) .map((key, value) => MapEntry(key.toString(), value.toString())); } + + Future> subjectGoalAverages( + {required String userId}) async { + List userData = + await db.query("user_data", where: "id = ?", whereArgs: [userId]); + if (userData.isEmpty) return {}; + String? goalAvgsJson = userData.elementAt(0)["goal_averages"] as String?; + if (goalAvgsJson == null) return {}; + return (jsonDecode(goalAvgsJson) as Map) + .map((key, value) => MapEntry(key.toString(), value.toString())); + } + + Future> subjectGoalBefores( + {required String userId}) async { + List userData = + await db.query("user_data", where: "id = ?", whereArgs: [userId]); + if (userData.isEmpty) return {}; + String? goalBeforesJson = userData.elementAt(0)["goal_befores"] as String?; + if (goalBeforesJson == null) return {}; + return (jsonDecode(goalBeforesJson) as Map) + .map((key, value) => MapEntry(key.toString(), value.toString())); + } } diff --git a/filcnaplo/lib/database/store.dart b/filcnaplo/lib/database/store.dart index 13192861..4083bec0 100644 --- a/filcnaplo/lib/database/store.dart +++ b/filcnaplo/lib/database/store.dart @@ -127,6 +127,7 @@ class UserDatabaseStore { where: "id = ?", whereArgs: [userId]); } + // renamed things Future storeRenamedSubjects(Map subjects, {required String userId}) async { String renamedSubjectsJson = jsonEncode(subjects); @@ -141,10 +142,25 @@ class UserDatabaseStore { where: "id = ?", whereArgs: [userId]); } + // goal planner Future storeSubjectGoalPlans(Map plans, {required String userId}) async { String goalPlansJson = jsonEncode(plans); await db.update("user_data", {"goal_plans": goalPlansJson}, where: "id = ?", whereArgs: [userId]); } + + Future storeSubjectGoalAverages(Map avgs, + {required String userId}) async { + String goalAvgsJson = jsonEncode(avgs); + await db.update("user_data", {"goal_averages": goalAvgsJson}, + where: "id = ?", whereArgs: [userId]); + } + + Future storeSubjectGoalBefores(Map befores, + {required String userId}) async { + String goalBeforesJson = jsonEncode(befores); + await db.update("user_data", {"goal_befores": goalBeforesJson}, + where: "id = ?", whereArgs: [userId]); + } } diff --git a/filcnaplo/pubspec.yaml b/filcnaplo/pubspec.yaml index be6afaab..751aa3e4 100644 --- a/filcnaplo/pubspec.yaml +++ b/filcnaplo/pubspec.yaml @@ -86,6 +86,7 @@ flutter: - assets/icons/ic_splash.png - assets/animations/ - assets/images/ + - assets/images/subject_covers/ fonts: - family: FilcIcons diff --git a/filcnaplo_mobile_ui/lib/common/round_border_icon.dart b/filcnaplo_mobile_ui/lib/common/round_border_icon.dart index f8c92203..ac1fdf47 100644 --- a/filcnaplo_mobile_ui/lib/common/round_border_icon.dart +++ b/filcnaplo_mobile_ui/lib/common/round_border_icon.dart @@ -3,12 +3,14 @@ import 'package:flutter/material.dart'; class RoundBorderIcon extends StatelessWidget { final Color color; final double width; + final double padding; final Widget icon; const RoundBorderIcon( {Key? key, this.color = Colors.black, this.width = 1.5, + this.padding = 5.0, required this.icon}) : super(key: key); @@ -20,7 +22,7 @@ class RoundBorderIcon extends StatelessWidget { borderRadius: BorderRadius.circular(50.0), ), child: Padding( - padding: const EdgeInsets.all(5.0), + padding: EdgeInsets.all(padding), child: icon, ), ); diff --git a/filcnaplo_mobile_ui/lib/pages/grades/grade_subject_view.dart b/filcnaplo_mobile_ui/lib/pages/grades/grade_subject_view.dart index 29217c80..0c0c1522 100755 --- a/filcnaplo_mobile_ui/lib/pages/grades/grade_subject_view.dart +++ b/filcnaplo_mobile_ui/lib/pages/grades/grade_subject_view.dart @@ -26,6 +26,7 @@ import 'package:filcnaplo_mobile_ui/pages/grades/subject_grades_container.dart'; import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_planner_screen.dart'; import 'package:filcnaplo_premium/models/premium_scopes.dart'; import 'package:filcnaplo_premium/providers/premium_provider.dart'; +import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_state_screen.dart'; import 'package:filcnaplo_premium/ui/mobile/premium/upsell.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -292,12 +293,11 @@ class _GradeSubjectViewState extends State { onTap: () { Navigator.of(context).push(CupertinoPageRoute( builder: (context) => - GoalPlannerScreen(subject: widget.subject))); + GoalStateScreen(subject: widget.subject))); }, child: Container( width: 54.0, - padding: const EdgeInsets.symmetric( - horizontal: 5.0, vertical: 8.0), + padding: const EdgeInsets.symmetric(vertical: 8.0), decoration: BoxDecoration( borderRadius: BorderRadius.circular(45.0), color: Theme.of(context) diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_planner_screen.dart b/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_planner_screen.dart index 3db2e2d6..4cf8acfe 100644 --- a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_planner_screen.dart +++ b/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_planner_screen.dart @@ -65,6 +65,15 @@ class _GoalPlannerScreenState extends State { return await dbProvider.userQuery.subjectGoalPlans(userId: user.id!); } + Future> fetchGoalAverages() async { + return await dbProvider.userQuery.subjectGoalAverages(userId: user.id!); + } + + // haha bees lol + Future> fetchGoalBees() async { + return await dbProvider.userQuery.subjectGoalBefores(userId: user.id!); + } + PlanResult getResult() { final currentAvg = GoalPlannerHelper.averageEvals(grades); @@ -148,7 +157,11 @@ class _GoalPlannerScreenState extends State { body: SafeArea( child: ListView( padding: const EdgeInsets.only( - left: 22.0, right: 22.0, top: 5.0, bottom: 220.0), + top: 5.0, + bottom: 220.0, + right: 15.0, + left: 2.0, + ), children: [ // Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -215,91 +228,99 @@ class _GoalPlannerScreenState extends State { ], ), const SizedBox(height: 12.0), - Text( - "set_a_goal".i18n, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 20.0, + Padding( + padding: const EdgeInsets.only(left: 22.0, right: 22.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "set_a_goal".i18n, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20.0, + ), + ), + const SizedBox(height: 4.0), + Text( + goalValue.toString(), + style: TextStyle( + fontWeight: FontWeight.w900, + fontSize: 48.0, + color: gradeColor(goalValue.round(), settingsProvider), + ), + ), + // Column( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Text( + // "select_subject".i18n, + // style: const TextStyle( + // fontWeight: FontWeight.bold, + // fontSize: 20.0, + // ), + // ), + // const SizedBox(height: 4.0), + // Column( + // children: [ + // Icon( + // SubjectIcon.resolveVariant( + // context: context, + // subject: widget.subject, + // ), + // size: 48.0, + // ), + // Text( + // (widget.subject.isRenamed + // ? widget.subject.renamedTo + // : widget.subject.name) ?? + // '', + // style: const TextStyle( + // fontSize: 17.0, + // fontWeight: FontWeight.w500, + // ), + // ) + // ], + // ) + // ], + // ) + const SizedBox(height: 24.0), + Text( + "pick_route".i18n, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 20.0, + ), + ), + const SizedBox(height: 12.0), + if (recommended != null) + RouteOption( + plan: recommended!, + mark: RouteMark.recommended, + selected: selectedRoute == recommended!, + onSelected: () => setState(() { + selectedRoute = recommended; + }), + ), + if (fastest != null && fastest != recommended) + RouteOption( + plan: fastest!, + mark: RouteMark.fastest, + selected: selectedRoute == fastest!, + onSelected: () => setState(() { + selectedRoute = fastest; + }), + ), + ...otherPlans.map((e) => RouteOption( + plan: e, + selected: selectedRoute == e, + onSelected: () => setState(() { + selectedRoute = e; + }), + )), + if (result != PlanResult.available) Text(result.name), + ], ), ), - const SizedBox(height: 4.0), - Text( - goalValue.toString(), - style: TextStyle( - fontWeight: FontWeight.w900, - fontSize: 48.0, - color: gradeColor(goalValue.round(), settingsProvider), - ), - ), - // Column( - // mainAxisAlignment: MainAxisAlignment.center, - // children: [ - // Text( - // "select_subject".i18n, - // style: const TextStyle( - // fontWeight: FontWeight.bold, - // fontSize: 20.0, - // ), - // ), - // const SizedBox(height: 4.0), - // Column( - // children: [ - // Icon( - // SubjectIcon.resolveVariant( - // context: context, - // subject: widget.subject, - // ), - // size: 48.0, - // ), - // Text( - // (widget.subject.isRenamed - // ? widget.subject.renamedTo - // : widget.subject.name) ?? - // '', - // style: const TextStyle( - // fontSize: 17.0, - // fontWeight: FontWeight.w500, - // ), - // ) - // ], - // ) - // ], - // ) - const SizedBox(height: 24.0), - Text( - "pick_route".i18n, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 20.0, - ), - ), - const SizedBox(height: 12.0), - if (recommended != null) - RouteOption( - plan: recommended!, - mark: RouteMark.recommended, - selected: selectedRoute == recommended!, - onSelected: () => setState(() { - selectedRoute = recommended; - }), - ), - if (fastest != null && fastest != recommended) - RouteOption( - plan: fastest!, - mark: RouteMark.fastest, - selected: selectedRoute == fastest!, - onSelected: () => setState(() { - selectedRoute = fastest; - }), - ), - ...otherPlans.map((e) => RouteOption( - plan: e, - selected: selectedRoute == e, - onSelected: () => setState(() { - selectedRoute = e; - }), - )), - if (result != PlanResult.available) Text(result.name), ], ), ), @@ -346,12 +367,25 @@ class _GoalPlannerScreenState extends State { } final goalPlans = await fetchGoalPlans(); + final goalAvgs = await fetchGoalAverages(); + final goalBeforeGrades = await fetchGoalBees(); + goalPlans[widget.subject.id] = selectedRoute!.dbString; + goalAvgs[widget.subject.id] = + goalValue.toStringAsFixed(1); + goalBeforeGrades[widget.subject.id] = + avg.toStringAsFixed(1); await dbProvider.userStore.storeSubjectGoalPlans( goalPlans, userId: user.id!); + await dbProvider.userStore.storeSubjectGoalAverages( + goalAvgs, + userId: user.id!); + await dbProvider.userStore.storeSubjectGoalBefores( + goalBeforeGrades, + userId: user.id!); Navigator.of(context).pop(); }, diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.dart b/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.dart new file mode 100644 index 00000000..03971600 --- /dev/null +++ b/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.dart @@ -0,0 +1,229 @@ +import 'package:filcnaplo/api/providers/database_provider.dart'; +import 'package:filcnaplo/api/providers/user_provider.dart'; +import 'package:filcnaplo/helpers/subject.dart'; +import 'package:filcnaplo_kreta_api/models/subject.dart'; +import 'package:filcnaplo_mobile_ui/common/average_display.dart'; +import 'package:filcnaplo_mobile_ui/common/panel/panel.dart'; +import 'package:filcnaplo_mobile_ui/common/round_border_icon.dart'; +import 'package:filcnaplo_premium/ui/mobile/goal_planner/goal_state_screen.i18n.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class GoalStateScreen extends StatefulWidget { + final Subject subject; + + const GoalStateScreen({Key? key, required this.subject}) : super(key: key); + + @override + State createState() => _GoalStateScreenState(); +} + +class _GoalStateScreenState extends State { + late UserProvider user; + late DatabaseProvider db; + + double goalAvg = 0.0; + double beforeAvg = 0.0; + double avgDifference = 0; + + @override + void initState() { + super.initState(); + user = Provider.of(context, listen: false); + db = Provider.of(context, listen: false); + + WidgetsBinding.instance.addPostFrameCallback((_) { + fetchGoalAverages(); + }); + } + + void fetchGoalAverages() async { + var goalAvgRes = await db.userQuery.subjectGoalAverages(userId: user.id!); + var beforeAvgRes = await db.userQuery.subjectGoalBefores(userId: user.id!); + + String? goalAvgStr = goalAvgRes[widget.subject.id]; + String? beforeAvgStr = beforeAvgRes[widget.subject.id]; + goalAvg = double.parse(goalAvgStr ?? '0.0'); + beforeAvg = double.parse(beforeAvgStr ?? '0.0'); + + avgDifference = ((goalAvg - beforeAvg) / beforeAvg.abs()) * 100; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/subject_covers/math_light.png'), + fit: BoxFit.fitWidth, + alignment: Alignment.topCenter, + ), + ), + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Theme.of(context).scaffoldBackgroundColor.withOpacity(0.2), + Theme.of(context).scaffoldBackgroundColor, + ], + stops: const [ + 0.1, + 0.22, + ], + ), + ), + child: Padding( + padding: const EdgeInsets.only(top: 10.0, left: 2.0, right: 2.0), + child: ListView( + children: [ + const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + BackButton(), + ], + ), + const SizedBox(height: 22.0), + Column( + children: [ + RoundBorderIcon( + icon: Icon( + SubjectIcon.resolveVariant( + context: context, + subject: widget.subject, + ), + size: 26.0, + weight: 2.5, + ), + padding: 8.0, + width: 2.5, + ), + const SizedBox( + height: 10.0, + ), + Text( + (widget.subject.isRenamed + ? widget.subject.renamedTo + : widget.subject.name) ?? + 'goal_planner_title'.i18n, + style: const TextStyle( + fontSize: 30.0, + fontWeight: FontWeight.w700, + ), + ), + Text( + 'almost_there'.i18n, + style: const TextStyle( + fontSize: 22.0, + fontWeight: FontWeight.w400, + height: 1.0, + ), + ), + ], + ), + const SizedBox(height: 28.0), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + 'started_with'.i18n, + style: const TextStyle( + fontWeight: FontWeight.w700, + fontSize: 20.0, + ), + ), + ], + ), + Row( + children: [ + Text( + 'current'.i18n, + style: const TextStyle( + fontWeight: FontWeight.w700, + fontSize: 20.0, + ), + ), + ], + ), + ], + ), + ), + const SizedBox(height: 10.0), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12.0), + child: Panel( + padding: const EdgeInsets.all(18.0), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'your_goal'.i18n, + style: const TextStyle( + fontSize: 23.0, + fontWeight: FontWeight.w700, + ), + ), + RawMaterialButton( + onPressed: () async {}, + fillColor: Colors.black, + shape: const StadiumBorder(), + padding: + const EdgeInsets.symmetric(horizontal: 18.0), + child: Text( + "change_it".i18n, + style: const TextStyle( + height: 1.0, + color: Colors.white, + fontSize: 14.0, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + Row( + children: [ + Text( + goalAvg.toString(), + style: const TextStyle( + height: 1.1, + fontSize: 42.0, + fontWeight: FontWeight.w800, + ), + ), + Center( + child: Container( + width: 54.0, + padding: + const EdgeInsets.symmetric(vertical: 8.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(45.0), + color: Colors.limeAccent.shade700 + .withOpacity(.15), + ), + child: Text(avgDifference.toString()), + ), + ), + ], + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.i18n.dart b/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.i18n.dart new file mode 100644 index 00000000..90fabd59 --- /dev/null +++ b/filcnaplo_premium/lib/ui/mobile/goal_planner/goal_state_screen.i18n.dart @@ -0,0 +1,39 @@ +import 'package:i18n_extension/i18n_extension.dart'; + +extension Localization on String { + static final _t = Translations.byLocale("hu_hu") + + { + "en_en": { + "goal_planner_title": "Goal Planning", + "almost_there": "Almost there! Keep going!", + "select_subject": "Subject", + "pick_route": "Pick a Route", + "track_it": "Track it!", + "recommended": "Recommended", + "fastest": "Fastest", + }, + "hu_hu": { + "goal_planner_title": "Cél követés", + "set_a_goal": "Kitűzött cél", + "select_subject": "Tantárgy", + "pick_route": "Válassz egy utat", + "track_it": "Követés!", + "recommended": "Ajánlott", + "fastest": "Leggyorsabb", + }, + "de_de": { + "goal_planner_title": "Zielplanung", + "set_a_goal": "Dein Ziel", + "select_subject": "Thema", + "pick_route": "Wähle einen Weg", + "track_it": "Verfolge es!", + "recommended": "Empfohlen", + "fastest": "Am schnellsten", + }, + }; + + String get i18n => localize(this, _t); + String fill(List params) => localizeFill(this, params); + String plural(int value) => localizePlural(value, this, _t); + String version(Object modifier) => localizeVersion(modifier, this, _t); +}