diff --git a/firka/lib/l10n b/firka/lib/l10n index a52a907..fa3a97f 160000 --- a/firka/lib/l10n +++ b/firka/lib/l10n @@ -1 +1 @@ -Subproject commit a52a907c9f02f90750b71e7144aeb5d0545465a8 +Subproject commit fa3a97f2d499bd6022643f0979c6d79e3ae9f08c diff --git a/firka/lib/ui/components/common_bottom_sheets.dart b/firka/lib/ui/components/common_bottom_sheets.dart index 6f1d230..ac9e276 100644 --- a/firka/lib/ui/components/common_bottom_sheets.dart +++ b/firka/lib/ui/components/common_bottom_sheets.dart @@ -986,8 +986,9 @@ Future showHomeworkBottomSheet( Future showGradeCalculatorBottomSheet( BuildContext context, AppInitialization data, - Subject subject, -) async { + Subject subject, { + void Function(int grade, int weight)? onAdd, +}) async { showModalBottomSheet( context: context, elevation: 100, @@ -1017,6 +1018,7 @@ Future showGradeCalculatorBottomSheet( child: _GradeCalculatorSheetContent( data: data, subject: subject, + onAdd: onAdd, ), ), ), @@ -1030,10 +1032,12 @@ Future showGradeCalculatorBottomSheet( class _GradeCalculatorSheetContent extends StatefulWidget { final AppInitialization data; final Subject subject; + final void Function(int grade, int weight)? onAdd; const _GradeCalculatorSheetContent({ required this.data, required this.subject, + this.onAdd, }); @override @@ -1193,9 +1197,9 @@ class _GradeCalculatorSheetContentState ), child: Slider( value: weightPercent.toDouble(), - min: 0, - max: 100, - divisions: 100, + min: 1, + max: 500, + divisions: 499, onChanged: (v) => setState(() => weightPercent = v.round()), ), ), @@ -1203,7 +1207,7 @@ class _GradeCalculatorSheetContentState ), SizedBox(width: 12), SizedBox( - width: 48, + width: 56, child: Text( '$weightPercent%', style: appStyle.fonts.B_16R.apply( @@ -1231,6 +1235,7 @@ class _GradeCalculatorSheetContentState setState(() { entries.add((selectedGrade, weightPercent)); }); + widget.onAdd?.call(selectedGrade, weightPercent); }, child: Text( widget.data.l10n.grade_calculator_add, @@ -1257,8 +1262,9 @@ class _GradeCalculatorSheetContentState Future showSubjectBottomSheetSettings( BuildContext context, AppInitialization data, - Subject subject, -) async { + Subject subject, { + void Function(int grade, int weight)? onAddFromCalculator, +}) async { final parentContext = context; showModalBottomSheet( context: context, @@ -1315,6 +1321,7 @@ Future showSubjectBottomSheetSettings( parentContext, data, subject, + onAdd: onAddFromCalculator, ); }, child: Container( diff --git a/firka/lib/ui/phone/pages/home/home_grades_subject.dart b/firka/lib/ui/phone/pages/home/home_grades_subject.dart index 341536f..807d10a 100644 --- a/firka/lib/ui/phone/pages/home/home_grades_subject.dart +++ b/firka/lib/ui/phone/pages/home/home_grades_subject.dart @@ -29,6 +29,7 @@ class HomeGradesSubjectScreen extends StatefulWidget { class _HomeGradesSubjectScreen extends FirkaState { Iterable? grades; + final List<(int grade, int weight)> _ghostEntries = []; void _onRefreshRequested(BuildContext context) async { final cubit = context.read(); @@ -55,6 +56,41 @@ class _HomeGradesSubjectScreen extends FirkaState { })(); } + List _gradesWithGhosts(Subject subject) { + final real = grades?.toList() ?? []; + if (_ghostEntries.isEmpty) return real; + final baseDate = real.isEmpty + ? DateTime.now() + : real + .map((g) => g.creationDate) + .reduce((a, b) => a.isAfter(b) ? a : b); + final osztalyzat = NameUidDesc( + uid: '1,Osztalyzat', + name: 'Osztalyzat', + description: '', + ); + final ghostGrades = []; + for (var i = 0; i < _ghostEntries.length; i++) { + final e = _ghostEntries[i]; + ghostGrades.add( + Grade( + uid: 'ghost-$i-${e.$1}-${e.$2}', + recordDate: baseDate.add(Duration(seconds: i)), + creationDate: baseDate.add(Duration(seconds: i)), + subject: subject, + type: osztalyzat, + valueType: osztalyzat, + teacher: '', + strValue: '${e.$1}', + sortIndex: 0, + numericValue: e.$1, + weightPercentage: e.$2, + ), + ); + } + return [...real, ...ghostGrades]; + } + @override Widget build(BuildContext context) { return BlocListener( @@ -72,7 +108,30 @@ class _HomeGradesSubjectScreen extends FirkaState { var aGrade = grades!.first; var groups = grades!.groupList((grade) => grade.recordDate); + final ghostGradeWidgets = _ghostEntries.reversed.map((e) { + return GestureDetector( + child: FirkaCard( + left: [ + Row( + children: [ + GradeWidget.gradeValue(e.$1), + SizedBox(width: 8), + Text( + '${widget.data.l10n.ghost_grade} ${e.$2}%', + style: appStyle.fonts.B_16SB.apply( + color: appStyle.colors.textPrimary, + ), + ), + ], + ), + ], + ), + onTap: () {}, + ); + }).toList(); + var gradeWidgets = List.empty(growable: true); + gradeWidgets.addAll(ghostGradeWidgets); for (var group in groups.entries) { gradeWidgets.add(SizedBox(height: 8)); @@ -190,6 +249,9 @@ class _HomeGradesSubjectScreen extends FirkaState { context, widget.data, aGrade.subject, + onAddFromCalculator: (g, w) { + setState(() => _ghostEntries.add((g, w))); + }, ); }, ), @@ -237,7 +299,9 @@ class _HomeGradesSubjectScreen extends FirkaState { SizedBox(height: 15), ], ), - GradeChartWithInteraction(grades: grades?.toList() ?? []), + GradeChartWithInteraction( + grades: _gradesWithGhosts(aGrade.subject), + ), SizedBox(height: 12), Padding( padding: EdgeInsets.only(left: 4), diff --git a/firka/lib/ui/phone/widgets/grade_chart.dart b/firka/lib/ui/phone/widgets/grade_chart.dart index e45a498..b7cd8b4 100644 --- a/firka/lib/ui/phone/widgets/grade_chart.dart +++ b/firka/lib/ui/phone/widgets/grade_chart.dart @@ -26,7 +26,7 @@ class _GradeChartState extends State { appStyle.colors.grade1, ]; - late final List spots; + late List spots; double? _subjectAverageInList(List grades, String subjectUid) { double weightedSum = 0; @@ -67,7 +67,10 @@ class _GradeChartState extends State { @override void initState() { super.initState(); + _computeSpots(); + } + void _computeSpots() { final sortedGrades = List.from(widget.grades) ..sort((a, b) => a.creationDate.compareTo(b.creationDate)); @@ -90,6 +93,14 @@ class _GradeChartState extends State { } } + @override + void didUpdateWidget(covariant GradeChart oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.grades.length != widget.grades.length) { + _computeSpots(); + } + } + @override Widget build(BuildContext context) { return ClipRRect(