Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add grades page #170

Merged
merged 18 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions .github/workflows/build-preview-apk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,7 @@ permissions:
repository-projects: write
security-events: write
statuses: write
on:
push:
branches:
- 'build-**'
- '!build-prerelease'
- '!build-release'
on: workflow_dispatch
jobs:
check_changes:
outputs:
Expand Down
293 changes: 291 additions & 2 deletions lib/api.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import 'dart:convert';

import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dio/dio.dart';
import 'package:eduapge2/timetable.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

Future<bool> isConnected() async {
var connectivityResult = await (Connectivity().checkConnectivity());
Expand All @@ -23,6 +24,9 @@ class EP2Data {
late User user;
late Timeline timeline;
late TimeTable timetable;
late Grades grades;

late DBI dbi;

static EP2Data? _instance;

Expand Down Expand Up @@ -120,6 +124,14 @@ class EP2Data {
await timetable.loadRecentTt();
}

grades = (await Grades.loadFromCache()) ?? Grades(events: {}, notes: {});

if (isInternetAvailable && !quickstart) {
await grades.loadGrades();
}

dbi = (await DBI.loadFromCache()) ?? DBI(subjects: {});

if (quickstart && isInternetAvailable) {
loadInBackground();
}
Expand All @@ -133,6 +145,68 @@ class EP2Data {
}
await timeline.loadMessages();
await timetable.loadRecentTt();
await grades.loadGrades();
}
}

class DBI {
final EP2Data data = EP2Data.getInstance();

late Map<String, Subject> subjects;

DBI({
required this.subjects,
});

Future<Subject> getSubject(String id) async {
if (subjects.containsKey(id)) {
return subjects[id]!;
} else {
try {
Response resp = await data.dio.get(
"${data.baseUrl}/api/subject/$id",
options: Options(
headers: {"Authorization": "Bearer ${data.user.token}"},
),
);

Subject subject = Subject.fromJson(resp.data);
subjects[id] = subject;
await saveToCache();
return subject;
} catch (e) {
return Subject(cbHidden: true, id: "", name: "", short: "");
}
}
}

factory DBI.fromJson(Map<String, dynamic> json) {
return DBI(
subjects: (json['Subjects'] as Map<String, dynamic>).map(
(key, value) => MapEntry(key, Subject.fromJson(value)),
),
);
}

Map<String, dynamic> toJson() {
return {
'Subjects': subjects.map((key, value) => MapEntry(key, value.toJson())),
};
}

Future<void> saveToCache() async {
final prefs = await SharedPreferences.getInstance();
prefs.setString('dbi', jsonEncode(toJson()));
}

static Future<DBI?> loadFromCache() async {
final prefs = await SharedPreferences.getInstance();
final dbiJson = prefs.getString('dbi');
if (dbiJson != null) {
return DBI.fromJson(jsonDecode(dbiJson));
} else {
return null;
}
}
}

Expand Down Expand Up @@ -1132,3 +1206,218 @@ class Timeline {
await saveToCache();
}
}

