Compare commits
32 Commits
4.1.0-beta
...
4.1.1-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d9f99a955 | ||
|
|
2c5939fab4 | ||
|
|
95ed503e53 | ||
|
|
51e2c63134 | ||
|
|
50bc03f403 | ||
|
|
f5bc16ba42 | ||
|
|
f4501ce251 | ||
|
|
3317472773 | ||
|
|
acdd47a49a | ||
|
|
fa8be89aaf | ||
|
|
5034af2fb4 | ||
|
|
87842de421 | ||
|
|
1f46a0509f | ||
|
|
8e9713e436 | ||
|
|
fe0a7d81ae | ||
|
|
f9e14349b7 | ||
|
|
a1f087758f | ||
|
|
4068abdb95 | ||
|
|
9314c613bc | ||
|
|
458e93e19f | ||
|
|
ba8d26d250 | ||
|
|
33e3495d9f | ||
|
|
f71e72e443 | ||
|
|
c615a33bd2 | ||
|
|
7ad0ea26e2 | ||
|
|
0ad663beb3 | ||
|
|
1366984c15 | ||
|
|
62d3895373 | ||
|
|
3579c4e821 | ||
|
|
5c39865d40 | ||
|
|
551b2849fe | ||
|
|
ce1c5eb0d8 |
@@ -1,39 +1,36 @@
|
|||||||
|
|
||||||
# Hozzájárulási útmutató
|
# Contribution guide
|
||||||
Köszönjük, ha programozással segíted a munkánkat!
|
Köszönjük, ha programozással segíted a munkánkat!
|
||||||
A folytatáshoz szükséged lesz egy Linuxot vagy Windowst futtató számítógépre, minimális programozási tapasztalatra és egy kis angoltudásra.
|
A folytatáshoz szükséged lesz egy Linux-ot vagy Windows-t futtató számítógépre, minimális programozási tapasztalatra és egy kis angoltudásra.
|
||||||
Segít, ha nem csak kicsit tudsz programozni, és ha ismered a Gitet és a GitHubot ;)
|
Segít, ha már gyakorlottabb vagy a programozásban, és ha ismered a [Git](https://git-scm.com/) és a [GitHub](https://github.com/) működését. ;)
|
||||||
|
|
||||||
## Miben segítsek?
|
## Miben segítsek?
|
||||||
Kérünk, **olyan dologgal járulj hozzá** a reFilchez, ami valószínűleg **sok embernek hasznos lesz** majd. Szeretnénk egy minél teljeskörűbb iskolai asszisztenst létrehozni, de az iskolaspecifikus, vagy külön neked hasznos funkciók helye inkább legyen a saját forkod.
|
Kérünk, **olyan dologgal járulj hozzá** a **reFilc**hez, ami valószínűleg **sok embernek hasznos lehet**. Szeretnénk egy minél teljeskörűbb iskolai asszisztenst létrehozni, de az iskolaspecifikus, vagy külön neked hasznos funkciók helye inkább legyen a saját Fork-od.
|
||||||
|
|
||||||
Fontos, hogy **mielőtt egy nagy volumenű projektbe belekezdesz, futtasd meg ötletedet a [Discord szerverünkön](https://dc.refilc.hu/),** ahol még azelőtt tudunk tanácsot adni, mielőtt sok-sok órát beleöltél volna egy esetleg felesleges dologba.
|
Fontos, hogy **mielőtt egy nagyobb méretű projektbe belekezdenél, futtasd meg ötletedet a [Discord szerverünkön](https://dc.refilc.hu/)**, ahol még azelőtt tudunk tanácsot adni, hogy sok-sok órát beleöltél volna egy esetleg felesleges dologba.
|
||||||
|
|
||||||
A legjobban annak örülünk, ha az [Issues](https://github.com/refilc/naplo/issues) oldalról szemezgetsz, **ha lehet, a [help wanted taggel megjelöltekkel kezdd](https://github.com/refilc/naplo/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22),** vagy ha új vagy a Flutterhez, ajánljuk figyelmedbe [ezeket a viszonylag könnyen javítható hibákat](https://github.com/refilc/naplo/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) (ha épp van ilyen).
|
A legjobban annak örülünk, ha az [Issues](https://github.com/refilc/naplo/issues) oldalról szemezgetsz. Ha még új vagy a Flutterben, ajánljuk figyelmedbe ezeket a [viszonylag könnyen javítható hibákat](https://github.com/refilc/naplo/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22), ha éppen van ilyen.
|
||||||
|
|
||||||
## Hogyan segítsek?
|
## Hogyan segítsek?
|
||||||
|
Nem ígérhetünk itt sem programozás-, sem Git-kurzust, de a projektspecifikus dolgokat leírjuk, és segítünk a Flutter telepítésében.
|
||||||
|
|
||||||
Nem ígérhetünk itt sem programozás-, sem git-kurzust, de a projektspecifikus dolgokat leírjuk, és segítünk a Flutter feltelepítésében.
|
A **reFilc** a Google által pár éve létrehozott **[Flutter](https://flutter.dev/)** keretrendszert használja, aminek nyelve a **[Dart](https://dart.dev/)**. Ha ismered a C#, Java, C++, vagy egyéb hasonló programnyelvek működését, **nem fog nagy gondot okozni a használata.** A felhasználói felület létrehozásában az is segíthet, ha foglalkoztál már korábban weboldalakkal vagy alkalmazásfejlesztéssel.
|
||||||
|
Ha még nem használtad a Flutter-t, mindenképp böngészd át a [YouTube csatornájukat](https://www.youtube.com/channel/UCwXdFgeE9KYzlDdR7TG9cMw).
|
||||||
|
Kód vagy UI teszteléséhez Flutter telepítése nélkül is használhatod a [DartPad](https://dartpad.dev/)-et.
|
||||||
|
|
||||||
A reFilc a Google által pár éve létrehozott **[Fluttert](https://flutter.dev/)** használja, aminek nyelve a **[Dart](https://dart.dev/)**. Ha ismered a C#-ot, Javát, C++t, vagy egyéb hasonló nyelvet, **nem fog gondot okozni a használata.** A felhasználói felület létrehozásában az is segíthet, ha foglalkoztál már korábban weboldalakkal.
|
#### [Segítség a Flutter telepítéséhez](https://docs.flutter.dev/get-started/install)
|
||||||
Ha még nem használtál Fluttert, mindenképp böngészd át a [YouTube csatornájukat](https://www.youtube.com/channel/UCwXdFgeE9KYzlDdR7TG9cMw).
|
**Használd a Flutter stable verzióját!** Írd be a terminálba: `flutter channel stable`
|
||||||
Könnyen tudsz kódot, vagy akár UI-t is tesztelni a [DartPad](https://dartpad.dev/) oldalon.
|
|
||||||
|
|
||||||
#### [Segítség a Flutter telepítéséhez és a forráskód futtatásához](https://docs.flutter.dev/get-started/install)
|
Ha nem értessz a Git-hez vagy a GitHub-hoz, ajánljuk figyelmedbe [ezt a cikket](https://medium.com/envienta-magyarorsz%C3%A1g/git-%C3%A9s-github-gyorstalpal%C3%B3-f2d78a732deb), viszont arra kérünk, hogy a használatukat ne a **reFilc**en próbáld ki először. Hozz létre egy saját Repo-t és abban tesztelgess. Ha már nagyjából kitapasztaltad, várjuk hozzájárulásodat.
|
||||||
Fontos: **Legyél a flutter beta verzióján!** Írd be: `flutter channel beta`
|
|
||||||
|
|
||||||
|
Készíts egy Fork-ot a saját GitHub fiókod alá.
|
||||||
|
A **reFilc** legfrissebb, **épp fejlesztés alatt álló verzióját a [master branch](https://github.com/refilc/naplo/tree/master)-en találod**. Kérjük ide Commit-olj és ide célozd a Fork-odból a Pull Request-edet. Írd le benne, hogy mit változtattál és ha lehet, csatolj képernyőképet is.
|
||||||
Ha nem értesz a Githez, ajánljuk figyelmedbe [ezt a cikket](https://medium.com/envienta-magyarorsz%C3%A1g/git-%C3%A9s-github-gyorstalpal%C3%B3-f2d78a732deb). Viszont arra kérünk, a Git használatát ne a reFilcen próbáld ki először, hozz létre előbb egy saját Repót, és abba tesztelgess. Ha már nagyjából kitapasztaltad, várjuk hozzájárulásodat.
|
Minél gyakrabban készíts minél részletesebben elnevezett Commit-okat, hogy mások is el tudjanak igazodni az általad beküldött kódban.
|
||||||
|
|
||||||
Készíts egy forkot a saját fiókod alá.
|
|
||||||
A reFilc legfrissebb, épp fejlesztés alatt álló verzióját a [master branch](https://github.com/refilc/naplo/tree/master)-en találod, kérjük ide commitolj, és ide célozd a forkodból a Pull Requested. Írd le benne, mit változtattál, és ha lehet, csatolj képernyőképet is.
|
|
||||||
Minél gyakrabban készíts minél részletesebben elnevezett commitokat, hogy el tudjunk tájékozódni az általad beküldött kódon.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Az általad fejlesztett funkciók mellé a changelogban odakerül GitHub felhasználóneved.
|
Az általad fejlesztett funkciók mellé a Changelog-ba odakerül a GitHub felhasználóneved.
|
||||||
Ha jelentős és rendszeres hozzájáruló vagy, Discordon megkapod a `DEV` rangot.
|
Ha jelentős és rendszeres hozzájáruló vagy, Discord-on megkaphatod a `DEV` rangot.
|
||||||
|
|
||||||
Ha bárhol elakadtál, keress minket Discordon.
|
Ha bárhol elakadtál vagy kérdésed van, keress bátran Discordon!
|
||||||
Jó fejlesztést kívánunk!
|
**Jó fejlesztést kívánunk!**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#### Nem hivatalos e-napló alkalmazás az eKRÉTA rendszerhez - tanulóktól, tanulóknak.
|
#### Nem hivatalos e-napló alkalmazás az eKRÉTA rendszerhez - tanulóktól, tanulóknak.
|
||||||
|
|
||||||
[](https://github.com/refilc/naplo/releases) [](http://dc.refilc.hu)
|
[](https://github.com/refilc/naplo/releases) [](https://dc.refilc.hu)
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
@@ -29,11 +29,13 @@ flutter run
|
|||||||
|
|
||||||
### Contribution
|
### Contribution
|
||||||
|
|
||||||
|
**Nézd meg a [Contribution guide](CONTRIBUTING.md)-ot!**
|
||||||
|
|
||||||
Az összes (ugyan azon verzióhoz tartozó) contribution meg fog jelenni a release-nél. Kérjük, írd le a Discord nevedet a Description-be, hogy adhassunk rangot.
|
Az összes (ugyan azon verzióhoz tartozó) contribution meg fog jelenni a release-nél. Kérjük, írd le a Discord nevedet a Description-be, hogy adhassunk rangot.
|
||||||
|
|
||||||
-------
|
-------
|
||||||
|
|
||||||
# Kudo
|
# Developers
|
||||||
|
|
||||||
**annon:** a Filc napló készítője (ez az app a Filcen alapul)
|
**annon:** a Filc napló készítője (ez az app a Filcen alapul)
|
||||||
|
|
||||||
|
|||||||
BIN
filcnaplo/assets/images/card_border.png
Normal file
BIN
filcnaplo/assets/images/card_border.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
15
filcnaplo/ios/Flutter/Generated 3.xcconfig
Normal file
15
filcnaplo/ios/Flutter/Generated 3.xcconfig
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// This is a generated file; do not edit or check into version control.
|
||||||
|
FLUTTER_ROOT=/Users/kima/development/flutter
|
||||||
|
FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo
|
||||||
|
COCOAPODS_PARALLEL_CODE_SIGN=true
|
||||||
|
FLUTTER_TARGET=/Users/kima/Documents/refilc/app/naplo/filcnaplo/lib/main.dart
|
||||||
|
FLUTTER_BUILD_DIR=build
|
||||||
|
FLUTTER_BUILD_NAME=4.1.0
|
||||||
|
FLUTTER_BUILD_NUMBER=213
|
||||||
|
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
|
||||||
|
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
|
||||||
|
DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC8yYTM0MDFjOWJiYjVhOWE5YWVjNzRkNGY3MzVkMThhOWRkM2ViZjJkLw==
|
||||||
|
DART_OBFUSCATION=false
|
||||||
|
TRACK_WIDGET_CREATION=true
|
||||||
|
TREE_SHAKE_ICONS=false
|
||||||
|
PACKAGE_CONFIG=/Users/kima/Documents/refilc/app/naplo/filcnaplo/.dart_tool/package_config.json
|
||||||
14
filcnaplo/ios/Flutter/flutter_export_environment 2.sh
Executable file
14
filcnaplo/ios/Flutter/flutter_export_environment 2.sh
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# This is a generated file; do not edit or check into version control.
|
||||||
|
export "FLUTTER_ROOT=/Users/kima/development/flutter"
|
||||||
|
export "FLUTTER_APPLICATION_PATH=/Users/kima/Documents/refilc/app/naplo/filcnaplo"
|
||||||
|
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
|
||||||
|
export "FLUTTER_TARGET=/Users/kima/Documents/refilc/app/naplo/filcnaplo/lib/main.dart"
|
||||||
|
export "FLUTTER_BUILD_DIR=build"
|
||||||
|
export "FLUTTER_BUILD_NAME=4.1.0"
|
||||||
|
export "FLUTTER_BUILD_NUMBER=213"
|
||||||
|
export "DART_DEFINES=RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==,RkxVVFRFUl9XRUJfQ0FOVkFTS0lUX1VSTD1odHRwczovL3d3dy5nc3RhdGljLmNvbS9mbHV0dGVyLWNhbnZhc2tpdC8yYTM0MDFjOWJiYjVhOWE5YWVjNzRkNGY3MzVkMThhOWRkM2ViZjJkLw=="
|
||||||
|
export "DART_OBFUSCATION=false"
|
||||||
|
export "TRACK_WIDGET_CREATION=true"
|
||||||
|
export "TREE_SHAKE_ICONS=false"
|
||||||
|
export "PACKAGE_CONFIG=/Users/kima/Documents/refilc/app/naplo/filcnaplo/.dart_tool/package_config.json"
|
||||||
@@ -488,7 +488,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 3.6.0;
|
MARKETING_VERSION = 3.6.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo;
|
PRODUCT_BUNDLE_IDENTIFIER = com.refilctest.naplo;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@@ -526,7 +526,7 @@
|
|||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo.livecardpro;
|
PRODUCT_BUNDLE_IDENTIFIER = com.refilctest.naplo.livecardpro;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@@ -567,7 +567,7 @@
|
|||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo.livecardpro;
|
PRODUCT_BUNDLE_IDENTIFIER = com.refilctest.naplo.livecardpro;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@@ -607,7 +607,7 @@
|
|||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo.livecardpro;
|
PRODUCT_BUNDLE_IDENTIFIER = com.refilctest.naplo.livecardpro;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@@ -746,7 +746,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 3.6.0;
|
MARKETING_VERSION = 3.6.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo;
|
PRODUCT_BUNDLE_IDENTIFIER = com.refilctest.naplo;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
@@ -774,7 +774,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 3.6.0;
|
MARKETING_VERSION = 3.6.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.refilc.naplo;
|
PRODUCT_BUNDLE_IDENTIFIER = com.refilctest.naplo;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>aps-environment</key>
|
|
||||||
<string>development</string>
|
|
||||||
<key>com.apple.security.application-groups</key>
|
<key>com.apple.security.application-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>group.refilcnaplo.livecard</string>
|
<string>group.refilcnaplo.livecard</string>
|
||||||
|
|||||||
@@ -7,7 +7,5 @@
|
|||||||
<key>NSExtensionPointIdentifier</key>
|
<key>NSExtensionPointIdentifier</key>
|
||||||
<string>com.apple.widgetkit-extension</string>
|
<string>com.apple.widgetkit-extension</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSSupportsLiveActivities</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -49,10 +49,16 @@ Future loginApi({
|
|||||||
}) async {
|
}) async {
|
||||||
Provider.of<KretaClient>(context, listen: false).userAgent =
|
Provider.of<KretaClient>(context, listen: false).userAgent =
|
||||||
Provider.of<SettingsProvider>(context, listen: false).config.userAgent;
|
Provider.of<SettingsProvider>(context, listen: false).config.userAgent;
|
||||||
|
|
||||||
Map<String, String> headers = {
|
Map<String, String> headers = {
|
||||||
"content-type": "application/x-www-form-urlencoded",
|
"content-type": "application/x-www-form-urlencoded",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
String nonceStr = await Provider.of<KretaClient>(context, listen: false)
|
||||||
|
.getAPI(KretaAPI.nonce, json: false);
|
||||||
|
|
||||||
|
Nonce nonce = getNonce(nonceStr, username, instituteCode);
|
||||||
|
headers.addAll(nonce.header());
|
||||||
|
|
||||||
Map? res = await Provider.of<KretaClient>(context, listen: false)
|
Map? res = await Provider.of<KretaClient>(context, listen: false)
|
||||||
.postAPI(KretaAPI.login,
|
.postAPI(KretaAPI.login,
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
String? _latestActivityId;
|
String? _latestActivityId;
|
||||||
Map<String, String> _lastActivity = {};
|
Map<String, String> _lastActivity = {};
|
||||||
|
|
||||||
|
bool _hasCheckedTimetable = false;
|
||||||
|
|
||||||
LiveCardProvider({
|
LiveCardProvider({
|
||||||
required TimetableProvider timetable,
|
required TimetableProvider timetable,
|
||||||
required SettingsProvider settings,
|
required SettingsProvider settings,
|
||||||
@@ -198,7 +200,8 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
List<Lesson> today = _today(_timetable);
|
List<Lesson> today = _today(_timetable);
|
||||||
|
|
||||||
if (today.isEmpty) {
|
if (today.isEmpty && !_hasCheckedTimetable) {
|
||||||
|
_hasCheckedTimetable = true;
|
||||||
await _timetable.fetch(week: Week.current());
|
await _timetable.fetch(week: Week.current());
|
||||||
today = _today(_timetable);
|
today = _today(_timetable);
|
||||||
}
|
}
|
||||||
@@ -252,7 +255,10 @@ class LiveCardProvider extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentLesson != null) {
|
if (now.isBefore(DateTime(now.year, DateTime.august, 31)) &&
|
||||||
|
now.isAfter(DateTime(now.year, DateTime.june, 14))) {
|
||||||
|
currentState = LiveCardState.summary;
|
||||||
|
} else if (currentLesson != null) {
|
||||||
currentState = LiveCardState.duringLesson;
|
currentState = LiveCardState.duringLesson;
|
||||||
} else if (nextLesson != null && prevLesson != null) {
|
} else if (nextLesson != null && prevLesson != null) {
|
||||||
currentState = LiveCardState.duringBreak;
|
currentState = LiveCardState.duringBreak;
|
||||||
|
|||||||
21
filcnaplo/lib/models/personality.dart
Normal file
21
filcnaplo/lib/models/personality.dart
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
class Personality {
|
||||||
|
PersonalityType type;
|
||||||
|
|
||||||
|
Personality({
|
||||||
|
this.type = PersonalityType.npc,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PersonalityType {
|
||||||
|
geek,
|
||||||
|
sick,
|
||||||
|
late,
|
||||||
|
quitter,
|
||||||
|
healthy,
|
||||||
|
acceptable,
|
||||||
|
fallible,
|
||||||
|
average,
|
||||||
|
diligent,
|
||||||
|
cheater,
|
||||||
|
npc
|
||||||
|
}
|
||||||
@@ -194,7 +194,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
premiumLogin: map["premium_login"],
|
premiumLogin: map["premium_login"],
|
||||||
lastAccountId: map["last_account_id"],
|
lastAccountId: map["last_account_id"],
|
||||||
renameSubjectsEnabled: map["renamed_subjects_enabled"] == 1,
|
renameSubjectsEnabled: map["renamed_subjects_enabled"] == 1,
|
||||||
renameSubjectsItalics: map["renamed_subjects_italics"] == 0,
|
renameSubjectsItalics: map["renamed_subjects_italics"] == 1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ description: "Nem hivatalos e-napló alkalmazás az e-Kréta rendszerhez"
|
|||||||
homepage: https://refilc.hu
|
homepage: https://refilc.hu
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 4.1.0+213
|
version: 4.1.1+215
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
@@ -65,6 +65,7 @@ dependencies:
|
|||||||
background_fetch: ^1.1.5
|
background_fetch: ^1.1.5
|
||||||
flutter_local_notifications: ^14.1.0
|
flutter_local_notifications: ^14.1.0
|
||||||
package_info_plus: ^4.0.2
|
package_info_plus: ^4.0.2
|
||||||
|
screenshot: ^2.1.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^2.0.1
|
flutter_lints: ^2.0.1
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ class Empty extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// make the face randomness a bit more constant (to avoid strokes)
|
|
||||||
int index = Random(DateTime.now().minute).nextInt(faces.length);
|
int index = Random(DateTime.now().minute).nextInt(faces.length);
|
||||||
|
|
||||||
return Center(
|
return Center(
|
||||||
@@ -32,9 +31,19 @@ class Empty extends StatelessWidget {
|
|||||||
child: Text.rich(
|
child: Text.rich(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: faces[index],
|
text: faces[index],
|
||||||
style: TextStyle(fontSize: 32.0, fontWeight: FontWeight.w500, color: AppColors.of(context).text.withOpacity(.75)),
|
style: TextStyle(
|
||||||
|
fontSize: 32.0,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: AppColors.of(context).text.withOpacity(.75)),
|
||||||
children: subtitle != null
|
children: subtitle != null
|
||||||
? [TextSpan(text: "\n" + subtitle!, style: TextStyle(fontSize: 18.0, height: 2.0, color: AppColors.of(context).text.withOpacity(.5)))]
|
? [
|
||||||
|
TextSpan(
|
||||||
|
text: "\n" + subtitle!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18.0,
|
||||||
|
height: 2.0,
|
||||||
|
color: AppColors.of(context).text.withOpacity(.5)))
|
||||||
|
]
|
||||||
: [],
|
: [],
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import 'package:dotted_border/dotted_border.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class EmptyCard extends StatefulWidget {
|
||||||
|
const EmptyCard({
|
||||||
|
Key? key,
|
||||||
|
required this.text,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final String text;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<EmptyCard> createState() => _EmptyCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EmptyCardState extends State<EmptyCard> {
|
||||||
|
bool hold = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onLongPressDown: (_) => setState(() => hold = true),
|
||||||
|
onLongPressEnd: (_) => setState(() => hold = false),
|
||||||
|
onLongPressCancel: () => setState(() => hold = false),
|
||||||
|
child: AnimatedScale(
|
||||||
|
scale: hold ? 1.018 : 1.0,
|
||||||
|
curve: Curves.easeInOutBack,
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
child: Container(
|
||||||
|
height: 444,
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(top: 12, bottom: 12, left: 12, right: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0x280008FF),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(5)),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.08),
|
||||||
|
offset: const Offset(0, 5),
|
||||||
|
blurRadius: 20,
|
||||||
|
spreadRadius: 10,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: DottedBorder(
|
||||||
|
color: Colors.black.withOpacity(0.9),
|
||||||
|
dashPattern: const [12, 12],
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(top: 20, bottom: 20, left: 20, right: 20),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
widget.text,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white.withOpacity(0.9),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,374 @@
|
|||||||
|
import 'package:dotted_border/dotted_border.dart';
|
||||||
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
|
import 'package:filcnaplo/helpers/average_helper.dart';
|
||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo/models/personality.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/absence.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import 'personality_card.i18n.dart';
|
||||||
|
|
||||||
|
class PersonalityCard extends StatefulWidget {
|
||||||
|
const PersonalityCard({
|
||||||
|
Key? key,
|
||||||
|
required this.user,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final UserProvider user;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<PersonalityCard> createState() => _PersonalityCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PersonalityCardState extends State<PersonalityCard> {
|
||||||
|
late GradeProvider gradeProvider;
|
||||||
|
late AbsenceProvider absenceProvider;
|
||||||
|
late TimetableProvider timetableProvider;
|
||||||
|
late SettingsProvider settings;
|
||||||
|
|
||||||
|
late List<int> subjectAvgsList = [];
|
||||||
|
late Map<Subject, double> subjectAvgs = {};
|
||||||
|
late double subjectAvg;
|
||||||
|
late List<Grade> classWorkGrades;
|
||||||
|
late Map<int, int> mostCommonGrade;
|
||||||
|
late List<Absence> absences = [];
|
||||||
|
final Map<Subject, Lesson> _lessonCount = {};
|
||||||
|
late int totalDelays;
|
||||||
|
late int unexcusedAbsences;
|
||||||
|
|
||||||
|
late PersonalityType finalPersonality;
|
||||||
|
|
||||||
|
bool hold = false;
|
||||||
|
|
||||||
|
List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider
|
||||||
|
.grades
|
||||||
|
.where((e) =>
|
||||||
|
e.subject == subject &&
|
||||||
|
e.type == GradeType.midYear &&
|
||||||
|
(days == 0 ||
|
||||||
|
e.date.isBefore(DateTime.now().subtract(Duration(days: days)))))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
gradeProvider = Provider.of<GradeProvider>(context, listen: false);
|
||||||
|
absenceProvider = Provider.of<AbsenceProvider>(context, listen: false);
|
||||||
|
timetableProvider = Provider.of<TimetableProvider>(context, listen: false);
|
||||||
|
settings = Provider.of<SettingsProvider>(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 getGrades() {
|
||||||
|
List<Subject> subjects = gradeProvider.grades
|
||||||
|
.map((e) => e.subject)
|
||||||
|
.toSet()
|
||||||
|
.toList()
|
||||||
|
..sort((a, b) => a.name.compareTo(b.name));
|
||||||
|
|
||||||
|
for (Subject subject in subjects) {
|
||||||
|
List<Grade> subjectGrades = getSubjectGrades(subject);
|
||||||
|
|
||||||
|
double avg = AverageHelper.averageEvals(subjectGrades);
|
||||||
|
if (avg != 0) subjectAvgs[subject] = avg;
|
||||||
|
|
||||||
|
subjectAvgsList.add(avg.round());
|
||||||
|
}
|
||||||
|
|
||||||
|
subjectAvg = subjectAvgs.isNotEmpty
|
||||||
|
? subjectAvgs.values.fold(0.0, (double a, double b) => a + b) /
|
||||||
|
subjectAvgs.length
|
||||||
|
: 0.0;
|
||||||
|
|
||||||
|
classWorkGrades =
|
||||||
|
gradeProvider.grades.where((a) => a.value.weight <= 75).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void getMostCommonGrade() {
|
||||||
|
Map<int, int> counts = {};
|
||||||
|
|
||||||
|
subjectAvgsList.map((e) {
|
||||||
|
if (counts.containsKey(e)) {
|
||||||
|
counts.update(e, (value) => value++);
|
||||||
|
} else {
|
||||||
|
counts[e] = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var maxValue = 0;
|
||||||
|
var maxKey = 0;
|
||||||
|
|
||||||
|
counts.forEach((k, v) {
|
||||||
|
if (v > maxValue) {
|
||||||
|
maxValue = v;
|
||||||
|
maxKey = k;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mostCommonGrade = {maxKey: maxValue};
|
||||||
|
}
|
||||||
|
|
||||||
|
void getAbsences() {
|
||||||
|
absences = absenceProvider.absences.where((a) => a.delay == 0).toList();
|
||||||
|
|
||||||
|
unexcusedAbsences = absences
|
||||||
|
.where((a) => a.state == Justification.unexcused && a.delay == 0)
|
||||||
|
.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getAndSortDelays() {
|
||||||
|
Iterable<int> unexcusedDelays = absences
|
||||||
|
.where((a) => a.state == Justification.unexcused && a.delay > 0)
|
||||||
|
.map((e) => e.delay);
|
||||||
|
totalDelays = unexcusedDelays.isNotEmpty
|
||||||
|
? unexcusedDelays.reduce((a, b) => a + b)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void doEverything() {
|
||||||
|
getGrades();
|
||||||
|
getMostCommonGrade();
|
||||||
|
getAbsences();
|
||||||
|
getAndSortDelays();
|
||||||
|
}
|
||||||
|
|
||||||
|
void getPersonality() {
|
||||||
|
if (settings.goodStudent) {
|
||||||
|
finalPersonality = PersonalityType.cheater;
|
||||||
|
} else if (subjectAvg > 4.7) {
|
||||||
|
finalPersonality = PersonalityType.geek;
|
||||||
|
} else if (mostCommonGrade.keys.toList()[0] == 1 &&
|
||||||
|
mostCommonGrade.values.toList()[0] > 1) {
|
||||||
|
finalPersonality = PersonalityType.fallible;
|
||||||
|
} else if (absences.length < 10) {
|
||||||
|
finalPersonality = PersonalityType.healthy;
|
||||||
|
} else if (unexcusedAbsences >= 10) {
|
||||||
|
finalPersonality = PersonalityType.quitter;
|
||||||
|
} else if (totalDelays > 50) {
|
||||||
|
finalPersonality = PersonalityType.late;
|
||||||
|
} else if (absences.length >= 100) {
|
||||||
|
finalPersonality = PersonalityType.sick;
|
||||||
|
} else if (mostCommonGrade.keys.toList()[0] == 2) {
|
||||||
|
finalPersonality = PersonalityType.acceptable;
|
||||||
|
} else if (mostCommonGrade.keys.toList()[0] == 3) {
|
||||||
|
finalPersonality = PersonalityType.average;
|
||||||
|
} else if (classWorkGrades.length >= 5) {
|
||||||
|
finalPersonality = PersonalityType.diligent;
|
||||||
|
} else {
|
||||||
|
finalPersonality = PersonalityType.npc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardInnerBuilder() {
|
||||||
|
Map<PersonalityType, Map<String, String>> personality = {
|
||||||
|
PersonalityType.geek: {
|
||||||
|
'emoji': '🤓',
|
||||||
|
'title': 't_geek',
|
||||||
|
'description': 'd_geek',
|
||||||
|
'subtitle': 's_geek',
|
||||||
|
'subvalue': subjectAvg.toStringAsFixed(2),
|
||||||
|
},
|
||||||
|
PersonalityType.sick: {
|
||||||
|
'emoji': '🤒',
|
||||||
|
'title': 't_sick',
|
||||||
|
'description': 'd_sick',
|
||||||
|
'subtitle': 's_sick',
|
||||||
|
'subvalue': absences.length.toString(),
|
||||||
|
},
|
||||||
|
PersonalityType.late: {
|
||||||
|
'emoji': '⌛',
|
||||||
|
'title': 't_late',
|
||||||
|
'description': 'd_late',
|
||||||
|
'subtitle': 's_late',
|
||||||
|
'subvalue': totalDelays.toString(),
|
||||||
|
},
|
||||||
|
PersonalityType.quitter: {
|
||||||
|
'emoji': '❓',
|
||||||
|
'title': 't_quitter',
|
||||||
|
'description': 'd_quitter',
|
||||||
|
'subtitle': 's_quitter',
|
||||||
|
'subvalue': unexcusedAbsences.toString(),
|
||||||
|
},
|
||||||
|
PersonalityType.healthy: {
|
||||||
|
'emoji': '😷',
|
||||||
|
'title': 't_healthy',
|
||||||
|
'description': 'd_healthy',
|
||||||
|
'subtitle': 's_healthy',
|
||||||
|
'subvalue': absences.length.toString(),
|
||||||
|
},
|
||||||
|
PersonalityType.acceptable: {
|
||||||
|
'emoji': '🤏',
|
||||||
|
'title': 't_acceptable',
|
||||||
|
'description': 'd_acceptable',
|
||||||
|
'subtitle': 's_acceptable',
|
||||||
|
'subvalue': mostCommonGrade.values.toList()[0].toString(),
|
||||||
|
},
|
||||||
|
PersonalityType.fallible: {
|
||||||
|
'emoji': '📉',
|
||||||
|
'title': 't_fallible',
|
||||||
|
'description': 'd_fallible',
|
||||||
|
'subtitle': 's_fallible',
|
||||||
|
'subvalue': mostCommonGrade.values.toList()[0].toString(),
|
||||||
|
},
|
||||||
|
PersonalityType.average: {
|
||||||
|
'emoji': '👌',
|
||||||
|
'title': 't_average',
|
||||||
|
'description': 'd_average',
|
||||||
|
'subtitle': 's_average',
|
||||||
|
'subvalue': mostCommonGrade.values.toList()[0].toString(),
|
||||||
|
},
|
||||||
|
PersonalityType.diligent: {
|
||||||
|
'emoji': '💫',
|
||||||
|
'title': 't_diligent',
|
||||||
|
'description': 'd_diligent',
|
||||||
|
'subtitle': 's_diligent',
|
||||||
|
'subvalue': classWorkGrades.length.toString(),
|
||||||
|
},
|
||||||
|
PersonalityType.cheater: {
|
||||||
|
'emoji': '🧑💻',
|
||||||
|
'title': 't_cheater',
|
||||||
|
'description': 'd_cheater',
|
||||||
|
'subtitle': 's_cheater',
|
||||||
|
'subvalue': '0',
|
||||||
|
},
|
||||||
|
PersonalityType.npc: {
|
||||||
|
'emoji': '⛰️',
|
||||||
|
'title': 't_npc',
|
||||||
|
'description': 'd_npc',
|
||||||
|
'subtitle': 's_npc',
|
||||||
|
'subvalue': '69420',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Map<PersonalityType, Widget> personalityWidgets = {};
|
||||||
|
|
||||||
|
for (var i in personality.keys) {
|
||||||
|
Widget w = Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
personality[i]?['emoji'] ?? '❓',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 128.0,
|
||||||
|
height: 1.2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
(personality[i]?['title'] ?? 'unknown').i18n,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 38.0,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
Text(
|
||||||
|
(personality[i]?['description'] ?? 'unknown_personality').i18n,
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
height: 1.2,
|
||||||
|
color: Colors.white.withOpacity(0.8),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 25),
|
||||||
|
Text(
|
||||||
|
(personality[i]?['subtitle'] ?? 'unknown').i18n,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 20.0,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
personality[i]?['subvalue'] ?? '0',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 69.0,
|
||||||
|
height: 1.15,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
personalityWidgets.addAll({i: w});
|
||||||
|
}
|
||||||
|
|
||||||
|
return personalityWidgets[finalPersonality] ?? Container();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
doEverything();
|
||||||
|
getPersonality();
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
|
onLongPressDown: (_) => setState(() => hold = true),
|
||||||
|
onLongPressEnd: (_) => setState(() => hold = false),
|
||||||
|
onLongPressCancel: () => setState(() => hold = false),
|
||||||
|
child: AnimatedScale(
|
||||||
|
scale: hold ? 1.018 : 1.0,
|
||||||
|
curve: Curves.easeInOutBack,
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
child: Container(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(top: 12, bottom: 12, left: 12, right: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0x280008FF),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(5)),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.08),
|
||||||
|
offset: const Offset(0, 5),
|
||||||
|
blurRadius: 20,
|
||||||
|
spreadRadius: 10,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: DottedBorder(
|
||||||
|
color: Colors.black.withOpacity(0.9),
|
||||||
|
dashPattern: const [12, 12],
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(top: 20, bottom: 20, left: 20, right: 20),
|
||||||
|
child: cardInnerBuilder(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
import 'package:i18n_extension/i18n_extension.dart';
|
||||||
|
|
||||||
|
extension Localization on String {
|
||||||
|
static final _t = Translations.byLocale("hu_hu") +
|
||||||
|
{
|
||||||
|
"en_en": {
|
||||||
|
// main
|
||||||
|
"unknown": "???",
|
||||||
|
"unknown_personality": "Unknown personality...",
|
||||||
|
// personalities
|
||||||
|
"t_geek": "Know-It-All",
|
||||||
|
"d_geek":
|
||||||
|
"You learn a lot, but don't worry - Being a know-it-all is a blessing in disguise. You'll be successful in life.",
|
||||||
|
"s_geek": "Year-end average",
|
||||||
|
"t_sick": "Sick",
|
||||||
|
"d_sick":
|
||||||
|
"Get well soon, bro. Even if you lied about being sick to skip school.",
|
||||||
|
"s_sick": "Absences",
|
||||||
|
"t_late": "Late",
|
||||||
|
"d_late":
|
||||||
|
"The tram's wheel got punctured. The airplane was derailed. Your dog ate your shoe. We believe you.",
|
||||||
|
"s_late": "Delays (minutes)",
|
||||||
|
"t_quitter": "Skipper",
|
||||||
|
"d_quitter": "Supplementary exam incoming.",
|
||||||
|
"s_quitter": "Igazolatlan hiányzások",
|
||||||
|
"t_healthy": "Healthy",
|
||||||
|
"d_healthy":
|
||||||
|
"As cool as a cucumber! You almost never missed a class.",
|
||||||
|
"s_healthy": "Absences",
|
||||||
|
"t_acceptable": "Acceptable",
|
||||||
|
"d_acceptable":
|
||||||
|
"Final exams are D. But who cares? It's still a grade. Not a good one, but it's definitely a grade.",
|
||||||
|
"s_acceptable": "D's",
|
||||||
|
"t_fallible": "Failed",
|
||||||
|
"d_fallible": "Good luck next year.",
|
||||||
|
"s_fallible": "F's",
|
||||||
|
"t_average": "It's okay",
|
||||||
|
"d_average": "Not good, not bad. The golden mean, if you will...",
|
||||||
|
"s_average": "C's",
|
||||||
|
"t_diligent": "Hard-worker",
|
||||||
|
"d_diligent":
|
||||||
|
"You noted everything, you made that presentation, and you lead the group project.",
|
||||||
|
"s_diligent": "Class work A's",
|
||||||
|
"t_cheater": "Cheater",
|
||||||
|
"d_cheater":
|
||||||
|
"You enabled the \"Good Student\" mode. Wow. You may have outsmarted me, but I have outsmarted your outsmarting.",
|
||||||
|
"s_cheater": "Bitches",
|
||||||
|
"t_npc": "NPC",
|
||||||
|
"d_npc":
|
||||||
|
"You're such a non-player character, we couldn't give you a personality.",
|
||||||
|
"s_npc": "In-game playtime (hours)",
|
||||||
|
},
|
||||||
|
"hu_hu": {
|
||||||
|
// main
|
||||||
|
"unknown": "???",
|
||||||
|
"unknown_personality": "Ismeretlen személyiség...",
|
||||||
|
// personalities
|
||||||
|
"t_geek": "Stréber",
|
||||||
|
"d_geek":
|
||||||
|
"Sokat tanulsz, de ezzel semmi baj! Ez egyben áldás és átok, de legalább az életben sikeres leszel.",
|
||||||
|
"s_geek": "Év végi átlagod",
|
||||||
|
"t_sick": "Beteges",
|
||||||
|
"d_sick":
|
||||||
|
"Jobbulást, tesó. Még akkor is, ha hazudtál arról, hogy beteg vagy, hogy ne kelljen suliba menned.",
|
||||||
|
"s_sick": "Hiányzásaid",
|
||||||
|
"t_late": "Késős",
|
||||||
|
"d_late":
|
||||||
|
"Kilyukadt a villamos kereke. Kisiklott a repülő. A kutyád megette a cipőd. Elhisszük.",
|
||||||
|
"s_late": "Késések (perc)",
|
||||||
|
"t_quitter": "Lógós",
|
||||||
|
"d_quitter": "Osztályzóvizsga incoming.",
|
||||||
|
"s_quitter": "Igazolatlan hiányzások",
|
||||||
|
"t_healthy": "Makk",
|
||||||
|
"d_healthy":
|
||||||
|
"...egészséges vagy! Egész évben alig hiányoztál az iskolából.",
|
||||||
|
"s_healthy": "Hiányzásaid",
|
||||||
|
"t_acceptable": "Elmegy",
|
||||||
|
"d_acceptable":
|
||||||
|
"A kettes érettségi is érettségi. Nem egy jó érettségi, de biztos, hogy egy érettségi.",
|
||||||
|
"s_acceptable": "Kettesek",
|
||||||
|
"t_fallible": "Bukós",
|
||||||
|
"d_fallible": "Jövőre több sikerrel jársz.",
|
||||||
|
"s_fallible": "Karók",
|
||||||
|
"t_average": "Közepes",
|
||||||
|
"d_average": "Se jó, se rossz. Az arany középút, ha akarsz...",
|
||||||
|
"s_average": "Hármasok",
|
||||||
|
"t_diligent": "Szorgalmas",
|
||||||
|
"d_diligent":
|
||||||
|
"Leírtad a jegyzetet, megcsináltad a prezentációt, és te vezetted a projektmunkát.",
|
||||||
|
"s_diligent": "Órai munka ötösök",
|
||||||
|
"t_cheater": "Csaló",
|
||||||
|
"d_cheater":
|
||||||
|
"Bekapcsoltad a “Jó Tanuló” módot. Wow. Azt hitted, túl járhatsz az eszemen, de kijátszottam a kijátszásod.",
|
||||||
|
"s_cheater": "Bitches",
|
||||||
|
"t_npc": "NPC",
|
||||||
|
"d_npc":
|
||||||
|
"Egy akkora nagy non-player character vagy, hogy neked semmilyen személyiség nem jutott ezen kívül.",
|
||||||
|
"s_npc": "In-game playtime (óra)",
|
||||||
|
},
|
||||||
|
"de_de": {
|
||||||
|
// main
|
||||||
|
"unknown": "???",
|
||||||
|
"unknown_personality": "Unbekannte Persönlichkeit...",
|
||||||
|
// personalities
|
||||||
|
"t_geek": "Besserwisser",
|
||||||
|
"d_geek":
|
||||||
|
"Du lernst eine Menge, aber sorge dich nicht - ein Besserwisser zu sein wird sich letzten Endes doch als Segen erweisen. Du wirst erfolgreich sein im Leben.",
|
||||||
|
"s_geek": "Durchschnittsschüler",
|
||||||
|
"t_sick": "Krank",
|
||||||
|
"d_sick":
|
||||||
|
"Werd schnell wieder gesund, Brudi. Selbst wenn du gelogen hast, nur um Schule zu schwänzen zu können.",
|
||||||
|
"s_sick": "Abwesenheiten",
|
||||||
|
"t_late": "Verspätet",
|
||||||
|
"d_late":
|
||||||
|
"Die Straßenbahn hat eine Reifenpanne. Das Flugzeug ist entgleist. Dein Hund hat deinen Schuh gefressen. Klar, wir glauben dir.",
|
||||||
|
"s_late": "Verspätung (Minuten)",
|
||||||
|
"t_quitter": "Schulschwänzer",
|
||||||
|
"d_quitter": "Ein zusätzlicher Test wird anstehen.",
|
||||||
|
"s_quitter": "Unentschuldigte Abwesenheiten",
|
||||||
|
"t_healthy": "Gesund",
|
||||||
|
"d_healthy":
|
||||||
|
"Du bist die Ruhe selbst! Du hast fast nie eine Unterrichtsstunde verpasst.",
|
||||||
|
"s_healthy": "Abwesenheiten",
|
||||||
|
"t_acceptable": "Akzeptabel",
|
||||||
|
"d_acceptable":
|
||||||
|
"Die Abschlussprüfungen waren gerade einmal eine 4. Aber wen juckt's? Es ist immer noch positiv. Nicht allzu gut, aber definitiv positiv.",
|
||||||
|
"s_acceptable": "4er",
|
||||||
|
"t_fallible": "Durchgefallen",
|
||||||
|
"d_fallible": "Viel Glück im nächsten Jahr.",
|
||||||
|
"s_fallible": "5er",
|
||||||
|
"t_average": "Es ist in Ordnung",
|
||||||
|
"d_average":
|
||||||
|
"Nicht gut, nicht schlecht. Der goldene Durchschnitt, wenn du so willst...",
|
||||||
|
"s_average": "3er",
|
||||||
|
"t_diligent": "Ein Fleißiger",
|
||||||
|
"d_diligent":
|
||||||
|
"Du hast bei allem mitgeschrieben, du hast den Vortrag gehalten, und du hast die Gruppenarbeit geleitet.",
|
||||||
|
"s_diligent": "1er Schüler",
|
||||||
|
"t_cheater": "Geschummelt",
|
||||||
|
"d_cheater":
|
||||||
|
"Du hast den „Guter Schüler“ Modus aktiviert. Wow. Du magst mich zwar vielleicht überlistet haben, aber ich habe deine Überlistung überlistet.",
|
||||||
|
"s_cheater": "Bitches",
|
||||||
|
"t_npc": "COM",
|
||||||
|
"d_npc":
|
||||||
|
"Du bist einfach so sehr wie ein Computer, dass wir dir nicht einmal eine Persönlichkeit geben konnten.",
|
||||||
|
"s_npc": "Spielzeit (Stunden)",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
String get i18n => localize(this, _t);
|
||||||
|
String fill(List<Object> params) => localizeFill(this, params);
|
||||||
|
String plural(int value) => localizePlural(value, this, _t);
|
||||||
|
String version(Object modifier) => localizeVersion(modifier, this, _t);
|
||||||
|
}
|
||||||
@@ -56,16 +56,43 @@ class _LiveCardState extends State<LiveCard> {
|
|||||||
case LiveCardState.summary:
|
case LiveCardState.summary:
|
||||||
child = LiveCardWidget(
|
child = LiveCardWidget(
|
||||||
key: const Key('livecard.summary'),
|
key: const Key('livecard.summary'),
|
||||||
title: '',
|
title: 'Vége a tanévnek! 🥳',
|
||||||
icon: FeatherIcons.arrowRight,
|
icon: FeatherIcons.arrowRight,
|
||||||
description: const Text(''),
|
description: Text(
|
||||||
onTap: () => Navigator.of(context).push(
|
'Irány az összefoglaláshoz',
|
||||||
MaterialPageRoute(
|
style: TextStyle(
|
||||||
builder: (BuildContext context) => const SummaryScreen(
|
fontWeight: FontWeight.w500,
|
||||||
currentPage: 'grades',
|
fontSize: 18.0,
|
||||||
),
|
color: Theme.of(context).textTheme.bodyMedium?.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
onTap: () {
|
||||||
|
// showSlidingBottomSheet(
|
||||||
|
// context,
|
||||||
|
// useRootNavigator: true,
|
||||||
|
// builder: (context) => SlidingSheetDialog(
|
||||||
|
// color: Colors.black.withOpacity(0.99),
|
||||||
|
// duration: const Duration(milliseconds: 400),
|
||||||
|
// scrollSpec: const ScrollSpec.bouncingScroll(),
|
||||||
|
// snapSpec: const SnapSpec(
|
||||||
|
// snap: true,
|
||||||
|
// snappings: [1.0],
|
||||||
|
// initialSnap: 1.0,
|
||||||
|
// positioning: SnapPositioning.relativeToAvailableSpace,
|
||||||
|
// ),
|
||||||
|
// minHeight: MediaQuery.of(context).size.height,
|
||||||
|
// cornerRadius: 16,
|
||||||
|
// cornerRadiusOnFullscreen: 0,
|
||||||
|
// builder: (context, state) => const Material(
|
||||||
|
// color: Colors.black,
|
||||||
|
// child: SummaryScreen(
|
||||||
|
// currentPage: 'start',
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
SummaryScreen.show(context: context, currentPage: 'start');
|
||||||
|
},
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case LiveCardState.morning:
|
case LiveCardState.morning:
|
||||||
|
|||||||
@@ -81,22 +81,35 @@ class _LiveCardWidgetState extends State<LiveCardWidget> {
|
|||||||
child: widget.isEvent
|
child: widget.isEvent
|
||||||
? Column(
|
? Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
widget.title ?? 'Esemény',
|
widget.title ?? 'Esemény',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 32,
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 24.0,
|
||||||
|
color:
|
||||||
|
Theme.of(context).textTheme.bodyMedium?.color,
|
||||||
fontStyle:
|
fontStyle:
|
||||||
widget.titleItalic ? FontStyle.italic : null,
|
widget.titleItalic ? FontStyle.italic : null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
widget.description ??
|
widget.description ??
|
||||||
const Text('Nincs leírás megadva.'),
|
Text(
|
||||||
|
'Nincs leírás megadva.',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontSize: 18.0,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium
|
||||||
|
?.color,
|
||||||
|
),
|
||||||
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 15,
|
height: 15,
|
||||||
child: Container(
|
child: Container(
|
||||||
|
|||||||
227
filcnaplo_mobile_ui/lib/screens/summary/pages/allsum_page.dart
Normal file
227
filcnaplo_mobile_ui/lib/screens/summary/pages/allsum_page.dart
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/absence.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.i18n.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class AllSumBody extends StatefulWidget {
|
||||||
|
const AllSumBody({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_AllSumBodyState createState() => _AllSumBodyState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AllSumBodyState extends State<AllSumBody> {
|
||||||
|
late UserProvider user;
|
||||||
|
late GradeProvider gradeProvider;
|
||||||
|
late HomeworkProvider homeworkProvider;
|
||||||
|
late AbsenceProvider absenceProvider;
|
||||||
|
//late TimetableProvider timetableProvider;
|
||||||
|
|
||||||
|
late Map<String, Map<String, dynamic>> things = {};
|
||||||
|
late List<Widget> firstSixTiles = [];
|
||||||
|
late List<Widget> lastSixTiles = [];
|
||||||
|
|
||||||
|
int avgDropValue = 0;
|
||||||
|
bool animation = false;
|
||||||
|
|
||||||
|
List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider
|
||||||
|
.grades
|
||||||
|
.where((e) =>
|
||||||
|
e.subject == subject &&
|
||||||
|
e.type == GradeType.midYear &&
|
||||||
|
(days == 0 ||
|
||||||
|
e.date.isBefore(DateTime.now().subtract(Duration(days: days)))))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
gradeProvider = Provider.of<GradeProvider>(context, listen: false);
|
||||||
|
homeworkProvider = Provider.of<HomeworkProvider>(context, listen: false);
|
||||||
|
absenceProvider = Provider.of<AbsenceProvider>(context, listen: false);
|
||||||
|
//timetableProvider = Provider.of<TimetableProvider>(context, listen: false);
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
|
setState(() {
|
||||||
|
animation = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void getGrades() {
|
||||||
|
var allGrades = gradeProvider.grades;
|
||||||
|
var testsGrades = gradeProvider.grades.where((a) => a.value.weight == 100);
|
||||||
|
var closingTestsGrades =
|
||||||
|
gradeProvider.grades.where((a) => a.value.weight >= 200);
|
||||||
|
|
||||||
|
things.addAll({
|
||||||
|
'tests': {'name': 'test'.i18n, 'value': testsGrades.length},
|
||||||
|
'closingTests': {
|
||||||
|
'name': 'closingtest'.i18n,
|
||||||
|
'value': closingTestsGrades.length
|
||||||
|
},
|
||||||
|
'grades': {'name': 'grade'.i18n, 'value': allGrades.length}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void getHomework() {
|
||||||
|
var allHomework = homeworkProvider.homework;
|
||||||
|
|
||||||
|
things.addAll({
|
||||||
|
'homework': {'name': 'hw'.i18n, 'value': allHomework.length}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void getSubjects() {
|
||||||
|
var allSubjects = gradeProvider.grades
|
||||||
|
.map((e) => e.subject)
|
||||||
|
.toSet()
|
||||||
|
.toList()
|
||||||
|
..sort((a, b) => a.name.compareTo(b.name));
|
||||||
|
//var totalLessons;
|
||||||
|
var totalLessons = 0;
|
||||||
|
|
||||||
|
things.addAll({
|
||||||
|
'subjects': {'name': 'subject'.i18n, 'value': allSubjects.length},
|
||||||
|
'lessons': {'name': 'lesson'.i18n, 'value': totalLessons}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void getAbsences() {
|
||||||
|
var allAbsences = absenceProvider.absences.where((a) => a.delay == 0);
|
||||||
|
var excusedAbsences = absenceProvider.absences
|
||||||
|
.where((a) => a.state == Justification.excused && a.delay == 0);
|
||||||
|
var unexcusedAbsences = absenceProvider.absences.where((a) =>
|
||||||
|
(a.state == Justification.unexcused ||
|
||||||
|
a.state == Justification.pending) &&
|
||||||
|
a.delay == 0);
|
||||||
|
|
||||||
|
things.addAll({
|
||||||
|
'absences': {'name': 'absence_sum'.i18n, 'value': allAbsences.length},
|
||||||
|
'excusedAbsences': {
|
||||||
|
'name': 'excused'.i18n,
|
||||||
|
'value': excusedAbsences.length
|
||||||
|
},
|
||||||
|
'unexcusedAbsences': {
|
||||||
|
'name': 'unexcused'.i18n,
|
||||||
|
'value': unexcusedAbsences.length
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void getDelays() {
|
||||||
|
var allDelays = absenceProvider.absences.where((a) => a.delay > 0);
|
||||||
|
var totalDelayTime = (allDelays.map((a) {
|
||||||
|
return a.delay;
|
||||||
|
}).toList())
|
||||||
|
.reduce((a, b) => a + b);
|
||||||
|
var unexcusedDelays = absenceProvider.absences
|
||||||
|
.where((a) => a.state == Justification.unexcused && a.delay > 0);
|
||||||
|
|
||||||
|
things.addAll({
|
||||||
|
'delays': {'name': 'delay_sum'.i18n, 'value': allDelays.length},
|
||||||
|
'totalDelay': {'name': 'min'.i18n, 'value': totalDelayTime},
|
||||||
|
'unexcusedDelays': {
|
||||||
|
'name': 'unexcused'.i18n,
|
||||||
|
'value': unexcusedDelays.length
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void getEverything() {
|
||||||
|
getGrades();
|
||||||
|
getHomework();
|
||||||
|
getSubjects();
|
||||||
|
getAbsences();
|
||||||
|
getDelays();
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateTiles() {
|
||||||
|
for (var i in things.values) {
|
||||||
|
Widget w = Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
i.values.toList()[1].toString(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
fontSize: 36.0,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
i.values.toList()[0],
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 18.0,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: az orakat es a hazikat szarul keri le, de majd meg lesz csinalva
|
||||||
|
if (firstSixTiles.length < 6) {
|
||||||
|
firstSixTiles.add(w);
|
||||||
|
} else if (lastSixTiles.length < 6) {
|
||||||
|
lastSixTiles.add(w);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
getEverything();
|
||||||
|
generateTiles();
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 45,
|
||||||
|
),
|
||||||
|
AnimatedContainer(
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
duration: const Duration(milliseconds: 420),
|
||||||
|
transform: Matrix4.translationValues(
|
||||||
|
animation ? 0 : MediaQuery.of(context).size.width, 0, 0),
|
||||||
|
height: 250,
|
||||||
|
child: GridView.count(
|
||||||
|
crossAxisCount: 3,
|
||||||
|
mainAxisSpacing: 0,
|
||||||
|
crossAxisSpacing: 5,
|
||||||
|
children: firstSixTiles,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 30,
|
||||||
|
),
|
||||||
|
AnimatedContainer(
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
duration: const Duration(milliseconds: 420),
|
||||||
|
transform: Matrix4.translationValues(
|
||||||
|
animation ? 0 : -MediaQuery.of(context).size.width, 0, 0),
|
||||||
|
height: 250,
|
||||||
|
child: GridView.count(
|
||||||
|
crossAxisCount: 3,
|
||||||
|
mainAxisSpacing: 0,
|
||||||
|
crossAxisSpacing: 5,
|
||||||
|
children: lastSixTiles,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,362 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'dart:math';
|
||||||
|
|
||||||
class GradesBody extends StatelessWidget {
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
|
import 'package:filcnaplo/helpers/average_helper.dart';
|
||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo/ui/widgets/grade/grade_tile.dart';
|
||||||
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.i18n.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
|
import 'package:i18n_extension/i18n_widget.dart';
|
||||||
|
|
||||||
|
List<String> faces = [
|
||||||
|
"(·.·)",
|
||||||
|
"(≥o≤)",
|
||||||
|
"(·_·)",
|
||||||
|
"(˚Δ˚)b",
|
||||||
|
"(^-^*)",
|
||||||
|
"(='X'=)",
|
||||||
|
"(>_<)",
|
||||||
|
"(;-;)",
|
||||||
|
"\\(^Д^)/",
|
||||||
|
"\\(o_o)/",
|
||||||
|
];
|
||||||
|
|
||||||
|
class GradesBody extends StatefulWidget {
|
||||||
const GradesBody({Key? key}) : super(key: key);
|
const GradesBody({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_GradesBodyState createState() => _GradesBodyState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GradesBodyState extends State<GradesBody> {
|
||||||
|
late UserProvider user;
|
||||||
|
late GradeProvider gradeProvider;
|
||||||
|
late SettingsProvider settings;
|
||||||
|
|
||||||
|
late double subjectAvg;
|
||||||
|
late double endYearAvg;
|
||||||
|
late String endYearAvgText;
|
||||||
|
|
||||||
|
List<Widget> subjectTiles5 = [];
|
||||||
|
List<Widget> subjectTiles3 = [];
|
||||||
|
List<Widget> subjectTiles1 = [];
|
||||||
|
|
||||||
|
int avgDropValue = 0;
|
||||||
|
bool animation = false;
|
||||||
|
|
||||||
|
List<Grade> getSubjectGrades(Subject subject, {int days = 0}) => gradeProvider
|
||||||
|
.grades
|
||||||
|
.where((e) =>
|
||||||
|
e.subject == subject &&
|
||||||
|
e.type == GradeType.midYear &&
|
||||||
|
(days == 0 ||
|
||||||
|
e.date.isBefore(DateTime.now().subtract(Duration(days: days)))))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
gradeProvider = Provider.of<GradeProvider>(context, listen: false);
|
||||||
|
settings = Provider.of<SettingsProvider>(context, listen: false);
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
|
setState(() {
|
||||||
|
animation = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateTiles({required int filter}) {
|
||||||
|
List<Subject> subjects = gradeProvider.grades
|
||||||
|
.map((e) => e.subject)
|
||||||
|
.toSet()
|
||||||
|
.toList()
|
||||||
|
..sort((a, b) => a.name.compareTo(b.name));
|
||||||
|
List<Widget> tiles = [];
|
||||||
|
|
||||||
|
Map<Subject, double> subjectAvgs = {};
|
||||||
|
|
||||||
|
var count = 1;
|
||||||
|
|
||||||
|
for (Subject subject in subjects) {
|
||||||
|
List<Grade> subjectGrades = getSubjectGrades(subject);
|
||||||
|
|
||||||
|
double avg = AverageHelper.averageEvals(subjectGrades);
|
||||||
|
if (avg != 0) subjectAvgs[subject] = avg;
|
||||||
|
|
||||||
|
Widget widget = AnimatedContainer(
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
duration: Duration(milliseconds: 300 + (count * 120)),
|
||||||
|
transform: Matrix4.translationValues(
|
||||||
|
animation ? 0 : MediaQuery.of(context).size.width, 0, 0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
GradeValueWidget(
|
||||||
|
GradeValue(avg.round(), '', '', 100),
|
||||||
|
fill: true,
|
||||||
|
size: 28.0,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Text(
|
||||||
|
subject.renamedTo ?? subject.name.capital(),
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 20.0,
|
||||||
|
color: Colors.white.withOpacity(0.98),
|
||||||
|
fontStyle: settings.renamedSubjectsItalics && subject.isRenamed
|
||||||
|
? FontStyle.italic
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (avg.round() == filter) {
|
||||||
|
tiles.add(widget);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tiles.isEmpty) {
|
||||||
|
int index = Random(DateTime.now().minute).nextInt(faces.length);
|
||||||
|
Widget faceWidget = 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_grades'.i18n}",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18.0,
|
||||||
|
height: 2.0,
|
||||||
|
color: Colors.white.withOpacity(0.5)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
tiles.insert(0, faceWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
subjectAvg = subjectAvgs.isNotEmpty
|
||||||
|
? subjectAvgs.values.fold(0.0, (double a, double b) => a + b) /
|
||||||
|
subjectAvgs.length
|
||||||
|
: 0.0;
|
||||||
|
|
||||||
|
List<Grade> endYearGrades = gradeProvider.grades
|
||||||
|
.where((grade) => grade.type == GradeType.endYear)
|
||||||
|
.toList();
|
||||||
|
endYearAvg = AverageHelper.averageEvals(endYearGrades, finalAvg: true);
|
||||||
|
endYearAvgText = endYearAvg.toStringAsFixed(1);
|
||||||
|
if (I18n.of(context).locale.languageCode != "en") {
|
||||||
|
endYearAvgText = endYearAvgText.replaceAll(".", ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter == 5) {
|
||||||
|
subjectTiles5 = List.castFrom(tiles);
|
||||||
|
if (subjectTiles5.length > 4) {
|
||||||
|
subjectTiles5.length = 4;
|
||||||
|
}
|
||||||
|
} else if (filter == 3) {
|
||||||
|
subjectTiles3 = List.castFrom(tiles);
|
||||||
|
if (subjectTiles3.length > 3) {
|
||||||
|
subjectTiles3.length = 3;
|
||||||
|
}
|
||||||
|
} else if (filter == 1) {
|
||||||
|
subjectTiles1 = List.castFrom(tiles);
|
||||||
|
if (subjectTiles1.length > 2) {
|
||||||
|
subjectTiles1.length = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getGrades() {
|
||||||
|
generateTiles(filter: 5);
|
||||||
|
generateTiles(filter: 3);
|
||||||
|
generateTiles(filter: 1);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const Column();
|
user = Provider.of<UserProvider>(context);
|
||||||
|
settings = Provider.of<SettingsProvider>(context);
|
||||||
|
|
||||||
|
getGrades();
|
||||||
|
|
||||||
|
return Expanded(
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: ((100 * subjectTiles5.length) /
|
||||||
|
(subjectTiles5[0].runtimeType == AnimatedContainer
|
||||||
|
? 1.95
|
||||||
|
: 1.2))
|
||||||
|
.toDouble(),
|
||||||
|
child: ListView.builder(
|
||||||
|
padding: const EdgeInsets.only(left: 5),
|
||||||
|
physics: const BouncingScrollPhysics(),
|
||||||
|
itemCount: max(subjectTiles5.length, 1),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (subjectTiles5.isNotEmpty) {
|
||||||
|
EdgeInsetsGeometry panelPadding =
|
||||||
|
const EdgeInsets.symmetric(horizontal: 24.0);
|
||||||
|
|
||||||
|
if (subjectTiles5[index].runtimeType == AnimatedContainer) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8),
|
||||||
|
child: subjectTiles5[index]);
|
||||||
|
} else {
|
||||||
|
return Padding(
|
||||||
|
padding: panelPadding, child: subjectTiles5[index]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12.0),
|
||||||
|
Text(
|
||||||
|
'tryagain'.i18n,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 22.0,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12.0),
|
||||||
|
SizedBox(
|
||||||
|
height: ((100 * subjectTiles3.length) /
|
||||||
|
(subjectTiles3[0].runtimeType == AnimatedContainer
|
||||||
|
? 1.95
|
||||||
|
: 1.2))
|
||||||
|
.toDouble(),
|
||||||
|
child: ListView.builder(
|
||||||
|
padding: const EdgeInsets.only(left: 5),
|
||||||
|
physics: const BouncingScrollPhysics(),
|
||||||
|
itemCount: max(subjectTiles3.length, 1),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (subjectTiles3.isNotEmpty) {
|
||||||
|
EdgeInsetsGeometry panelPadding =
|
||||||
|
const EdgeInsets.symmetric(horizontal: 24.0);
|
||||||
|
|
||||||
|
if (subjectTiles3[index].runtimeType == AnimatedContainer) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8),
|
||||||
|
child: subjectTiles3[index]);
|
||||||
|
} else {
|
||||||
|
return Padding(
|
||||||
|
padding: panelPadding, child: subjectTiles3[index]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12.0),
|
||||||
|
Text(
|
||||||
|
'oops'.i18n,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 22.0,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12.0),
|
||||||
|
SizedBox(
|
||||||
|
height: ((100 * subjectTiles1.length) /
|
||||||
|
(subjectTiles1[0].runtimeType == AnimatedContainer
|
||||||
|
? 1.95
|
||||||
|
: 1.2))
|
||||||
|
.toDouble(),
|
||||||
|
child: ListView.builder(
|
||||||
|
padding: const EdgeInsets.only(left: 5),
|
||||||
|
physics: const BouncingScrollPhysics(),
|
||||||
|
itemCount: max(subjectTiles1.length, 1),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (subjectTiles1.isNotEmpty) {
|
||||||
|
EdgeInsetsGeometry panelPadding =
|
||||||
|
const EdgeInsets.symmetric(horizontal: 24.0);
|
||||||
|
|
||||||
|
if (subjectTiles1[index].runtimeType == AnimatedContainer) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8),
|
||||||
|
child: subjectTiles1[index]);
|
||||||
|
} else {
|
||||||
|
return Padding(
|
||||||
|
padding: panelPadding, child: subjectTiles1[index]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 30.0),
|
||||||
|
Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'endyear_avg'.i18n,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 22.0,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(top: 10.0),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16.0, vertical: 4.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: gradeColor(context: context, value: endYearAvg)
|
||||||
|
.withOpacity(.2),
|
||||||
|
border: Border.all(
|
||||||
|
color: (gradeColor(context: context, value: endYearAvg))
|
||||||
|
.withOpacity(0.0),
|
||||||
|
width: 2.0,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(45.0),
|
||||||
|
),
|
||||||
|
child: AutoSizeText.rich(
|
||||||
|
TextSpan(
|
||||||
|
text: endYearAvgText,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
minFontSize: 5,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: gradeColor(context: context, value: endYearAvg),
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
fontSize: 32.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
319
filcnaplo_mobile_ui/lib/screens/summary/pages/lessons_page.dart
Normal file
319
filcnaplo_mobile_ui/lib/screens/summary/pages/lessons_page.dart
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
|
import 'package:filcnaplo/helpers/subject.dart';
|
||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo/utils/format.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/absence.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/absence_provider.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
|
||||||
|
import 'package:filcnaplo_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 {
|
||||||
|
Subject subject;
|
||||||
|
List<Absence> absences;
|
||||||
|
double percentage;
|
||||||
|
|
||||||
|
SubjectAbsence(
|
||||||
|
{required this.subject, this.absences = const [], this.percentage = 0.0});
|
||||||
|
}
|
||||||
|
|
||||||
|
class LessonsBody extends StatefulWidget {
|
||||||
|
const LessonsBody({Key? key}) : super(key: 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<Subject, 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<Subject, 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.withOpacity(0.5)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,128 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'dart:io';
|
||||||
|
|
||||||
class PersonalityBody extends StatelessWidget {
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/personality_card/empty_card.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/common/personality_card/personality_card.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.i18n.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:screenshot/screenshot.dart';
|
||||||
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:image_gallery_saver/image_gallery_saver.dart';
|
||||||
|
|
||||||
|
class PersonalityBody extends StatefulWidget {
|
||||||
const PersonalityBody({Key? key}) : super(key: key);
|
const PersonalityBody({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PersonalityBodyState createState() => _PersonalityBodyState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PersonalityBodyState extends State<PersonalityBody> {
|
||||||
|
late UserProvider user;
|
||||||
|
|
||||||
|
bool isRevealed = false;
|
||||||
|
|
||||||
|
ScreenshotController screenshotController = ScreenshotController();
|
||||||
|
|
||||||
|
sharePersonality() async {
|
||||||
|
await screenshotController.capture().then((image) async {
|
||||||
|
if (image != null) {
|
||||||
|
final directory = await getApplicationDocumentsDirectory();
|
||||||
|
if (await File('${directory.path}/refilc_personality.png').exists()) {
|
||||||
|
await File('${directory.path}/refilc_personality.png').delete();
|
||||||
|
}
|
||||||
|
final imagePath =
|
||||||
|
await File('${directory.path}/refilc_personality.png').create();
|
||||||
|
await imagePath.writeAsBytes(image);
|
||||||
|
|
||||||
|
await Share.shareXFiles([XFile(imagePath.path)]);
|
||||||
|
}
|
||||||
|
}).catchError((err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
savePersonality() async {
|
||||||
|
await screenshotController.capture().then((image) async {
|
||||||
|
if (image != null) {
|
||||||
|
await ImageGallerySaver.saveImage(image, name: 'refilc_personality');
|
||||||
|
}
|
||||||
|
}).catchError((err) {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const Column();
|
user = Provider.of<UserProvider>(context);
|
||||||
|
|
||||||
|
return Expanded(
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 30),
|
||||||
|
AnimatedCrossFade(
|
||||||
|
duration: const Duration(milliseconds: 1000),
|
||||||
|
sizeCurve: Curves.easeInToLinear,
|
||||||
|
firstChild: Screenshot(
|
||||||
|
controller: screenshotController,
|
||||||
|
child: PersonalityCard(user: user),
|
||||||
|
),
|
||||||
|
secondChild: GestureDetector(
|
||||||
|
onTap: () => setState(() {
|
||||||
|
isRevealed = true;
|
||||||
|
}),
|
||||||
|
child: EmptyCard(text: 'click_reveal'.i18n),
|
||||||
|
),
|
||||||
|
crossFadeState: isRevealed
|
||||||
|
? CrossFadeState.showFirst
|
||||||
|
: CrossFadeState.showSecond,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 30),
|
||||||
|
if (isRevealed)
|
||||||
|
Center(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await sharePersonality();
|
||||||
|
},
|
||||||
|
icon: const Icon(
|
||||||
|
FeatherIcons.share,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 30,
|
||||||
|
),
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateProperty.all(
|
||||||
|
Colors.white.withOpacity(0.2)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await savePersonality();
|
||||||
|
},
|
||||||
|
icon: const Icon(
|
||||||
|
FeatherIcons.bookmark,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 30,
|
||||||
|
),
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateProperty.all(
|
||||||
|
Colors.white.withOpacity(0.2)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 60),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:filcnaplo_kreta_api/providers/grade_provider.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.dart';
|
||||||
|
import 'package:filcnaplo_mobile_ui/screens/summary/summary_screen.i18n.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart';
|
||||||
|
|
||||||
|
class StartBody extends StatefulWidget {
|
||||||
|
const StartBody({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_StartBodyState createState() => _StartBodyState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _StartBodyState extends State<StartBody> {
|
||||||
|
late UserProvider user;
|
||||||
|
late GradeProvider gradeProvider;
|
||||||
|
late SettingsProvider settings;
|
||||||
|
|
||||||
|
late String firstName;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
gradeProvider = Provider.of<GradeProvider>(context, listen: false);
|
||||||
|
settings = Provider.of<SettingsProvider>(context, listen: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 40.0),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
showSlidingBottomSheet(
|
||||||
|
context,
|
||||||
|
useRootNavigator: true,
|
||||||
|
builder: (context) => SlidingSheetDialog(
|
||||||
|
color: Colors.black.withOpacity(0.99),
|
||||||
|
duration: const Duration(milliseconds: 400),
|
||||||
|
scrollSpec: const ScrollSpec.bouncingScroll(),
|
||||||
|
snapSpec: const SnapSpec(
|
||||||
|
snap: true,
|
||||||
|
snappings: [1.0],
|
||||||
|
initialSnap: 1.0,
|
||||||
|
positioning: SnapPositioning.relativeToAvailableSpace,
|
||||||
|
),
|
||||||
|
minHeight: MediaQuery.of(context).size.height,
|
||||||
|
cornerRadius: 16,
|
||||||
|
cornerRadiusOnFullscreen: 0,
|
||||||
|
builder: (context, state) => const Material(
|
||||||
|
color: Colors.black,
|
||||||
|
child: SummaryScreen(
|
||||||
|
currentPage: 'grades',
|
||||||
|
isBottomSheet: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(
|
||||||
|
FeatherIcons.arrowRight,
|
||||||
|
size: 145,
|
||||||
|
color: Colors.white,
|
||||||
|
grade: 0.001,
|
||||||
|
weight: 0.001,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'start'.i18n,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontSize: 16.0,
|
||||||
|
color: Colors.white.withOpacity(0.7),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 169.69),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,48 @@
|
|||||||
|
import 'package:confetti/confetti.dart';
|
||||||
|
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||||
|
import 'package:filcnaplo/models/settings.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:wtf_sliding_sheet/wtf_sliding_sheet.dart';
|
||||||
|
import 'summary_screen.i18n.dart';
|
||||||
|
|
||||||
|
import 'pages/allsum_page.dart';
|
||||||
|
import 'pages/start_page.dart';
|
||||||
import 'pages/grades_page.dart';
|
import 'pages/grades_page.dart';
|
||||||
|
import 'pages/lessons_page.dart';
|
||||||
|
import 'pages/personality_page.dart';
|
||||||
|
|
||||||
class SummaryScreen extends StatefulWidget {
|
class SummaryScreen extends StatefulWidget {
|
||||||
final String currentPage;
|
final String currentPage;
|
||||||
|
final bool isBottomSheet;
|
||||||
|
|
||||||
const SummaryScreen({Key? key, this.currentPage = 'personality'})
|
const SummaryScreen({
|
||||||
: super(key: key);
|
Key? key,
|
||||||
|
this.currentPage = 'personality',
|
||||||
|
this.isBottomSheet = false,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_SummaryScreenState createState() => _SummaryScreenState();
|
_SummaryScreenState createState() => _SummaryScreenState();
|
||||||
|
|
||||||
|
static show(
|
||||||
|
{required BuildContext context,
|
||||||
|
String currentPage = 'personality'}) =>
|
||||||
|
Navigator.of(context, rootNavigator: true).push(CupertinoPageRoute(
|
||||||
|
builder: (context) => SummaryScreen(currentPage: currentPage)));
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SummaryScreenState extends State<SummaryScreen> {
|
class _SummaryScreenState extends State<SummaryScreen>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
late UserProvider user;
|
||||||
|
late SettingsProvider settings;
|
||||||
|
|
||||||
|
ConfettiController? _confettiController;
|
||||||
|
|
||||||
|
late String firstName;
|
||||||
|
|
||||||
final LinearGradient _backgroundGradient = const LinearGradient(
|
final LinearGradient _backgroundGradient = const LinearGradient(
|
||||||
colors: [
|
colors: [
|
||||||
Color(0xff1d56ac),
|
Color(0xff1d56ac),
|
||||||
@@ -22,34 +53,170 @@ class _SummaryScreenState extends State<SummaryScreen> {
|
|||||||
stops: [-1.0, 1.0],
|
stops: [-1.0, 1.0],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_confettiController?.dispose();
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
user = Provider.of<UserProvider>(context);
|
||||||
body: Container(
|
settings = Provider.of<SettingsProvider>(context);
|
||||||
|
|
||||||
|
List<String> nameParts = user.displayName?.split(" ") ?? ["?"];
|
||||||
|
if (!settings.presentationMode) {
|
||||||
|
firstName = nameParts.length > 1 ? nameParts[1] : nameParts[0];
|
||||||
|
} else {
|
||||||
|
firstName = "János";
|
||||||
|
}
|
||||||
|
|
||||||
|
return widget.isBottomSheet
|
||||||
|
? buildContainer()
|
||||||
|
: Scaffold(
|
||||||
|
body: buildContainer(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildContainer() {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(gradient: _backgroundGradient),
|
||||||
|
child: Container(
|
||||||
decoration: BoxDecoration(gradient: _backgroundGradient),
|
decoration: BoxDecoration(gradient: _backgroundGradient),
|
||||||
child: Container(
|
width: MediaQuery.of(context).size.width,
|
||||||
decoration: BoxDecoration(gradient: _backgroundGradient),
|
height: MediaQuery.of(context).size.height,
|
||||||
width: MediaQuery.of(context).size.width,
|
child: SafeArea(
|
||||||
height: MediaQuery.of(context).size.height,
|
child: Padding(
|
||||||
child: SafeArea(
|
padding: const EdgeInsets.only(
|
||||||
child: Padding(
|
left: 24.0,
|
||||||
padding: EdgeInsets.only(
|
right: 24.0,
|
||||||
left: 24.0,
|
top: 15.0,
|
||||||
right: 24.0,
|
bottom: 40.0,
|
||||||
top: 26.0 + MediaQuery.of(context).padding.top,
|
),
|
||||||
bottom: 52.0,
|
child: Column(
|
||||||
),
|
crossAxisAlignment: widget.currentPage == 'start'
|
||||||
child: widget.currentPage == 'grades'
|
? CrossAxisAlignment.center
|
||||||
? const GradesBody()
|
: CrossAxisAlignment.start,
|
||||||
: widget.currentPage == 'lessons'
|
mainAxisAlignment: widget.currentPage == 'start'
|
||||||
? const GradesBody()
|
? MainAxisAlignment.spaceBetween
|
||||||
: widget.currentPage == 'allsum'
|
: MainAxisAlignment.start,
|
||||||
? const GradesBody()
|
children: [
|
||||||
: const GradesBody(),
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'greeting'.i18n.fill([firstName]),
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
softWrap: true,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w900,
|
||||||
|
fontSize: 26.0,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
widget.currentPage == 'start'
|
||||||
|
? 'title_start'.i18n
|
||||||
|
: widget.currentPage == 'grades'
|
||||||
|
? 'title_grades'.i18n
|
||||||
|
: widget.currentPage == 'lessons'
|
||||||
|
? 'title_lessons'.i18n
|
||||||
|
: widget.currentPage == 'personality'
|
||||||
|
? 'title_personality'.i18n
|
||||||
|
: '',
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.fade,
|
||||||
|
softWrap: false,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 22.0,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
widget.currentPage != 'start'
|
||||||
|
? IconButton(
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
if (widget.currentPage == 'grades') {
|
||||||
|
openNewPage(page: 'lessons');
|
||||||
|
} else if (widget.currentPage == 'lessons') {
|
||||||
|
openNewPage(page: 'allsum');
|
||||||
|
} else if (widget.currentPage == 'allsum') {
|
||||||
|
openNewPage(page: 'personality');
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).maybePop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
widget.currentPage == 'personality'
|
||||||
|
? FeatherIcons.x
|
||||||
|
: FeatherIcons.arrowRight,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Container()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12.0),
|
||||||
|
widget.currentPage == 'start'
|
||||||
|
? const StartBody()
|
||||||
|
: widget.currentPage == 'grades'
|
||||||
|
? const GradesBody()
|
||||||
|
: widget.currentPage == 'lessons'
|
||||||
|
? const LessonsBody()
|
||||||
|
: widget.currentPage == 'allsum'
|
||||||
|
? const AllSumBody()
|
||||||
|
: const PersonalityBody(),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void openNewPage({String page = 'personality'}) {
|
||||||
|
showSlidingBottomSheet(
|
||||||
|
context,
|
||||||
|
useRootNavigator: true,
|
||||||
|
builder: (context) => SlidingSheetDialog(
|
||||||
|
color: Colors.black.withOpacity(0.99),
|
||||||
|
duration: const Duration(milliseconds: 400),
|
||||||
|
scrollSpec: const ScrollSpec.bouncingScroll(),
|
||||||
|
snapSpec: const SnapSpec(
|
||||||
|
snap: true,
|
||||||
|
snappings: [1.0],
|
||||||
|
initialSnap: 1.0,
|
||||||
|
positioning: SnapPositioning.relativeToAvailableSpace,
|
||||||
|
),
|
||||||
|
minHeight: MediaQuery.of(context).size.height,
|
||||||
|
cornerRadius: 16,
|
||||||
|
cornerRadiusOnFullscreen: 0,
|
||||||
|
builder: (context, state) => Material(
|
||||||
|
color: Colors.black,
|
||||||
|
child: SummaryScreen(
|
||||||
|
currentPage: page,
|
||||||
|
isBottomSheet: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
//SummaryScreen.show(context: context, currentPage: page);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,111 @@ import 'package:i18n_extension/i18n_extension.dart';
|
|||||||
extension SettingsLocalization on String {
|
extension SettingsLocalization on String {
|
||||||
static final _t = Translations.byLocale("hu_hu") +
|
static final _t = Translations.byLocale("hu_hu") +
|
||||||
{
|
{
|
||||||
"en_en": {},
|
"en_en": {
|
||||||
"hu_hu": {},
|
// main thingies
|
||||||
"de_de": {},
|
"no_grades": "No grades found",
|
||||||
|
"no_lesson": "No lessons found",
|
||||||
|
"greeting": "You had a good year, %s!",
|
||||||
|
"title_start": "So let's summarize...",
|
||||||
|
"title_grades": "Let's look at your marks... 📖",
|
||||||
|
"title_lessons": "Your favorite lesson 💓",
|
||||||
|
"title_personality": "Your personality is...",
|
||||||
|
// start page
|
||||||
|
"start": "Start",
|
||||||
|
// grades page
|
||||||
|
"tryagain": "He puts the master to the test! 🔃",
|
||||||
|
"oops": "Ouch... 🥴",
|
||||||
|
"endyear_avg": "Year-end average",
|
||||||
|
// lessons page
|
||||||
|
"absence": "%s absence(s)",
|
||||||
|
"delay": "A total of %s minute(s) late",
|
||||||
|
"dontfelt": "You didn't like it...",
|
||||||
|
"youlate": "You're late!",
|
||||||
|
// allsum page
|
||||||
|
"test": "test(s)",
|
||||||
|
"closingtest": "module test(s)",
|
||||||
|
"grade": "grades",
|
||||||
|
"hw": "homework",
|
||||||
|
"subject": "subjects",
|
||||||
|
"lesson": "lessons",
|
||||||
|
"absence_sum": "absence(s)",
|
||||||
|
"excused": "excused",
|
||||||
|
"unexcused": "unexcused",
|
||||||
|
"delay_sum": "delay(s)",
|
||||||
|
"min": "minute(s)",
|
||||||
|
// personality page
|
||||||
|
"click_reveal": "Click to reveal...",
|
||||||
|
},
|
||||||
|
"hu_hu": {
|
||||||
|
// main thingies
|
||||||
|
"no_grades": "Nincsenek jegyek",
|
||||||
|
"no_lesson": "Nincsenek tanórák",
|
||||||
|
"greeting": "Jó éved volt, %s!",
|
||||||
|
"title_start": "Összegezzünk hát...",
|
||||||
|
"title_grades": "Nézzük a jegyeidet... 📖",
|
||||||
|
"title_lessons": "A kedvenc órád 💓",
|
||||||
|
"title_personality": "A te személyiséged...",
|
||||||
|
// start page
|
||||||
|
"start": "Kezdés",
|
||||||
|
// grades page
|
||||||
|
"tryagain": "Próba teszi a mestert! 🔃",
|
||||||
|
"oops": "Ajjaj... 🥴",
|
||||||
|
"endyear_avg": "Év végi átlagod",
|
||||||
|
// lessons page
|
||||||
|
"absence": "%s hiányzás",
|
||||||
|
"delay": "Összesen %s perc késés",
|
||||||
|
"dontfelt": "Nem volt kedved hozzá...",
|
||||||
|
"youlate": "Késtél!",
|
||||||
|
// allsum page
|
||||||
|
"test": "dolgozat",
|
||||||
|
"closingtest": "témazáró",
|
||||||
|
"grade": "jegy",
|
||||||
|
"hw": "házi",
|
||||||
|
"subject": "tantárgy",
|
||||||
|
"lesson": "óra",
|
||||||
|
"absence_sum": "hiányzás",
|
||||||
|
"excused": "igazolt",
|
||||||
|
"unexcused": "igazolatlan",
|
||||||
|
"delay_sum": "késés",
|
||||||
|
"min": "perc",
|
||||||
|
// personality page
|
||||||
|
"click_reveal": "Kattints a felfedéshez...",
|
||||||
|
},
|
||||||
|
"de_de": {
|
||||||
|
// main thingies
|
||||||
|
"no_grades": "Keine Grade gefunden",
|
||||||
|
"no_lesson": "Keine Lektionen gefunden",
|
||||||
|
"greeting": "Du hattest ein gutes Jahr, %s!",
|
||||||
|
"title_start": "Fassen wir also zusammen...",
|
||||||
|
"title_grades": "Schauen wir uns eure Tickets an... 📖",
|
||||||
|
"title_lessons": "Deine Lieblingsuhr 💓",
|
||||||
|
"title_personality": "Deine Persönlichkeit...",
|
||||||
|
// start page
|
||||||
|
"start": "Anfang",
|
||||||
|
// grades page
|
||||||
|
"tryagain": "Er stellt den Meister auf die Probe! 🔃",
|
||||||
|
"oops": "Autsch... 🥴",
|
||||||
|
"endyear_avg": "Ihr Jahresenddurchschnitt",
|
||||||
|
// lessons page
|
||||||
|
"absence": "%s Abwesenheit(en)",
|
||||||
|
"delay": "Insgesamt %s Minute(n) zu spät",
|
||||||
|
"dontfelt": "Es hat dir nicht gefallen...",
|
||||||
|
"youlate": "Du bist spät!",
|
||||||
|
// allsum page
|
||||||
|
"test": "These(n)",
|
||||||
|
"closingtest": "Modultest",
|
||||||
|
"grade": "Grad",
|
||||||
|
"hw": "Hausaufgaben",
|
||||||
|
"subject": "Themen",
|
||||||
|
"lesson": "Lektionen",
|
||||||
|
"absence_sum": "Abwesenheit(en)",
|
||||||
|
"excused": "bescheinigte",
|
||||||
|
"unexcused": "unentschuldigte",
|
||||||
|
"delay_sum": "Verzögerung(en)",
|
||||||
|
"min": "Minute(n)",
|
||||||
|
// personality page
|
||||||
|
"click_reveal": "Klicken Sie hier, um es anzuzeigen...",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
String get i18n => localize(this, _t);
|
String get i18n => localize(this, _t);
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ dependencies:
|
|||||||
background_fetch: ^1.1.5
|
background_fetch: ^1.1.5
|
||||||
wtf_sliding_sheet: ^1.0.0
|
wtf_sliding_sheet: ^1.0.0
|
||||||
package_info_plus: ^4.0.2
|
package_info_plus: ^4.0.2
|
||||||
|
dotted_border: ^2.0.0+3
|
||||||
|
screenshot: ^2.1.0
|
||||||
|
image_gallery_saver: ^2.0.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^1.0.0
|
flutter_lints: ^1.0.0
|
||||||
|
|||||||
@@ -293,13 +293,10 @@ class _ModifySubjectNamesState extends State<ModifySubjectNames> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Panel(
|
Panel(
|
||||||
child: PanelButton(
|
child: SwitchListTile(
|
||||||
title: Text("italics_toggle".i18n),
|
title: Text("italics_toggle".i18n),
|
||||||
trailing: Switch(
|
onChanged: (value) => settings.update(renamedSubjectsItalics: value),
|
||||||
value: settings.renamedSubjectsItalics,
|
value: settings.renamedSubjectsItalics,),
|
||||||
onChanged: (value) =>
|
|
||||||
settings.update(renamedSubjectsItalics: value),
|
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
|
|||||||
Reference in New Issue
Block a user