From 98d7468f24d7aa599e7e86491c524259630436b0 Mon Sep 17 00:00:00 2001
From: Kima <kimavideos97@gmail.com>
Date: Mon, 18 Sep 2023 19:29:55 +0200
Subject: [PATCH] tried to fix timetable and handle kreten api error

---
 .../lib/api/providers/status_provider.dart    | 20 +++++++++++--
 filcnaplo_kreta_api/lib/client/client.dart    |  3 ++
 .../lib/providers/timetable_provider.dart     | 18 ++++++++----
 .../widgets/missed_exam/missed_exam_view.dart | 29 ++++++++++++++-----
 .../lib/screens/navigation/status_bar.dart    | 18 +++++++++---
 .../screens/navigation/status_bar.i18n.dart   |  3 ++
 6 files changed, 72 insertions(+), 19 deletions(-)

diff --git a/filcnaplo/lib/api/providers/status_provider.dart b/filcnaplo/lib/api/providers/status_provider.dart
index ca4cd5a..5822366 100644
--- a/filcnaplo/lib/api/providers/status_provider.dart
+++ b/filcnaplo/lib/api/providers/status_provider.dart
@@ -2,7 +2,7 @@ import 'package:connectivity_plus/connectivity_plus.dart';
 import 'package:flutter/widgets.dart';
 import 'package:http/http.dart' as http;
 
