finished new grades page (subjects now actually)

This commit is contained in:
Kima
2024-04-28 15:47:45 +02:00
parent 28ce83765a
commit ee0613d720
3 changed files with 351 additions and 205 deletions

View File

@@ -4,7 +4,12 @@ import 'package:animations/animations.dart';
import 'package:refilc/api/providers/database_provider.dart';
import 'package:refilc/api/providers/user_provider.dart';
import 'package:refilc/models/settings.dart';
import 'package:refilc/ui/widgets/lesson/lesson_tile.dart';
import 'package:refilc/utils/format.dart';
import 'package:refilc_kreta_api/controllers/timetable_controller.dart';
import 'package:refilc_kreta_api/models/exam.dart';
import 'package:refilc_kreta_api/models/lesson.dart';
import 'package:refilc_kreta_api/providers/exam_provider.dart';
// import 'package:refilc_kreta_api/client/api.dart';
// import 'package:refilc_kreta_api/client/client.dart';
import 'package:refilc_kreta_api/providers/grade_provider.dart';
@@ -14,10 +19,13 @@ import 'package:refilc_kreta_api/models/grade.dart';
import 'package:refilc_kreta_api/models/subject.dart';
import 'package:refilc_mobile_ui/common/average_display.dart';
import 'package:refilc_mobile_ui/common/bottom_sheet_menu/rounded_bottom_sheet.dart';
import 'package:refilc_mobile_ui/common/filter_bar.dart';
import 'package:refilc_mobile_ui/common/panel/panel.dart';
import 'package:refilc_mobile_ui/common/splitted_panel/splitted_panel.dart';
import 'package:refilc_mobile_ui/common/trend_display.dart';
import 'package:refilc_mobile_ui/common/widgets/cretification/certification_tile.dart';
import 'package:refilc/ui/widgets/grade/grade_tile.dart';
import 'package:refilc_mobile_ui/common/widgets/exam/exam_viewable.dart';
import 'package:refilc_mobile_ui/common/widgets/grade/grade_viewable.dart';
import 'package:refilc_mobile_ui/common/hero_scrollview.dart';
import 'package:refilc_mobile_ui/pages/grades/calculator/grade_calculator.dart';
@@ -53,12 +61,14 @@ class GradeSubjectView extends StatefulWidget {
State<GradeSubjectView> createState() => _GradeSubjectViewState();
}
class _GradeSubjectViewState extends State<GradeSubjectView> {
class _GradeSubjectViewState extends State<GradeSubjectView>
with TickerProviderStateMixin {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
// Controllers
PersistentBottomSheetController? _sheetController;
final ScrollController _scrollController = ScrollController();
late TabController _tabController;
List<Widget> gradeTiles = [];
@@ -68,6 +78,9 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
late SettingsProvider settingsProvider;
late DatabaseProvider dbProvider;
late UserProvider user;
late ExamProvider examProvider;
late TimetableController _timetableController;
late double average;
late Widget gradeGraph;
@@ -79,6 +92,8 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
List<Grade> getSubjectGrades(GradeSubject subject) => !gradeCalcMode
? gradeProvider.grades.where((e) => e.subject == subject).toList()
: calculatorProvider.grades.where((e) => e.subject == subject).toList();
List<Exam> getSubjectExams(GradeSubject subject) =>
examProvider.exams.where((e) => e.subject == subject).toList();
bool showGraph(List<Grade> subjectGrades) {
if (gradeCalcMode) return true;
@@ -93,7 +108,11 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
return subjectGrades.where((e) => e.type == GradeType.midYear).length > 1;
}
void buildTiles(List<Grade> subjectGrades) {
void buildTiles(
List<Grade> subjectGrades, {
List<Lesson>? nextWeekLessons,
List<Exam>? subjectExams,
}) {
List<Widget> tiles = [];
tiles.add(Panel(
@@ -128,57 +147,99 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
),
));
if (showGraph(subjectGrades)) {
tiles.addAll(
[
const SizedBox(
height: 5.0,
),
FilterBar(
padding: EdgeInsets.zero,
items: [
Tab(text: "grades".i18n),
Tab(text: "timetable".i18n),
Tab(text: "exams".i18n),
],
controller: _tabController,
disableFading: true,
),
],
);
if (showGraph(subjectGrades) && _tabController.index == 0) {
tiles.add(gradeGraph);
} else {
tiles.add(Container(height: 24.0));
tiles.add(Container(height: 20.0));
}
tiles.add(Padding(
padding: const EdgeInsets.only(bottom: 24.0),
child: Panel(
child: GradesCount(grades: getSubjectGrades(widget.subject).toList()),
),
));
if (_tabController.index == 0) {
tiles.add(Padding(
padding: const EdgeInsets.only(bottom: 24.0),
child: Panel(
child: GradesCount(grades: getSubjectGrades(widget.subject).toList()),
),
));
}
// ignore: no_leading_underscores_for_local_identifiers
List<Widget> _gradeTiles = [];
List<Widget> _tiles = [];
if (!gradeCalcMode) {
subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
if (_tabController.index == 0) {
subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
_gradeTiles.add(const SizedBox(
height: 4.0,
));
_tiles.add(const SizedBox(
height: 4.0,
));
for (var grade in subjectGrades) {
if (grade.type == GradeType.midYear) {
_gradeTiles.add(GradeViewable(grade));
} else {
_gradeTiles.add(CertificationTile(
grade,
padding: EdgeInsets.only(
bottom: 8.0,
top: (subjectGrades.first.id == grade.id) ? 0.0 : 8.0),
newStyle: true,
for (var grade in subjectGrades) {
if (grade.type == GradeType.midYear) {
_tiles.add(GradeViewable(grade));
} else {
_tiles.add(CertificationTile(
grade,
padding: EdgeInsets.only(
bottom: 8.0,
top: (subjectGrades.first.id == grade.id) ? 0.0 : 8.0),
newStyle: true,
));
}
}
_tiles.add(const SizedBox(
height: 4.0,
));
}
if (_tabController.index == 1) {
nextWeekLessons!.sort((a, b) => -a.date.compareTo(b.date));
for (var lesson in nextWeekLessons) {
_tiles.add(LessonTile(
lesson,
subjectPageView: true,
));
}
}
if (_tabController.index == 2) {
subjectExams!.sort((a, b) => -a.writeDate.compareTo(b.writeDate));
_gradeTiles.add(const SizedBox(
height: 4.0,
));
for (var exam in subjectExams) {
_tiles.add(ExamViewable(
exam,
showSubject: false,
));
}
}
} else if (subjectGrades.isNotEmpty) {
_gradeTiles.add(const SizedBox(
_tiles.add(const SizedBox(
height: 8.0,
));
subjectGrades.sort((a, b) => -a.date.compareTo(b.date));
for (var grade in subjectGrades) {
_gradeTiles.add(GradeTile(grade));
_tiles.add(GradeTile(grade));
}
_gradeTiles.add(const SizedBox(
_tiles.add(const SizedBox(
height: 8.0,
));
}
@@ -197,15 +258,29 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
child: child,
);
},
child: _gradeTiles.isNotEmpty
? Panel(
key: ValueKey(gradeCalcMode),
title: Text(
gradeCalcMode ? "Ghost Grades".i18n : "Grades".i18n,
),
child: Column(
children: _gradeTiles,
))
child: _tiles.isNotEmpty
? (_tabController.index == 0
? Panel(
key: ValueKey(gradeCalcMode),
title: Text(
gradeCalcMode ? "Ghost Grades".i18n : "Grades".i18n,
),
child: Column(
children: _tiles,
))
: _tabController.index == 1
? SplittedPanel(
padding: EdgeInsets.zero,
cardPadding: const EdgeInsets.only(
left: 6.0, right: 12.0, top: 6.0, bottom: 6.0),
title: Text("upcoming_lessons".i18n),
children: _tiles,
)
: SplittedPanel(
padding: EdgeInsets.zero,
title: Text("exams".i18n),
children: _tiles,
))
: const SizedBox(),
),
);
@@ -220,6 +295,15 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
super.initState();
user = Provider.of<UserProvider>(context, listen: false);
dbProvider = Provider.of<DatabaseProvider>(context, listen: false);
_tabController = TabController(length: 3, vsync: this);
_timetableController = TimetableController();
_timetableController.jump(_timetableController.currentWeek,
context: context, initial: true, skip: true);
if (DateTime.now().day > 5) {
_timetableController.next(context);
}
}
void fetchGoalPlans() async {
@@ -234,6 +318,13 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
gradeProvider = Provider.of<GradeProvider>(context);
calculatorProvider = Provider.of<GradeCalculatorProvider>(context);
settingsProvider = Provider.of<SettingsProvider>(context);
examProvider = Provider.of<ExamProvider>(context);
List<Lesson> nextWeekLessons = (_timetableController.days ?? [])
.expand((e) => e)
.where((e) => e.subject.id == widget.subject.id)
.toList();
List<Exam> subjectExams = getSubjectExams(widget.subject);
List<Grade> subjectGrades = getSubjectGrades(widget.subject).toList();
average = AverageHelper.averageEvals(subjectGrades);
@@ -266,7 +357,11 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
);
if (!gradeCalcMode) {
buildTiles(subjectGrades);
buildTiles(
subjectGrades,
nextWeekLessons: nextWeekLessons,
subjectExams: subjectExams,
);
} else {
List<Grade> ghostGrades = calculatorProvider.ghosts
.where((e) => e.subject == widget.subject)
@@ -324,94 +419,105 @@ class _GradeSubjectViewState extends State<GradeSubjectView> {
onRefresh: () async {},
color: Theme.of(context).colorScheme.secondary,
child: HeroScrollView(
showTitleUnscroll: false,
onClose: () {
if (_sheetController != null && gradeCalcMode) {
_sheetController!.close();
} else {
Navigator.of(context).pop();
}
},
navBarItems: [
const SizedBox(width: 6.0),
if (widget.groupAverage != 0)
Center(
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(50.0),
),
child: AverageDisplay(
average: widget.groupAverage, border: true),
showTitleUnscroll: false,
onClose: () {
if (_sheetController != null && gradeCalcMode) {
_sheetController!.close();
} else {
Navigator.of(context).pop();
}
},
navBarItems: [
const SizedBox(width: 6.0),
if (widget.groupAverage != 0)
Center(
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(50.0),
),
child: AverageDisplay(
average: widget.groupAverage, border: true),
),
const SizedBox(width: 6.0),
if (average != 0)
Center(
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(50.0),
),
child: AverageDisplay(average: average),
),
const SizedBox(width: 6.0),
if (average != 0)
Center(
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(50.0),
),
child: AverageDisplay(average: average),
),
const SizedBox(width: 6.0),
if (plan != '')
Center(
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(50.0),
),
child: GestureDetector(
onTap: () {
Navigator.of(context).push(CupertinoPageRoute(
builder: (context) =>
GoalStateScreen(subject: widget.subject)));
},
child: Container(
width: 54.0,
padding: const EdgeInsets.symmetric(vertical: 8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(45.0),
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(.15),
),
child: Icon(
FeatherIcons.flag,
size: 17.0,
weight: 2.5,
color: Theme.of(context).colorScheme.primary,
),
),
const SizedBox(width: 6.0),
if (plan != '')
Center(
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(50.0),
),
child: GestureDetector(
onTap: () {
Navigator.of(context).push(CupertinoPageRoute(
builder: (context) =>
GoalStateScreen(subject: widget.subject)));
},
child: Container(
width: 54.0,
padding: const EdgeInsets.symmetric(vertical: 8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(45.0),
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(.15),
),
child: Icon(
FeatherIcons.flag,
size: 17.0,
weight: 2.5,
color: Theme.of(context).colorScheme.primary,
),
),
),
),
const SizedBox(width: 12.0),
],
icon: SubjectIcon.resolveVariant(
subject: widget.subject, context: context),
scrollController: _scrollController,
title: widget.subject.renamedTo ?? widget.subject.name.capital(),
italic: settingsProvider.renamedSubjectsItalics &&
widget.subject.isRenamed,
child: SubjectGradesContainer(
child: CupertinoScrollbar(
child: ListView.builder(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.symmetric(horizontal: 24.0),
shrinkWrap: true,
itemBuilder: (context, index) => gradeTiles[index],
itemCount: gradeTiles.length,
),
),
)),
const SizedBox(width: 12.0),
],
icon: SubjectIcon.resolveVariant(
subject: widget.subject, context: context),
scrollController: _scrollController,
title: widget.subject.renamedTo ?? widget.subject.name.capital(),
italic: settingsProvider.renamedSubjectsItalics &&
widget.subject.isRenamed,
// child: TabBarView(
// physics: const BouncingScrollPhysics(),
// controller: _tabController,
// children: List.generate(
// 3, (index) => filterViewBuilder(context, index))),
// ),
child: SubjectGradesContainer(
child: CupertinoScrollbar(
child: ListView.builder(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.symmetric(horizontal: 24.0),
shrinkWrap: true,
itemBuilder: (context, index) => gradeTiles[index],
itemCount: gradeTiles.length,
),
),
),
),
));
}
Widget filterViewBuilder(context, int activeData) {
return Container();
}
void gradeCalc(BuildContext context) {
// Scroll to the top of the page
_scrollController.animateTo(100,