2025-01-31 10:24:37 +01:00

322 lines
9.1 KiB
Dart

// ignore_for_file: no_leading_underscores_for_local_identifiers
import 'dart:math';
import 'package:refilc/api/providers/user_provider.dart';
import 'package:refilc/helpers/subject.dart';
import 'package:refilc/models/settings.dart';
import 'package:refilc/utils/format.dart';
import 'package:refilc_kreta_api/models/absence.dart';
import 'package:refilc_kreta_api/models/lesson.dart';
import 'package:refilc_kreta_api/models/subject.dart';
import 'package:refilc_kreta_api/models/week.dart';
import 'package:refilc_kreta_api/providers/absence_provider.dart';
import 'package:refilc_kreta_api/providers/timetable_provider.dart';
import 'package:refilc_mobile_ui/screens/summary/summary_screen.i18n.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
List<String> faces = [
"(·.·)",
"(≥o≤)",
"(·_·)",
"(˚Δ˚)b",
"(^-^*)",
"(='X'=)",
"(>_<)",
"(;-;)",
"\\(^Д^)/",
"\\(o_o)/",
];
class SubjectAbsence {
GradeSubject subject;
List<Absence> absences;
double percentage;
SubjectAbsence(
{required this.subject, this.absences = const [], this.percentage = 0.0});
}
class LessonsBody extends StatefulWidget {
const LessonsBody({super.key});
@override
LessonsBodyState createState() => LessonsBodyState();
}
class LessonsBodyState extends State<LessonsBody> {
late UserProvider user;
late AbsenceProvider absenceProvider;
late SettingsProvider settingsProvider;
late TimetableProvider timetableProvider;
late List<SubjectAbsence> absences = [];
late List<Widget> lessons = [];
late List<Absence> delays = [];
final Map<GradeSubject, Lesson> _lessonCount = {};
@override
void initState() {
super.initState();
absenceProvider = Provider.of<AbsenceProvider>(context, listen: false);
settingsProvider = Provider.of<SettingsProvider>(context, listen: false);
timetableProvider = Provider.of<TimetableProvider>(context, listen: false);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
for (final lesson in timetableProvider.getWeek(Week.current()) ?? []) {
if (!lesson.isEmpty &&
lesson.subject.id != '' &&
lesson.lessonYearIndex != null) {
_lessonCount.update(
lesson.subject,
(value) {
if (lesson.lessonYearIndex! > value.lessonYearIndex!) {
return lesson;
} else {
return value;
}
},
ifAbsent: () => lesson,
);
}
}
setState(() {});
});
}
void buildSubjectAbsences() {
Map<GradeSubject, SubjectAbsence> _absences = {};
for (final absence in absenceProvider.absences) {
if (absence.delay != 0) continue;
if (!_absences.containsKey(absence.subject)) {
_absences[absence.subject] =
SubjectAbsence(subject: absence.subject, absences: [absence]);
} else {
_absences[absence.subject]?.absences.add(absence);
}
}
_absences.forEach((subject, absence) {
final absentLessonsOfSubject = absenceProvider.absences
.where((e) => e.subject == subject && e.delay == 0)
.length;
final totalLessonsOfSubject = _lessonCount[subject]?.lessonYearIndex ?? 0;
double absentLessonsOfSubjectPercentage;
if (absentLessonsOfSubject <= totalLessonsOfSubject) {
absentLessonsOfSubjectPercentage =
absentLessonsOfSubject / totalLessonsOfSubject * 100;
} else {
absentLessonsOfSubjectPercentage = -1;
}
_absences[subject]?.percentage =
absentLessonsOfSubjectPercentage.clamp(-1, 100.0);
});
absences = _absences.values.toList();
absences.sort((a, b) => -a.percentage.compareTo(b.percentage));
}
void getAndSortDelays() {
delays = absenceProvider.absences;
delays.sort((a, b) => -a.delay.compareTo(b.delay));
}
void generateTiles() {
Widget leastAbsent = Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
SubjectIcon.resolveVariant(
subject: absences.last.subject, context: context),
color: Colors.white,
size: 64,
),
Text(
absences.last.subject.renamedTo ??
absences.last.subject.name.capital(),
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.w800,
fontSize: 36.0,
fontStyle: absences.last.subject.isRenamed &&
settingsProvider.renamedSubjectsItalics
? FontStyle.italic
: null,
color: Colors.white,
),
),
Text(
'absence'.i18n.fill([absences.last.absences.length]),
style: const TextStyle(
fontSize: 18.0,
color: Colors.white,
),
)
],
),
);
if (absences.last.absences.isNotEmpty) {
lessons.add(leastAbsent);
} else {
lessons.add(buildFaceWidget());
}
Widget mostAbsent = Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
SubjectIcon.resolveVariant(
subject: absences.first.subject, context: context),
color: Colors.white,
size: 64,
),
Text(
absences.first.subject.renamedTo ??
absences.first.subject.name.capital(),
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.w800,
fontSize: 36.0,
fontStyle: absences.first.subject.isRenamed &&
settingsProvider.renamedSubjectsItalics
? FontStyle.italic
: null,
color: Colors.white,
),
),
Text(
'absence'.i18n.fill([absences.first.absences.length]),
style: const TextStyle(
fontSize: 18.0,
color: Colors.white,
),
)
],
),
);
if (absences.first.absences.isNotEmpty) {
lessons.add(mostAbsent);
} else {
lessons.add(buildFaceWidget());
}
Widget mostDelays = Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
SubjectIcon.resolveVariant(
subject: delays.first.subject, context: context),
color: Colors.white,
size: 64,
),
Text(
delays.first.subject.renamedTo ??
delays.first.subject.name.capital(),
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.w800,
fontSize: 36.0,
fontStyle: delays.first.subject.isRenamed &&
settingsProvider.renamedSubjectsItalics
? FontStyle.italic
: null,
color: Colors.white,
),
),
Text(
'delay'.i18n.fill([delays.first.delay]),
style: const TextStyle(
fontSize: 18.0,
color: Colors.white,
),
)
],
),
);
if (delays.first.delay != 0) {
lessons.add(mostDelays);
} else {
lessons.add(buildFaceWidget());
}
}
@override
Widget build(BuildContext context) {
buildSubjectAbsences();
getAndSortDelays();
generateTiles();
return Expanded(
child: ListView(
children: [
lessons[0],
const SizedBox(height: 18.0),
Text(
'dontfelt'.i18n,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22.0,
color: Colors.white,
),
),
const SizedBox(height: 18.0),
lessons[1],
const SizedBox(height: 18.0),
Text(
'youlate'.i18n,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22.0,
color: Colors.white,
),
),
const SizedBox(height: 18.0),
lessons[2],
],
),
);
}
Widget buildFaceWidget() {
int index = Random(DateTime.now().minute).nextInt(faces.length);
return Center(
child: Text.rich(
TextSpan(
text: faces[index],
style: const TextStyle(
fontSize: 32.0,
fontWeight: FontWeight.w500,
color: Colors.white,
),
children: [
TextSpan(
text: "\n${'no_lesson'.i18n}",
style: TextStyle(
fontSize: 18.0,
height: 2.0,
color: Colors.white.withValues(alpha: 0.5)),
),
],
),
textAlign: TextAlign.center,
),
);
}
}