diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 19de2ad..005d2b7 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -1,12 +1,12 @@ plugins { - id("com.android.application") id("kotlin-android") - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("com.android.application") + id("com.google.gms.google-services") id("dev.flutter.flutter-gradle-plugin") } android { - namespace = "com.example.yimaru_app" + namespace = "com.yimaru.lms.app" compileSdk = flutter.compileSdkVersion ndkVersion = flutter.ndkVersion @@ -15,25 +15,24 @@ android { targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() + kotlin { + compilerOptions { + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) + } } + defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "com.example.yimaru_app" - // You can update the following values to match your application needs. - // For more information, see: https://flutter.dev/to/review-gradle-config. minSdk = flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion + applicationId = "com.yimaru.lms.app" versionCode = flutter.versionCode versionName = flutter.versionName + targetSdk = flutter.targetSdkVersion + } buildTypes { release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. signingConfig = signingConfigs.getByName("debug") } } diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..cd2ee71 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,51 @@ +{ + "project_info": { + "project_number": "574860813475", + "project_id": "yimaru-lms-e834e", + "storage_bucket": "yimaru-lms-e834e.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:574860813475:android:cd7fa6cf3a0527d97acb16", + "android_client_info": { + "package_name": "com.yimaru.lms.app" + } + }, + "oauth_client": [ + { + "client_id": "574860813475-01gh5tk0bu5bgj68r02sgh5pk5greoku.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.yimaru.lms.app", + "certificate_hash": "fc91f52846d27c62bba3e16bc98982fb9953eca1" + } + }, + { + "client_id": "574860813475-631s3mo8ha2qc2jeb5e2aosn0967niik.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.yimaru.lms.app", + "certificate_hash": "928ead08b5e39d6a861a55ae7cceb8c402d1ee7a" + } + } + ], + "api_key": [ + { + "current_key": "AIzaSyC7QlhcuSNte49CERnRKPrQbyLbwErIRmk" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "574860813475-n5o17gpprdqmhcml99tiqhafb17rob0r.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 6561fcc..e39aa8a 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,13 @@ + + + + + + + + + diff --git a/assets/icons/a_2.svg b/assets/icons/a_2.svg new file mode 100644 index 0000000..9bdbd2e --- /dev/null +++ b/assets/icons/a_2.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/b1.svg b/assets/icons/b1.svg deleted file mode 100644 index 4a75083..0000000 --- a/assets/icons/b1.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/assets/icons/b_1.svg b/assets/icons/b_1.svg new file mode 100644 index 0000000..85f988e --- /dev/null +++ b/assets/icons/b_1.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/b_2.svg b/assets/icons/b_2.svg new file mode 100644 index 0000000..40dfb5d --- /dev/null +++ b/assets/icons/b_2.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/profile.png b/assets/images/profile.png index 7d74c01..156251c 100644 Binary files a/assets/images/profile.png and b/assets/images/profile.png differ diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..4d7ff66 --- /dev/null +++ b/firebase.json @@ -0,0 +1 @@ +{"flutter":{"platforms":{"android":{"default":{"projectId":"yimaru-lms-e834e","appId":"1:574860813475:android:cd7fa6cf3a0527d97acb16","fileOutput":"android/app/google-services.json"}},"dart":{"lib/firebase_options.dart":{"projectId":"yimaru-lms-e834e","configurations":{"android":"1:574860813475:android:cd7fa6cf3a0527d97acb16","ios":"1:574860813475:ios:3ac9f7c4ae1771287acb16"}}}}}} \ No newline at end of file diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 79e3510..f72da0a 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -368,7 +368,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.yimaruApp; + PRODUCT_BUNDLE_IDENTIFIER = com.yimaru.lms.app; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -384,7 +384,7 @@ CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.yimaruApp.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = com.yimaru.lms.app.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -401,7 +401,7 @@ CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.yimaruApp.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = com.yimaru.lms.app.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; @@ -416,7 +416,7 @@ CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.yimaruApp.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = com.yimaru.lms.app.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; @@ -547,7 +547,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.yimaruApp; + PRODUCT_BUNDLE_IDENTIFIER = com.yimaru.lms.app; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -569,7 +569,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.yimaruApp; + PRODUCT_BUNDLE_IDENTIFIER = com.yimaru.lms.app; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/lib/app/app.dart b/lib/app/app.dart index cd406ac..50af9db 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -30,6 +30,14 @@ import 'package:yimaru_app/services/status_checker_service.dart'; import 'package:yimaru_app/ui/views/welcome/welcome_view.dart'; import 'package:yimaru_app/ui/views/assessment/assessment_view.dart'; import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart'; +import 'package:yimaru_app/ui/views/failure/failure_view.dart'; +import 'package:yimaru_app/services/permission_handler_service.dart'; +import 'package:yimaru_app/services/image_picker_service.dart'; +import 'package:yimaru_app/services/google_auth_service.dart'; +import 'package:yimaru_app/services/image_downloader_service.dart'; +import 'package:yimaru_app/ui/views/forget_password/forget_password_view.dart'; +import 'package:yimaru_app/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart'; +import 'package:yimaru_app/ui/views/learn_practice/learn_practice_view.dart'; // @stacked-import @StackedApp( @@ -57,6 +65,10 @@ import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart'; MaterialRoute(page: WelcomeView), MaterialRoute(page: AssessmentView), MaterialRoute(page: LearnLessonView), + MaterialRoute(page: FailureView), + MaterialRoute(page: ForgetPasswordView), + MaterialRoute(page: LearnLessonDetailView), + MaterialRoute(page: LearnPracticeView), // @stacked-route ], dependencies: [ @@ -68,6 +80,10 @@ import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart'; LazySingleton(classType: SecureStorageService), LazySingleton(classType: DioService), LazySingleton(classType: StatusCheckerService), + LazySingleton(classType: PermissionHandlerService), + LazySingleton(classType: ImagePickerService), + LazySingleton(classType: GoogleAuthService), + LazySingleton(classType: ImageDownloaderService), // @stacked-service ], bottomsheets: [ diff --git a/lib/app/app.locator.dart b/lib/app/app.locator.dart index 4319ba3..77ac6ff 100644 --- a/lib/app/app.locator.dart +++ b/lib/app/app.locator.dart @@ -14,6 +14,10 @@ import 'package:stacked_shared/stacked_shared.dart'; import '../services/api_service.dart'; import '../services/authentication_service.dart'; import '../services/dio_service.dart'; +import '../services/google_auth_service.dart'; +import '../services/image_downloader_service.dart'; +import '../services/image_picker_service.dart'; +import '../services/permission_handler_service.dart'; import '../services/secure_storage_service.dart'; import '../services/status_checker_service.dart'; @@ -36,4 +40,8 @@ Future setupLocator({ locator.registerLazySingleton(() => SecureStorageService()); locator.registerLazySingleton(() => DioService()); locator.registerLazySingleton(() => StatusCheckerService()); + locator.registerLazySingleton(() => PermissionHandlerService()); + locator.registerLazySingleton(() => ImagePickerService()); + locator.registerLazySingleton(() => GoogleAuthService()); + locator.registerLazySingleton(() => ImageDownloaderService()); } diff --git a/lib/app/app.router.dart b/lib/app/app.router.dart index 871f60e..a6686e2 100644 --- a/lib/app/app.router.dart +++ b/lib/app/app.router.dart @@ -5,24 +5,31 @@ // ************************************************************************** // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:flutter/material.dart' as _i25; +import 'package:flutter/material.dart' as _i29; import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart' as _i1; -import 'package:stacked_services/stacked_services.dart' as _i26; +import 'package:stacked_services/stacked_services.dart' as _i30; import 'package:yimaru_app/ui/views/account_privacy/account_privacy_view.dart' as _i10; import 'package:yimaru_app/ui/views/assessment/assessment_view.dart' as _i23; import 'package:yimaru_app/ui/views/call_support/call_support_view.dart' as _i13; import 'package:yimaru_app/ui/views/downloads/downloads_view.dart' as _i7; +import 'package:yimaru_app/ui/views/failure/failure_view.dart' as _i25; +import 'package:yimaru_app/ui/views/forget_password/forget_password_view.dart' + as _i26; import 'package:yimaru_app/ui/views/home/home_view.dart' as _i2; import 'package:yimaru_app/ui/views/language/language_view.dart' as _i14; import 'package:yimaru_app/ui/views/learn/learn_view.dart' as _i19; import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart' as _i24; +import 'package:yimaru_app/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart' + as _i27; import 'package:yimaru_app/ui/views/learn_level/learn_level_view.dart' as _i20; import 'package:yimaru_app/ui/views/learn_module/learn_module_view.dart' as _i21; +import 'package:yimaru_app/ui/views/learn_practice/learn_practice_view.dart' + as _i28; import 'package:yimaru_app/ui/views/login/login_view.dart' as _i18; import 'package:yimaru_app/ui/views/onboarding/onboarding_view.dart' as _i3; import 'package:yimaru_app/ui/views/ongoing_progress/ongoing_progress_view.dart' @@ -89,6 +96,14 @@ class Routes { static const learnLessonView = '/learn-lesson-view'; + static const failureView = '/failure-view'; + + static const forgetPasswordView = '/forget-password-view'; + + static const learnLessonDetailView = '/learn-lesson-detail-view'; + + static const learnPracticeView = '/learn-practice-view'; + static const all = { homeView, onboardingView, @@ -113,6 +128,10 @@ class Routes { welcomeView, assessmentView, learnLessonView, + failureView, + forgetPasswordView, + learnLessonDetailView, + learnPracticeView, }; } @@ -210,17 +229,33 @@ class StackedRouter extends _i1.RouterBase { Routes.learnLessonView, page: _i24.LearnLessonView, ), + _i1.RouteDef( + Routes.failureView, + page: _i25.FailureView, + ), + _i1.RouteDef( + Routes.forgetPasswordView, + page: _i26.ForgetPasswordView, + ), + _i1.RouteDef( + Routes.learnLessonDetailView, + page: _i27.LearnLessonDetailView, + ), + _i1.RouteDef( + Routes.learnPracticeView, + page: _i28.LearnPracticeView, + ), ]; final _pagesMap = { _i2.HomeView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i2.HomeView(), settings: data, ); }, _i3.OnboardingView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i3.OnboardingView(), settings: data, ); @@ -229,133 +264,159 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const StartupViewArguments(), ); - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => _i4.StartupView(key: args.key, label: args.label), settings: data, ); }, _i5.ProfileView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i5.ProfileView(), settings: data, ); }, _i6.ProfileDetailView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i6.ProfileDetailView(), settings: data, ); }, _i7.DownloadsView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i7.DownloadsView(), settings: data, ); }, _i8.ProgressView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i8.ProgressView(), settings: data, ); }, _i9.OngoingProgressView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i9.OngoingProgressView(), settings: data, ); }, _i10.AccountPrivacyView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i10.AccountPrivacyView(), settings: data, ); }, _i11.SupportView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i11.SupportView(), settings: data, ); }, _i12.TelegramSupportView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i12.TelegramSupportView(), settings: data, ); }, _i13.CallSupportView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i13.CallSupportView(), settings: data, ); }, _i14.LanguageView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i14.LanguageView(), settings: data, ); }, _i15.PrivacyPolicyView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i15.PrivacyPolicyView(), settings: data, ); }, _i16.TermsAndConditionsView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i16.TermsAndConditionsView(), settings: data, ); }, _i17.RegisterView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i17.RegisterView(), settings: data, ); }, _i18.LoginView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i18.LoginView(), settings: data, ); }, _i19.LearnView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i19.LearnView(), settings: data, ); }, _i20.LearnLevelView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i20.LearnLevelView(), settings: data, ); }, _i21.LearnModuleView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i21.LearnModuleView(), settings: data, ); }, _i22.WelcomeView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i22.WelcomeView(), settings: data, ); }, _i23.AssessmentView: (data) { final args = data.getArgs(nullOk: false); - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => _i23.AssessmentView(key: args.key, data: args.data), settings: data, ); }, _i24.LearnLessonView: (data) { - return _i25.MaterialPageRoute( + return _i29.MaterialPageRoute( builder: (context) => const _i24.LearnLessonView(), settings: data, ); }, + _i25.FailureView: (data) { + final args = data.getArgs(nullOk: false); + return _i29.MaterialPageRoute( + builder: (context) => + _i25.FailureView(key: args.key, label: args.label), + settings: data, + ); + }, + _i26.ForgetPasswordView: (data) { + return _i29.MaterialPageRoute( + builder: (context) => const _i26.ForgetPasswordView(), + settings: data, + ); + }, + _i27.LearnLessonDetailView: (data) { + return _i29.MaterialPageRoute( + builder: (context) => const _i27.LearnLessonDetailView(), + settings: data, + ); + }, + _i28.LearnPracticeView: (data) { + return _i29.MaterialPageRoute( + builder: (context) => const _i28.LearnPracticeView(), + settings: data, + ); + }, }; @override @@ -371,7 +432,7 @@ class StartupViewArguments { this.label = 'Loading', }); - final _i25.Key? key; + final _i29.Key? key; final String label; @@ -398,7 +459,7 @@ class AssessmentViewArguments { required this.data, }); - final _i25.Key? key; + final _i29.Key? key; final Map data; @@ -419,7 +480,34 @@ class AssessmentViewArguments { } } -extension NavigatorStateExtension on _i26.NavigationService { +class FailureViewArguments { + const FailureViewArguments({ + this.key, + required this.label, + }); + + final _i29.Key? key; + + final String label; + + @override + String toString() { + return '{"key": "$key", "label": "$label"}'; + } + + @override + bool operator ==(covariant FailureViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && other.label == label; + } + + @override + int get hashCode { + return key.hashCode ^ label.hashCode; + } +} + +extension NavigatorStateExtension on _i30.NavigationService { Future navigateToHomeView([ int? routerId, bool preventDuplicates = true, @@ -449,7 +537,7 @@ extension NavigatorStateExtension on _i26.NavigationService { } Future navigateToStartupView({ - _i25.Key? key, + _i29.Key? key, String label = 'Loading', int? routerId, bool preventDuplicates = true, @@ -718,7 +806,7 @@ extension NavigatorStateExtension on _i26.NavigationService { } Future navigateToAssessmentView({ - _i25.Key? key, + _i29.Key? key, required Map data, int? routerId, bool preventDuplicates = true, @@ -748,6 +836,65 @@ extension NavigatorStateExtension on _i26.NavigationService { transition: transition); } + Future navigateToFailureView({ + _i29.Key? key, + required String label, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo(Routes.failureView, + arguments: FailureViewArguments(key: key, label: label), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToForgetPasswordView([ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + ]) async { + return navigateTo(Routes.forgetPasswordView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToLearnLessonDetailView([ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + ]) async { + return navigateTo(Routes.learnLessonDetailView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToLearnPracticeView([ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + ]) async { + return navigateTo(Routes.learnPracticeView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + Future replaceWithHomeView([ int? routerId, bool preventDuplicates = true, @@ -777,7 +924,7 @@ extension NavigatorStateExtension on _i26.NavigationService { } Future replaceWithStartupView({ - _i25.Key? key, + _i29.Key? key, String label = 'Loading', int? routerId, bool preventDuplicates = true, @@ -1046,7 +1193,7 @@ extension NavigatorStateExtension on _i26.NavigationService { } Future replaceWithAssessmentView({ - _i25.Key? key, + _i29.Key? key, required Map data, int? routerId, bool preventDuplicates = true, @@ -1075,4 +1222,63 @@ extension NavigatorStateExtension on _i26.NavigationService { parameters: parameters, transition: transition); } + + Future replaceWithFailureView({ + _i29.Key? key, + required String label, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return replaceWith(Routes.failureView, + arguments: FailureViewArguments(key: key, label: label), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithForgetPasswordView([ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + ]) async { + return replaceWith(Routes.forgetPasswordView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithLearnLessonDetailView([ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + ]) async { + return replaceWith(Routes.learnLessonDetailView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithLearnPracticeView([ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + ]) async { + return replaceWith(Routes.learnPracticeView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } } diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart new file mode 100644 index 0000000..f2470b8 --- /dev/null +++ b/lib/firebase_options.dart @@ -0,0 +1,70 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: type=lint +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for web - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return android; + case TargetPlatform.iOS: + return ios; + case TargetPlatform.macOS: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for macos - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.windows: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for windows - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'AIzaSyC7QlhcuSNte49CERnRKPrQbyLbwErIRmk', + appId: '1:574860813475:android:cd7fa6cf3a0527d97acb16', + messagingSenderId: '574860813475', + projectId: 'yimaru-lms-e834e', + storageBucket: 'yimaru-lms-e834e.firebasestorage.app', + ); + + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyBBcQ17JB6RBTjD7G7mh6Xf_FMUGxP5cC8', + appId: '1:574860813475:ios:3ac9f7c4ae1771287acb16', + messagingSenderId: '574860813475', + projectId: 'yimaru-lms-e834e', + storageBucket: 'yimaru-lms-e834e.firebasestorage.app', + androidClientId: + '574860813475-01gh5tk0bu5bgj68r02sgh5pk5greoku.apps.googleusercontent.com', + iosBundleId: 'com.yimaru.lms.app', + ); +} diff --git a/lib/models/assessment.dart b/lib/models/assessment.dart index e1cc5e5..9a6da65 100644 --- a/lib/models/assessment.dart +++ b/lib/models/assessment.dart @@ -1,17 +1,35 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:yimaru_app/models/option.dart'; -import 'package:yimaru_app/models/question.dart'; part 'assessment.g.dart'; @JsonSerializable() class Assessment { - @JsonKey(name: 'Question') - final Question? question; + final int? id; + + final int? points; + + final String? status; + + @JsonKey(name: 'question_type') + final String? questionType; + + @JsonKey(name: 'question_text') + final String? questionText; + + @JsonKey(name: 'difficulty_level') + final String? difficultyLevel; - @JsonKey(name: 'Options') final List