class Event {
final String provider;
final String id;
final String studentID;
final String subjectID;
final String eventID;
final String month;
final String data;
final String date;
final String teacherID;
final String signed;
final String signedAdult;
final String timestamp;
final String state;
final String color;
final String eventName;
final String firstAverage;
final dynamic eventType;
final dynamic weight;
final String classID;
final String planID;
final dynamic gradeCount;
final dynamic moreData;
final String average;

Event({
required this.provider,
required this.id,
required this.studentID,
required this.subjectID,
required this.eventID,
required this.month,
required this.data,
required this.date,
required this.teacherID,
required this.signed,
required this.signedAdult,
required this.timestamp,
required this.state,
required this.color,
required this.eventName,
required this.firstAverage,
required this.eventType,
required this.weight,
required this.classID,
required this.planID,
required this.gradeCount,
required this.moreData,
required this.average,
});

factory Event.fromJson(Map<String, dynamic> json) {
return Event(
provider: json['provider'] as String,
id: json['znamkaid'] as String,
studentID: json['studentid'] as String,
subjectID: json['predmetid'] as String,
eventID: json['udalostID'] as String,
month: json['mesiac'] as String,
data: json['data'] as String,
date: json['datum'] as String,
teacherID: json['ucitelid'] as String,
signed: json['podpisane'] as String,
signedAdult: json['podpisane_rodic'] as String,
timestamp: json['timestamp'] as String,
state: json['stav'] as String,
color: json['p_farba'] as String,
eventName: json['p_meno'] as String,
firstAverage: json['p_najskor_priemer'] as String,
eventType: json['p_typ_udalosti'],
weight: json['p_vaha'],
classID: json['TriedaID'] as String,
planID: json['planid'] as String,
gradeCount: json['p_pocet_znamok'],
moreData: json['moredata'],
average: json['priemer'] as String,
);
}

Map<String, dynamic> toJson() {
return {
'provider': provider,
'znamkaid': id,
'studentid': studentID,
'predmetid': subjectID,
'udalostID': eventID,
'mesiac': month,
'data': data,
'datum': date,
'ucitelid': teacherID,
'podpisane': signed,
'podpisane_rodic': signedAdult,
'timestamp': timestamp,
'stav': state,
'p_farba': color,
'p_meno': eventName,
'p_najskor_priemer': firstAverage,
'p_typ_udalosti': eventType,
'p_vaha': weight,
'TriedaID': classID,
'planid': planID,
'p_pocet_znamok': gradeCount,
'moredata': moreData,
'priemer': average,
};
}
}

class Note {
final String id;
final String date;
final String text;
final String type;
final String subjectID;

Note({
required this.id,
required this.date,
required this.text,
required this.type,
required this.subjectID,
});

factory Note.fromJson(Map<String, dynamic> json) {
return Note(
id: json['VcelickaID'] as String,
date: json['p_datum'] as String,
text: json['p_text'] as String,
type: json['p_typ'] as String,
subjectID: json['PredmetID'] as String,
);
}

Map<String, dynamic> toJson() {
return {
'VcelickaID': id,
'p_datum': date,
'p_text': text,
'p_typ': type,
'PredmetID': subjectID,
};
}
}

class Grades {
EP2Data data = EP2Data.getInstance();

final Map<String, Event> events;
final Map<String, Note> notes;

Grades({
required this.events,
required this.notes,
});

factory Grades.fromJson(Map<String, dynamic> json) {
return Grades(
events: (json['Events'] as Map<String, dynamic>).map(
(key, value) =>
MapEntry(key, Event.fromJson(value as Map<String, dynamic>)),
),
notes: (json['Notes'] as Map<String, dynamic>).map(
(key, value) =>
MapEntry(key, Note.fromJson(value as Map<String, dynamic>)),
),
);
}

Map<String, dynamic> toJson() {
return {
'Events': events.map((key, value) => MapEntry(key, value.toJson())),
'Notes': notes.map((key, value) => MapEntry(key, value.toJson())),
};
}

Future<void> saveToCache() async {
final timelineJson = jsonEncode(toJson());
await data.sharedPreferences.setString('grades', timelineJson);
}

static Future<Grades?> loadFromCache() async {
final prefs = await SharedPreferences.getInstance();
final timelineJson = prefs.getString('grades');
if (timelineJson != null) {
return Grades.fromJson(jsonDecode(timelineJson));
} else {
return null;
}
}

Future<void> loadGrades() async {
Response response = await data.dio.get(
"${data.baseUrl}/api/grades",
options: Options(
headers: {
"Authorization": "Bearer ${data.user.token}",
},
),
);

Map<String, dynamic> newEvents = response.data["Events"];
Map<String, dynamic> newNotes = response.data["Notes"];

newEvents.forEach((key, value) {
events[key] = Event.fromJson(value);
});

newNotes.forEach((key, value) {
notes[key] = Note.fromJson(value);
});

await saveToCache();
}
}
Loading
Loading