diff --git a/.env.example b/.env.example deleted file mode 100644 index b9ee1bf..0000000 --- a/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -BASE_URL_DEV = -BASE_URL_PROD = \ No newline at end of file diff --git a/.github/workflows/config.yml b/.github/workflows/config.yml index 7a6aa06..8d0969d 100644 --- a/.github/workflows/config.yml +++ b/.github/workflows/config.yml @@ -21,7 +21,7 @@ jobs: - uses: subosito/flutter-action@v1 with: channel: "stable" - flutter-version: '3.0.5' + flutter-version: '3.10.5' - run: | flutter doctor flutter pub get diff --git a/.github/workflows/firebase-hosting-production-pull-request.yml b/.github/workflows/firebase-hosting-production-pull-request.yml deleted file mode 100644 index aebf27f..0000000 --- a/.github/workflows/firebase-hosting-production-pull-request.yml +++ /dev/null @@ -1,26 +0,0 @@ -# This file was auto-generated by the Firebase CLI -# https://github.com/firebase/firebase-tools - -name: Deploy to Firebase Hosting on PR -'on': - pull_request: - branches: - - main - -jobs: - build_and_preview: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - run: >- - echo "${{ secrets.ENV }}" | base64 --decode > ${{ github.workspace }}/.env && - sudo snap install flutter --classic && flutter - config --enable-web && flutter pub get && flutter pub run build_runner build --delete-conflicting-outputs && - flutter build web -t lib/main_production.dart - - uses: FirebaseExtended/action-hosting-deploy@v0 - with: - repoToken: '${{ secrets.GITHUB_TOKEN }}' - firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_ULAS_KELAS }}' - projectId: ulas-kelas - env: - FIREBASE_CLI_PREVIEWS: hostingchannels diff --git a/.github/workflows/firebase-hosting-pull-request.yml b/.github/workflows/firebase-hosting-pull-request.yml deleted file mode 100644 index acba522..0000000 --- a/.github/workflows/firebase-hosting-pull-request.yml +++ /dev/null @@ -1,27 +0,0 @@ -# This file was auto-generated by the Firebase CLI -# https://github.com/firebase/firebase-tools - -name: Deploy to Firebase Hosting on PR -'on': - pull_request: - branches: - - development - -jobs: - build_and_preview: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - run: >- - echo "${{ secrets.ENV }}" | base64 --decode > ${{ github.workspace }}/.env && - sudo snap install flutter --classic && - flutter config --enable-web && flutter pub get && - flutter pub run build_runner build --delete-conflicting-outputs && - flutter build web -t lib/main_development.dart - - uses: FirebaseExtended/action-hosting-deploy@v0 - with: - repoToken: '${{ secrets.GITHUB_TOKEN }}' - firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_ULAS_KELAS }}' - projectId: ulas-kelas - env: - FIREBASE_CLI_PREVIEWS: hostingchannels diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..51ac037 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "ulaskelas-frontend", + "request": "launch", + "type": "dart" + }, + { + "name": "ulaskelas-frontend (profile mode)", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "ulaskelas-frontend (release mode)", + "request": "launch", + "type": "dart", + "flutterMode": "release" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..385f27a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "interactive" +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8859de9..bb7d712 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,10 @@ This document briefly describes some guidance on how you can contribute to this 1. **[lib/main_development.dart](lib/main_development.dart)**: The entry of Project. +## PR + +Please PR on the development branch first :smile: + While creating PR, below materials could be helpful: * [Effective Dart](https://www.dartlang.org/guides/language/effective-dart) diff --git a/README.md b/README.md index 8241a7a..7a35544 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 👨‍💻 Ulas Kelas -[![Generic badge](https://img.shields.io/badge/Flutter-v3.0.5-blue)](https://flutter.dev/docs) -[![Generic badge](https://img.shields.io/badge/Dart-v2.13.4-blue)](https://dart.dev/guides) +[![Generic badge](https://img.shields.io/badge/Flutter-v3.10.5-blue)](https://flutter.dev/docs) +[![Generic badge](https://img.shields.io/badge/Dart-v3.0.6-blue)](https://dart.dev/guides) [![test](https://github.com/RistekCSUI/ulaskelas-frontend/actions/workflows/config.yml/badge.svg)](https://github.com/RistekCSUI/ulaskelas-frontend/actions/workflows/config.yml) [![Deploy Web](https://github.com/RistekCSUI/ulaskelas-frontend/actions/workflows/firebase-hosting-merge.yml/badge.svg)](https://github.com/RistekCSUI/ulaskelas-frontend/actions/workflows/firebase-hosting-merge.yml) [![codecov](https://codecov.io/gh/RistekCSUI/ulaskelas-frontend/branch/main/graph/badge.svg?token=SHFALBJG9U)](https://codecov.io/gh/RistekCSUI/ulaskelas-frontend) @@ -12,38 +12,34 @@ Ulas Kelas app ## ⚡️ Getting Started -### 🚚 How to run, drive, and build Apk +### 🚚 How to run -Example how to run release development app +Make sure you have [Backend](https://github.com/ristekoss/ulaskelas-backend) running on your local's + +Update .env.example with your local's url, for example: ``` -flutter clean -flutter pub get -flutter run -t lib/main_development.dart --release --flavor development +BASE_URL_DEV = localhost:3000 +BASE_URL_PROD = "" ``` -Example how to build release development app +Add key.properties to /android ``` -flutter clean -flutter pub get -flutter build apk -t lib/main_development.dart --release --no-shrink --flavor development --split-per-abi +storePassword= +storePasswordDevelopment= +keyPassword= +keyPasswordDevelopment= +keyAlias= +keyAliasDevelopment= +storeFile= +storeFileDevelopment= ``` -Example how to build bundle release production app +Example how to run development app ``` flutter clean flutter pub get -flutter build appbundle -t lib/main_production.dart --release --no-shrink --flavor production -``` - -Example how to run flutter web app -``` -flutter run -t lib/main_development.dart -d chrome -``` - -Example how to drive automation test on development environment -note that automation test doesn't support release mode -``` -flutter drive -t test_driver/app.dart --flavor development +dart run build_runner build --delete-conflicting-outputs +flutter run -t lib/main_development.dart --flavor development ``` ### ⚙️ Supported Flavor @@ -112,7 +108,7 @@ examples: feat: Form Login ci: refactor analysis job -before push +### before push 1. flutter analyze 2. flutter test diff --git a/analysis_options.yaml b/analysis_options.yaml index 6f5c2e5..09e0ea0 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:very_good_analysis/analysis_options.2.4.0.yaml +include: package:very_good_analysis/analysis_options.5.0.0.yaml analyzer: # We should disable linter for generated code @@ -9,13 +9,13 @@ analyzer: - lib/**/*.freezed.dart - test/**/*.mocks.dart - strong-mode: - implicit-casts: true - implicit-dynamic: true - errors: # Allow having TODOs in the code. todo: ignore + language: + strict-casts: false + strict-inference: false + strict-raw-types: false # LINTER Preferences # diff --git a/android/app/build.gradle b/android/app/build.gradle index 929c27c..1040073 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -8,7 +8,7 @@ if (localPropertiesFile.exists()) { def flutterRoot = localProperties.getProperty('flutter.sdk') if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") + throw GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") } def flutterVersionCode = localProperties.getProperty('flutter.versionCode') @@ -34,7 +34,7 @@ if (keystorePropertiesFile.exists()) { } android { - compileSdkVersion 31 + compileSdkVersion 33 sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -43,8 +43,8 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.ristek.ulaskelas" - minSdkVersion 19 - targetSdkVersion 30 + minSdkVersion 26 + targetSdkVersion 31 versionCode flutterVersionCode.toInteger() versionName flutterVersionName multiDexEnabled true diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index bf485dc..2f43e27 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -41,6 +41,7 @@ android:icon="@mipmap/ic_launcher"> _AppWrapperState(); @@ -27,6 +28,7 @@ class _AppWrapperState extends State { @override void initState() { super.initState(); + MixpanelService.track('open_app'); splashTime(); } @@ -122,7 +124,7 @@ A new version of this app available on the store, please update into the newer v Text( 'by RISTEK Fasilkom UI', style: FontTheme.poppins14w500white(), - ) + ), ], ), ), diff --git a/lib/authentication_page.dart b/lib/authentication_page.dart index c0507c1..c496543 100644 --- a/lib/authentication_page.dart +++ b/lib/authentication_page.dart @@ -4,13 +4,14 @@ import 'package:flutter/material.dart'; import 'package:ristek_material_component/ristek_material_component.dart'; import 'package:states_rebuilder/states_rebuilder.dart'; import 'package:ulaskelas/features/matkul/bookmarks/domain/entities/query_bookmark.dart'; +import 'package:ulaskelas/services/_services.dart'; import 'core/bases/states/_states.dart'; import 'core/constants/_constants.dart'; import 'core/theme/_theme.dart'; class AuthenticationPage extends StatelessWidget { - const AuthenticationPage({Key? key}) : super(key: key); + const AuthenticationPage({super.key}); @override Widget build(BuildContext context) { @@ -69,6 +70,7 @@ Aplikasi ulasan mata kuliah Fasilkom UI.\nMasuk dan buat ulasanmu sekarang!''', } Future _ssoLogin() async { + MixpanelService.track('login'); if (authRM.state.isLoading) { return; } @@ -81,6 +83,7 @@ Aplikasi ulasan mata kuliah Fasilkom UI.\nMasuk dan buat ulasanmu sekarang!''', await Future.delayed(const Duration(seconds: 1)); await authRM.setState((s) => s.ssoLogin()); if (authRM.state.isLogin) { + MixpanelService.track('login_success'); await profileRM.state.retrieveData(); await bookmarkRM.state.retrieveData(QueryBookmark()); if (profileRM.state.profile.isBlocked ?? false) { diff --git a/lib/core/bases/states/_states.dart b/lib/core/bases/states/_states.dart index 4de154b..e8e11d4 100644 --- a/lib/core/bases/states/_states.dart +++ b/lib/core/bases/states/_states.dart @@ -33,6 +33,8 @@ import 'package:ulaskelas/onboarding_page.dart'; import 'package:ulaskelas/services/_services.dart'; import 'package:universal_html/html.dart'; +import '../../utils/util.dart'; + part 'auth_state.dart'; part 'cleaner.dart'; part 'global_state.dart'; diff --git a/lib/core/bases/states/auth_state.dart b/lib/core/bases/states/auth_state.dart index 6b57b06..623b084 100644 --- a/lib/core/bases/states/auth_state.dart +++ b/lib/core/bases/states/auth_state.dart @@ -91,7 +91,7 @@ class AuthState { path: '/static.html', ); - final url = '${Endpoints.sso}/?redirect_url=${redirectUri.toString()}'; + final url = '${Endpoints.sso}/?redirect_url=$redirectUri'; Logger().w(Uri.parse(url).query); Logger().w(redirectUri.toString()); diff --git a/lib/core/bases/states/global_state.dart b/lib/core/bases/states/global_state.dart index c51ddcb..4dda723 100644 --- a/lib/core/bases/states/global_state.dart +++ b/lib/core/bases/states/global_state.dart @@ -2,12 +2,12 @@ part of '_states.dart'; /// Top level injection final searchCourseRM = RM.inject( - () => SearchCourseState(), + SearchCourseState.new, autoDisposeWhenNotUsed: false, ); final filterRM = RM.inject( - () => FilterState(), + FilterState.new, autoDisposeWhenNotUsed: false, ); @@ -17,66 +17,66 @@ final filterRM = RM.inject( // ); final reviewFormRM = RM.inject( - () => ReviewCourseFormState(), + ReviewCourseFormState.new, autoDisposeWhenNotUsed: false, ); final searchTagRM = RM.inject( - () => SearchTagState(), + SearchTagState.new, ); final bookmarkRM = RM.inject( - () => BookmarkState(), + BookmarkState.new, autoDisposeWhenNotUsed: false, ); final authRM = RM.inject( - () => AuthState(), + AuthState.new, autoDisposeWhenNotUsed: false, ); final progressWebView = RM.inject( - () => ProgressWebViewState(), + ProgressWebViewState.new, ); final currentTermCourseRM = RM.inject( - () => CurrentTermCourseState(), + CurrentTermCourseState.new, autoDisposeWhenNotUsed: false, ); final profileRM = RM.inject( - () => ProfileState(), + ProfileState.new, autoDisposeWhenNotUsed: false, ); final reviewCourseRM = RM.inject( - () => ReviewCourseState(), + ReviewCourseState.new, autoDisposeWhenNotUsed: false, ); final reviewHistoryRM = RM.inject( - () => ReviewHistoryState(), + ReviewHistoryState.new, autoDisposeWhenNotUsed: false, ); final courseDetailRM = RM.inject( - () => CourseDetailState(), + CourseDetailState.new, ); final leaderboardRM = RM.inject( - () => LeaderboardState(), + LeaderboardState.new, ); final calculatorRM = RM.inject( - () => CalculatorState(), + CalculatorState.new, ); final componentRM = RM.inject( - () => ComponentState(), + ComponentState.new, ); final componentFormRM = RM.inject( - () => ComponentFormState(), + ComponentFormState.new, autoDisposeWhenNotUsed: false, ); @@ -91,25 +91,25 @@ class GlobalState { ), ), ), - Inject(() => NavigationServiceState()), - Inject(() => FilterState()), - Inject(() => SearchCourseState()), + Inject(NavigationServiceState.new), + Inject(FilterState.new), + Inject(SearchCourseState.new), // Inject(() => ReviewState()), - Inject(() => SearchTagState()), - Inject(() => BookmarkState()), - Inject(() => CalculatorState()), + Inject(SearchTagState.new), + Inject(BookmarkState.new), + Inject(CalculatorState.new), ]; } static List injectData = [ - Inject(() => ThemeState()), - Inject(() => NavigationServiceState()), - Inject(() => FilterState()), - Inject(() => SearchCourseState()), + Inject(ThemeState.new), + Inject(NavigationServiceState.new), + Inject(FilterState.new), + Inject(SearchCourseState.new), // Inject(() => ReviewState()), - Inject(() => SearchTagState()), - Inject(() => BookmarkState()), - Inject(() => CalculatorState()), + Inject(SearchTagState.new), + Inject(BookmarkState.new), + Inject(CalculatorState.new), ]; static ReactiveModel theme() { diff --git a/lib/core/bases/states/navigation_state.dart b/lib/core/bases/states/navigation_state.dart index 6f4e8d3..5d4d12c 100644 --- a/lib/core/bases/states/navigation_state.dart +++ b/lib/core/bases/states/navigation_state.dart @@ -78,6 +78,7 @@ class NavigationServiceState implements Navigation { } Future goToFilterPage() { + MixpanelService.track('open_course_filter'); return nav.push( const FilterPage(), RouteName.mainPage, @@ -88,6 +89,7 @@ class NavigationServiceState implements Navigation { int courseId, String courseCode, ) { + MixpanelService.track('view_course'); return nav.push( DetailMatkulPage( courseId: courseId, @@ -116,7 +118,18 @@ class NavigationServiceState implements Navigation { Future goToAllReviewMatkulPage({ required int courseId, required String courseCode, + required CourseModel course, }) { + MixpanelService.track( + 'view_all_reviews', + params: { + 'course_id': course.code.toString(), + 'course_name': course.name.toString(), + 'review_count': course.reviewCount.toString(), + 'course_rating_avg': + course.ratingAverage.toString(), + }, + ); return nav.push( AllReviewMatkulPage( courseId: courseId, @@ -134,6 +147,7 @@ class NavigationServiceState implements Navigation { } Future goToHomeDaftarMatkul() { + MixpanelService.track('view_this_semester_courses'); return nav.push( const HomeCourseListPage(), RouteName.homeDaftarMatkul, @@ -141,6 +155,7 @@ class NavigationServiceState implements Navigation { } Future goToHomeDaftarUlasan() { + MixpanelService.track('view_all_reviews'); return nav.push( const HomeDaftarUlasanPage(), RouteName.homeDaftarUlasan, @@ -190,6 +205,7 @@ class NavigationServiceState implements Navigation { } Future goToSearchCourseCalculatorPage() { + MixpanelService.track('calculator_add_course'); return nav.push( const SearchCourseCalculator(), RouteName.searchCourseCalculator, @@ -202,6 +218,16 @@ class NavigationServiceState implements Navigation { required double totalScore, required double totalPercentage, }) { + MixpanelService.track( + 'calculator_view_course', + params: { + 'course_id': courseName, + 'final_letter_grade': getFinalGrade( + totalScore, + ), + 'final_grade': totalScore.toString(), + }, + ); return nav.push( CalculatorComponentPage( calculatorId: calculatorId, diff --git a/lib/core/bases/states/state_initializer.dart b/lib/core/bases/states/state_initializer.dart index 6fee015..95d4901 100644 --- a/lib/core/bases/states/state_initializer.dart +++ b/lib/core/bases/states/state_initializer.dart @@ -45,7 +45,7 @@ class StateInitializer { } } -//todo(fauzi) recheck this class +// TODO(fauzi): recheck this class // class SlightInitializer { // ReactiveModel rm; // String ck; diff --git a/lib/core/bases/widgets/confirmation_modal_dialog.dart b/lib/core/bases/widgets/confirmation_modal_dialog.dart index 2c75d7f..a3aba6c 100644 --- a/lib/core/bases/widgets/confirmation_modal_dialog.dart +++ b/lib/core/bases/widgets/confirmation_modal_dialog.dart @@ -56,7 +56,7 @@ class ConfirmationModalDialog extends DialogBox { padding: const EdgeInsets.all(8), child: Text( noLabel, - style: theme.textTheme.button?.copyWith( + style: theme.textTheme.labelLarge?.copyWith( color: BaseColors.mineShaft, ), textAlign: TextAlign.center, diff --git a/lib/core/bases/widgets/empty_view.dart b/lib/core/bases/widgets/empty_view.dart index c7b2aa3..444d8a0 100644 --- a/lib/core/bases/widgets/empty_view.dart +++ b/lib/core/bases/widgets/empty_view.dart @@ -5,11 +5,9 @@ import 'package:ulaskelas/core/theme/_theme.dart'; class EmptyView extends StatelessWidget { const EmptyView({ - Key? key, - required this.title, - required this.description, + required this.title, required this.description, super.key, this.padTop, - }) : super(key: key); + }); final String title; final String description; @@ -18,13 +16,12 @@ class EmptyView extends StatelessWidget { @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; - final _padTop = padTop ?? size.height * .1; return Padding( padding: const EdgeInsets.all(20), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - HeightSpace(_padTop), + HeightSpace(padTop ?? size.height * .1), Image.asset( Ilustration.notfound, width: size.width * .6, @@ -39,7 +36,7 @@ class EmptyView extends StatelessWidget { const HeightSpace(10), Text( description, - style: Theme.of(context).textTheme.caption, + style: Theme.of(context).textTheme.bodySmall, textAlign: TextAlign.center, ), const HeightSpace(40), diff --git a/lib/core/bases/widgets/svg_image.dart b/lib/core/bases/widgets/svg_image.dart index f32eaf9..ad125f1 100644 --- a/lib/core/bases/widgets/svg_image.dart +++ b/lib/core/bases/widgets/svg_image.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; - +// ignore_for_file: deprecated_member_use // TODO(Any): next update class SVGImage extends SvgPicture { diff --git a/lib/core/client/api_call.dart b/lib/core/client/api_call.dart index 2c2e03f..3bad4c8 100644 --- a/lib/core/client/api_call.dart +++ b/lib/core/client/api_call.dart @@ -7,8 +7,8 @@ Future> apiCall(Future t) async { final futureCall = await t; return Right(futureCall); } on DioError catch (e) { - Logger().wtf(e.error.runtimeType); - Logger().wtf(e.error.toString()); + Logger().f(e.error.runtimeType); + Logger().f(e.error.toString()); if (e.error is ArgumentError) { final error = e.error as ArgumentError; return Left(GeneralFailure(message: error.message)); diff --git a/lib/core/client/dio.dart b/lib/core/client/dio.dart index b4d9b02..018a18b 100644 --- a/lib/core/client/dio.dart +++ b/lib/core/client/dio.dart @@ -7,11 +7,11 @@ Future getIt( if (kDebugMode) { Logger().i({'url': url, 'headers': '${Pref.getHeaders()}'}); } - final _getHeaders = headers ?? Pref.getHeaders(); + final getHeaders = headers ?? Pref.getHeaders(); final resp = await Dio().get( url, options: Options( - headers: _getHeaders, + headers: getHeaders, receiveTimeout: 5000, sendTimeout: 6000, ), @@ -35,12 +35,12 @@ Future postIt( 'model': '$model', }); } - final _getHeaders = headers ?? Pref.getHeaders(); + final getHeaders = headers ?? Pref.getHeaders(); final resp = await Dio().post( url, data: json.encode(model), options: Options( - headers: _getHeaders, + headers: getHeaders, receiveTimeout: 5000, sendTimeout: 6000, ), @@ -64,12 +64,12 @@ Future putIt( 'model': '$model', }); } - final _getHeaders = headers ?? Pref.getHeaders(); + final getHeaders = headers ?? Pref.getHeaders(); final resp = await Dio().put( url, data: model, options: Options( - headers: _getHeaders, + headers: getHeaders, receiveTimeout: 5000, sendTimeout: 6000, ), @@ -93,12 +93,12 @@ Future deleteIt( 'model': '$model', }); } - final _getHeaders = headers ?? Pref.getHeaders(); + final getHeaders = headers ?? Pref.getHeaders(); final resp = await Dio().delete( url, data: model, options: Options( - headers: _getHeaders, + headers: getHeaders, receiveTimeout: 5000, sendTimeout: 6000, ), diff --git a/lib/core/constants/error_codes_const.dart b/lib/core/constants/error_codes_const.dart index 5cd23f3..b6f8f0c 100644 --- a/lib/core/constants/error_codes_const.dart +++ b/lib/core/constants/error_codes_const.dart @@ -1,4 +1,4 @@ // Created by Muhamad Fauzi Ridwan on 11/08/21. -//todo list of errorCode +// TODO(any): list of errorCode class ErrorCode {} diff --git a/lib/core/constants/notification_type_const.dart b/lib/core/constants/notification_type_const.dart index 3671d78..264bac2 100644 --- a/lib/core/constants/notification_type_const.dart +++ b/lib/core/constants/notification_type_const.dart @@ -2,5 +2,5 @@ part of '_constants.dart'; -//todo notification type +// TODO(any): notification type class NotificationType {} diff --git a/lib/core/constants/route_name_const.dart b/lib/core/constants/route_name_const.dart index 66bd2f3..cb18d2c 100644 --- a/lib/core/constants/route_name_const.dart +++ b/lib/core/constants/route_name_const.dart @@ -2,7 +2,7 @@ part of '_constants.dart'; -//todo routeName +// TODO(any): routeName class RouteName { static const String mainPage = 'main'; static const String onboardingPage = 'onboarding'; diff --git a/lib/core/environment/config.dart b/lib/core/environment/config.dart index b9adace..f7c9035 100644 --- a/lib/core/environment/config.dart +++ b/lib/core/environment/config.dart @@ -20,7 +20,7 @@ class Config { appName = flavor.value; assetsPath = baseConfig.assetAbsolutePath; packageName = 'com.ristek.ulaskelas'; - //todo grouping + // TODO(any): grouping imagesPath = '${assetsPath!}/images'; iconsPath = '${assetsPath!}/icons'; @@ -38,6 +38,7 @@ class Config { await HiveDataBaseService.init(); } await Pref.init(); + await MixpanelService.init(); // TODO(fauzi): Implement notification plugin // await notificationPlugin.init(); @@ -55,6 +56,7 @@ class Config { } static bool get isDevelopment => appFlavor == Flavor.development; + static BaseConfig get baseConfig => _baseConfig()!; static BaseConfig? _baseConfig() { @@ -74,9 +76,10 @@ class Config { class BaseConfig { const BaseConfig({ - this.assetAbsolutePath = Constants.assetPath, required this.endpoints, + this.assetAbsolutePath = Constants.assetPath, }); + final String assetAbsolutePath; final BaseEndpoints endpoints; } diff --git a/lib/core/environment/secrets.dart b/lib/core/environment/secrets.dart index 5ec8b61..16d5fe5 100644 --- a/lib/core/environment/secrets.dart +++ b/lib/core/environment/secrets.dart @@ -1,9 +1,13 @@ -import 'package:envify/envify.dart'; +import 'package:envied/envied.dart'; part 'secrets.g.dart'; -@Envify(name: 'Secret') +@Envied(name: 'Secret', path: '.env') abstract class Secret { - static const baseUrlDev = _Secret.baseUrlDev; - static const baseUrlProd = _Secret.baseUrlProd; + @EnviedField(varName: 'BASE_URL_DEV') + static const String baseUrlDev = _Secret.baseUrlDev; + @EnviedField(varName: 'BASE_URL_PROD') + static const String baseUrlProd = _Secret.baseUrlProd; + @EnviedField(varName: 'MIXPANEL_TOKEN') + static const String mixpanelToken = _Secret.mixpanelToken; } diff --git a/lib/core/error/failures.dart b/lib/core/error/failures.dart index 3984aee..bea208c 100644 --- a/lib/core/error/failures.dart +++ b/lib/core/error/failures.dart @@ -21,22 +21,16 @@ class DioFailure implements Exception { switch (dioError.type) { case DioErrorType.cancel: message = 'Request to API server was cancelled'; - break; case DioErrorType.connectTimeout: message = 'Connection timeout with API server'; - break; case DioErrorType.other: message = 'Connection to API server failed due to internet connection'; - break; case DioErrorType.receiveTimeout: message = 'Receive timeout in connection with API server'; - break; case DioErrorType.sendTimeout: message = 'Send timeout in connection with API server'; - break; case DioErrorType.response: message = _handleResponseError(dioError.response); - break; } } @@ -67,69 +61,59 @@ class DioFailure implements Exception { class NetworkFailure extends Failure { NetworkFailure({ - String? code, - String? message, + super.code, + super.message, }) : super( - code: code, - message: message, title: 'Network Failure', ); } class NotFoundFailure extends Failure { NotFoundFailure({ - String? code, - String? message, + super.code, + super.message, }) : super( - code: code, - message: message, title: 'Not Found Failure', ); } class BadRequestFailure extends Failure { BadRequestFailure({ - String? code, - String? message, + super.code, + super.message, }) : super( - code: code, - message: message, title: 'Bad Request Failure', ); } class GeneralFailure extends Failure { GeneralFailure({ - String? message, + super.message, }) : super( - message: message, title: 'General Failure', ); } class TimeoutFailure extends Failure { TimeoutFailure({ - String? message, + super.message, }) : super( - message: message, title: 'Timeout Failure', ); } class ArgumentFailure extends Failure { ArgumentFailure({ - String? message, + super.message, }) : super( - message: message, title: 'Argument Failure', ); } class UnAuthorizeFailure extends Failure { UnAuthorizeFailure({ - String? message, + super.message, }) : super( - message: message, title: 'UnAuthorize Failure', ); } diff --git a/lib/core/theme/ulaskelas_theme.dart b/lib/core/theme/ulaskelas_theme.dart index 75f0ed4..b7daecf 100644 --- a/lib/core/theme/ulaskelas_theme.dart +++ b/lib/core/theme/ulaskelas_theme.dart @@ -14,8 +14,8 @@ class UlaskelasThemeImpl implements UlaskelasTheme { secondaryHeaderColor: BaseColors.goldenrod, shadowColor: BaseColors.gray5, textTheme: TextTheme( - caption: FontTheme.poppins12w400black(), - button: FontTheme.poppins14w700black().copyWith( + bodySmall: FontTheme.poppins12w400black(), + labelLarge: FontTheme.poppins14w700black().copyWith( fontWeight: FontWeight.w600, ), ), diff --git a/lib/core/utils/util.dart b/lib/core/utils/util.dart new file mode 100644 index 0000000..216d895 --- /dev/null +++ b/lib/core/utils/util.dart @@ -0,0 +1,23 @@ +String getFinalGrade(double score) { + var grade = 'E'; + switch (score) { + case >= 85: + grade = 'A'; + case >= 80: + grade = 'A-'; + case >= 75: + grade = 'B+'; + case >= 70: + grade = 'B'; + case >= 65: + grade = 'B-'; + case >= 60: + grade = 'C+'; + case >= 55: + grade = 'C'; + case >= 40: + grade = 'D'; + } + + return grade; +} diff --git a/lib/features/home/presentation/pages/_pages.dart b/lib/features/home/presentation/pages/_pages.dart index 5df60b9..24cb8f2 100644 --- a/lib/features/home/presentation/pages/_pages.dart +++ b/lib/features/home/presentation/pages/_pages.dart @@ -15,6 +15,7 @@ import 'package:ulaskelas/features/home/presentation/widgets/_widgets.dart'; import 'package:ulaskelas/features/matkul/form/domain/entities/query_review.dart'; import 'package:ulaskelas/features/matkul/search/presentation/widgets/_widgets.dart'; import 'package:ulaskelas/features/matkul/search/presentation/widgets/skeleton_card_course.dart'; +import 'package:ulaskelas/services/_services.dart'; part 'home_daftar_matkul_page.dart'; part 'home_daftar_ulasan_page.dart'; diff --git a/lib/features/home/presentation/pages/home_daftar_matkul_page.dart b/lib/features/home/presentation/pages/home_daftar_matkul_page.dart index 4a1ede9..37a8e9a 100644 --- a/lib/features/home/presentation/pages/home_daftar_matkul_page.dart +++ b/lib/features/home/presentation/pages/home_daftar_matkul_page.dart @@ -2,8 +2,8 @@ part of '_pages.dart'; class HomeCourseListPage extends StatefulWidget { const HomeCourseListPage({ - Key? key, - }) : super(key: key); + super.key, + }); @override _HomeCourseListPageState createState() => _HomeCourseListPageState(); diff --git a/lib/features/home/presentation/pages/home_daftar_ulasan_page.dart b/lib/features/home/presentation/pages/home_daftar_ulasan_page.dart index bce6b41..0220023 100644 --- a/lib/features/home/presentation/pages/home_daftar_ulasan_page.dart +++ b/lib/features/home/presentation/pages/home_daftar_ulasan_page.dart @@ -2,8 +2,8 @@ part of '_pages.dart'; class HomeDaftarUlasanPage extends StatefulWidget { const HomeDaftarUlasanPage({ - Key? key, - }) : super(key: key); + super.key, + }); @override _HomeDaftarUlasanPageState createState() => _HomeDaftarUlasanPageState(); @@ -38,8 +38,8 @@ class _HomeDaftarUlasanPageState extends BaseStateful { onRefresh: retrieveData, child: OnBuilder.all( listenTo: reviewHistoryRM, - onIdle: () => WaitingView(), - onWaiting: () => WaitingView(), + onIdle: WaitingView.new, + onWaiting: WaitingView.new, onError: (dynamic error, refresh) => Text(error.toString()), onData: (data) { if (data.reviewHistories.isEmpty) { @@ -75,6 +75,7 @@ class _HomeDaftarUlasanPageState extends BaseStateful { review.course!, review.courseCode!, ); + MixpanelService.track('view_my_review'); }, ); }, diff --git a/lib/features/home/presentation/pages/home_page.dart b/lib/features/home/presentation/pages/home_page.dart index 265c8d0..88b6afc 100644 --- a/lib/features/home/presentation/pages/home_page.dart +++ b/lib/features/home/presentation/pages/home_page.dart @@ -5,8 +5,8 @@ part of '_pages.dart'; class HomePage extends StatefulWidget { const HomePage({ required this.onSeeAllCourse, - Key? key, - }) : super(key: key); + super.key, + }); final VoidCallback onSeeAllCourse; @@ -110,7 +110,7 @@ class _HomePageState extends BaseStateful { Text( 'Lihat Semua Mata Kuliah', style: FontTheme.poppins14w400purple(), - ) + ), ], ), Icon( @@ -141,7 +141,7 @@ class _HomePageState extends BaseStateful { 'Lihat Semua', style: FontTheme.poppins13w400purple(), ), - ) + ), ], ), ), @@ -224,7 +224,7 @@ class _HomePageState extends BaseStateful { 'Lihat Semua', style: FontTheme.poppins13w400purple(), ), - ) + ), ], ), ), @@ -260,10 +260,14 @@ class _HomePageState extends BaseStateful { final review = data.summaries[i]; return CardMatkulReview( review: review, - onTap: () => nav.goToDetailMatkulPage( - review.course!, - review.courseCode.toString(), - ), + onTap: () { + nav.goToDetailMatkulPage( + review.course!, + review.courseCode.toString(), + ); + + MixpanelService.track('view_my_review'); + }, ); }, ); diff --git a/lib/features/home/presentation/states/current_semester_matkul_state.dart b/lib/features/home/presentation/states/current_semester_matkul_state.dart index 25457b3..19e6075 100644 --- a/lib/features/home/presentation/states/current_semester_matkul_state.dart +++ b/lib/features/home/presentation/states/current_semester_matkul_state.dart @@ -4,11 +4,11 @@ part of '_states.dart'; class CurrentTermCourseState { CurrentTermCourseState() { - final _remoteDataSource = CourseRemoteDataSourceImpl(); - final _localDataSource = CourseLocalDataSourceImpl(); + final remoteDataSource = CourseRemoteDataSourceImpl(); + final localDataSource = CourseLocalDataSourceImpl(); _repo = CourseRepositoryImpl( - _remoteDataSource, - _localDataSource, + remoteDataSource, + localDataSource, ); } diff --git a/lib/features/home/presentation/states/review_history_state.dart b/lib/features/home/presentation/states/review_history_state.dart index af1ef3d..eb2c63c 100644 --- a/lib/features/home/presentation/states/review_history_state.dart +++ b/lib/features/home/presentation/states/review_history_state.dart @@ -4,11 +4,11 @@ part of '_states.dart'; class ReviewHistoryState { ReviewHistoryState() { - final _remoteDataSource = ReviewRemoteDataSourceImpl(); - final _localDataSource = ReviewLocalDataSourceImpl(); + final remoteDataSource = ReviewRemoteDataSourceImpl(); + final localDataSource = ReviewLocalDataSourceImpl(); _repo = ReviewRepositoryImpl( - _remoteDataSource, - _localDataSource, + remoteDataSource, + localDataSource, ); } diff --git a/lib/features/home/presentation/widgets/card_matkul_home.dart b/lib/features/home/presentation/widgets/card_matkul_home.dart index a9a1da2..90ff109 100644 --- a/lib/features/home/presentation/widgets/card_matkul_home.dart +++ b/lib/features/home/presentation/widgets/card_matkul_home.dart @@ -2,10 +2,9 @@ part of '_widgets.dart'; class CardMatkulHome extends StatelessWidget { const CardMatkulHome({ - Key? key, - required this.model, + required this.model, super.key, this.onTap, - }) : super(key: key); + }); final MatkulModelHome model; final VoidCallback? onTap; diff --git a/lib/features/home/presentation/widgets/card_matkul_review.dart b/lib/features/home/presentation/widgets/card_matkul_review.dart index 6104251..df5db8d 100644 --- a/lib/features/home/presentation/widgets/card_matkul_review.dart +++ b/lib/features/home/presentation/widgets/card_matkul_review.dart @@ -2,10 +2,9 @@ part of '_widgets.dart'; class CardMatkulReview extends StatelessWidget { const CardMatkulReview({ - Key? key, - required this.review, + required this.review, super.key, this.onTap, - }) : super(key: key); + }); final ReviewModel review; final VoidCallback? onTap; @@ -110,11 +109,11 @@ class CardMatkulReview extends StatelessWidget { : (review.hateSpeechStatus == 'WAITING') ? TagStatus.pending : TagStatus.rejected, - ) + ), ], - ) + ), ], - ) + ), ], ), ), diff --git a/lib/features/kalkulator/presentation/pages/_pages.dart b/lib/features/kalkulator/presentation/pages/_pages.dart index aea5f61..1ffab36 100644 --- a/lib/features/kalkulator/presentation/pages/_pages.dart +++ b/lib/features/kalkulator/presentation/pages/_pages.dart @@ -7,7 +7,9 @@ import 'package:states_rebuilder/states_rebuilder.dart'; import 'package:ulaskelas/core/bases/states/_states.dart'; import 'package:ulaskelas/core/constants/_constants.dart'; import 'package:ulaskelas/core/theme/_theme.dart'; +import 'package:ulaskelas/core/utils/util.dart'; import 'package:ulaskelas/features/kalkulator/domain/entities/query_calculator.dart'; +import 'package:ulaskelas/services/_services.dart'; import '../../../matkul/main/domain/entities/query_search_course.dart'; import '../../../matkul/search/presentation/states/_states.dart'; import '../../../matkul/search/presentation/widgets/_widgets.dart'; diff --git a/lib/features/kalkulator/presentation/pages/edit_komponen_page.dart b/lib/features/kalkulator/presentation/pages/edit_komponen_page.dart index f7ffcb0..5f36c69 100644 --- a/lib/features/kalkulator/presentation/pages/edit_komponen_page.dart +++ b/lib/features/kalkulator/presentation/pages/edit_komponen_page.dart @@ -2,7 +2,6 @@ part of '_pages.dart'; class EditComponentPage extends StatefulWidget { const EditComponentPage({ - Key? key, required this.id, required this.calculatorId, required this.courseName, @@ -11,7 +10,8 @@ class EditComponentPage extends StatefulWidget { required this.componentName, required this.componentScore, required this.componentWeight, - }) : super(key: key); + super.key, + }); final int id; final int calculatorId; @@ -81,12 +81,12 @@ class _EditComponentPageState extends BaseStateful { ), ); nav.replaceToComponentPage( - calculatorId: widget.calculatorId, - courseName: widget.courseName, - totalScore: widget.totalScore - - (widget.componentScore * widget.componentWeight / 100), - totalPercentage: - widget.totalPercentage - widget.componentWeight, + calculatorId: widget.calculatorId, + courseName: widget.courseName, + totalScore: widget.totalScore - + (widget.componentScore * widget.componentWeight / 100), + totalPercentage: + widget.totalPercentage - widget.componentWeight, ); }, child: Text( @@ -107,7 +107,7 @@ class _EditComponentPageState extends BaseStateful { await onSubmitCallBack(context); }, ), - ) + ), ], ); } diff --git a/lib/features/kalkulator/presentation/pages/kalkulator_page.dart b/lib/features/kalkulator/presentation/pages/kalkulator_page.dart index 49bfacb..2124a9b 100644 --- a/lib/features/kalkulator/presentation/pages/kalkulator_page.dart +++ b/lib/features/kalkulator/presentation/pages/kalkulator_page.dart @@ -2,8 +2,8 @@ part of '_pages.dart'; class CalculatorPage extends StatefulWidget { const CalculatorPage({ - Key? key, - }) : super(key: key); + super.key, + }); @override _CalculatorPageState createState() => _CalculatorPageState(); @@ -36,17 +36,17 @@ class _CalculatorPageState extends BaseStateful { @override Widget buildNarrowLayout( - BuildContext context, - SizingInformation sizeInfo, - ) { + BuildContext context, + SizingInformation sizeInfo, + ) { return SafeArea( child: RefreshIndicator( key: refreshIndicatorKey, onRefresh: retrieveData, child: OnBuilder.all( listenTo: calculatorRM, - onIdle: () => WaitingView(), - onWaiting: () => WaitingView(), + onIdle: WaitingView.new, + onWaiting: WaitingView.new, onError: (dynamic error, refresh) => const Text('error'), onData: (data) { final calculators = data.calculators; @@ -74,7 +74,7 @@ class _CalculatorPageState extends BaseStateful { Text( ''' Kamu Belum memiliki kalkulator nilai tersimpan. Silakan tambahkan terlebih dahulu.''', - style: Theme.of(context).textTheme.caption, + style: Theme.of(context).textTheme.bodySmall, textAlign: TextAlign.center, ), const HeightSpace(30), @@ -82,8 +82,7 @@ Kamu Belum memiliki kalkulator nilai tersimpan. Silakan tambahkan terlebih dahul width: double.infinity, text: 'Tambah Mata Kuliah', backgroundColor: BaseColors.purpleHearth, - onPressed: () => - nav.goToSearchCourseCalculatorPage(), + onPressed: () => nav.goToSearchCourseCalculatorPage(), ), ], ), @@ -97,7 +96,7 @@ Kamu Belum memiliki kalkulator nilai tersimpan. Silakan tambahkan terlebih dahul padding: const EdgeInsets.all(20), itemCount: calculatorRM.state.calculators.length + 1, itemBuilder: (context, index) { - if (index == calculators.length){ + if (index == calculators.length) { return Padding( padding: const EdgeInsets.symmetric( vertical: 20, @@ -114,21 +113,18 @@ Kamu Belum memiliki kalkulator nilai tersimpan. Silakan tambahkan terlebih dahul final calculator = calculators[index]; return CardCalculator( model: calculator, - onTap: () { - nav.goToComponentCalculatorPage( - calculatorId: calculator.id!, - courseName: calculator.courseName!, - totalScore: calculator.totalScore!, - totalPercentage: calculator.totalPercentage!, - ); - }, + onTap: () => nav.goToComponentCalculatorPage( + calculatorId: calculator.id!, + courseName: calculator.courseName!, + totalScore: calculator.totalScore!, + totalPercentage: calculator.totalPercentage!, + ), ); }, separatorBuilder: (BuildContext context, int index) => - const SizedBox(height: 16), + const SizedBox(height: 16), ), ), - ], ); }, @@ -139,9 +135,9 @@ Kamu Belum memiliki kalkulator nilai tersimpan. Silakan tambahkan terlebih dahul @override Widget buildWideLayout( - BuildContext context, - SizingInformation sizeInfo, - ) { + BuildContext context, + SizingInformation sizeInfo, + ) { return buildNarrowLayout(context, sizeInfo); } diff --git a/lib/features/kalkulator/presentation/pages/komponen_form_page.dart b/lib/features/kalkulator/presentation/pages/komponen_form_page.dart index 883ae20..e6719dc 100644 --- a/lib/features/kalkulator/presentation/pages/komponen_form_page.dart +++ b/lib/features/kalkulator/presentation/pages/komponen_form_page.dart @@ -2,12 +2,12 @@ part of '_pages.dart'; class ComponentFormPage extends StatefulWidget { const ComponentFormPage({ - Key? key, required this.calculatorId, required this.courseName, required this.totalScore, required this.totalPercentage, - }) : super(key: key); + super.key, + }); final int calculatorId; final String courseName; @@ -65,15 +65,15 @@ class _ComponentFormPageState extends BaseStateful { await onSubmitCallBack(context); }, ), - ) + ), ], ); } double _temporaryUpdateScore( - double newScore, - double newWeight, - ) { + double newScore, + double newWeight, + ) { return widget.totalScore + (newScore * newWeight / 100); } @@ -90,6 +90,7 @@ class _ComponentFormPageState extends BaseStateful { if (componentFormRM.state.isLoading) { return; } + MixpanelService.track('calculator_add_course_component'); if (componentFormRM.state.formKey.currentState!.validate()) { // progressDialogue(context); await componentFormRM.state.submitForm(widget.calculatorId); @@ -103,7 +104,8 @@ class _ComponentFormPageState extends BaseStateful { componentFormRM.state.formData.weight!, ), totalPercentage: _temporaryUpdateWeight( - componentFormRM.state.formData.weight!,), + componentFormRM.state.formData.weight!, + ), ); componentFormRM.state.cleanForm(); return; diff --git a/lib/features/kalkulator/presentation/pages/komponen_kalkulator_page.dart b/lib/features/kalkulator/presentation/pages/komponen_kalkulator_page.dart index 02fc697..edff3f9 100644 --- a/lib/features/kalkulator/presentation/pages/komponen_kalkulator_page.dart +++ b/lib/features/kalkulator/presentation/pages/komponen_kalkulator_page.dart @@ -1,13 +1,15 @@ +// ignore_for_file: lines_longer_than_80_chars + part of '_pages.dart'; class CalculatorComponentPage extends StatefulWidget { const CalculatorComponentPage({ - Key? key, required this.calculatorId, required this.courseName, required this.totalScore, required this.totalPercentage, - }) : super(key: key); + super.key, + }); final int calculatorId; final String courseName; @@ -75,7 +77,7 @@ class _CalculatorComponentPageState Text( _getFinalScoreAndGrade(widget.totalScore), style: FontTheme.poppins14w600black(), - ) + ), ], ), Padding( @@ -103,7 +105,7 @@ class _CalculatorComponentPageState textAlign: TextAlign.center, style: FontTheme.poppins12w600black(), ), - ) + ), ], ), ), @@ -181,7 +183,9 @@ class _CalculatorComponentPageState nav.pop(); calculatorRM.setState( (s) => s.deleteCalculator( - QueryCalculator(id: widget.calculatorId), + query: QueryCalculator(id: widget.calculatorId,), + courseName: widget.courseName, + totalScore: widget.totalScore, ), ); }, @@ -193,7 +197,7 @@ class _CalculatorComponentPageState ), ), ), - ) + ), ], ), ), diff --git a/lib/features/kalkulator/presentation/pages/search_course_calculator.dart b/lib/features/kalkulator/presentation/pages/search_course_calculator.dart index 33743b0..5df0c04 100644 --- a/lib/features/kalkulator/presentation/pages/search_course_calculator.dart +++ b/lib/features/kalkulator/presentation/pages/search_course_calculator.dart @@ -2,8 +2,8 @@ part of '_pages.dart'; class SearchCourseCalculator extends StatefulWidget { const SearchCourseCalculator({ - Key? key, - }) : super(key: key); + super.key, + }); @override _SearchCourseCalculatorState createState() => _SearchCourseCalculatorState(); diff --git a/lib/features/kalkulator/presentation/states/_states.dart b/lib/features/kalkulator/presentation/states/_states.dart index 731c935..795f199 100644 --- a/lib/features/kalkulator/presentation/states/_states.dart +++ b/lib/features/kalkulator/presentation/states/_states.dart @@ -9,6 +9,9 @@ import 'package:ulaskelas/features/kalkulator/domain/entities/query_calculator.d import 'package:ulaskelas/features/kalkulator/domain/entities/query_component.dart'; import 'package:ulaskelas/features/kalkulator/domain/repositories/_repositories.dart'; +import '../../../../core/utils/util.dart'; +import '../../../../services/_services.dart'; + part 'calculator_state.dart'; part 'component_state.dart'; part 'component_form_state.dart'; diff --git a/lib/features/kalkulator/presentation/states/calculator_state.dart b/lib/features/kalkulator/presentation/states/calculator_state.dart index 28b120b..06d7234 100644 --- a/lib/features/kalkulator/presentation/states/calculator_state.dart +++ b/lib/features/kalkulator/presentation/states/calculator_state.dart @@ -2,12 +2,13 @@ part of '_states.dart'; class CalculatorState { CalculatorState() { - final _remoteDataSource = CalculatorRemoteDataSourceImpl(); - _repo = CalculatorRepositoryImpl(_remoteDataSource); + final remoteDataSource = CalculatorRemoteDataSourceImpl(); + _repo = CalculatorRepositoryImpl(remoteDataSource); } late CalculatorRepository _repo; List? _calculators; + List get calculators => _calculators ?? []; bool hasReachedMax = false; @@ -45,16 +46,26 @@ class CalculatorState { _calculators = result.data; print(_calculators); }); - } - ); + }); calculatorRM.notify(); } - Future deleteCalculator(QueryCalculator query) async { + Future deleteCalculator({ + required QueryCalculator query, + required String courseName, + required double totalScore, + }) async { final resp = await _repo.deleteCalculator(query); + MixpanelService.track( + 'calculator_delete_course_component', + params: { + 'course_id': courseName, + 'final_letter_grade': totalScore.toString(), + 'final_grade': getFinalGrade(totalScore), + }, + ); await resp.fold((failure) { - ErrorMessenger('Kalkulator gagal dihapus') - .show(ctx!); + ErrorMessenger('Kalkulator gagal dihapus').show(ctx!); }, (result) async { SuccessMessenger('Kalkulator berhasil dipahus').show(ctx!); final calcResp = await _repo.getAllCalculator(); @@ -64,8 +75,7 @@ class CalculatorState { _calculators = result.data; print(_calculators); }); - } - ); + }); calculatorRM.notify(); } } diff --git a/lib/features/kalkulator/presentation/states/component_form_state.dart b/lib/features/kalkulator/presentation/states/component_form_state.dart index 2979be0..b21397c 100644 --- a/lib/features/kalkulator/presentation/states/component_form_state.dart +++ b/lib/features/kalkulator/presentation/states/component_form_state.dart @@ -2,9 +2,9 @@ part of '_states.dart'; class ComponentFormState { ComponentFormState() { - final _remoteDataSource = ComponentRemoteDataSourceImpl(); + final remoteDataSource = ComponentRemoteDataSourceImpl(); _repo = ComponentRepositoryImpl( - _remoteDataSource, + remoteDataSource, ); } diff --git a/lib/features/kalkulator/presentation/states/component_state.dart b/lib/features/kalkulator/presentation/states/component_state.dart index 6c1e230..44b4fbe 100644 --- a/lib/features/kalkulator/presentation/states/component_state.dart +++ b/lib/features/kalkulator/presentation/states/component_state.dart @@ -2,8 +2,8 @@ part of '_states.dart'; class ComponentState{ ComponentState() { - final _remoteDataSource = ComponentRemoteDataSourceImpl(); - _repo = ComponentRepositoryImpl(_remoteDataSource); + final remoteDataSource = ComponentRemoteDataSourceImpl(); + _repo = ComponentRepositoryImpl(remoteDataSource); } late ComponentRepository _repo; diff --git a/lib/features/kalkulator/presentation/widgets/card_calculator.dart b/lib/features/kalkulator/presentation/widgets/card_calculator.dart index 597337d..422bf7d 100644 --- a/lib/features/kalkulator/presentation/widgets/card_calculator.dart +++ b/lib/features/kalkulator/presentation/widgets/card_calculator.dart @@ -2,10 +2,9 @@ part of '_widgets.dart'; class CardCalculator extends StatelessWidget { const CardCalculator({ - Key? key, - required this.model, + required this.model, super.key, this.onTap, - }) : super(key: key); + }); final CalculatorModel model; final VoidCallback? onTap; diff --git a/lib/features/kalkulator/presentation/widgets/card_component.dart b/lib/features/kalkulator/presentation/widgets/card_component.dart index 64f36e5..5e93c6c 100644 --- a/lib/features/kalkulator/presentation/widgets/card_component.dart +++ b/lib/features/kalkulator/presentation/widgets/card_component.dart @@ -2,13 +2,13 @@ part of '_widgets.dart'; class CardCompononent extends StatelessWidget { const CardCompononent({ - Key? key, - this.onTap, required this.id, required this.name, required this.score, required this.weight, - }) : super(key: key); + super.key, + this.onTap, + }); final int id; final String name; @@ -47,17 +47,19 @@ class CardCompononent extends StatelessWidget { ), ), Expanded( - child: Text(score.toStringAsFixed(2), + child: Text( + score.toStringAsFixed(2), style: FontTheme.poppins12w400black(), textAlign: TextAlign.right, ), ), Expanded( - child: Text('${weight.toStringAsFixed(1)}%', + child: Text( + '${weight.toStringAsFixed(1)}%', style: FontTheme.poppins12w400black(), textAlign: TextAlign.right, ), - ) + ), ], ), ), diff --git a/lib/features/kalkulator/presentation/widgets/card_course_simplified.dart b/lib/features/kalkulator/presentation/widgets/card_course_simplified.dart index 5dcf731..e68b6fa 100644 --- a/lib/features/kalkulator/presentation/widgets/card_course_simplified.dart +++ b/lib/features/kalkulator/presentation/widgets/card_course_simplified.dart @@ -2,10 +2,9 @@ part of '_widgets.dart'; class CardCourseSimplified extends StatelessWidget { const CardCourseSimplified({ - Key? key, - required this.model, + required this.model, super.key, this.onTap, - }) : super(key: key); + }); final CourseModel model; final VoidCallback? onTap; diff --git a/lib/features/kalkulator/presentation/widgets/search_list_view_simplified.dart b/lib/features/kalkulator/presentation/widgets/search_list_view_simplified.dart index 756bf91..61477de 100644 --- a/lib/features/kalkulator/presentation/widgets/search_list_view_simplified.dart +++ b/lib/features/kalkulator/presentation/widgets/search_list_view_simplified.dart @@ -2,12 +2,12 @@ part of '_widgets.dart'; class SearchListViewSimplified extends StatelessWidget { const SearchListViewSimplified({ - Key? key, required this.refreshIndicatorKey, required this.scrollController, required this.onScroll, required this.onRefresh, - }) : super(key: key); + super.key, + }); final GlobalKey refreshIndicatorKey; final ScrollController scrollController; @@ -86,8 +86,9 @@ Mata kuliah yang kamu cari tidak ada di aplikasi. Silakan coba lagi dengan kata model: course, onTap: () { nav.pop(); - calculatorRM.setState((s) => - s.postCalculator(course.code!),); + calculatorRM.setState( + (s) => s.postCalculator(course.code!), + ); }, ); }, diff --git a/lib/features/kalkulator/presentation/widgets/simpan_button.dart b/lib/features/kalkulator/presentation/widgets/simpan_button.dart index 8cc7f78..ff631d9 100644 --- a/lib/features/kalkulator/presentation/widgets/simpan_button.dart +++ b/lib/features/kalkulator/presentation/widgets/simpan_button.dart @@ -2,11 +2,9 @@ part of '_widgets.dart'; class SimpanButton extends StatelessWidget { const SimpanButton({ - Key? key, - required this.onTap, - required this.text, + required this.onTap, required this.text, super.key, this.isLoading = false, - }) : super(key: key); + }); final VoidCallback onTap; final String text; @@ -23,7 +21,7 @@ class SimpanButton extends StatelessWidget { color: Color.fromRGBO(0, 0, 0, 0.05), blurRadius: 4, offset: Offset(0, -2), - ) + ), ], ), child: AutoLayoutButton( diff --git a/lib/features/leaderboard/presentation/pages/guideline_page.dart b/lib/features/leaderboard/presentation/pages/guideline_page.dart index fe03fc1..e015104 100644 --- a/lib/features/leaderboard/presentation/pages/guideline_page.dart +++ b/lib/features/leaderboard/presentation/pages/guideline_page.dart @@ -1,7 +1,7 @@ part of '_pages.dart'; class GuidelinePage extends StatelessWidget { - const GuidelinePage({Key? key}) : super(key: key); + const GuidelinePage({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/features/leaderboard/presentation/pages/leaderboard_page.dart b/lib/features/leaderboard/presentation/pages/leaderboard_page.dart index 6424cc6..c578c40 100644 --- a/lib/features/leaderboard/presentation/pages/leaderboard_page.dart +++ b/lib/features/leaderboard/presentation/pages/leaderboard_page.dart @@ -1,7 +1,7 @@ part of '_pages.dart'; class LeaderboardPage extends StatefulWidget { - const LeaderboardPage({Key? key}) : super(key: key); + const LeaderboardPage({super.key}); @override _LeaderboardPageState createState() => _LeaderboardPageState(); diff --git a/lib/features/leaderboard/presentation/states/leaderboard_state.dart b/lib/features/leaderboard/presentation/states/leaderboard_state.dart index e455731..b77f39c 100644 --- a/lib/features/leaderboard/presentation/states/leaderboard_state.dart +++ b/lib/features/leaderboard/presentation/states/leaderboard_state.dart @@ -2,9 +2,9 @@ part of '_states.dart'; class LeaderboardState { LeaderboardState() { - final _remoteDataSource = LeaderboardRemoteDataSourceImpl(); + final remoteDataSource = LeaderboardRemoteDataSourceImpl(); _repo = LeaderboardRepositoryImpl( - _remoteDataSource, + remoteDataSource, ); } diff --git a/lib/features/leaderboard/presentation/widgets/leaderboard_card.dart b/lib/features/leaderboard/presentation/widgets/leaderboard_card.dart index ac9a1df..34acc71 100644 --- a/lib/features/leaderboard/presentation/widgets/leaderboard_card.dart +++ b/lib/features/leaderboard/presentation/widgets/leaderboard_card.dart @@ -2,10 +2,8 @@ part of '_widgets.dart'; class LeaderboardCard extends StatelessWidget { const LeaderboardCard({ - Key? key, - required this.rank, - required this.model, - }) : super(key: key); + required this.rank, required this.model, super.key, + }); final int rank; final LeaderboardModel model; diff --git a/lib/features/leaderboard/presentation/widgets/leaderboard_tag.dart b/lib/features/leaderboard/presentation/widgets/leaderboard_tag.dart index a4c3fcd..c5af972 100644 --- a/lib/features/leaderboard/presentation/widgets/leaderboard_tag.dart +++ b/lib/features/leaderboard/presentation/widgets/leaderboard_tag.dart @@ -4,10 +4,10 @@ part of '_widgets.dart'; class TagLeaderboard extends StatelessWidget { /// Creates Tag Widget const TagLeaderboard({ - Key? key, + super.key, this.label = 'Kamu', this.rank, - }) : super(key: key); + }); /// Specify the label text final String label; @@ -56,7 +56,7 @@ class TagLeaderboard extends StatelessWidget { return [ BaseColors.purpleHearth, BaseColors.purpleHearth, - BaseColors.white + BaseColors.white, ]; }else if(rank == 1){ return [ diff --git a/lib/features/leaderboard/presentation/widgets/skeleton_card_leaderboard.dart b/lib/features/leaderboard/presentation/widgets/skeleton_card_leaderboard.dart index 0762a31..5de05e4 100644 --- a/lib/features/leaderboard/presentation/widgets/skeleton_card_leaderboard.dart +++ b/lib/features/leaderboard/presentation/widgets/skeleton_card_leaderboard.dart @@ -1,7 +1,7 @@ part of '_widgets.dart'; class SkeletonCardLeaderboard extends StatelessWidget { - const SkeletonCardLeaderboard({Key? key}) : super(key: key); + const SkeletonCardLeaderboard({super.key}); @override Widget build(BuildContext context) { @@ -42,7 +42,7 @@ class SkeletonCardLeaderboard extends StatelessWidget { ), ), ), - ) + ), ], ), title: Container( diff --git a/lib/features/matkul/bookmarks/presentation/pages/_pages.dart b/lib/features/matkul/bookmarks/presentation/pages/_pages.dart index d639406..3a102f4 100644 --- a/lib/features/matkul/bookmarks/presentation/pages/_pages.dart +++ b/lib/features/matkul/bookmarks/presentation/pages/_pages.dart @@ -8,5 +8,6 @@ import 'package:ulaskelas/features/matkul/bookmarks/domain/entities/query_bookma import 'package:ulaskelas/features/matkul/bookmarks/presentation/states/_states.dart'; import 'package:ulaskelas/features/matkul/bookmarks/presentation/widgets/_widgets.dart'; import 'package:ulaskelas/features/matkul/search/presentation/widgets/_widgets.dart'; +import 'package:ulaskelas/services/_services.dart'; part 'bookmarks_page.dart'; diff --git a/lib/features/matkul/bookmarks/presentation/pages/bookmarks_page.dart b/lib/features/matkul/bookmarks/presentation/pages/bookmarks_page.dart index 8b6c357..15ae056 100644 --- a/lib/features/matkul/bookmarks/presentation/pages/bookmarks_page.dart +++ b/lib/features/matkul/bookmarks/presentation/pages/bookmarks_page.dart @@ -4,8 +4,8 @@ part of '_pages.dart'; class BookmarksPage extends StatefulWidget { const BookmarksPage({ - Key? key, - }) : super(key: key); + super.key, + }); @override _BookmarksPageState createState() => _BookmarksPageState(); @@ -44,8 +44,8 @@ class _BookmarksPageState extends BaseStateful { onRefresh: retrieveData, child: OnBuilder.all( listenTo: bookmarkRM, - onIdle: () => WaitingView(), - onWaiting: () => WaitingView(), + onIdle: WaitingView.new, + onWaiting: WaitingView.new, onError: (dynamic error, refresh) => const Text('error'), onData: (data) { final bookmarks = data.bookmarks; @@ -71,7 +71,7 @@ class _BookmarksPageState extends BaseStateful { Text( ''' Kamu Belum memiliki Mata kuliah tersimpan. Silakan tambahkan terlebih dahulu.''', - style: Theme.of(context).textTheme.caption, + style: Theme.of(context).textTheme.bodySmall, textAlign: TextAlign.center, ), const HeightSpace(40), @@ -87,10 +87,18 @@ Kamu Belum memiliki Mata kuliah tersimpan. Silakan tambahkan terlebih dahulu.''' // TODO(paw): set course_id return CardBookmark( model: bookmark, - onTap: () => nav.goToDetailMatkulPage( - bookmark.courseId!, - bookmark.courseCode!, - ), + onTap: () { + nav.goToDetailMatkulPage( + bookmark.courseId!, + bookmark.courseCode!, + ); + MixpanelService.track( + 'open_profile_saved_course', + params: { + 'course_id': bookmark.courseCode!, + }, + ); + }, ); }, separatorBuilder: (BuildContext context, int index) => diff --git a/lib/features/matkul/bookmarks/presentation/states/_states.dart b/lib/features/matkul/bookmarks/presentation/states/_states.dart index e66b7e0..d59ce46 100644 --- a/lib/features/matkul/bookmarks/presentation/states/_states.dart +++ b/lib/features/matkul/bookmarks/presentation/states/_states.dart @@ -7,4 +7,6 @@ import 'package:ulaskelas/features/matkul/bookmarks/domain/entities/query_bookma import 'package:ulaskelas/features/matkul/bookmarks/domain/repositories/_repositories.dart'; import 'package:ulaskelas/features/matkul/search/data/models/_models.dart'; +import '../../../../../services/_services.dart'; + part 'bookmark_state.dart'; diff --git a/lib/features/matkul/bookmarks/presentation/states/bookmark_state.dart b/lib/features/matkul/bookmarks/presentation/states/bookmark_state.dart index e0187b4..75bd760 100644 --- a/lib/features/matkul/bookmarks/presentation/states/bookmark_state.dart +++ b/lib/features/matkul/bookmarks/presentation/states/bookmark_state.dart @@ -2,11 +2,11 @@ part of '_states.dart'; class BookmarkState { BookmarkState() { - final _remoteDataSource = BookmarkRemoteDataSourceImpl(); - final _localDataSource = BookmarkLocalDataSourceImpl(); + final remoteDataSource = BookmarkRemoteDataSourceImpl(); + final localDataSource = BookmarkLocalDataSourceImpl(); _repo = BookmarkRepositoryImpl( - _remoteDataSource, - _localDataSource, + remoteDataSource, + localDataSource, ); } @@ -44,6 +44,7 @@ class BookmarkState { /// tap to toggle Bookmark Future toggleBookmark(BookmarkModel bookmark) async { + MixpanelService.track('bookmark_course'); final resp = await _repo.getAllBookmark(QueryBookmark()); resp.fold((failure) { throw failure; diff --git a/lib/features/matkul/bookmarks/presentation/widgets/card_bookmark.dart b/lib/features/matkul/bookmarks/presentation/widgets/card_bookmark.dart index fa3b33d..58b4293 100644 --- a/lib/features/matkul/bookmarks/presentation/widgets/card_bookmark.dart +++ b/lib/features/matkul/bookmarks/presentation/widgets/card_bookmark.dart @@ -2,10 +2,9 @@ part of '_widgets.dart'; class CardBookmark extends StatelessWidget { const CardBookmark({ - Key? key, - required this.model, + required this.model, super.key, this.onTap, - }) : super(key: key); + }); final BookmarkModel model; final VoidCallback? onTap; diff --git a/lib/features/matkul/detail/presentation/pages/_pages.dart b/lib/features/matkul/detail/presentation/pages/_pages.dart index 35de4bf..0287877 100644 --- a/lib/features/matkul/detail/presentation/pages/_pages.dart +++ b/lib/features/matkul/detail/presentation/pages/_pages.dart @@ -15,6 +15,8 @@ import 'package:ulaskelas/features/matkul/form/presentation/states/_states.dart' import 'package:ulaskelas/features/matkul/search/data/models/_models.dart'; import 'package:ulaskelas/features/matkul/search/presentation/widgets/_widgets.dart'; +import '../../../../../services/_services.dart'; + part 'detail_matkul_page.dart'; part 'review_matkul_page.dart'; part 'all_review_matkul_page.dart'; diff --git a/lib/features/matkul/detail/presentation/pages/all_review_matkul_page.dart b/lib/features/matkul/detail/presentation/pages/all_review_matkul_page.dart index b177f2b..fdeb6af 100644 --- a/lib/features/matkul/detail/presentation/pages/all_review_matkul_page.dart +++ b/lib/features/matkul/detail/presentation/pages/all_review_matkul_page.dart @@ -2,10 +2,8 @@ part of '_pages.dart'; class AllReviewMatkulPage extends StatefulWidget { const AllReviewMatkulPage({ - Key? key, - required this.courseId, - required this.courseCode, - }) : super(key: key); + required this.courseId, required this.courseCode, super.key, + }); final int courseId; final String courseCode; @@ -102,8 +100,8 @@ class _AllReviewMatkulPageState extends BaseStateful { onRefresh: retrieveData, child: OnBuilder.all( listenTo: courseDetailRM, - onIdle: () => WaitingView(), - onWaiting: () => WaitingView(), + onIdle: WaitingView.new, + onWaiting: WaitingView.new, onError: (dynamic error, refresh) => const Text('error'), onData: (data) { final course = data.detailCourse; @@ -135,7 +133,7 @@ class _AllReviewMatkulPageState extends BaseStateful { size: 28, ), ), - ) + ), ], ); }, @@ -151,7 +149,7 @@ class _AllReviewMatkulPageState extends BaseStateful { color: Color.fromRGBO(0, 0, 0, 0.05), blurRadius: 4, offset: Offset(0, -2), - ) + ), ], ), child: TulisUlasanButton( @@ -163,7 +161,7 @@ class _AllReviewMatkulPageState extends BaseStateful { } }, ), - ) + ), ], ); } diff --git a/lib/features/matkul/detail/presentation/pages/detail_matkul_page.dart b/lib/features/matkul/detail/presentation/pages/detail_matkul_page.dart index e8def52..2fb0b2a 100644 --- a/lib/features/matkul/detail/presentation/pages/detail_matkul_page.dart +++ b/lib/features/matkul/detail/presentation/pages/detail_matkul_page.dart @@ -8,10 +8,10 @@ part of '_pages.dart'; /// ```; class DetailMatkulPage extends StatefulWidget { const DetailMatkulPage({ - Key? key, required this.courseId, required this.courseCode, - }) : super(key: key); + super.key, + }); final int courseId; final String courseCode; @@ -59,12 +59,10 @@ class _DetailMatkulPageState extends BaseStateful { bool get _isBottom { if (!scrollController.hasClients) { - print('no client'); return false; } final maxScroll = scrollController.position.maxScrollExtent; final currentScroll = scrollController.offset; - print(currentScroll >= (maxScroll * 0.9)); return currentScroll >= (maxScroll * 0.9); } @@ -103,8 +101,8 @@ class _DetailMatkulPageState extends BaseStateful { onRefresh: retrieveData, child: OnBuilder.all( listenTo: courseDetailRM, - onIdle: () => WaitingView(), - onWaiting: () => WaitingView(), + onIdle: WaitingView.new, + onWaiting: WaitingView.new, onError: (dynamic error, refresh) => const Text('error'), onData: (data) { final course = data.detailCourse; @@ -116,7 +114,7 @@ class _DetailMatkulPageState extends BaseStateful { TitleAndBookMark(course: course), const HeightSpace(24), if (course.tags?.isNotEmpty ?? false) - _buildMatkulTag(course), + _buildMatkulTag(course), const HeightSpace(16), _buildMatkulDescription(course), const HeightSpace(32), @@ -130,6 +128,7 @@ class _DetailMatkulPageState extends BaseStateful { onTap: () => nav.goToAllReviewMatkulPage( courseId: widget.courseId, courseCode: widget.courseCode, + course: course, ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -168,11 +167,11 @@ class _DetailMatkulPageState extends BaseStateful { } Widget _buildMatkulTag(CourseModel course) { - return Row( + return Wrap( children: course.tags! .map( (e) => Padding( - padding: const EdgeInsets.only(right: 8), + padding: const EdgeInsets.only(right: 8, bottom: 8), child: Tag( label: e, ), @@ -227,9 +226,7 @@ class _DetailMatkulPageState extends BaseStateful { final review = data.reviews[data.reviews.length - i - 1]; return ReviewCard( review: review, - onLiked: () { - reviewCourseRM.state.like(review); - }, + onLiked: () => reviewCourseRM.state.like(review), ); }, ); @@ -246,7 +243,7 @@ class _DetailMatkulPageState extends BaseStateful { children: [ Center( child: Text( - '${course.ratingAverage ?? 0.0}', + (course.ratingAverage ?? 0.0).toStringAsFixed(1), style: FontTheme.poppins36w700black(), ), ), @@ -260,7 +257,7 @@ class _DetailMatkulPageState extends BaseStateful { '${course.reviewCount} Ulasan', style: FontTheme.poppins12w400black(), ), - ) + ), ], ), const WidthSpace(32), @@ -349,7 +346,7 @@ class _DetailMatkulPageState extends BaseStateful { ); } }, - ) + ), ], ); } diff --git a/lib/features/matkul/detail/presentation/pages/review_matkul_page.dart b/lib/features/matkul/detail/presentation/pages/review_matkul_page.dart index 922d52d..2e79f87 100644 --- a/lib/features/matkul/detail/presentation/pages/review_matkul_page.dart +++ b/lib/features/matkul/detail/presentation/pages/review_matkul_page.dart @@ -3,7 +3,7 @@ part of '_pages.dart'; class ReviewMatkulPage extends StatefulWidget { - const ReviewMatkulPage({Key? key}) : super(key: key); + const ReviewMatkulPage({super.key}); @override _ReviewMatkulPageState createState() => _ReviewMatkulPageState(); @@ -37,7 +37,7 @@ class _ReviewMatkulPageState extends BaseStateful { children: [ TulisUlasanButton( onTap: () {}, - ) + ), ], ); } diff --git a/lib/features/matkul/detail/presentation/states/course_detail_state.dart b/lib/features/matkul/detail/presentation/states/course_detail_state.dart index 425e389..4e5ad81 100644 --- a/lib/features/matkul/detail/presentation/states/course_detail_state.dart +++ b/lib/features/matkul/detail/presentation/states/course_detail_state.dart @@ -5,11 +5,11 @@ import 'package:ulaskelas/features/matkul/search/data/models/_models.dart'; class CourseDetailState { CourseDetailState() { - final _remoteDataSource = CourseRemoteDataSourceImpl(); - final _localDataSource = CourseLocalDataSourceImpl(); + final remoteDataSource = CourseRemoteDataSourceImpl(); + final localDataSource = CourseLocalDataSourceImpl(); _repo = CourseRepositoryImpl( - _remoteDataSource, - _localDataSource, + remoteDataSource, + localDataSource, ); } diff --git a/lib/features/matkul/detail/presentation/widgets/_widgets.dart b/lib/features/matkul/detail/presentation/widgets/_widgets.dart index 52ed30e..9206a6f 100644 --- a/lib/features/matkul/detail/presentation/widgets/_widgets.dart +++ b/lib/features/matkul/detail/presentation/widgets/_widgets.dart @@ -10,6 +10,7 @@ import 'package:ulaskelas/features/leaderboard/presentation/widgets/_widgets.dar import 'package:ulaskelas/features/matkul/bookmarks/data/models/_models.dart'; import 'package:ulaskelas/features/matkul/form/data/models/_models.dart'; import 'package:ulaskelas/features/matkul/search/data/models/_models.dart'; +import 'package:ulaskelas/services/_services.dart'; import 'package:ulaskelas/services/launch_service.dart'; part 'review_card.dart'; diff --git a/lib/features/matkul/detail/presentation/widgets/review_card.dart b/lib/features/matkul/detail/presentation/widgets/review_card.dart index 9e022f8..a492059 100644 --- a/lib/features/matkul/detail/presentation/widgets/review_card.dart +++ b/lib/features/matkul/detail/presentation/widgets/review_card.dart @@ -2,12 +2,12 @@ part of '_widgets.dart'; class ReviewCard extends StatelessWidget { const ReviewCard({ - Key? key, required this.review, + super.key, this.imgUrl, this.onLiked, this.status, - }) : super(key: key); + }); final ReviewModel review; final String? imgUrl; @@ -76,7 +76,8 @@ class ReviewCard extends StatelessWidget { ? TagStatus.pending : TagStatus.rejected, ), - if (status == null && review.rankTop20 != null && + if (status == null && + review.rankTop20 != null && review.rankTop20! > 0 && review.rankTop20! < 21) TagLeaderboard( @@ -95,8 +96,7 @@ class ReviewCard extends StatelessWidget { PopupMenu( username: review.author.toString(), isAnonymous: review.isAnonym ?? false, - reviewId: review.id!, - // userId: review.author, + review: review, ), Container(), ], @@ -177,9 +177,9 @@ class ReviewCard extends StatelessWidget { // color: likesCountColor, ), ), - ) + ), ], - ) + ), ], ), ); @@ -188,22 +188,22 @@ class ReviewCard extends StatelessWidget { class PopupMenu extends StatelessWidget { const PopupMenu({ - Key? key, required this.username, - required this.reviewId, + required this.review, + super.key, this.isAnonymous = false, - }) : super(key: key); + }); final String username; final bool isAnonymous; - final int reviewId; + final ReviewModel review; @override Widget build(BuildContext context) { return PopupMenuButton( padding: EdgeInsets.zero, iconSize: 18, - onSelected: (value) => _onSelected(context, value), + onSelected: (value) => _onSelected(context, value, review), itemBuilder: (context) => [ _buildItem( value: 1, @@ -241,16 +241,24 @@ class PopupMenu extends StatelessWidget { ); } - void _onSelected(BuildContext context, int value) { + void _onSelected(BuildContext context, int value, ReviewModel review) { switch (value) { case 1: + MixpanelService.track( + 'report_review', + params: { + 'course_id': review.courseCode.toString(), + 'course_name': review.courseName.toString(), + 'previous_likes': review.likesCount.toString(), + 'score_given_by_review': review.courseReviewCount.toString(), + }, + ); LaunchServices.openEmail( 'team@ristek.cs.ui.ac.id', ''' -Report User Content for ${isAnonymous ? 'Review id $reviewId' : username}''', +Report User Content for ${isAnonymous ? 'Review id ${review.id}' : username}''', 'enter report message', ); - break; default: } } diff --git a/lib/features/matkul/detail/presentation/widgets/star_rating.dart b/lib/features/matkul/detail/presentation/widgets/star_rating.dart index 728d6b0..440043a 100644 --- a/lib/features/matkul/detail/presentation/widgets/star_rating.dart +++ b/lib/features/matkul/detail/presentation/widgets/star_rating.dart @@ -8,13 +8,13 @@ class StarRating extends StatelessWidget { final double paddingSize; const StarRating({ - Key? key, + super.key, this.starCount = 5, this.rating = .0, this.onRatingChanged, this.starSize = 16, this.paddingSize = 0, - }) : super(key: key); + }); Widget buildStar(BuildContext context, int index) { Widget icon; @@ -64,11 +64,10 @@ class _HalfFilledIcon extends StatelessWidget { final Color color; const _HalfFilledIcon({ - Key? key, required this.icon, required this.size, required this.color, - }): super(key: key); + }); @override Widget build(BuildContext context) { diff --git a/lib/features/matkul/detail/presentation/widgets/title_and_bookmark.dart b/lib/features/matkul/detail/presentation/widgets/title_and_bookmark.dart index 739aa5c..9110148 100644 --- a/lib/features/matkul/detail/presentation/widgets/title_and_bookmark.dart +++ b/lib/features/matkul/detail/presentation/widgets/title_and_bookmark.dart @@ -2,9 +2,9 @@ part of '_widgets.dart'; class TitleAndBookMark extends StatelessWidget { const TitleAndBookMark({ - Key? key, required this.course, - }) : super(key: key); + super.key, + }); final CourseModel course; @@ -37,6 +37,7 @@ class TitleAndBookMark extends StatelessWidget { shortName: course.shortName, ); bookmarkRM.setState((s) => s.toggleBookmark(bookmark)); + MixpanelService.track('bookmark_course'); }, child: Icon( Icons.bookmark, diff --git a/lib/features/matkul/detail/presentation/widgets/tulis_ulasan_button.dart b/lib/features/matkul/detail/presentation/widgets/tulis_ulasan_button.dart index 5fe1ef8..d1aa8d6 100644 --- a/lib/features/matkul/detail/presentation/widgets/tulis_ulasan_button.dart +++ b/lib/features/matkul/detail/presentation/widgets/tulis_ulasan_button.dart @@ -2,11 +2,10 @@ part of '_widgets.dart'; class TulisUlasanButton extends StatelessWidget { const TulisUlasanButton({ - Key? key, - required this.onTap, + required this.onTap, super.key, this.isLoading = false, this.text = 'Tulis Ulasan', - }) : super(key: key); + }); final VoidCallback onTap; final bool isLoading; diff --git a/lib/features/matkul/form/data/models/tag_model.dart b/lib/features/matkul/form/data/models/tag_model.dart index 2e28ae1..2f133ec 100644 --- a/lib/features/matkul/form/data/models/tag_model.dart +++ b/lib/features/matkul/form/data/models/tag_model.dart @@ -2,8 +2,7 @@ part of '_models.dart'; class TagModel { TagModel({ - this.id, - required this.name, + required this.name, this.id, }); TagModel.fromJson(Map json) { diff --git a/lib/features/matkul/form/presentation/pages/_pages.dart b/lib/features/matkul/form/presentation/pages/_pages.dart index 2773534..fd02e45 100644 --- a/lib/features/matkul/form/presentation/pages/_pages.dart +++ b/lib/features/matkul/form/presentation/pages/_pages.dart @@ -15,6 +15,7 @@ import 'package:ulaskelas/features/matkul/form/presentation/states/_states.dart' import 'package:ulaskelas/features/matkul/form/presentation/widgets/_widgets.dart'; import 'package:ulaskelas/features/matkul/search/data/models/_models.dart'; import 'package:ulaskelas/features/matkul/search/presentation/widgets/_widgets.dart'; +import 'package:ulaskelas/services/_services.dart'; part 'add_review_matkul_tag_page.dart'; part 'review_matkul_form_page.dart'; diff --git a/lib/features/matkul/form/presentation/pages/add_review_matkul_tag_page.dart b/lib/features/matkul/form/presentation/pages/add_review_matkul_tag_page.dart index 598df81..9d8209f 100644 --- a/lib/features/matkul/form/presentation/pages/add_review_matkul_tag_page.dart +++ b/lib/features/matkul/form/presentation/pages/add_review_matkul_tag_page.dart @@ -3,7 +3,7 @@ part of '_pages.dart'; class AddReviewMatkulTagPage extends StatefulWidget { - const AddReviewMatkulTagPage({Key? key}) : super(key: key); + const AddReviewMatkulTagPage({super.key}); @override _AddReviewMatkulTagPageState createState() => _AddReviewMatkulTagPageState(); @@ -105,7 +105,7 @@ Pilih maksimal 3 kategori yang menurutmu dapat\nmerepresentasikan mata kuliah in }, ), ), - ) + ), ], ); } @@ -128,8 +128,8 @@ Pilih maksimal 3 kategori yang menurutmu dapat\nmerepresentasikan mata kuliah in onRefresh: retrieveData, child: OnBuilder.all( listenTo: searchTagRM, - onIdle: () => WaitingView(), - onWaiting: () => WaitingView(), + onIdle: WaitingView.new, + onWaiting: WaitingView.new, onError: (dynamic error, refresh) => const Text('error'), onData: (data) { final matkulTags = data.tags; diff --git a/lib/features/matkul/form/presentation/pages/review_matkul_form_page.dart b/lib/features/matkul/form/presentation/pages/review_matkul_form_page.dart index 3a430a5..accdc72 100644 --- a/lib/features/matkul/form/presentation/pages/review_matkul_form_page.dart +++ b/lib/features/matkul/form/presentation/pages/review_matkul_form_page.dart @@ -4,9 +4,9 @@ part of '_pages.dart'; class ReviewMatkulFormPage extends StatefulWidget { const ReviewMatkulFormPage({ - Key? key, required this.course, - }) : super(key: key); + super.key, + }); final CourseModel course; @@ -130,9 +130,11 @@ class _ReviewMatkulFormPageState extends BaseStateful { reviewFormStateData.ratingFitToStudyBook != null && reviewFormStateData.ratingBeneficial != null && reviewFormStateData.ratingRecommended != null) { - await reviewFormRM.state - .submitForm(widget.course.code!); + await reviewFormRM.state.submitForm( + course: widget.course, + ); await Future.delayed(const Duration(milliseconds: 150)); + reviewFormRM.state.cleanForm(); nav.pop(); await nav.replaceToReviewPendingPage(); diff --git a/lib/features/matkul/form/presentation/pages/success_form_page.dart b/lib/features/matkul/form/presentation/pages/success_form_page.dart index e858b8d..ea636ba 100644 --- a/lib/features/matkul/form/presentation/pages/success_form_page.dart +++ b/lib/features/matkul/form/presentation/pages/success_form_page.dart @@ -1,7 +1,7 @@ part of '_pages.dart'; class SuccessFormPage extends StatefulWidget { - const SuccessFormPage({Key? key}) : super(key: key); + const SuccessFormPage({super.key}); @override _SuccessFormPageState createState() => _SuccessFormPageState(); @@ -53,7 +53,7 @@ class _SuccessFormPageState extends BaseStateful { onPressed: () { nav.pop(); }, - ) + ), ], ), ), diff --git a/lib/features/matkul/form/presentation/states/_states.dart b/lib/features/matkul/form/presentation/states/_states.dart index 8357ac8..464a7f6 100644 --- a/lib/features/matkul/form/presentation/states/_states.dart +++ b/lib/features/matkul/form/presentation/states/_states.dart @@ -16,6 +16,9 @@ import 'package:ulaskelas/features/matkul/form/domain/entities/query_search_tag. import 'package:ulaskelas/features/matkul/form/domain/repositories/_repositories.dart'; import 'package:ulaskelas/features/matkul/search/domain/entities/_entities.dart'; +import '../../../../../services/_services.dart'; +import '../../../search/data/models/_models.dart'; + part 'review_course_form_state.dart'; part 'search_tag_state.dart'; part 'review_course_state.dart'; diff --git a/lib/features/matkul/form/presentation/states/review_course_form_state.dart b/lib/features/matkul/form/presentation/states/review_course_form_state.dart index 973d86a..06d8421 100644 --- a/lib/features/matkul/form/presentation/states/review_course_form_state.dart +++ b/lib/features/matkul/form/presentation/states/review_course_form_state.dart @@ -4,11 +4,11 @@ part of '_states.dart'; class ReviewCourseFormState { ReviewCourseFormState() { - final _remoteDataSource = ReviewRemoteDataSourceImpl(); - final _localDataSource = ReviewLocalDataSourceImpl(); + final remoteDataSource = ReviewRemoteDataSourceImpl(); + final localDataSource = ReviewLocalDataSourceImpl(); _repo = ReviewRepositoryImpl( - _remoteDataSource, - _localDataSource, + remoteDataSource, + localDataSource, ); } @@ -18,17 +18,21 @@ class ReviewCourseFormState { final _descController = TextEditingController(); final semesters = ['Semester ganjil', 'Semester genap']; - final years = ['2022', '2021', '2020', '2019', '2018', '2017']; + final years = [ + for (var i = 0; i < 5; i++) (DateTime.now().year - i).toString(), + ]; bool isLoading = false; /// Submitting form data - Future submitForm(String courseCode) async { + Future submitForm({ + required CourseModel course, + }) async { isLoading = true; reviewFormRM.notify(); final result = {}; // TODO(Any): sync with current matkul - result['course_code'] = courseCode; + result['course_code'] = course.code; result['semester'] = _formData.semester! == semesters[0] ? 1 : 2; result['academic_year'] = getPairedYear(result['semester'], _formData.year!); @@ -43,6 +47,19 @@ class ReviewCourseFormState { result['rating_recommended'] = _formData.ratingRecommended; final resp = await _repo.createReview(result); + MixpanelService.track( + 'write_review', + params: { + 'course_id': course.code.toString(), + 'course_name': course.name.toString(), + 'created_at': DateTime.now().toString(), + 'period_taking': _formData.semester.toString(), + 'year_taking': _formData.year.toString(), + 'avg_rating_given': reviewFormRM.state.getAvgRating().toString(), + 'tags': _formData.tagData.toString(), + 'anonymous_review': _formData.isAnonymous.toString(), + }, + ); isLoading = false; reviewFormRM.notify(); resp.fold((failure) { @@ -112,6 +129,15 @@ class ReviewCourseFormState { _formData.ratingRecommended = ratingRecommended; } + double getAvgRating() { + return ((_formData.ratingBeneficial ?? 0) + + (_formData.ratingFitToCredit ?? 0) + + (_formData.ratingFitToStudyBook ?? 0) + + (_formData.ratingRecommended ?? 0) + + (_formData.ratingUnderstandable ?? 0)) / + 5; + } + /// Cleaning form when success submitting form void cleanForm() { _formData = ReviewMatkulData(); diff --git a/lib/features/matkul/form/presentation/states/review_course_state.dart b/lib/features/matkul/form/presentation/states/review_course_state.dart index d4a1d03..c8cef0c 100644 --- a/lib/features/matkul/form/presentation/states/review_course_state.dart +++ b/lib/features/matkul/form/presentation/states/review_course_state.dart @@ -4,14 +4,14 @@ part of '_states.dart'; class ReviewCourseState { ReviewCourseState() { - final _remoteDataSource = ReviewRemoteDataSourceImpl(); - final _localDataSource = ReviewLocalDataSourceImpl(); + final remoteDataSource = ReviewRemoteDataSourceImpl(); + final localDataSource = ReviewLocalDataSourceImpl(); _repo = ReviewRepositoryImpl( - _remoteDataSource, - _localDataSource, + remoteDataSource, + localDataSource, ); - final _likeRemoteDataSource = LikeRemoteDataSourceImpl(); - _likeRepo = LikeRepositoryImpl(_likeRemoteDataSource); + final likeRemoteDataSource = LikeRemoteDataSourceImpl(); + _likeRepo = LikeRepositoryImpl(likeRemoteDataSource); } late ReviewRepository _repo; @@ -111,5 +111,14 @@ class ReviewCourseState { } reviewCourseRM.notify(); }); + MixpanelService.track( + 'like_review', + params: { + 'course_id': review.courseCode.toString(), + 'course_name': review.courseName.toString(), + 'review_count': review.likesCount.toString(), + 'course_rating_avg': review.ratingAverage.toString(), + }, + ); } } diff --git a/lib/features/matkul/form/presentation/states/search_tag_state.dart b/lib/features/matkul/form/presentation/states/search_tag_state.dart index 76475c1..c5c02c0 100644 --- a/lib/features/matkul/form/presentation/states/search_tag_state.dart +++ b/lib/features/matkul/form/presentation/states/search_tag_state.dart @@ -2,11 +2,11 @@ part of '_states.dart'; class SearchTagState implements FutureState { SearchTagState() { - final _remoteDataSource = TagRemoteDataSourceImpl(); - final _localDataSource = TagLocalDataSourceImpl(); + final remoteDataSource = TagRemoteDataSourceImpl(); + final localDataSource = TagLocalDataSourceImpl(); _repo = TagRepositoryImpl( - _remoteDataSource, - _localDataSource, + remoteDataSource, + localDataSource, ); } diff --git a/lib/features/matkul/form/presentation/widgets/form_rating_component.dart b/lib/features/matkul/form/presentation/widgets/form_rating_component.dart index 150889b..2d66b52 100644 --- a/lib/features/matkul/form/presentation/widgets/form_rating_component.dart +++ b/lib/features/matkul/form/presentation/widgets/form_rating_component.dart @@ -2,10 +2,8 @@ part of '_widgets.dart'; class RatingComponent extends StatelessWidget { const RatingComponent({ - Key? key, - required this.text, - required this.starRating, - }) : super(key: key); + required this.text, required this.starRating, super.key, + }); final String text; final StarRating starRating; diff --git a/lib/features/matkul/form/presentation/widgets/guideline_card.dart b/lib/features/matkul/form/presentation/widgets/guideline_card.dart index 42340c2..02e097a 100644 --- a/lib/features/matkul/form/presentation/widgets/guideline_card.dart +++ b/lib/features/matkul/form/presentation/widgets/guideline_card.dart @@ -1,7 +1,7 @@ part of '_widgets.dart'; class GuidelineCard extends StatelessWidget { - const GuidelineCard({Key? key}) : super(key: key); + const GuidelineCard({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/features/matkul/search/presentation/pages/_pages.dart b/lib/features/matkul/search/presentation/pages/_pages.dart index 1679527..f995f12 100644 --- a/lib/features/matkul/search/presentation/pages/_pages.dart +++ b/lib/features/matkul/search/presentation/pages/_pages.dart @@ -11,6 +11,7 @@ import 'package:ulaskelas/core/theme/_theme.dart'; import 'package:ulaskelas/features/matkul/main/domain/entities/query_search_course.dart'; import 'package:ulaskelas/features/matkul/search/presentation/states/_states.dart'; import 'package:ulaskelas/features/matkul/search/presentation/widgets/_widgets.dart'; +import 'package:ulaskelas/services/_services.dart'; part 'filter_page.dart'; part 'search_course_page.dart'; diff --git a/lib/features/matkul/search/presentation/pages/filter_page.dart b/lib/features/matkul/search/presentation/pages/filter_page.dart index 77e23a2..70081d7 100644 --- a/lib/features/matkul/search/presentation/pages/filter_page.dart +++ b/lib/features/matkul/search/presentation/pages/filter_page.dart @@ -4,8 +4,8 @@ part of '_pages.dart'; class FilterPage extends StatefulWidget { const FilterPage({ - Key? key, - }) : super(key: key); + super.key, + }); @override _FilterPageState createState() => _FilterPageState(); @@ -158,10 +158,19 @@ class _FilterPageState extends BaseStateful { text: 'Terapkan Filter', onTap: () { nav.pop(true); + MixpanelService.track( + 'apply_course_filter', + params: { + 'jenis_matkul': filterRM.state.selectedType.toString(), + 'jumlah_sks': filterRM.state.selectedSks.toString(), + 'semester_wajib_ambil': + filterRM.state.selectedSemester.toString(), + }, + ); }, ), ), - ) + ), ], ); }, diff --git a/lib/features/matkul/search/presentation/pages/search_course_page.dart b/lib/features/matkul/search/presentation/pages/search_course_page.dart index 8b29b1c..7778a29 100644 --- a/lib/features/matkul/search/presentation/pages/search_course_page.dart +++ b/lib/features/matkul/search/presentation/pages/search_course_page.dart @@ -4,8 +4,8 @@ part of '_pages.dart'; class SearchCoursePage extends StatefulWidget { const SearchCoursePage({ - Key? key, - }) : super(key: key); + super.key, + }); @override _SearchCoursePageState createState() => _SearchCoursePageState(); @@ -78,9 +78,8 @@ class _SearchCoursePageState focusNode.unfocus(); searchCourseRM.state.controller.clear(); }, - onFieldSubmitted: (val) { - searchCourseRM.state.addToHistory(val); - }, + onFieldSubmitted: (val) => + searchCourseRM.state.addToHistory(val), onChange: onQueryChanged, ), ), diff --git a/lib/features/matkul/search/presentation/states/_states.dart b/lib/features/matkul/search/presentation/states/_states.dart index 737f4a4..aa6bd3f 100644 --- a/lib/features/matkul/search/presentation/states/_states.dart +++ b/lib/features/matkul/search/presentation/states/_states.dart @@ -13,5 +13,7 @@ import 'package:ulaskelas/features/matkul/main/domain/repositories/_repositories import 'package:ulaskelas/features/matkul/search/data/models/_models.dart'; import 'package:ulaskelas/features/matkul/search/domain/entities/_entities.dart'; +import '../../../../../services/_services.dart'; + part 'filter_state.dart'; part 'search_course_state.dart'; diff --git a/lib/features/matkul/search/presentation/states/search_course_state.dart b/lib/features/matkul/search/presentation/states/search_course_state.dart index fb0c394..866924b 100644 --- a/lib/features/matkul/search/presentation/states/search_course_state.dart +++ b/lib/features/matkul/search/presentation/states/search_course_state.dart @@ -5,11 +5,11 @@ part of '_states.dart'; class SearchCourseState implements FutureState { SearchCourseState() { - final _remoteDataSource = CourseRemoteDataSourceImpl(); - final _localDataSource = CourseLocalDataSourceImpl(); + final remoteDataSource = CourseRemoteDataSourceImpl(); + final localDataSource = CourseLocalDataSourceImpl(); _repo = CourseRepositoryImpl( - _remoteDataSource, - _localDataSource, + remoteDataSource, + localDataSource, ); } @@ -161,6 +161,12 @@ class SearchCourseState if (history.length == 11) { _history?.removeLast(); } + MixpanelService.track( + 'search_course', + params: { + 'query': query, + }, + ); // TODO(pawpaw): save to local storage } diff --git a/lib/features/matkul/search/presentation/widgets/_widgets.dart b/lib/features/matkul/search/presentation/widgets/_widgets.dart index 0997690..390b99b 100644 --- a/lib/features/matkul/search/presentation/widgets/_widgets.dart +++ b/lib/features/matkul/search/presentation/widgets/_widgets.dart @@ -9,6 +9,7 @@ import 'package:ulaskelas/core/theme/_theme.dart'; import 'package:ulaskelas/features/matkul/search/data/models/_models.dart'; import 'package:ulaskelas/features/matkul/search/presentation/states/_states.dart'; import 'package:ulaskelas/features/matkul/search/presentation/widgets/skeleton_card_course.dart'; +import 'package:ulaskelas/services/_services.dart'; part 'base_app_bar.dart'; part 'card_course.dart'; diff --git a/lib/features/matkul/search/presentation/widgets/base_app_bar.dart b/lib/features/matkul/search/presentation/widgets/base_app_bar.dart index 500926d..37a1daf 100644 --- a/lib/features/matkul/search/presentation/widgets/base_app_bar.dart +++ b/lib/features/matkul/search/presentation/widgets/base_app_bar.dart @@ -4,16 +4,15 @@ part of '_widgets.dart'; class BaseAppBar extends AppBar { BaseAppBar({ - Key? key, + super.key, Function()? onBackPress, String? label, - List? actions, + super.actions, bool hasLeading = true, - bool centerTitle = true, + bool super.centerTitle = true, double? elevation, Color? color, }) : super( - key: key, elevation: elevation ?? 1, shadowColor: Colors.grey[300], backgroundColor: color ?? BaseColors.white, @@ -28,11 +27,9 @@ class BaseAppBar extends AppBar { onPressed: onBackPress ?? () => nav.pop(), ) : null, - centerTitle: centerTitle, title: Text( label.toString(), style: FontTheme.poppins14w700black(), ), - actions: actions, ); } diff --git a/lib/features/matkul/search/presentation/widgets/card_course.dart b/lib/features/matkul/search/presentation/widgets/card_course.dart index 1a11b93..3dcb7c6 100644 --- a/lib/features/matkul/search/presentation/widgets/card_course.dart +++ b/lib/features/matkul/search/presentation/widgets/card_course.dart @@ -4,10 +4,9 @@ part of '_widgets.dart'; class CardCourse extends StatelessWidget { const CardCourse({ - Key? key, - required this.model, + required this.model, super.key, this.onTap, - }) : super(key: key); + }); final CourseModel model; final VoidCallback? onTap; diff --git a/lib/features/matkul/search/presentation/widgets/empty_view.dart b/lib/features/matkul/search/presentation/widgets/empty_view.dart index 308dcdd..6ba6041 100644 --- a/lib/features/matkul/search/presentation/widgets/empty_view.dart +++ b/lib/features/matkul/search/presentation/widgets/empty_view.dart @@ -4,11 +4,9 @@ part of '_widgets.dart'; class DetailView extends StatelessWidget { const DetailView({ - Key? key, - required this.title, - required this.description, + required this.title, required this.description, super.key, this.isEmptyView = false, - }) : super(key: key); + }); final String title; final String description; @@ -40,7 +38,7 @@ class DetailView extends StatelessWidget { const HeightSpace(10), Text( description, - style: Theme.of(context).textTheme.caption, + style: Theme.of(context).textTheme.bodySmall, textAlign: TextAlign.center, ), const HeightSpace(20), diff --git a/lib/features/matkul/search/presentation/widgets/search_list_view.dart b/lib/features/matkul/search/presentation/widgets/search_list_view.dart index 7e81129..059609e 100644 --- a/lib/features/matkul/search/presentation/widgets/search_list_view.dart +++ b/lib/features/matkul/search/presentation/widgets/search_list_view.dart @@ -4,12 +4,12 @@ part of '_widgets.dart'; class SearchListView extends StatelessWidget { const SearchListView({ - Key? key, required this.refreshIndicatorKey, required this.scrollController, required this.onScroll, required this.onRefresh, - }) : super(key: key); + super.key, + }); final GlobalKey refreshIndicatorKey; final ScrollController scrollController; @@ -41,6 +41,7 @@ class SearchListView extends StatelessWidget { text: 'Filter', onPressed: () async { await nav.goToFilterPage(); + if (filterRM.state.hasFilter) { await refreshIndicatorKey.currentState?.show(); } diff --git a/lib/features/matkul/search/presentation/widgets/skeleton_card_course.dart b/lib/features/matkul/search/presentation/widgets/skeleton_card_course.dart index 960ae14..629ef73 100644 --- a/lib/features/matkul/search/presentation/widgets/skeleton_card_course.dart +++ b/lib/features/matkul/search/presentation/widgets/skeleton_card_course.dart @@ -4,7 +4,7 @@ import 'package:shimmer/shimmer.dart'; import 'package:ulaskelas/core/theme/_theme.dart'; class SkeletonCardCourse extends StatelessWidget { - const SkeletonCardCourse({Key? key}) : super(key: key); + const SkeletonCardCourse({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/features/profile/presentation/pages/profile_page.dart b/lib/features/profile/presentation/pages/profile_page.dart index 9526493..0a78a49 100644 --- a/lib/features/profile/presentation/pages/profile_page.dart +++ b/lib/features/profile/presentation/pages/profile_page.dart @@ -8,11 +8,12 @@ import 'package:ulaskelas/core/bases/states/_states.dart'; import 'package:ulaskelas/core/theme/_theme.dart'; import 'package:ulaskelas/features/matkul/search/presentation/widgets/_widgets.dart'; import 'package:ulaskelas/features/profile/presentation/widgets/profile_data.dart'; +import 'package:ulaskelas/services/_services.dart'; class ProfilePage extends StatefulWidget { const ProfilePage({ - Key? key, - }) : super(key: key); + super.key, + }); @override _ProfilePageState createState() => _ProfilePageState(); @@ -46,34 +47,32 @@ class _ProfilePageState extends BaseStateful { vertical: 10, ), child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - const SizedBox(height: 42), - Icon( - Icons.account_circle, - size: 140, - color: Colors.grey[300], - ), - // CircleAvatar( - // radius: 100, - // backgroundColor: Colors.grey[300], - // ), - const SizedBox(height: 34), - ProfileData( - 'Nama', - profileRM.state.profile.name.toString(), - ), - // TODO(pawpaw): angkatan. - ProfileData( - 'Angkatan', - profileRM.state.profile.generation.toString(), - ), - ProfileData( - 'Jurusan', - profileRM.state.profile.studyProgram.toString(), - ), - const Expanded( - child: SizedBox(), + children: [ + Expanded( + child: ListView( + children: [ + const SizedBox(height: 42), + Icon( + Icons.account_circle, + size: 140, + color: Colors.grey[300], + ), + const SizedBox(height: 24), + ProfileData( + 'Nama', + profileRM.state.profile.name.toString(), + ), + // TODO(pawpaw): angkatan. + ProfileData( + 'Angkatan', + profileRM.state.profile.generation.toString(), + ), + ProfileData( + 'Jurusan', + profileRM.state.profile.studyProgram.toString(), + ), + ], + ), ), Center( child: InkWell( @@ -89,12 +88,10 @@ class _ProfilePageState extends BaseStateful { ), ), ), - const HeightSpace(30), + const HeightSpace(24), Center( child: InkWell( - onTap: () { - nav.goToHomeDaftarUlasan(); - }, + onTap: () => nav.goToHomeDaftarUlasan(), child: Text( 'Riwayat Ulasan', style: FontTheme.poppins14w500black().copyWith( @@ -104,7 +101,7 @@ class _ProfilePageState extends BaseStateful { ), ), ), - const HeightSpace(30), + const HeightSpace(24), SecondaryButton( width: double.infinity, text: 'Keluar', diff --git a/lib/features/profile/presentation/states/profile_state.dart b/lib/features/profile/presentation/states/profile_state.dart index d61f05d..53ec667 100644 --- a/lib/features/profile/presentation/states/profile_state.dart +++ b/lib/features/profile/presentation/states/profile_state.dart @@ -7,11 +7,11 @@ import 'package:ulaskelas/features/profile/domain/entities/profile_repository.da class ProfileState { ProfileState() { - final _remoteDataSource = ProfileRemoteDataSourceImpl(); - final _localDataSource = ProfileLocalDataSourceImpl(); + final remoteDataSource = ProfileRemoteDataSourceImpl(); + final localDataSource = ProfileLocalDataSourceImpl(); _repo = ProfileRepositoryImpl( - _remoteDataSource, - _localDataSource, + remoteDataSource, + localDataSource, ); } ProfileRepository? _repo; diff --git a/lib/features/profile/presentation/widgets/keluar_button.dart b/lib/features/profile/presentation/widgets/keluar_button.dart index 0a84f76..85634ca 100644 --- a/lib/features/profile/presentation/widgets/keluar_button.dart +++ b/lib/features/profile/presentation/widgets/keluar_button.dart @@ -3,7 +3,7 @@ import 'package:google_fonts/google_fonts.dart'; import 'package:ulaskelas/core/theme/_theme.dart'; class KeluarButton extends StatelessWidget { - const KeluarButton(this.handler, {Key? key}) : super(key: key); + const KeluarButton(this.handler, {super.key}); final Function() handler; @override diff --git a/lib/features/profile/presentation/widgets/profile_data.dart b/lib/features/profile/presentation/widgets/profile_data.dart index 667047d..55b3d79 100644 --- a/lib/features/profile/presentation/widgets/profile_data.dart +++ b/lib/features/profile/presentation/widgets/profile_data.dart @@ -2,8 +2,10 @@ import 'package:flutter/material.dart'; import 'package:ulaskelas/core/theme/_theme.dart'; class ProfileData extends StatelessWidget { - const ProfileData(this.title, this.data, {Key? key}) : super(key: key); - final String title, data; + final String title; + final String data; + const ProfileData(this.title, this.data, {super.key}); + @override Widget build(BuildContext context) { @@ -24,7 +26,7 @@ class ProfileData extends StatelessWidget { data, style: FontTheme.poppins12w400black(), ), - ) + ), ], ), ); diff --git a/lib/features/sso/presentation/pages/sso_web_page.dart b/lib/features/sso/presentation/pages/sso_web_page.dart index 1d73adb..50bfb1f 100644 --- a/lib/features/sso/presentation/pages/sso_web_page.dart +++ b/lib/features/sso/presentation/pages/sso_web_page.dart @@ -3,7 +3,7 @@ part of '_pages.dart'; class SSOWebPage extends StatefulWidget { - const SSOWebPage({Key? key}) : super(key: key); + const SSOWebPage({super.key}); @override _SSOWebPageState createState() => _SSOWebPageState(); @@ -17,7 +17,7 @@ class _SSOWebPageState extends BaseStateful { @override void init() { - if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView(); + if (Platform.isAndroid) WebView.platform = AndroidWebView(); } @override @@ -60,7 +60,7 @@ class _SSOWebPageState extends BaseStateful { } return const SizedBox.shrink(); }, - ) + ), ], ); } diff --git a/lib/main_page.dart b/lib/main_page.dart index e0ee79e..149391f 100644 --- a/lib/main_page.dart +++ b/lib/main_page.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:ristek_material_component/ristek_material_component.dart'; import 'package:ulaskelas/features/kalkulator/presentation/pages/_pages.dart'; +import 'package:ulaskelas/services/_services.dart'; import 'core/bases/states/_states.dart'; import 'features/home/presentation/pages/_pages.dart'; import 'features/leaderboard/presentation/pages/_pages.dart'; @@ -10,7 +11,7 @@ import 'features/matkul/search/presentation/pages/_pages.dart'; import 'features/profile/presentation/pages/profile_page.dart'; class MainPage extends StatefulWidget { - const MainPage({Key? key}) : super(key: key); + const MainPage({super.key}); @override _MainPageState createState() => _MainPageState(); @@ -24,7 +25,10 @@ class _MainPageState extends BaseStateful { void init() { _children = [ HomePage( - onSeeAllCourse: () => setState(() => _selectedIndex = 1), + onSeeAllCourse: () { + setState(() => _selectedIndex = 1); + MixpanelService.track('view_all_courses'); + }, ), const SearchCoursePage(), const LeaderboardPage(), @@ -70,7 +74,19 @@ class _MainPageState extends BaseStateful { Widget? _convexNavigation() { return RistekBotNavBar( initialActiveIndex: _selectedIndex, - onTap: (int index) => setState(() => _selectedIndex = index), + onTap: (int index) { + switch (index) { + case 1: + MixpanelService.track('open_courses'); + case 2: + MixpanelService.track('open_klasemen'); + case 3: + MixpanelService.track('open_calculator'); + case 4: + MixpanelService.track('open_profile'); + } + setState(() => _selectedIndex = index); + }, items: const [ RistekBotNavItem( icon: Icons.home, diff --git a/lib/onboarding_page.dart b/lib/onboarding_page.dart index 2fdb909..6a867bc 100644 --- a/lib/onboarding_page.dart +++ b/lib/onboarding_page.dart @@ -10,8 +10,8 @@ import 'core/constants/_constants.dart'; class OnboardingPage extends StatefulWidget { const OnboardingPage({ - Key? key, - }) : super(key: key); + super.key, + }); @override _OnboardingPageState createState() => _OnboardingPageState(); @@ -146,14 +146,14 @@ Kamu juga dapat memberikan ulasan terhadap mata kuliah yang sudah kamu ambil. Ul class OnboardingPageBody extends StatelessWidget { const OnboardingPageBody({ - Key? key, required this.index, required this.height, required this.width, required this.title, required this.description, required this.image, - }) : super(key: key); + super.key, + }); final int index; final double height; diff --git a/lib/services/_services.dart b/lib/services/_services.dart index a278451..8c724d7 100644 --- a/lib/services/_services.dart +++ b/lib/services/_services.dart @@ -7,10 +7,12 @@ import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:intl/intl.dart'; import 'package:logger/logger.dart'; +import 'package:mixpanel_flutter/mixpanel_flutter.dart'; import 'package:path_provider/path_provider.dart'; import 'package:share/share.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:ulaskelas/core/_core.dart'; +import 'package:ulaskelas/core/environment/secrets.dart'; part 'date_service.dart'; part 'delay_service.dart'; @@ -19,3 +21,4 @@ part 'file_service.dart'; part 'hive_db_service.dart'; part 'pref_service.dart'; part 'share_service.dart'; +part 'mixpanel_service.dart'; diff --git a/lib/services/mixpanel_service.dart b/lib/services/mixpanel_service.dart new file mode 100644 index 0000000..dae4b68 --- /dev/null +++ b/lib/services/mixpanel_service.dart @@ -0,0 +1,30 @@ +part of '_services.dart'; + +class MixpanelService { + static Mixpanel? _mixpanel; + + static Future init() async { + Logger().i('Initializing Mixpanel Service'); + _mixpanel = await Mixpanel.init( + Secret.mixpanelToken, + trackAutomaticEvents: true, + ); + } + + static Future get instance async { + return _mixpanel ??= await Mixpanel.init( + Secret.mixpanelToken, + trackAutomaticEvents: true, + ); + } + + static void track(String eventName, {Map? params}) { + _mixpanel!.track(eventName, properties: params); + Logger().i( + ''' + Track Events: $eventName, + Parameters: $params + ''' + ); + } +} diff --git a/lib/services/pref_service.dart b/lib/services/pref_service.dart index fa77d75..013db9b 100644 --- a/lib/services/pref_service.dart +++ b/lib/services/pref_service.dart @@ -59,7 +59,7 @@ class Pref { final token = getString(PreferencesKeys.ulasKelasCred); return { 'Authorization': 'Token $token', - 'Content-Type': 'application/json' + 'Content-Type': 'application/json', }; } } diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 8fce4cf..dce6ef2 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,14 +5,16 @@ import FlutterMacOS import Foundation +import firebase_analytics import firebase_core import firebase_crashlytics import package_info -import path_provider_macos -import shared_preferences_macos +import path_provider_foundation +import shared_preferences_foundation import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin")) FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 166ebb2..442a95f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,310 +5,330 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a + url: "https://pub.dev" source: hosted - version: "31.0.0" + version: "61.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "3f2bd3396aae3e349b9ecb3880c9a77aa13c1497ba7ac6314813afd48fcb506f" + url: "https://pub.dev" + source: hosted + version: "1.3.15" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 + url: "https://pub.dev" source: hosted - version: "2.8.0" + version: "5.13.0" another_flushbar: dependency: transitive description: name: another_flushbar - url: "https://pub.dartlang.org" + sha256: "19bf9520230ec40b300aaf9dd2a8fefcb277b25ecd1c4838f530566965befc2a" + url: "https://pub.dev" source: hosted - version: "1.12.29" - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.11" + version: "1.12.30" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.2" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.8.2" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" build: dependency: transitive description: name: build - url: "https://pub.dartlang.org" + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.1" build_config: dependency: transitive description: name: build_config - url: "https://pub.dartlang.org" + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - url: "https://pub.dartlang.org" + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.0.1" build_resolvers: dependency: transitive description: name: build_resolvers - url: "https://pub.dartlang.org" + sha256: "64e12b0521812d1684b1917bc80945625391cb9bdd4312536b1d69dcb6133ed8" + url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.4.1" build_runner: dependency: "direct dev" description: name: build_runner - url: "https://pub.dartlang.org" + sha256: "67d591d602906ef9201caf93452495ad1812bea2074f04e25dbd7c133785821b" + url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.7" build_runner_core: dependency: transitive description: name: build_runner_core - url: "https://pub.dartlang.org" + sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185 + url: "https://pub.dev" source: hosted - version: "7.2.4" + version: "7.2.11" built_collection: dependency: transitive description: name: built_collection - url: "https://pub.dartlang.org" + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" source: hosted version: "5.1.1" built_value: dependency: transitive description: name: built_value - url: "https://pub.dartlang.org" + sha256: "69acb7007eb2a31dc901512bfe0f7b767168be34cb734835d54c070bfa74c1b2" + url: "https://pub.dev" source: hosted - version: "8.4.1" + version: "8.8.0" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" charcode: dependency: transitive description: name: charcode - url: "https://pub.dartlang.org" + sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 + url: "https://pub.dev" source: hosted version: "1.3.1" checked_yaml: dependency: transitive description: name: checked_yaml - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - cli_util: - dependency: transitive - description: - name: cli_util - url: "https://pub.dartlang.org" + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" source: hosted - version: "0.3.5" + version: "2.0.3" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" code_builder: dependency: transitive description: name: code_builder - url: "https://pub.dartlang.org" + sha256: b2151ce26a06171005b379ecff6e08d34c470180ffe16b8e14b6d52be292b55f + url: "https://pub.dev" source: hosted - version: "4.3.0" + version: "4.8.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.2" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.1.1" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.3" csslib: dependency: transitive description: name: csslib - url: "https://pub.dartlang.org" + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" + url: "https://pub.dev" source: hosted - version: "0.17.2" + version: "1.0.0" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.6" dart_style: dependency: transitive description: name: dart_style - url: "https://pub.dartlang.org" + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" + url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.2" dio: dependency: "direct main" description: name: dio - url: "https://pub.dartlang.org" + sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" + url: "https://pub.dev" source: hosted version: "4.0.6" - dotenv: - dependency: transitive - description: - name: dotenv - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0" - envify: + envied: dependency: "direct main" description: - name: envify - url: "https://pub.dartlang.org" + name: envied + sha256: "60d3f5606c7b35bc6ef493e650d916b34351d8af2e58b7ac45881ba59dfcf039" + url: "https://pub.dev" source: hosted - version: "2.0.2" - envify_generator: + version: "0.3.0+3" + envied_generator: dependency: "direct dev" description: - name: envify_generator - url: "https://pub.dartlang.org" + name: envied_generator + sha256: dfdbe5dc52863e54c036a4c4042afbdf1bd528cb4c1e638ecba26228ba72e9e5 + url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "0.3.0+3" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.0" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" - source: hosted - version: "6.1.2" - firebase: - dependency: transitive - description: - name: firebase - url: "https://pub.dartlang.org" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" source: hosted - version: "9.0.3" + version: "6.1.4" firebase_analytics: dependency: "direct main" description: name: firebase_analytics - url: "https://pub.dartlang.org" + sha256: "0712a597fe3f9eabc619efdf6419a4880c0a4044ed48558bf984db28ce5e1896" + url: "https://pub.dev" source: hosted - version: "8.3.4" + version: "10.7.3" firebase_analytics_platform_interface: dependency: transitive description: name: firebase_analytics_platform_interface - url: "https://pub.dartlang.org" + sha256: "9a6599a02a67a040f2221656eef16d29112529d16ee0f8dde09e635e891b860b" + url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.8.3" firebase_analytics_web: dependency: transitive description: name: firebase_analytics_web - url: "https://pub.dartlang.org" + sha256: "7d7e181991b1f9d39ff9fcefbcf66281d5dd5994e9c24da0a7a0cc9e9344dcab" + url: "https://pub.dev" source: hosted - version: "0.3.0+1" + version: "0.5.5+10" firebase_core: dependency: "direct main" description: name: firebase_core - url: "https://pub.dartlang.org" + sha256: "070eb6ee4e5087fb7f9e792a328ce1cc3007a932c8fcb519c65d3bd358566264" + url: "https://pub.dev" source: hosted - version: "1.22.0" + version: "2.24.1" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - url: "https://pub.dartlang.org" + sha256: c437ae5d17e6b5cc7981cf6fd458a5db4d12979905f9aafd1fea930428a9fe63 + url: "https://pub.dev" source: hosted - version: "4.5.1" + version: "5.0.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - url: "https://pub.dartlang.org" + sha256: d585bdf3c656c3f7821ba1bd44da5f13365d22fcecaf5eb75c4295246aaa83c0 + url: "https://pub.dev" source: hosted - version: "1.7.2" + version: "2.10.0" firebase_crashlytics: dependency: "direct main" description: name: firebase_crashlytics - url: "https://pub.dartlang.org" + sha256: "1cd997ff1dc3ada2749f25dbe1d29cbf5f63c496d25119f53a9a9ad2e35d343b" + url: "https://pub.dev" source: hosted - version: "2.8.10" + version: "3.4.7" firebase_crashlytics_platform_interface: dependency: transitive description: name: firebase_crashlytics_platform_interface - url: "https://pub.dartlang.org" + sha256: "36063e9cf1e4a4bd7457d89cd839572f30a07615dcb2c8c790dbba5655737969" + url: "https://pub.dev" source: hosted - version: "3.2.16" + version: "3.6.15" fixnum: dependency: transitive description: name: fixnum - url: "https://pub.dartlang.org" + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -328,21 +348,24 @@ packages: dependency: transitive description: name: flutter_spinkit - url: "https://pub.dartlang.org" + sha256: b39c753e909d4796906c5696a14daf33639a76e017136c8d82bf3e620ce5bb8e + url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.2.0" flutter_svg: dependency: "direct main" description: name: flutter_svg - url: "https://pub.dartlang.org" + sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c + url: "https://pub.dev" source: hosted - version: "0.22.0" + version: "2.0.9" flutter_switch: dependency: "direct main" description: name: flutter_switch - url: "https://pub.dartlang.org" + sha256: b91477f926bba135d2d203d7b24367492662d8d9c3aa6adb960b14c1087d3c41 + url: "https://pub.dev" source: hosted version: "0.3.2" flutter_test: @@ -354,9 +377,10 @@ packages: dependency: "direct main" description: name: flutter_vector_icons - url: "https://pub.dartlang.org" + sha256: "20a77e282f8cb438c8edcee4eec85d8497d5f4cbeb07d116e9d2d01c9edfc5e2" + url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "2.0.0" flutter_web_plugins: dependency: transitive description: flutter @@ -366,9 +390,10 @@ packages: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "3.2.0" fuchsia_remote_debug_protocol: dependency: transitive description: flutter @@ -378,366 +403,410 @@ packages: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" google_fonts: dependency: "direct main" description: name: google_fonts - url: "https://pub.dartlang.org" + sha256: "2776c66b3e97c6cdd58d1bd3281548b074b64f1fd5c8f82391f7456e38849567" + url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "4.0.5" graphs: dependency: transitive description: name: graphs - url: "https://pub.dartlang.org" + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.3.1" hive: dependency: "direct main" description: name: hive - url: "https://pub.dartlang.org" + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" source: hosted - version: "1.6.0-nullsafety.2" + version: "2.2.3" html: - dependency: transitive + dependency: "direct main" description: name: html - url: "https://pub.dartlang.org" + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" + url: "https://pub.dev" source: hosted - version: "0.15.0" + version: "0.15.4" http: dependency: transitive description: name: http - url: "https://pub.dartlang.org" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.1.0" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" source: hosted version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.2" intl: dependency: "direct main" description: name: intl - url: "https://pub.dartlang.org" + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.1" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.6.7" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "4.8.1" logger: dependency: "direct main" description: name: logger - url: "https://pub.dartlang.org" + sha256: "6bbb9d6f7056729537a4309bda2e74e18e5d9f14302489cc1e93f33b3fe32cac" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "2.0.2+1" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.2.0" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" source: hosted - version: "0.12.11" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + url: "https://pub.dev" source: hosted - version: "0.1.4" + version: "0.5.0" material_design_icons_flutter: dependency: "direct main" description: name: material_design_icons_flutter - url: "https://pub.dartlang.org" + sha256: "6f986b7a51f3ad4c00e33c5c84e8de1bdd140489bbcdc8b66fc1283dad4dea5a" + url: "https://pub.dev" source: hosted - version: "4.0.5955" + version: "7.0.7296" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + url: "https://pub.dev" source: hosted - version: "1.7.0" + version: "1.10.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.0.4" + mixpanel_flutter: + dependency: "direct main" + description: + name: mixpanel_flutter + sha256: "5dc993ade5eaad51ebb6c91230971a3443ac30a3d1d24399bc3db74c5705d400" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + navigation_builder: + dependency: transitive + description: + name: navigation_builder + sha256: "95e25150191d9cd4e4b86504f33cd9e786d1e6732edb2e3e635bbedc5ef0dea7" + url: "https://pub.dev" + source: hosted + version: "0.0.3" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" source: hosted version: "2.1.0" package_info: dependency: "direct main" description: name: package_info - url: "https://pub.dartlang.org" + sha256: "6c07d9d82c69e16afeeeeb6866fe43985a20b3b50df243091bfc4a4ad2b03b75" + url: "https://pub.dev" source: hosted version: "2.0.2" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" source: hosted - version: "1.8.1" - path_drawing: - dependency: transitive - description: - name: path_drawing - url: "https://pub.dartlang.org" - source: hosted - version: "0.5.1+1" + version: "1.8.3" path_parsing: dependency: transitive description: name: path_parsing - url: "https://pub.dartlang.org" + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" source: hosted - version: "0.2.1" + version: "1.0.1" path_provider: dependency: "direct main" description: name: path_provider - url: "https://pub.dartlang.org" + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.dartlang.org" + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + url: "https://pub.dev" source: hosted - version: "2.0.20" - path_provider_ios: + version: "2.2.1" + path_provider_foundation: dependency: transitive description: - name: path_provider_ios - url: "https://pub.dartlang.org" + name: path_provider_foundation + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.7" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - url: "https://pub.dartlang.org" + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.2.1" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "5.4.0" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 + url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.2" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 + url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.7" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" source: hosted version: "1.5.1" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted version: "4.2.4" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.4" pubspec_parse: dependency: transitive description: name: pubspec_parse - url: "https://pub.dartlang.org" + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.3" ristek_material_component: dependency: "direct main" description: name: ristek_material_component - url: "https://pub.dartlang.org" + sha256: "0f0986bd7113f8d8dfbb6955bfa180764dc6cb151fa3ebd5583aa97f22750de0" + url: "https://pub.dev" source: hosted version: "0.0.15" rxdart: dependency: "direct main" description: name: rxdart - url: "https://pub.dartlang.org" + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" source: hosted - version: "0.27.5" + version: "0.27.7" share: dependency: "direct main" description: name: share - url: "https://pub.dartlang.org" + sha256: "97e6403f564ed1051a01534c2fc919cb6e40ea55e60a18ec23cee6e0ce19f4be" + url: "https://pub.dev" source: hosted version: "2.0.4" shared_preferences: dependency: "direct main" description: name: shared_preferences - url: "https://pub.dartlang.org" + sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.2.2" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - url: "https://pub.dartlang.org" + sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + url: "https://pub.dev" source: hosted - version: "2.0.13" - shared_preferences_ios: + version: "2.2.1" + shared_preferences_foundation: dependency: transitive description: - name: shared_preferences_ios - url: "https://pub.dartlang.org" + name: shared_preferences_foundation + sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.4" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - url: "https://pub.dartlang.org" + sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + url: "https://pub.dev" source: hosted - version: "2.1.1" - shared_preferences_macos: - dependency: transitive - description: - name: shared_preferences_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.4" + version: "2.3.2" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" + sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.3.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - url: "https://pub.dartlang.org" + sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf + url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.2.1" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - url: "https://pub.dartlang.org" + sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.2" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.4.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.0.4" shimmer: dependency: "direct main" description: name: shimmer - url: "https://pub.dartlang.org" + sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9" + url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "3.0.0" sky_engine: dependency: transitive description: flutter @@ -747,254 +816,322 @@ packages: dependency: transitive description: name: source_gen - url: "https://pub.dartlang.org" + sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16 + url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.4.0" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.1" states_rebuilder: dependency: "direct main" description: name: states_rebuilder - url: "https://pub.dartlang.org" + sha256: bf1a5ab5c543acdefce35e60f482eb7ab592339484fe3266d147ee597f18dc92 + url: "https://pub.dev" source: hosted - version: "6.1.0+1" + version: "6.3.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" stream_transform: dependency: transitive description: name: stream_transform - url: "https://pub.dartlang.org" + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" sync_http: dependency: transitive description: name: sync_http - url: "https://pub.dartlang.org" + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.3.1" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + url: "https://pub.dev" source: hosted - version: "0.4.9" + version: "0.6.0" timing: dependency: transitive description: name: timing - url: "https://pub.dartlang.org" + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.1" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.3.2" universal_html: dependency: "direct main" description: name: universal_html - url: "https://pub.dartlang.org" + sha256: "56536254004e24d9d8cfdb7dbbf09b74cf8df96729f38a2f5c238163e3d58971" + url: "https://pub.dev" source: hosted - version: "2.0.8" + version: "2.2.4" universal_io: dependency: transitive description: name: universal_io - url: "https://pub.dartlang.org" + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" + url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.2.2" url_launcher: dependency: "direct main" description: name: url_launcher - url: "https://pub.dartlang.org" + sha256: b1c9e98774adf8820c96fbc7ae3601231d324a7d5ebd8babe27b6dfac91357ba + url: "https://pub.dev" source: hosted - version: "6.1.5" + version: "6.2.1" url_launcher_android: dependency: transitive description: name: url_launcher_android - url: "https://pub.dartlang.org" + sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" + url: "https://pub.dev" source: hosted - version: "6.0.19" + version: "6.2.0" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - url: "https://pub.dartlang.org" + sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3 + url: "https://pub.dev" source: hosted - version: "6.0.17" + version: "6.2.1" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - url: "https://pub.dartlang.org" + sha256: "9f2d390e096fdbe1e6e6256f97851e51afc2d9c423d3432f1d6a02a8a9a8b9fd" + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.1.0" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - url: "https://pub.dartlang.org" + sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.1.0" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - url: "https://pub.dartlang.org" + sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.0" url_launcher_web: dependency: transitive description: name: url_launcher_web - url: "https://pub.dartlang.org" + sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" + url: "https://pub.dev" source: hosted - version: "2.0.13" + version: "2.2.0" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - url: "https://pub.dartlang.org" + sha256: "7754a1ad30ee896b265f8d14078b0513a4dba28d358eabb9d5f339886f4a1adc" + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.1.0" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "0f0c746dd2d6254a0057218ff980fc7f5670fd0fcf5e4db38a490d31eed4ad43" + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "0edf6d630d1bfd5589114138ed8fada3234deacc37966bec033d3047c29248b7" + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: d24333727332d9bd20990f1483af4e09abdb9b1fc7c3db940b56ab5c42790c26 + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" very_good_analysis: dependency: "direct dev" description: name: very_good_analysis - url: "https://pub.dartlang.org" + sha256: "9ae7f3a3bd5764fb021b335ca28a34f040cd0ab6eec00a1b213b445dae58a4b8" + url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "5.1.0" vm_service: dependency: transitive description: name: vm_service - url: "https://pub.dartlang.org" + sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f + url: "https://pub.dev" source: hosted - version: "8.2.2" + version: "11.7.1" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.0" webdriver: dependency: transitive description: name: webdriver - url: "https://pub.dartlang.org" + sha256: "3c923e918918feeb90c4c9fdf1fe39220fa4c0e8e2c0fffaded174498ef86c49" + url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.2" webview_flutter: dependency: "direct main" description: name: webview_flutter - url: "https://pub.dartlang.org" + sha256: "392c1d83b70fe2495de3ea2c84531268d5b8de2de3f01086a53334d8b6030a88" + url: "https://pub.dev" source: hosted - version: "2.8.0" + version: "3.0.4" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - url: "https://pub.dartlang.org" + sha256: "8b3b2450e98876c70bfcead876d9390573b34b9418c19e28168b74f6cb252dbd" + url: "https://pub.dev" source: hosted - version: "2.10.1" + version: "2.10.4" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - url: "https://pub.dartlang.org" + sha256: "812165e4e34ca677bdfbfa58c01e33b27fd03ab5fa75b70832d4b7d4ca1fa8cf" + url: "https://pub.dev" source: hosted - version: "1.9.3" + version: "1.9.5" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - url: "https://pub.dartlang.org" + sha256: a5364369c758892aa487cbf59ea41d9edd10f9d9baf06a94e80f1bd1b4c7bbc0 + url: "https://pub.dev" source: hosted - version: "2.9.4" + version: "2.9.5" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 + url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "5.1.1" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" + url: "https://pub.dev" source: hosted - version: "0.2.0+2" + version: "1.0.3" xml: dependency: transitive description: name: xml - url: "https://pub.dartlang.org" + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + url: "https://pub.dev" source: hosted - version: "5.4.1" + version: "6.3.0" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" sdks: - dart: ">=2.17.0 <3.0.0" - flutter: ">=3.0.0" + dart: ">=3.1.0 <4.0.0" + flutter: ">=3.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index 7588b2f..7e8b275 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,7 +6,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+3 environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=3.0.0 <4.0.0" dependencies: flutter: @@ -15,28 +15,31 @@ dependencies: cupertino_icons: ^1.0.4 ristek_material_component: ^0.0.15 states_rebuilder: ^6.1.0+1 - logger: ^1.0.0 - firebase_analytics: ^8.2.0 - firebase_crashlytics: ^2.4.4 - firebase_core: ^1.10.6 - google_fonts: ^2.2.0 + logger: ^2.0.1 + firebase_analytics: ^10.0.0 + firebase_crashlytics: ^3.0.0 + firebase_core: ^2.0.0 + google_fonts: ^4.0.4 share: ^2.0.4 - hive: ^1.4.4 + hive: ^2.2.3 path_provider: ^2.0.8 rxdart: ^0.27.1 shared_preferences: ^2.0.11 - flutter_svg: ^0.22.0 - intl: ^0.17.0 - webview_flutter: ^2.8.0 + flutter_svg: ^2.0.7 + intl: ^0.18.0 + webview_flutter: ^3.0.0 url_launcher: ^6.0.17 flutter_switch: ^0.3.2 universal_html: ^2.0.8 - dio: ^4.0.4 - material_design_icons_flutter: ^4.0.5955 - flutter_vector_icons: ^1.0.0 + dio: ^4.0.6 + material_design_icons_flutter: ^7.0.7296 + flutter_vector_icons: ^2.0.0 package_info: ^2.0.2 - shimmer: ^2.0.0 - envify: ^2.0.2 + shimmer: ^3.0.0 +# envify: ^2.0.3 + envied: ^0.3.0+3 + html: ^0.15.4 + mixpanel_flutter: ^2.2.0 dev_dependencies: flutter_test: @@ -45,13 +48,14 @@ dev_dependencies: sdk: flutter # Help optimization. - very_good_analysis: ^2.4.0 + very_good_analysis: ^5.0.0+1 # provides a concrete way of generating files using Dart code. - build_runner: ^2.2.0 + build_runner: ^2.4.6 # See envify. - envify_generator: ^2.0.2 +# envify_generator: ^2.0.2 + envied_generator: ^0.3.0+3 flutter: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 4f78848..ec8e8d4 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,9 +6,12 @@ #include "generated_plugin_registrant.h" +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + FirebaseCorePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 88b22e5..02d26c3 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + firebase_core url_launcher_windows )