-enum Status { network, maintenance, syncing }
+enum Status { network, maintenance, syncing, apiError }
 
 class StatusProvider extends ChangeNotifier {
   final List<Status> _stack = [];
@@ -37,7 +37,8 @@ class StatusProvider extends ChangeNotifier {
   }
 
   void triggerRequest(http.Response res) {
-    if (res.headers.containsKey("x-maintenance-mode") || res.statusCode == 503) {
+    if (res.headers.containsKey("x-maintenance-mode") ||
+        res.statusCode == 503) {
       if (!_stack.contains(Status.maintenance)) {
         _stack.insert(0, Status.maintenance);
         notifyListeners();
@@ -48,6 +49,21 @@ class StatusProvider extends ChangeNotifier {
         notifyListeners();
       }
     }
+
+    if (res.body == "invalid_grant" ||
+        res.body.replaceAll(' ', '') == '' ||
+        res.statusCode == 400) {
+      if (!_stack.contains(Status.apiError)) {
+        _stack.insert(0, Status.apiError);
+        notifyListeners();
+      }
+    } else {
+      if (_stack.contains(Status.apiError) &&
+          res.request?.url.path != '/nonce') {
+        _stack.remove(Status.apiError);
+        notifyListeners();
+      }
+    }
   }
 
   void triggerSync({required int current, required int max}) {
diff --git a/filcnaplo_kreta_api/lib/client/client.dart b/filcnaplo_kreta_api/lib/client/client.dart
index 5217a76..f150e3b 100644
--- a/filcnaplo_kreta_api/lib/client/client.dart
+++ b/filcnaplo_kreta_api/lib/client/client.dart
@@ -89,6 +89,9 @@ class KretaClient {
       }
 
       if (res == null) throw "Login error";
+      if (res.body == 'invalid_grant' || res.body.replaceAll(' ', '') == '') {
+        throw "Auth error";
+      }
 
       if (json) {
         return jsonDecode(res.body);
diff --git a/filcnaplo_kreta_api/lib/providers/timetable_provider.dart b/filcnaplo_kreta_api/lib/providers/timetable_provider.dart
index 1e31308..1b9a3ef 100644
--- a/filcnaplo_kreta_api/lib/providers/timetable_provider.dart
+++ b/filcnaplo_kreta_api/lib/providers/timetable_provider.dart
@@ -67,15 +67,21 @@ class TimetableProvider with ChangeNotifier {
     String iss = user.instituteCode;
     List? lessonsJson = await _kreta
         .getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
-    if (lessonsJson == null) throw "Cannot fetch Lessons for User ${user.id}";
-    List<Lesson> lessonsList = lessonsJson.map((e) => Lesson.fromJson(e)).toList();
 
-    if (lessons.isEmpty && lessons.isEmpty) return;
+    if (lessonsJson == null) {
+      return;
+      // throw "Cannot fetch Lessons for User ${user.id}";
+    } else {
+      List<Lesson> lessonsList =
+          lessonsJson.map((e) => Lesson.fromJson(e)).toList();
 
-    lessons[week] = lessonsList;
+      if (lessons.isEmpty) return;
 
-    await store();
-    await convertBySettings();
+      lessons[week] = lessonsList;
+
+      await store();
+      await convertBySettings();
+    }
   }
 
   // Stores Lessons in the database
diff --git a/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart b/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart
index 53bf9ca..6178cc7 100755
--- a/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart
+++ b/filcnaplo_mobile_ui/lib/common/widgets/missed_exam/missed_exam_view.dart
@@ -15,7 +15,8 @@ class MissedExamView extends StatelessWidget {
 
   final List<Lesson> missedExams;
 
-  static show(List<Lesson> missedExams, {required BuildContext context}) => showRoundedModalBottomSheet(context, child: MissedExamView(missedExams));
+  static show(List<Lesson> missedExams, {required BuildContext context}) =>
+      showRoundedModalBottomSheet(context, child: MissedExamView(missedExams));
 
   @override
   Widget build(BuildContext context) {
@@ -25,7 +26,8 @@ class MissedExamView extends StatelessWidget {
 }
 
 class MissedExamViewTile extends StatelessWidget {
-  const MissedExamViewTile(this.lesson, {Key? key, this.padding}) : super(key: key);
+  const MissedExamViewTile(this.lesson, {Key? key, this.padding})
+      : super(key: key);
 
   final EdgeInsetsGeometry? padding;
   final Lesson lesson;
@@ -33,23 +35,36 @@ class MissedExamViewTile extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);
+
+    String? teacherName = lesson.teacher.isRenamed
+        ? lesson.teacher.renamedTo
+        : lesson.teacher.name;
+
     return Material(
       type: MaterialType.transparency,
       child: Padding(
-        padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
+        padding: padding ??
+            const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
         child: ListTile(
-          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
+          shape:
+              RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
           leading: Icon(
-            SubjectIcon.resolveVariant(subject: lesson.subject, context: context),
+            SubjectIcon.resolveVariant(
+                subject: lesson.subject, context: context),
             color: AppColors.of(context).text.withOpacity(.8),
             size: 32.0,
           ),
           title: Text(
             "${lesson.subject.renamedTo ?? lesson.subject.name.capital()} • ${lesson.date.format(context)}",
-            style: TextStyle(fontWeight: FontWeight.w600, fontStyle: lesson.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null),
+            style: TextStyle(
+                fontWeight: FontWeight.w600,
+                fontStyle: lesson.subject.isRenamed &&
+                        settingsProvider.renamedSubjectsItalics
+                    ? FontStyle.italic
+                    : null),
           ),
           subtitle: Text(
-            "missed_exam_contact".i18n.fill([lesson.teacher]),
+            "missed_exam_contact".i18n.fill([teacherName ?? '']),
             style: const TextStyle(fontWeight: FontWeight.w500),
           ),
           trailing: const Icon(FeatherIcons.arrowRight),
diff --git a/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.dart b/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.dart
index 8bcbd39..d79078f 100755
--- a/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.dart
+++ b/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.dart
@@ -39,7 +39,9 @@ class _StatusBarState extends State<StatusBar> {
             height: currentStatus != null ? 28.0 : 0,
             decoration: BoxDecoration(
               color: backgroundColor,
-              boxShadow: [BoxShadow(color: Theme.of(context).shadowColor, blurRadius: 8.0)],
+              boxShadow: [
+                BoxShadow(color: Theme.of(context).shadowColor, blurRadius: 8.0)
+              ],
               borderRadius: BorderRadius.circular(45.0),
             ),
           ),
@@ -53,9 +55,12 @@ class _StatusBarState extends State<StatusBar> {
                 height: currentStatus != null ? 28.0 : 0,
                 duration: const Duration(milliseconds: 250),
                 curve: Curves.easeInOut,
-                width: MediaQuery.of(context).size.width * statusProvider.progress - 16.0,
+                width: MediaQuery.of(context).size.width *
+                        statusProvider.progress -
+                    16.0,
                 decoration: BoxDecoration(
-                  color: Theme.of(context).colorScheme.secondary.withOpacity(0.8),
+                  color:
+                      Theme.of(context).colorScheme.secondary.withOpacity(0.8),
                   borderRadius: BorderRadius.circular(45.0),
                 ),
               ),
@@ -82,6 +87,8 @@ class _StatusBarState extends State<StatusBar> {
         return "Syncing data".i18n;
       case Status.maintenance:
         return "KRETA Maintenance".i18n;
+      case Status.apiError:
+        return "KRETA API error".i18n;
       case Status.network:
         return "No connection".i18n;
       default:
@@ -93,10 +100,13 @@ class _StatusBarState extends State<StatusBar> {
     switch (status) {
       case Status.maintenance:
         return AppColors.of(context).red;
+      case Status.apiError:
+        return AppColors.of(context).red;
       case Status.network:
       case Status.syncing:
       default:
-        HSLColor color = HSLColor.fromColor(Theme.of(context).scaffoldBackgroundColor);
+        HSLColor color =
+            HSLColor.fromColor(Theme.of(context).scaffoldBackgroundColor);
         if (color.lightness >= 0.5) {
           color = color.withSaturation(0.3);
           color = color.withLightness(color.lightness - 0.1);
diff --git a/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.i18n.dart b/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.i18n.dart
index ca3acb8..e86b9d2 100755
--- a/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.i18n.dart
+++ b/filcnaplo_mobile_ui/lib/screens/navigation/status_bar.i18n.dart
@@ -6,16 +6,19 @@ extension Localization on String {
         "en_en": {
           "Syncing data": "Syncing data",
           "KRETA Maintenance": "KRETA Maintenance",
+          "KRETA API error": "KRETA API Error",
           "No connection": "No connection",
         },
         "hu_hu": {
           "Syncing data": "Adatok frissítése",
           "KRETA Maintenance": "KRÉTA Karbantartás",
+          "KRETA API error": "KRÉTA API Hiba",
           "No connection": "Nincs kapcsolat",
         },
         "de_de": {
           "Syncing data": "Daten aktualisieren",
           "KRETA Maintenance": "KRETA Wartung",
+          "KRETA API error": "KRETA API Fehler",
           "No connection": "Keine Verbindung",
         },
       };