diff --git a/firka/lib/api/client/kreta_client.dart b/firka/lib/api/client/kreta_client.dart index e76cd23..dc288cb 100644 --- a/firka/lib/api/client/kreta_client.dart +++ b/firka/lib/api/client/kreta_client.dart @@ -495,6 +495,51 @@ class KretaClient { return (resp, statusCode, null, false); } + ApiResponse>? classGroupAveragesCache; + + Future>> getClassGroupAverages( + ClassGroup classGroup, { + bool forceCache = true, + }) async { + String? err; + if (classGroup.studyTask == null) { + err = "classGroup.studyTask is null"; + logger.warning(err); + return ApiResponse([], 0, err, false); + } + if (!forceCache) { + classGroupAveragesCache = null; + } else if (classGroupAveragesCache != null) { + return classGroupAveragesCache!; + } + var studyTaskUid = classGroup.studyTask!.uid.toString().split(",").first; + var (resp, status, ex, cached) = await _cachingGet( + CacheId.getClassGroupAvg, + KretaEndpoints.getClassGroupAvg(model.iss!, studyTaskUid), + forceCache, + 0, + ); + + var items = List.empty(growable: true); + try { + List rawItems = resp; + for (var item in rawItems) { + items.add(ClassGroupSubjectAverage.fromJson(item)); + } + } catch (ex) { + err = ex.toString(); + } + + if (ex != null) { + err = ex.toString(); + } + + if (ex == null) { + classGroupAveragesCache = ApiResponse(items, 200, null, true); + } + return ApiResponse(items, status, err, cached); + } + ApiResponse? studentCache; Future> getStudent({bool forceCache = true}) async { diff --git a/firka/lib/api/consts.dart b/firka/lib/api/consts.dart index 23d5b62..d715c0d 100644 --- a/firka/lib/api/consts.dart +++ b/firka/lib/api/consts.dart @@ -84,6 +84,9 @@ class KretaEndpoints { static String getClassGroups(String iss) => ka.KretaEndpoints.getClassGroups(iss); + static String getClassGroupAvg(String iss, String studyGroupId) => + ka.KretaEndpoints.getClassGroupAvg(iss, studyGroupId); + static String getNoticeBoard(String iss) => ka.KretaEndpoints.getNoticeBoard(iss); diff --git a/firka/lib/data/models/generic_cache_model.dart b/firka/lib/data/models/generic_cache_model.dart index 4a9ecfe..f256137 100644 --- a/firka/lib/data/models/generic_cache_model.dart +++ b/firka/lib/data/models/generic_cache_model.dart @@ -13,6 +13,7 @@ enum CacheId { getSubjectAvg, getLessons, getHomework, + getClassGroupAvg, } @collection diff --git a/firka/lib/ui/components/common_bottom_sheets.dart b/firka/lib/ui/components/common_bottom_sheets.dart index d862350..535b2d2 100644 --- a/firka/lib/ui/components/common_bottom_sheets.dart +++ b/firka/lib/ui/components/common_bottom_sheets.dart @@ -344,7 +344,7 @@ Future showGradeBottomSheet( style: appStyle.fonts.B_14R.apply(color: appStyle.colors.textSecondary), ), SizedBox(height: 20), - GradeSmallCard([], grade.subject), + GradeSmallCard([], null, grade.subject), SizedBox(height: 10), FirkaCard( margin: EdgeInsets.all(0), @@ -384,7 +384,6 @@ Future showGradeBottomSheet( color: appStyle.colors.buttonSecondaryFill, ), onTap: () { - Navigator.pop(context); context.go('/grades/subject', extra: grade.subject); }, ), @@ -407,7 +406,7 @@ Future showHomeworkBottomSheet( style: appStyle.fonts.B_14R.apply(color: appStyle.colors.textSecondary), ), SizedBox(height: 20), - GradeSmallCard([], homework.subject), + GradeSmallCard([], null, homework.subject), SizedBox(height: 20), Flexible( fit: FlexFit.loose, diff --git a/firka/lib/ui/phone/pages/home/home_grades.dart b/firka/lib/ui/phone/pages/home/home_grades.dart index b38d7cc..ce9be34 100644 --- a/firka/lib/ui/phone/pages/home/home_grades.dart +++ b/firka/lib/ui/phone/pages/home/home_grades.dart @@ -34,6 +34,7 @@ class _HomeGradesScreen extends FirkaState { ApiResponse>? week; ApiResponse>? classGroups; ApiResponse>? lessons; + ApiResponse>? classAvgs; void _onRefreshRequested(BuildContext context) async { final cubit = context.read(); @@ -50,6 +51,10 @@ class _HomeGradesScreen extends FirkaState { group, forceCache: false, ); + classAvgs = await widget.data.client.getClassGroupAverages( + group, + forceCache: false, + ); await Future.delayed(Duration(milliseconds: 100)); } if (mounted) { @@ -73,6 +78,7 @@ class _HomeGradesScreen extends FirkaState { if (classGroups?.response?.isNotEmpty ?? false) { var group = classGroups!.response!.first; lessons = await widget.data.client.getSubjectAverage(group); + classAvgs = await widget.data.client.getClassGroupAverages(group); await Future.delayed(Duration(milliseconds: 100)); } if (mounted) setState(() {}); @@ -92,7 +98,10 @@ class _HomeGradesScreen extends FirkaState { } Widget _buildContent(BuildContext context) { - if (grades == null || week == null) { + if (grades == null || + lessons == null || + classAvgs == null || + week == null) { return SizedBox( height: MediaQuery.of(context).size.height / 1.35, child: Column( @@ -105,6 +114,13 @@ class _HomeGradesScreen extends FirkaState { final allLessons = lessons!.response!; final subjectAverage = allGrades.getSubjectAverage(); + final classAverages = classAvgs!.response! + .map((c) => c.classGroupAverage) + .nonNulls; + + double? classAverage = classAverages.isNotEmpty + ? classAverages.reduce((f, s) => f + s) + : null; final Set subjects = HashSet( hashCode: (s) => s.uid.hashCode, @@ -119,7 +135,13 @@ class _HomeGradesScreen extends FirkaState { in subjects.toList()..sort((s1, s2) => s1.name.compareTo(s2.name))) { gradeCards.add( GestureDetector( - child: GradeSmallCard(allGrades, subject), + child: GradeSmallCard( + allGrades, + classAvgs!.response! + .firstWhereOrNull((s) => s.subject.uid == subject.uid) + ?.classGroupAverage, + subject, + ), onTap: () { context.go('/grades/subject', extra: subject); }, @@ -209,6 +231,30 @@ class _HomeGradesScreen extends FirkaState { ), ), ], + right: [ + if (classAverage != null) + Container( + width: 48, + height: 26, + decoration: ShapeDecoration( + color: Colors.transparent, + shape: RoundedRectangleBorder( + side: BorderSide( + color: getGradeColor(classAverage), + ), + borderRadius: BorderRadius.circular(12), + ), + ), + child: Center( + child: Text( + classAverage.toStringAsFixed(2), + style: appStyle.fonts.B_16R.apply( + color: getGradeColor(classAverage), + ), + ), + ), + ), + ], ), FirkaCard( left: [ diff --git a/firka_common/lib/ui/shared/grade_small_card.dart b/firka_common/lib/ui/shared/grade_small_card.dart index dac5e6d..de32479 100644 --- a/firka_common/lib/ui/shared/grade_small_card.dart +++ b/firka_common/lib/ui/shared/grade_small_card.dart @@ -7,11 +7,16 @@ import 'package:firka_common/ui/shared/class_icon.dart'; import 'package:firka_common/ui/theme/style.dart'; class GradeSmallCard extends StatelessWidget { - final double? average; + final double? studentAverage; + final double? classAverage; final Subject subject; - GradeSmallCard(List grades, this.subject, {super.key}) - : average = grades.getAverageBySubject(subject); + GradeSmallCard( + List grades, + this.classAverage, + this.subject, { + super.key, + }) : studentAverage = grades.getAverageBySubject(subject); @override Widget build(BuildContext context) { @@ -38,26 +43,45 @@ class GradeSmallCard extends StatelessWidget { overflow: TextOverflow.ellipsis, ), ), - average == null - ? const SizedBox() - : Container( - width: 48, - height: 26, - decoration: ShapeDecoration( - color: getGradeColor(average!).withAlpha(38), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - child: Center( - child: Text( - average!.toStringAsFixed(2), - style: appStyle.fonts.B_16R.apply( - color: getGradeColor(average!), - ), - ), + if (classAverage != null) + Container( + width: 48, + height: 26, + decoration: ShapeDecoration( + color: Colors.transparent, + shape: RoundedRectangleBorder( + side: BorderSide(color: getGradeColor(classAverage!)), + borderRadius: BorderRadius.circular(12), + ), + ), + child: Center( + child: Text( + classAverage!.toStringAsFixed(2), + style: appStyle.fonts.B_16R.apply( + color: getGradeColor(classAverage!), ), ), + ), + ), + if (studentAverage != null) + Container( + width: 48, + height: 26, + decoration: ShapeDecoration( + color: getGradeColor(studentAverage!).withAlpha(38), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ), + child: Center( + child: Text( + studentAverage!.toStringAsFixed(2), + style: appStyle.fonts.B_16R.apply( + color: getGradeColor(studentAverage!), + ), + ), + ), + ), ], ), ); diff --git a/kreta_api/lib/src/endpoints.dart b/kreta_api/lib/src/endpoints.dart index 5ec97ad..e474786 100644 --- a/kreta_api/lib/src/endpoints.dart +++ b/kreta_api/lib/src/endpoints.dart @@ -29,6 +29,9 @@ class KretaEndpoints { static String getSubjectAvg(String iss, String studyGroupId) => "${kreta(iss)}/ellenorzo/v3/sajat/Ertekelesek/Atlagok/TantargyiAtlagok?oktatasiNevelesiFeladatUid=$studyGroupId&oktatasiNevelesiFeladatUid=$studyGroupId"; + static String getClassGroupAvg(String iss, String studyGroupId) => + "${kreta(iss)}/ellenorzo/v3/sajat/Ertekelesek/Atlagok/OsztalyAtlagok?oktatasiNevelesiFeladatUid=$studyGroupId&oktatasiNevelesiFeladatUid=$studyGroupId"; + static String getTimeTable(String iss) => "${kreta(iss)}/ellenorzo/v3/sajat/OrarendElemek"; diff --git a/kreta_api/lib/src/model/class_group.dart b/kreta_api/lib/src/model/class_group.dart index edfed1f..8f41ac2 100644 --- a/kreta_api/lib/src/model/class_group.dart +++ b/kreta_api/lib/src/model/class_group.dart @@ -84,3 +84,30 @@ class SubjectAverage extends UidObj { return 'SubjectAverage(uid: "$uid", name: "${subject.name}", category: "${subject.category.name}", average: $average)'; } } + +class ClassGroupSubjectAverage extends UidObj { + final Subject subject; + final double? studentAverage; + final double? classGroupAverage; + + ClassGroupSubjectAverage({ + required super.uid, + required this.subject, + this.classGroupAverage, + this.studentAverage, + }); + + factory ClassGroupSubjectAverage.fromJson(Map json) { + return ClassGroupSubjectAverage( + uid: json['Uid'], + subject: Subject.fromJson(json['Tantargy']), + studentAverage: json.dbl('TanuloAtlag'), + classGroupAverage: json.dbl('OsztalyCsoportAtlag'), + ); + } + + @override + String toString() { + return 'ClassGroupSubjectAverage(uid: "$uid", subject: $subject)'; + } +}