diff --git a/lib/app/app.router.dart b/lib/app/app.router.dart index a6686e2..ee9993e 100644 --- a/lib/app/app.router.dart +++ b/lib/app/app.router.dart @@ -412,8 +412,13 @@ class StackedRouter extends _i1.RouterBase { ); }, _i28.LearnPracticeView: (data) { + final args = data.getArgs(nullOk: false); return _i29.MaterialPageRoute( - builder: (context) => const _i28.LearnPracticeView(), + builder: (context) => _i28.LearnPracticeView( + key: args.key, + title: args.title, + subtitle: args.subtitle, + buttonLabel: args.buttonLabel), settings: data, ); }, @@ -507,6 +512,45 @@ class FailureViewArguments { } } +class LearnPracticeViewArguments { + const LearnPracticeViewArguments({ + this.key, + required this.title, + required this.subtitle, + required this.buttonLabel, + }); + + final _i29.Key? key; + + final String title; + + final String subtitle; + + final String buttonLabel; + + @override + String toString() { + return '{"key": "$key", "title": "$title", "subtitle": "$subtitle", "buttonLabel": "$buttonLabel"}'; + } + + @override + bool operator ==(covariant LearnPracticeViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && + other.title == title && + other.subtitle == subtitle && + other.buttonLabel == buttonLabel; + } + + @override + int get hashCode { + return key.hashCode ^ + title.hashCode ^ + subtitle.hashCode ^ + buttonLabel.hashCode; + } +} + extension NavigatorStateExtension on _i30.NavigationService { Future navigateToHomeView([ int? routerId, @@ -881,14 +925,23 @@ extension NavigatorStateExtension on _i30.NavigationService { transition: transition); } - Future navigateToLearnPracticeView([ + Future navigateToLearnPracticeView({ + _i29.Key? key, + required String title, + required String subtitle, + required String buttonLabel, int? routerId, bool preventDuplicates = true, Map? parameters, Widget Function(BuildContext, Animation, Animation, Widget)? transition, - ]) async { + }) async { return navigateTo(Routes.learnPracticeView, + arguments: LearnPracticeViewArguments( + key: key, + title: title, + subtitle: subtitle, + buttonLabel: buttonLabel), id: routerId, preventDuplicates: preventDuplicates, parameters: parameters, @@ -1268,14 +1321,23 @@ extension NavigatorStateExtension on _i30.NavigationService { transition: transition); } - Future replaceWithLearnPracticeView([ + Future replaceWithLearnPracticeView({ + _i29.Key? key, + required String title, + required String subtitle, + required String buttonLabel, int? routerId, bool preventDuplicates = true, Map? parameters, Widget Function(BuildContext, Animation, Animation, Widget)? transition, - ]) async { + }) async { return replaceWith(Routes.learnPracticeView, + arguments: LearnPracticeViewArguments( + key: key, + title: title, + subtitle: subtitle, + buttonLabel: buttonLabel), id: routerId, preventDuplicates: preventDuplicates, parameters: parameters, diff --git a/lib/models/user_model.dart b/lib/models/user_model.dart index ce6dced..86af957 100644 --- a/lib/models/user_model.dart +++ b/lib/models/user_model.dart @@ -12,12 +12,10 @@ class UserModel { final String? country; - final String? occupation; final bool? userInfoLoaded; - @JsonKey(name: 'user_id') final int? userId; @@ -55,7 +53,7 @@ class UserModel { this.accessToken, this.refreshToken, this.profilePicture, - this.userInfoLoaded , + this.userInfoLoaded, this.profileCompleted, }); diff --git a/lib/models/user_model.g.dart b/lib/models/user_model.g.dart index 2f20493..e52ef39 100644 --- a/lib/models/user_model.g.dart +++ b/lib/models/user_model.g.dart @@ -19,8 +19,8 @@ UserModel _$UserModelFromJson(Map json) => UserModel( accessToken: json['access_token'] as String?, refreshToken: json['refresh_token'] as String?, profilePicture: json['profile_picture_url'] as String?, + userInfoLoaded: json['userInfoLoaded'] as bool?, profileCompleted: json['profile_completed'] as bool?, - userInfoLoaded: json['userInfoLoaded'] as bool? ?? false, ); Map _$UserModelToJson(UserModel instance) => { diff --git a/lib/services/api_service.dart b/lib/services/api_service.dart index 4ad59da..ee9e687 100644 --- a/lib/services/api_service.dart +++ b/lib/services/api_service.dart @@ -11,7 +11,8 @@ class ApiService { final _service = locator(); // Register - Future> registerWithEmail(Map data) async { + Future> registerWithEmail( + Map data) async { try { Response response = await _service.dio.post( '$kBaseUrl/$kUserUrl/$kRegisterUrl', diff --git a/lib/services/authentication_service.dart b/lib/services/authentication_service.dart index b409316..cb56a97 100644 --- a/lib/services/authentication_service.dart +++ b/lib/services/authentication_service.dart @@ -37,7 +37,6 @@ class AuthenticationService with ListenableServiceMixin { await _secureService.setString('refreshToken', refresh); } - Future saveUserCredential(Map data) async { await _secureService.setInt('userId', data['userId']); await _secureService.setString('accessToken', data['accessToken']); @@ -71,8 +70,8 @@ class AuthenticationService with ListenableServiceMixin { notifyListeners(); } - Future saveProfileImage(String image) async { - await _secureService.setString('profileImage', image); + Future saveProfilePicture(String image) async { + await _secureService.setString('profilePicture', image); _user = UserModel( email: _user?.email, gender: _user?.gender, @@ -87,7 +86,7 @@ class AuthenticationService with ListenableServiceMixin { refreshToken: _user?.refreshToken, profileCompleted: _user?.profileCompleted, userInfoLoaded: _user?.userInfoLoaded ?? false, - profilePicture: await _secureService.getString('profileImage'), + profilePicture: await _secureService.getString('profilePicture'), ); notifyListeners(); @@ -175,8 +174,8 @@ class AuthenticationService with ListenableServiceMixin { occupation: await _secureService.getString('occupation'), accessToken: await _secureService.getString('accessToken'), refreshToken: await _secureService.getString('refreshToken'), - profilePicture: await _secureService.getString('profileImage'), userInfoLoaded: await _secureService.getBool('userInfoLoaded'), + profilePicture: await _secureService.getString('profilePicture'), profileCompleted: await _secureService.getBool('profileCompleted'), ); return _user; diff --git a/lib/ui/common/app_colors.dart b/lib/ui/common/app_colors.dart index 3308842..2c70916 100644 --- a/lib/ui/common/app_colors.dart +++ b/lib/ui/common/app_colors.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; const Color kcBlack = Colors.black; const Color kcRed = Color(0xffFF4C4C); +const Color kcBlue = Color(0xff135BEC); const Color kcGreen = Color(0xFF1DE964); const Color kcBackgroundColor = kcWhite; const Color kcWhite = Color(0xFFFFFFFF); diff --git a/lib/ui/common/enmus.dart b/lib/ui/common/enmus.dart index 80a8eb4..f7071a9 100644 --- a/lib/ui/common/enmus.dart +++ b/lib/ui/common/enmus.dart @@ -11,6 +11,7 @@ enum ProficiencyLevels { a1, a2, b1, b2, none } // State object enum StateObjects { + homeView, verifyOtp, resendOtp, profileImage, diff --git a/lib/ui/common/ui_helpers.dart b/lib/ui/common/ui_helpers.dart index 32e43da..8484829 100644 --- a/lib/ui/common/ui_helpers.dart +++ b/lib/ui/common/ui_helpers.dart @@ -178,6 +178,12 @@ TextStyle style18P600 = const TextStyle( fontWeight: FontWeight.w600, ); +TextStyle style16W600 = const TextStyle( + fontSize: 16, + color: kcWhite, + fontWeight: FontWeight.w600, +); + TextStyle style18W600 = const TextStyle( fontSize: 18, color: kcWhite, @@ -190,6 +196,12 @@ TextStyle style25W600 = const TextStyle( fontWeight: FontWeight.w600, ); +TextStyle style12RP600 = const TextStyle( + fontSize: 12, + color: kcPrimaryColor, + fontWeight: FontWeight.w600, +); + TextStyle style12R700 = const TextStyle( fontSize: 12, @@ -197,10 +209,19 @@ TextStyle style12R700 = const TextStyle( fontWeight: FontWeight.w700, ); +TextStyle style12DG400 = const TextStyle( + fontSize: 12, + color: kcDarkGrey, +); + TextStyle style14P400 = const TextStyle( color: kcPrimaryColor, ); +TextStyle style14B400 = const TextStyle( + color: kcBlue, +); + TextStyle style14P600 = const TextStyle( color: kcPrimaryColor, fontWeight: FontWeight.w600, @@ -224,6 +245,12 @@ TextStyle style16DG600 = const TextStyle( fontWeight: FontWeight.w600, ); +TextStyle style16B600 = const TextStyle( + fontSize: 16, + color: kcBlue, + fontWeight: FontWeight.w600, +); + TextStyle style18DG500 = const TextStyle( fontSize: 18, color: kcDarkGrey, diff --git a/lib/ui/views/account_privacy/account_privacy_view.dart b/lib/ui/views/account_privacy/account_privacy_view.dart index a9cfbbc..761e83e 100644 --- a/lib/ui/views/account_privacy/account_privacy_view.dart +++ b/lib/ui/views/account_privacy/account_privacy_view.dart @@ -57,8 +57,9 @@ class AccountPrivacyView extends StackedView { ); Widget _buildAppbar(AccountPrivacyViewModel viewModel) => SmallAppBar( - title: 'Account Privacy', + showBackButton: true, onTap: viewModel.pop, + title: 'Account Privacy', ); Widget _buildContentWrapper(AccountPrivacyViewModel viewModel) => diff --git a/lib/ui/views/assessment/assessment_viewmodel.dart b/lib/ui/views/assessment/assessment_viewmodel.dart index 52dd973..c1ab7e6 100644 --- a/lib/ui/views/assessment/assessment_viewmodel.dart +++ b/lib/ui/views/assessment/assessment_viewmodel.dart @@ -235,7 +235,7 @@ class AssessmentViewModel extends BaseViewModel { await _navigationService.navigateToLanguageView(); Future replaceWithHome() async => - await _navigationService.clearStackAndShowView(const HomeView()); + await _navigationService.clearStackAndShow(Routes.homeView); // Remote api call Future getAssessments() async => await runBusyFuture(_getAssessments()); diff --git a/lib/ui/views/call_support/call_support_view.dart b/lib/ui/views/call_support/call_support_view.dart index 68d3cc3..2394c02 100644 --- a/lib/ui/views/call_support/call_support_view.dart +++ b/lib/ui/views/call_support/call_support_view.dart @@ -50,8 +50,9 @@ class CallSupportView extends StackedView { ); Widget _buildAppbar(CallSupportViewModel viewModel) => SmallAppBar( - title: 'Call Support', + showBackButton: true, onTap: viewModel.pop, + title: 'Call Support', ); Widget _buildExpandedColumn(CallSupportViewModel viewModel) => diff --git a/lib/ui/views/downloads/downloads_view.dart b/lib/ui/views/downloads/downloads_view.dart index ec37b00..b1d5ce8 100644 --- a/lib/ui/views/downloads/downloads_view.dart +++ b/lib/ui/views/downloads/downloads_view.dart @@ -54,8 +54,9 @@ class DownloadsView extends StackedView { ]; Widget _buildAppbar(DownloadsViewModel viewModel) => SmallAppBar( - title: 'Offline Downloads', onTap: viewModel.pop, + showBackButton: true, + title: 'Offline Downloads', ); Widget _buildContentWrapper(DownloadsViewModel viewModel) => diff --git a/lib/ui/views/forget_password/forget_password_view.dart b/lib/ui/views/forget_password/forget_password_view.dart index 312b9ec..d4f039d 100644 --- a/lib/ui/views/forget_password/forget_password_view.dart +++ b/lib/ui/views/forget_password/forget_password_view.dart @@ -29,8 +29,6 @@ class ForgetPasswordView extends StackedView confirmPasswordController.clear(); } - - void _clearDataOnNavigation(ForgetPasswordViewModel viewModel) { if (viewModel.currentPage == 0) { emailController.clear(); @@ -77,10 +75,6 @@ class ForgetPasswordView extends StackedView _pop(value: value, viewModel: viewModel), child: _buildBody(viewModel)); - - - - Widget _buildBody(ForgetPasswordViewModel viewModel) => IndexedStack(index: viewModel.currentPage, children: _buildScreens()); @@ -96,6 +90,4 @@ class ForgetPasswordView extends StackedView passwordController: passwordController, resetCodeController: resetCodeController, confirmPasswordController: confirmPasswordController); - - } diff --git a/lib/ui/views/forget_password/forget_password_viewmodel.dart b/lib/ui/views/forget_password/forget_password_viewmodel.dart index 320c2fd..6274535 100644 --- a/lib/ui/views/forget_password/forget_password_viewmodel.dart +++ b/lib/ui/views/forget_password/forget_password_viewmodel.dart @@ -3,6 +3,7 @@ import 'package:stacked_services/stacked_services.dart'; import 'package:yimaru_app/ui/views/login/login_view.dart'; import '../../../app/app.locator.dart'; +import '../../../app/app.router.dart'; import '../../../services/api_service.dart'; import '../../../services/status_checker_service.dart'; import '../../common/enmus.dart'; @@ -190,7 +191,7 @@ class ForgetPasswordViewModel extends FormViewModel { void pop() => _navigationService.back(); Future replaceWithLogin() async => - await _navigationService.clearStackAndShowView(const LoginView()); + await _navigationService.clearStackAndShow(Routes.loginView); // Remote api calls diff --git a/lib/ui/views/forget_password/screens/request_reset_code_screen.dart b/lib/ui/views/forget_password/screens/request_reset_code_screen.dart index d4b9f09..077b796 100644 --- a/lib/ui/views/forget_password/screens/request_reset_code_screen.dart +++ b/lib/ui/views/forget_password/screens/request_reset_code_screen.dart @@ -20,10 +20,11 @@ class RequestCodeScreen extends ViewModelWidget { required this.emailController, }); - - Widget getPadding(context){ - double half = screenHeight(context)/2; - return SizedBox(height: half + 375 - half,); + Widget getPadding(context) { + double half = screenHeight(context) / 2; + return SizedBox( + height: half + 375 - half, + ); } void _inAppPop(ForgetPasswordViewModel viewModel) { @@ -32,9 +33,8 @@ class RequestCodeScreen extends ViewModelWidget { } void _clearDataOnNavigation(ForgetPasswordViewModel viewModel) { - emailController.clear(); - viewModel.resetRequestResetCodeScreen(); - + emailController.clear(); + viewModel.resetRequestResetCodeScreen(); } Future _addUserData(ForgetPasswordViewModel viewModel) async { @@ -48,69 +48,89 @@ class RequestCodeScreen extends ViewModelWidget { await viewModel.requestResetCode(); } - @override Widget build(BuildContext context, ForgetPasswordViewModel viewModel) => _buildScaffoldWrapper(context: context, viewModel: viewModel); - Widget _buildScaffoldWrapper( {required BuildContext context, - required ForgetPasswordViewModel viewModel}) => Scaffold( - backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(context: context, viewModel: viewModel), - ); + Widget _buildScaffoldWrapper( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => + Scaffold( + backgroundColor: kcBackgroundColor, + body: _buildScaffoldStack(context: context, viewModel: viewModel), + ); - Widget _buildScaffoldStack( {required BuildContext context, - required ForgetPasswordViewModel viewModel}) => Stack( - children: [ - _buildScaffold(context: context,viewModel: viewModel), - _buildRequestResetCodeState(viewModel), - ], - ); + Widget _buildScaffoldStack( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => + Stack( + children: [ + _buildScaffold(context: context, viewModel: viewModel), + _buildRequestResetCodeState(viewModel), + ], + ); - Widget _buildScaffold( {required BuildContext context, - required ForgetPasswordViewModel viewModel}) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: _buildScaffoldChildren(context: context, viewModel: viewModel), - ); + Widget _buildScaffold( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + _buildScaffoldChildren(context: context, viewModel: viewModel), + ); - List _buildScaffoldChildren( {required BuildContext context, - required ForgetPasswordViewModel viewModel}) => - [_buildAppBar(viewModel), _buildExpandedBody(context: context, viewModel: viewModel)]; + List _buildScaffoldChildren( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => + [ + _buildAppBar(viewModel), + _buildExpandedBody(context: context, viewModel: viewModel) + ]; - Widget _buildAppBar(ForgetPasswordViewModel viewModel) => LargeAppBar( - showBackButton: true, - showLanguageSelection: true, - onPop: () => _inAppPop(viewModel), - ); + Widget _buildAppBar(ForgetPasswordViewModel viewModel) => LargeAppBar( + showBackButton: true, + showLanguageSelection: true, + onPop: () => _inAppPop(viewModel), + ); - Widget _buildExpandedBody( {required BuildContext context, - required ForgetPasswordViewModel viewModel}) => - Expanded(child: _buildColumnScroller(context: context, viewModel: viewModel)); + Widget _buildExpandedBody( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => + Expanded( + child: _buildColumnScroller(context: context, viewModel: viewModel)); - Widget _buildColumnScroller( {required BuildContext context, - required ForgetPasswordViewModel viewModel}) => + Widget _buildColumnScroller( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => SingleChildScrollView( child: _buildBodyWrapper(context: context, viewModel: viewModel), ); - Widget _buildBodyWrapper( {required BuildContext context, - required ForgetPasswordViewModel viewModel}) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 15), - child: _buildBody(context: context, viewModel: viewModel), - ); - - Widget _buildBody( {required BuildContext context, - required ForgetPasswordViewModel viewModel}) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: _buildBodyChildren(context: context, viewModel: viewModel), - ); - - List _buildBodyChildren( {required BuildContext context, - required ForgetPasswordViewModel viewModel}) => - [_buildUpperColumn(viewModel),getPadding(context), _buildContinueButtonWrapper(viewModel)]; + Widget _buildBodyWrapper( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildBody(context: context, viewModel: viewModel), + ); + Widget _buildBody( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _buildBodyChildren(context: context, viewModel: viewModel), + ); + List _buildBodyChildren( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => + [ + _buildUpperColumn(viewModel), + getPadding(context), + _buildContinueButtonWrapper(viewModel) + ]; Widget _buildUpperColumn(ForgetPasswordViewModel viewModel) => Column( mainAxisSize: MainAxisSize.min, diff --git a/lib/ui/views/forget_password/screens/reset_password_screen.dart b/lib/ui/views/forget_password/screens/reset_password_screen.dart index e5e19ef..eb3e47e 100644 --- a/lib/ui/views/forget_password/screens/reset_password_screen.dart +++ b/lib/ui/views/forget_password/screens/reset_password_screen.dart @@ -31,12 +31,10 @@ class ResetPasswordScreen extends ViewModelWidget { } void _clearDataOnNavigation(ForgetPasswordViewModel viewModel) { - - passwordController.clear(); - resetCodeController.clear(); - confirmPasswordController.clear(); - viewModel.resetResetPasswordScreen(); - + passwordController.clear(); + resetCodeController.clear(); + confirmPasswordController.clear(); + viewModel.resetResetPasswordScreen(); } Future _reset(ForgetPasswordViewModel viewModel) async { @@ -55,56 +53,56 @@ class ResetPasswordScreen extends ViewModelWidget { Widget build(BuildContext context, ForgetPasswordViewModel viewModel) => _buildScaffoldWrapper(context: context, viewModel: viewModel); - Widget _buildScaffoldWrapper( {required BuildContext context, - required ForgetPasswordViewModel viewModel}) => Scaffold( - backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(context: context, viewModel: viewModel), - ); + Widget _buildScaffoldWrapper( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => + Scaffold( + backgroundColor: kcBackgroundColor, + body: _buildScaffoldStack(context: context, viewModel: viewModel), + ); - Widget _buildScaffoldStack( {required BuildContext context, - required ForgetPasswordViewModel viewModel}) => Stack( - children: [ - _buildScaffold(viewModel), - _buildResetPasswordState(viewModel), - ], - ); + Widget _buildScaffoldStack( + {required BuildContext context, + required ForgetPasswordViewModel viewModel}) => + Stack( + children: [ + _buildScaffold(viewModel), + _buildResetPasswordState(viewModel), + ], + ); - Widget _buildScaffold( ForgetPasswordViewModel viewModel) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: _buildScaffoldChildren(viewModel), - ); + Widget _buildScaffold(ForgetPasswordViewModel viewModel) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: _buildScaffoldChildren(viewModel), + ); - List _buildScaffoldChildren( ForgetPasswordViewModel viewModel) => + List _buildScaffoldChildren(ForgetPasswordViewModel viewModel) => [_buildAppBar(viewModel), _buildExpandedBody(viewModel)]; - Widget _buildAppBar(ForgetPasswordViewModel viewModel) => LargeAppBar( - showBackButton: true, - showLanguageSelection: true, - onPop: () => _inAppPop(viewModel), - ); + Widget _buildAppBar(ForgetPasswordViewModel viewModel) => LargeAppBar( + showBackButton: true, + showLanguageSelection: true, + onPop: () => _inAppPop(viewModel), + ); - Widget _buildExpandedBody( ForgetPasswordViewModel viewModel) => + Widget _buildExpandedBody(ForgetPasswordViewModel viewModel) => Expanded(child: _buildColumnScroller(viewModel)); - Widget _buildColumnScroller( ForgetPasswordViewModel viewModel) => + Widget _buildColumnScroller(ForgetPasswordViewModel viewModel) => SingleChildScrollView( child: _buildBodyWrapper(viewModel), ); - Widget _buildBodyWrapper( ForgetPasswordViewModel viewModel) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 15), - child: _buildBody(viewModel), - ); + Widget _buildBodyWrapper(ForgetPasswordViewModel viewModel) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildBody(viewModel), + ); Widget _buildBody(ForgetPasswordViewModel viewModel) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: _buildBodyColumnChildren(viewModel), - ); - - - - + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _buildBodyColumnChildren(viewModel), + ); List _buildBodyColumnChildren(ForgetPasswordViewModel viewModel) => [ verticalSpaceMedium, diff --git a/lib/ui/views/home/home_view.dart b/lib/ui/views/home/home_view.dart index ce8a1e9..5ec3a05 100644 --- a/lib/ui/views/home/home_view.dart +++ b/lib/ui/views/home/home_view.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; import 'package:stacked/stacked.dart'; import 'package:yimaru_app/ui/common/app_colors.dart'; +import 'package:yimaru_app/ui/common/enmus.dart'; import 'package:yimaru_app/ui/views/learn/learn_view.dart'; import 'package:yimaru_app/ui/views/profile/profile_view.dart'; import 'package:yimaru_app/ui/views/startup/startup_view.dart'; @@ -16,19 +18,22 @@ class HomeView extends StackedView { @override void onViewModelReady(HomeViewModel viewModel) async { - await viewModel.getProfileStatus(); - await viewModel.getProfileData(); + await _init(viewModel); super.onViewModelReady(viewModel); } + Future _init(HomeViewModel viewModel) async => + await viewModel.initialize(); + @override Widget builder( BuildContext context, HomeViewModel viewModel, Widget? child) => _buildScaffoldWrapper(viewModel); - Widget _buildScaffoldWrapper(HomeViewModel viewModel) => viewModel.isBusy - ? const StartupView(label: 'Checking user info') - : _buildScaffold(viewModel); + Widget _buildScaffoldWrapper(HomeViewModel viewModel) => + viewModel.busy(StateObjects.homeView) + ? const StartupView(label: 'Checking user info') + : _buildScaffold(viewModel); Widget _buildScaffold(HomeViewModel viewModel) => Scaffold( body: getViewForIndex(viewModel.currentIndex), diff --git a/lib/ui/views/home/home_viewmodel.dart b/lib/ui/views/home/home_viewmodel.dart index 524e616..bb84db0 100644 --- a/lib/ui/views/home/home_viewmodel.dart +++ b/lib/ui/views/home/home_viewmodel.dart @@ -37,6 +37,7 @@ class HomeViewModel extends ReactiveViewModel { int get currentIndex => _currentIndex; + // Bottom navigation void setCurrentIndex(int index) { _currentIndex = index; rebuildUi(); @@ -63,72 +64,76 @@ class HomeViewModel extends ReactiveViewModel { // Navigation Future replaceWithFailure() async => - await _navigationService.clearStackAndShowView( - const FailureView(label: 'Check your internet connection to proceed'), - ); + await _navigationService.clearStackAndShow(Routes.failureView, + arguments: 'Check your internet connection to proceed'); Future replaceWithOnboarding() async => await _navigationService.replaceWithOnboardingView(); // Remote api calls + // Initialize user data + Future initialize() async => + await runBusyFuture(_initialize(), busyObject: StateObjects.homeView); + + Future _initialize() async { + await _getProfileStatus(); + await _getProfileData(); + } + + // Profile status + Future _getProfileStatus() async { + Map response = {}; + if (_user?.profileCompleted == null) { + if (await _statusChecker.checkConnection()) { + print('BREAK-POINT 1'); + response = await _apiService.getProfileStatus(_user); + } else { + print('BREAK-POINT 2'); + await replaceWithFailure(); + } + } else if (!(_user?.profileCompleted ?? false)) { + print('BREAK-POINT 3'); + response = {'data': false, 'status': ResponseStatus.success}; + } else { + print('BREAK-POINT 4'); + response = {'data': true, 'status': ResponseStatus.success}; + } + + if (response['status'] == ResponseStatus.success && !response['data']) { + print('BREAK-POINT 5'); + await replaceWithOnboarding(); + } else if (response['status'] == ResponseStatus.success && + response['data']) { + print('BREAK-POINT 6'); + await saveProfileStatus(response['data']); + } + } + // Profile data - Future getProfileData() async => await runBusyFuture(_getProfileData()); Future _getProfileData() async { - print('RESPONSE FOR USER DATA ${_user?.firstName}'); - if (!(_user?.userInfoLoaded ?? false)) { - print('RESPONSE FOR USER DATA 1'); - if (await _statusChecker.checkConnection()) { - Map response = {}; + Map response = {}; + print('BREAK-POINT: Profile-Completed ${_user?.profileCompleted}'); - if (_user?.profileCompleted != null && - (_user?.profileCompleted ?? false)) { - if (await _statusChecker.checkConnection()) { - response = await _apiService.getProfileData(_user?.userId); + if (_user?.profileCompleted != null && + (_user?.profileCompleted ?? false)) { + if (await _statusChecker.checkConnection()) { + response = await _apiService.getProfileData(_user?.userId); - if (response['status'] == ResponseStatus.success) { - UserModel user = response['data'] as UserModel; + if (response['status'] == ResponseStatus.success) { + print('BREAK-POINT 8'); - String image = - await _imageDownloaderService.downloader(user.profilePicture); + UserModel user = response['data'] as UserModel; - await _authenticationService.saveUserData( - image: image, data: user); - } + String image = + await _imageDownloaderService.downloader(user.profilePicture); + + await _authenticationService.saveUserData(image: image, data: user); } } } } } - - // Profile status - Future getProfileStatus() async => - await runBusyFuture(_getProfileStatus()); - - Future _getProfileStatus() async { - if (await _statusChecker.checkConnection()) { - Map response = {}; - - if (_user?.profileCompleted == null) { - if (await _statusChecker.checkConnection()) { - response = await _apiService.getProfileStatus(_user); - } else { - await replaceWithFailure(); - } - } else if (!(_user?.profileCompleted ?? false)) { - response = {'data': false, 'status': ResponseStatus.success}; - } else { - response = {'data': true, 'status': ResponseStatus.success}; - } - - if (response['status'] == ResponseStatus.success && !response['data']) { - await replaceWithOnboarding(); - } else if (response['status'] == ResponseStatus.success && - response['data']) { - await saveProfileStatus(response['data']); - } - } - } } diff --git a/lib/ui/views/language/language_view.dart b/lib/ui/views/language/language_view.dart index 4db2aec..791145e 100644 --- a/lib/ui/views/language/language_view.dart +++ b/lib/ui/views/language/language_view.dart @@ -72,6 +72,7 @@ class LanguageView extends StackedView { ); Widget _buildAppbar(LanguageViewModel viewModel) => SmallAppBar( + showBackButton: true, onTap: viewModel.pop, title: 'Language Preference', ); diff --git a/lib/ui/views/learn_lesson/learn_lesson_view.dart b/lib/ui/views/learn_lesson/learn_lesson_view.dart index 3f29bf0..0e8173a 100644 --- a/lib/ui/views/learn_lesson/learn_lesson_view.dart +++ b/lib/ui/views/learn_lesson/learn_lesson_view.dart @@ -51,6 +51,7 @@ class LearnLessonView extends StackedView { Widget _buildAppBar(LearnLessonViewModel viewModel) => SmallAppBar( onTap: viewModel.pop, + showBackButton: true, ); Widget _buildLevelsColumnWrapper(LearnLessonViewModel viewModel) => @@ -122,6 +123,8 @@ class LearnLessonView extends StackedView { thumbnail: viewModel.lessons[index]['thumbnail'], onLessonTap: () async => await viewModel.navigateToLearnLessonDetail(), + onPracticeTap: () async => await viewModel.navigateToLearnPractice(), + ), ); @@ -130,11 +133,13 @@ class LearnLessonView extends StackedView { required String thumbnail, GestureTapCallback? onLessonTap, required ProgressStatuses status, + GestureTapCallback? onPracticeTap, }) => LearnLessonTile( title: title, status: status, thumbnail: thumbnail, onLessonTap: onLessonTap, + onPracticeTap: onPracticeTap, ); } diff --git a/lib/ui/views/learn_lesson/learn_lesson_viewmodel.dart b/lib/ui/views/learn_lesson/learn_lesson_viewmodel.dart index a467282..b6e8a3f 100644 --- a/lib/ui/views/learn_lesson/learn_lesson_viewmodel.dart +++ b/lib/ui/views/learn_lesson/learn_lesson_viewmodel.dart @@ -34,4 +34,12 @@ class LearnLessonViewModel extends BaseViewModel { Future navigateToLearnLessonDetail() async => await _navigationService.navigateToLearnLessonDetailView(); + + Future navigateToLearnPractice() async => + await _navigationService.navigateToLearnPracticeView( + buttonLabel: 'Start Practice', + title: 'Let \'s practice what you just learnt!', + subtitle: + 'I’ll ask you a few questions, and you can respond naturally.', + ); } diff --git a/lib/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart b/lib/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart index 13a75d7..3faf531 100644 --- a/lib/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart +++ b/lib/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart @@ -15,13 +15,11 @@ import 'learn_lesson_detail_viewmodel.dart'; class LearnLessonDetailView extends StackedView { const LearnLessonDetailView({Key? key}) : super(key: key); - - Future _navigate(LearnLessonDetailViewModel viewModel)async{ + Future _navigate(LearnLessonDetailViewModel viewModel) async { await viewModel.pause(); await viewModel.navigateToLearnPractice(); } - // @override // void onDispose(LearnLessonDetailViewModel viewModel) { // print('DISPOSED'); @@ -70,6 +68,7 @@ class LearnLessonDetailView extends StackedView { Widget _buildAppBar(LearnLessonDetailViewModel viewModel) => SmallAppBar( onTap: viewModel.pop, + showBackButton: true, ); Widget _buildBodyColumnWrapper(LearnLessonDetailViewModel viewModel) => @@ -173,6 +172,6 @@ class LearnLessonDetailView extends StackedView { borderRadius: 12, foregroundColor: kcWhite, backgroundColor: kcPrimaryColor, - onTap: ()async => await _navigate(viewModel), + onTap: () async => await _navigate(viewModel), ); } diff --git a/lib/ui/views/learn_lesson_detail/learn_lesson_detail_viewmodel.dart b/lib/ui/views/learn_lesson_detail/learn_lesson_detail_viewmodel.dart index b60be87..9cef707 100644 --- a/lib/ui/views/learn_lesson_detail/learn_lesson_detail_viewmodel.dart +++ b/lib/ui/views/learn_lesson_detail/learn_lesson_detail_viewmodel.dart @@ -53,7 +53,7 @@ class LearnLessonDetailViewModel extends BaseViewModel { // rebuildUi(); } - Future pause()async{ + Future pause() async { await _chewieController?.pause(); } @@ -67,6 +67,11 @@ class LearnLessonDetailViewModel extends BaseViewModel { // Navigation void pop() => _navigationService.back(); - Future navigateToLearnPractice() async=>await _navigationService.navigateToLearnPracticeView(); - + Future navigateToLearnPractice() async => + await _navigationService.navigateToLearnPracticeView( + buttonLabel: 'Start Practice', + title: 'Let \'s practice what you just learnt!', + subtitle: + 'I’ll ask you a few questions, and you can respond naturally.', + ); } diff --git a/lib/ui/views/learn_level/learn_level_view.dart b/lib/ui/views/learn_level/learn_level_view.dart index 7bcfed6..971756f 100644 --- a/lib/ui/views/learn_level/learn_level_view.dart +++ b/lib/ui/views/learn_level/learn_level_view.dart @@ -45,6 +45,7 @@ class LearnLevelView extends StackedView { Widget _buildAppBar(LearnLevelViewModel viewModel) => SmallAppBar( onTap: viewModel.pop, + showBackButton: true, ); Widget _buildLevelsColumnWrapper(LearnLevelViewModel viewModel) => diff --git a/lib/ui/views/learn_level/learn_level_viewmodel.dart b/lib/ui/views/learn_level/learn_level_viewmodel.dart index 01141b6..3cee422 100644 --- a/lib/ui/views/learn_level/learn_level_viewmodel.dart +++ b/lib/ui/views/learn_level/learn_level_viewmodel.dart @@ -22,8 +22,17 @@ class LearnLevelViewModel extends BaseViewModel { List> get learnSubLevels => _learnSubLevels; + // Navigation + void pop() => _navigationService.back(); + Future navigateToLearnModule() async => _navigationService.navigateToLearnModuleView(); - void pop() => _navigationService.back(); + Future navigateToLearnPractice() async => + await _navigationService.navigateToLearnPracticeView( + title: 'Let’s Practice Level 1', + buttonLabel: 'Begin Level Practice', + subtitle: + 'Let’s quickly review what you’ve learned in this level! ', + ); } diff --git a/lib/ui/views/learn_module/learn_module_view.dart b/lib/ui/views/learn_module/learn_module_view.dart index e0afc81..19434c6 100644 --- a/lib/ui/views/learn_module/learn_module_view.dart +++ b/lib/ui/views/learn_module/learn_module_view.dart @@ -47,6 +47,7 @@ class LearnModuleView extends StackedView { Widget _buildAppBar(LearnModuleViewModel viewModel) => SmallAppBar( onTap: viewModel.pop, + showBackButton: true, ); Widget _buildLevelsColumnWrapper(LearnModuleViewModel viewModel) => diff --git a/lib/ui/views/learn_module/learn_module_viewmodel.dart b/lib/ui/views/learn_module/learn_module_viewmodel.dart index 5205cb0..68a4187 100644 --- a/lib/ui/views/learn_module/learn_module_viewmodel.dart +++ b/lib/ui/views/learn_module/learn_module_viewmodel.dart @@ -10,13 +10,13 @@ class LearnModuleViewModel extends BaseViewModel { final List> _modules = [ { - 'status': ProgressStatuses.started, + 'status': ProgressStatuses.completed, 'title': 'Module 1: Greetings & Introductions', 'subtitle': 'Learn how to introduce yourself, talk about your surroundings, and start simple conversations.', }, { - 'status': ProgressStatuses.pending, + 'status': ProgressStatuses.started, 'title': 'Module 2: Everyday Basics', 'subtitle': 'Learn numbers, colors, and common objects.', }, @@ -39,4 +39,12 @@ class LearnModuleViewModel extends BaseViewModel { Future navigateToLearnLesson() async => await _navigationService.navigateToLearnLessonView(); + + Future navigateToLearnPractice() async => + await _navigationService.navigateToLearnPracticeView( + title: 'Let’s Practice Module 1', + buttonLabel: 'Begin Module Practice', + subtitle: + 'Let’s quickly review what you’ve learned in this module! ', + ); } diff --git a/lib/ui/views/learn_practice/learn_practice_view.dart b/lib/ui/views/learn_practice/learn_practice_view.dart index 4f3fc90..62c3dd1 100644 --- a/lib/ui/views/learn_practice/learn_practice_view.dart +++ b/lib/ui/views/learn_practice/learn_practice_view.dart @@ -1,8 +1,12 @@ import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart'; -import 'package:yimaru_app/ui/views/learn_practice/screens/listen_speaker_screen.dart'; -import 'package:yimaru_app/ui/views/learn_practice/screens/practice_intro_screen.dart'; -import 'package:yimaru_app/ui/views/learn_practice/screens/start_practice_screen.dart'; +import 'package:yimaru_app/ui/views/learn_practice/screens/finish_learn_practice_screen.dart'; +import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_completion_screen.dart'; +import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_result_screen.dart'; +import 'package:yimaru_app/ui/views/learn_practice/screens/listen_learn_practice_speaker_screen.dart'; +import 'package:yimaru_app/ui/views/learn_practice/screens/learn_practice_intro_screen.dart'; +import 'package:yimaru_app/ui/views/learn_practice/screens/speak_to_learn_practice_listener_screen.dart'; +import 'package:yimaru_app/ui/views/learn_practice/screens/start_learn_practice_screen.dart'; import 'package:yimaru_app/ui/widgets/profile_image.dart'; import 'package:yimaru_app/ui/widgets/speaking_partner_image.dart'; @@ -13,7 +17,16 @@ import '../../widgets/small_app_bar.dart'; import 'learn_practice_viewmodel.dart'; class LearnPracticeView extends StackedView { - const LearnPracticeView({Key? key}) : super(key: key); + final String title; + final String subtitle; + final String buttonLabel; + + const LearnPracticeView( + {Key? key, + required this.title, + required this.subtitle, + required this.buttonLabel}) + : super(key: key); @override LearnPracticeViewModel viewModelBuilder(BuildContext context) => @@ -27,46 +40,59 @@ class LearnPracticeView extends StackedView { ) => _buildPracticeScreensWrapper(viewModel); - - - Widget _buildPracticeScreensWrapper(LearnPracticeViewModel viewModel) => PopScope( - canPop: true, - onPopInvokedWithResult: (value, data) { - if (!value) return; - WidgetsBinding.instance.addPostFrameCallback((_) => viewModel.goBack()); - }, - child: _buildScaffoldWrapper(viewModel)); + Widget _buildPracticeScreensWrapper(LearnPracticeViewModel viewModel) => + PopScope( + canPop: true, + onPopInvokedWithResult: (value, data) { + if (!value) return; + WidgetsBinding.instance + .addPostFrameCallback((_) => viewModel.goBack()); + }, + child: _buildScaffoldWrapper(viewModel)); Widget _buildScaffoldWrapper(LearnPracticeViewModel viewModel) => Scaffold( - backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(viewModel), - ); - - Widget _buildScaffoldStack(LearnPracticeViewModel viewModel) => Stack(children: [ - _buildBody(viewModel), - //_buildLoginWithEmailState(viewModel), - //_buildLoginWithGoogleState(viewModel) - ]); - - + backgroundColor: kcBackgroundColor, + body: _buildScaffoldStack(viewModel), + ); + Widget _buildScaffoldStack(LearnPracticeViewModel viewModel) => + Stack(children: [ + _buildBody(viewModel), + //_buildLoginWithEmailState(viewModel), + //_buildLoginWithGoogleState(viewModel) + ]); Widget _buildBody(LearnPracticeViewModel viewModel) => - IndexedStack( - - index: viewModel.currentIndex, children: _buildScreens()); + IndexedStack(index: viewModel.currentIndex, children: _buildScreens()); List _buildScreens() => [ - _buildPracticeIntroScreen(), - _buildStartPracticeScreen(), - _buildListenSpeakerScreen() - ]; + _buildLearnPracticeIntroScreen(), + _buildStartLearnPracticeScreen(), + _buildListenLearnPracticeSpeakerScreen(), + _buildSpeakToLearnPracticeListenerScreen(), + _buildFinishLearnPracticeScreen(), + _buildLearnPracticeResultScreen(), + _buildLearnPracticeCompletionScreen() + ]; - Widget _buildPracticeIntroScreen() => const PracticeIntroScreen(); + Widget _buildLearnPracticeIntroScreen() => LearnPracticeIntroScreen( + title: title, + subtitle: subtitle, + buttonLabel: buttonLabel, + ); - Widget _buildStartPracticeScreen() => const StartPracticeScreen(); + Widget _buildStartLearnPracticeScreen() => const StartLearnPracticeScreen(); - Widget _buildListenSpeakerScreen() => const ListenSpeakerScreen(); + Widget _buildListenLearnPracticeSpeakerScreen() => + const ListenLearnPracticeSpeakerScreen(); + Widget _buildSpeakToLearnPracticeListenerScreen() => + const SpeakToLearnPracticeListenerScreen(); + + Widget _buildFinishLearnPracticeScreen() => const FinishLearnPracticeScreen(); + + Widget _buildLearnPracticeResultScreen() => const LearnPracticeResultScreen(); + + Widget _buildLearnPracticeCompletionScreen() => const LearnPracticeCompletionScreen(); } diff --git a/lib/ui/views/learn_practice/learn_practice_viewmodel.dart b/lib/ui/views/learn_practice/learn_practice_viewmodel.dart index a435375..3c5fcc9 100644 --- a/lib/ui/views/learn_practice/learn_practice_viewmodel.dart +++ b/lib/ui/views/learn_practice/learn_practice_viewmodel.dart @@ -11,24 +11,30 @@ class LearnPracticeViewModel extends BaseViewModel { int get currentIndex => _currentIndex; + // Practice results + final List> _practiceResults = [ + {'question': 'What is your name?'}, + {'question': 'Where are you from?'}, + {'question': 'Where are you from?'} + ]; + + List> get practiceResults => _practiceResults; + // In-app navigation void goTo(int page) { - _currentIndex = page; rebuildUi(); } void goBack() { - if(_currentIndex == 0){ + if (_currentIndex == 0) { pop(); - }else{ + } else { _currentIndex--; rebuildUi(); } - } // Navigation void pop() => _navigationService.back(); - } diff --git a/lib/ui/views/learn_practice/screens/finish_learn_practice_screen.dart b/lib/ui/views/learn_practice/screens/finish_learn_practice_screen.dart new file mode 100644 index 0000000..9a899ea --- /dev/null +++ b/lib/ui/views/learn_practice/screens/finish_learn_practice_screen.dart @@ -0,0 +1,129 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/views/learn_practice/learn_practice_viewmodel.dart'; +import 'package:yimaru_app/ui/widgets/cancel_learn_practice_sheet.dart'; +import 'package:yimaru_app/ui/widgets/custom_linear_progress_indicator.dart'; + +import '../../../common/app_colors.dart'; +import '../../../common/ui_helpers.dart'; +import '../../../widgets/custom_column_button.dart'; +import '../../../widgets/custom_elevated_button.dart'; +import '../../../widgets/small_app_bar.dart'; + +class FinishLearnPracticeScreen + extends ViewModelWidget { + const FinishLearnPracticeScreen({super.key}); + + @override + Widget build(BuildContext context, LearnPracticeViewModel viewModel) => + _buildScaffoldWrapper(viewModel); + + Widget _buildScaffoldWrapper(LearnPracticeViewModel viewModel) => Scaffold( + backgroundColor: kcBackgroundColor, + body: _buildScaffold(viewModel), + ); + + Widget _buildScaffold(LearnPracticeViewModel viewModel) => + SafeArea(child: _buildBodyColumnWrapper(viewModel)); + + Widget _buildBodyColumnWrapper(LearnPracticeViewModel viewModel) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildBodyColumn(viewModel), + ); + + Widget _buildBodyColumn(viewModel) => Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _buildBodyColumnChildren(viewModel), + ); + + List _buildBodyColumnChildren(LearnPracticeViewModel viewModel) => [ + _buildAppBarWrapper(viewModel), + _buildSpeakingIndicatorWrapper(viewModel), + _buildLowerButtonsSectionWrapper(viewModel) + ]; + + Widget _buildAppBarWrapper(LearnPracticeViewModel viewModel) => Column( + children: [ + verticalSpaceMedium, + _buildAppBar(viewModel), + ], + ); + + Widget _buildAppBar(LearnPracticeViewModel viewModel) => SmallAppBar( + showBackButton: false, + onTap: viewModel.goBack, + title: 'Practice Speaking', + ); + + Widget _buildSpeakingIndicatorWrapper(LearnPracticeViewModel viewModel) => + Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: _buildSpeakingIndicatorChildren(), + ); + + List _buildSpeakingIndicatorChildren() => [ + _buildIcon(), + verticalSpaceMedium, + _buildTitle(), + _buildSubtitle(), + ]; + + Widget _buildIcon() => SvgPicture.asset('assets/icons/success.svg'); + + Widget _buildTitle() => Text( + 'Practice Completed!', + style: style25DG600, + textAlign: TextAlign.center, + ); + + Widget _buildSubtitle() => Text( + 'You sound more confident this time - great improvement!', + style: style14DG400, + textAlign: TextAlign.center, + ); + + Widget _buildLowerButtonsSectionWrapper(LearnPracticeViewModel viewModel) => + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: _buildLowerButtonsSection(viewModel), + ); + + Widget _buildLowerButtonsSection(LearnPracticeViewModel viewModel) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: _buildLowerButtonsSectionChildren(viewModel), + ); + + List _buildLowerButtonsSectionChildren( + LearnPracticeViewModel viewModel) => + [ + _buildContinueButton(viewModel), + verticalSpaceSmall, + _buildPracticeAgainButton(viewModel), + verticalSpaceMedium, + ]; + + Widget _buildContinueButton(LearnPracticeViewModel viewModel) => + CustomElevatedButton( + height: 55, + borderRadius: 12, + foregroundColor: kcWhite, + text: 'Continue Practice', + onTap: () => viewModel.goTo(5), + backgroundColor: kcPrimaryColor, + ); + + Widget _buildPracticeAgainButton(LearnPracticeViewModel viewModel) => + CustomElevatedButton( + height: 55, + borderRadius: 12, + text: 'Practice Again', + backgroundColor: kcWhite, + borderColor: kcPrimaryColor, + onTap: () => viewModel.goTo(1), + foregroundColor: kcPrimaryColor, + ); +} diff --git a/lib/ui/views/learn_practice/screens/learn_practice_completion_screen.dart b/lib/ui/views/learn_practice/screens/learn_practice_completion_screen.dart new file mode 100644 index 0000000..f41d56f --- /dev/null +++ b/lib/ui/views/learn_practice/screens/learn_practice_completion_screen.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/views/learn_practice/learn_practice_viewmodel.dart'; +import 'package:yimaru_app/ui/widgets/small_app_bar.dart'; + +import '../../../common/app_colors.dart'; +import '../../../common/ui_helpers.dart'; +import '../../../widgets/custom_elevated_button.dart'; + +class LearnPracticeCompletionScreen extends ViewModelWidget { + const LearnPracticeCompletionScreen({super.key}); + + @override + Widget build(BuildContext context, LearnPracticeViewModel viewModel) => + _buildScaffoldWrapper(viewModel); + + Widget _buildScaffoldWrapper(LearnPracticeViewModel viewModel) => Scaffold( + backgroundColor: kcBackgroundColor, + body: _buildBodyWrapper(viewModel), + ); + + + + Widget _buildBodyWrapper(LearnPracticeViewModel viewModel) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildBody(viewModel), + ); + + Widget _buildBody(LearnPracticeViewModel viewModel) => Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _buildBodyChildren(viewModel), + ); + + List _buildBodyChildren(LearnPracticeViewModel viewModel) => + [_buildUpperColumn(viewModel), _buildContinueButtonWrapper(viewModel)]; + + Widget _buildUpperColumn(LearnPracticeViewModel viewModel) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: _buildUpperColumnChildren(viewModel), + ); + + List _buildUpperColumnChildren(LearnPracticeViewModel viewModel) => [ + verticalSpaceMassive, + _buildIcon(), + verticalSpaceMedium, + _buildTitle(), + verticalSpaceSmall, + _buildSubtitle(), + ]; + + Widget _buildIcon() => SvgPicture.asset( + 'assets/icons/complete.svg', + ); + + Widget _buildTitle() => Text( + 'Yay, you’ve completed A1 ', + style: style25DG600, + textAlign: TextAlign.center, + ); + + Widget _buildSubtitle() => Text( + 'We’re now analyzing your speaking skills', + textAlign: TextAlign.center, + style: style14MG400, + ); + + Widget _buildContinueButtonWrapper(LearnPracticeViewModel viewModel) => Padding( + padding: const EdgeInsets.only(bottom: 50), + child: _buildContinueButton(viewModel), + ); + + Widget _buildContinueButton(LearnPracticeViewModel viewModel) => + CustomElevatedButton( + height: 55, + borderRadius: 12, + text: 'Continue', + foregroundColor: kcWhite, + onTap: () => viewModel.pop(), + backgroundColor: kcPrimaryColor, + ); +} \ No newline at end of file diff --git a/lib/ui/views/learn_practice/screens/practice_intro_screen.dart b/lib/ui/views/learn_practice/screens/learn_practice_intro_screen.dart similarity index 56% rename from lib/ui/views/learn_practice/screens/practice_intro_screen.dart rename to lib/ui/views/learn_practice/screens/learn_practice_intro_screen.dart index 4830da2..34a75a0 100644 --- a/lib/ui/views/learn_practice/screens/practice_intro_screen.dart +++ b/lib/ui/views/learn_practice/screens/learn_practice_intro_screen.dart @@ -9,53 +9,61 @@ import '../../../widgets/custom_elevated_button.dart'; import '../../../widgets/small_app_bar.dart'; import '../../../widgets/speaking_partner_image.dart'; -class PracticeIntroScreen extends ViewModelWidget { - const PracticeIntroScreen({super.key}); +class LearnPracticeIntroScreen extends ViewModelWidget { + final String title; + final String subtitle; + final String buttonLabel; + + const LearnPracticeIntroScreen( + {super.key, + required this.title, + required this.subtitle, + required this.buttonLabel}); @override - Widget build(BuildContext context,LearnPracticeViewModel viewModel) => _buildScaffoldWrapper(viewModel); - - + Widget build(BuildContext context, LearnPracticeViewModel viewModel) => + _buildScaffoldWrapper(viewModel); Widget _buildScaffoldWrapper(LearnPracticeViewModel viewModel) => Scaffold( - backgroundColor: kcBackgroundColor, - body: _buildScaffold(viewModel), - ); + backgroundColor: kcBackgroundColor, + body: _buildScaffold(viewModel), + ); Widget _buildScaffold(LearnPracticeViewModel viewModel) => SafeArea(child: _buildColumnWrapper(viewModel)); Widget _buildColumnWrapper(LearnPracticeViewModel viewModel) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 15), - child: _buildColumn(viewModel), - ); + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildColumn(viewModel), + ); Widget _buildColumn(LearnPracticeViewModel viewModel) => Column( - children: [ - verticalSpaceMedium, - _buildAppBar(viewModel), - _buildBodyColumnWrapper(viewModel), - ], - ); + children: [ + verticalSpaceMedium, + _buildAppBar(viewModel), + _buildBodyColumnWrapper(viewModel), + ], + ); Widget _buildAppBar(LearnPracticeViewModel viewModel) => SmallAppBar( - onTap: viewModel.goBack, - title: 'Practice Speaking', - ); + showBackButton: true, + onTap: viewModel.goBack, + title: 'Practice Speaking', + ); Widget _buildBodyColumnWrapper(LearnPracticeViewModel viewModel) => Expanded( - child: _buildBodyColumn(viewModel), - ); + child: _buildBodyColumn(viewModel), + ); Widget _buildBodyColumn(LearnPracticeViewModel viewModel) => Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: _buildBodyColumnChildren(viewModel), - ); + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _buildBodyColumnChildren(viewModel), + ); List _buildBodyColumnChildren(LearnPracticeViewModel viewModel) => [ - _buildPracticeColumnWrapper(viewModel), - _buildContinueButtonWrapper(viewModel) - ]; + _buildPracticeColumnWrapper(viewModel), + _buildContinueButtonWrapper(viewModel) + ]; Widget _buildPracticeColumnWrapper(LearnPracticeViewModel viewModel) => Expanded(child: _buildPracticeColumnScrollView(viewModel)); @@ -66,10 +74,10 @@ class PracticeIntroScreen extends ViewModelWidget { ); Widget _buildPracticeColumn(LearnPracticeViewModel viewModel) => Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: _buildPracticeColumnChildren(viewModel), - ); + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: _buildPracticeColumnChildren(viewModel), + ); List _buildPracticeColumnChildren(LearnPracticeViewModel viewModel) => [ @@ -83,28 +91,30 @@ class PracticeIntroScreen extends ViewModelWidget { _buildSubtitle() ]; - Widget _buildImage() => const SpeakingPartnerImage(radius: 75,); + Widget _buildImage() => const SpeakingPartnerImage( + radius: 75, + ); Widget _buildPartnerName() => Text.rich( - TextSpan(text: 'Daniel', style: style14DG600, children: [ - TextSpan( - text: ' - Your Speaking Partner', - style: style14MG400, - ) - ]), - ); + TextSpan(text: 'Daniel', style: style14DG600, children: [ + TextSpan( + text: ' - Your Speaking Partner', + style: style14MG400, + ) + ]), + ); Widget _buildTitle() => Text( - 'Let \'s practice what you just learnt!', - style: style25DG600, - textAlign: TextAlign.center, - ); + title, + style: style25DG600, + textAlign: TextAlign.center, + ); Widget _buildSubtitle() => Text( - 'I’ll ask you a few questions, and you can respond naturally.', - style: style14DG400, - textAlign: TextAlign.center, - ); + subtitle, + style: style14DG400, + textAlign: TextAlign.center, + ); Widget _buildContinueButtonWrapper(LearnPracticeViewModel viewModel) => Padding( @@ -116,9 +126,9 @@ class PracticeIntroScreen extends ViewModelWidget { CustomElevatedButton( height: 55, borderRadius: 12, - text: 'Start Practice', + text: buttonLabel, foregroundColor: kcWhite, - onTap: ()=> viewModel.goTo(1), + onTap: () => viewModel.goTo(1), backgroundColor: kcPrimaryColor, ); } diff --git a/lib/ui/views/learn_practice/screens/learn_practice_result_screen.dart b/lib/ui/views/learn_practice/screens/learn_practice_result_screen.dart new file mode 100644 index 0000000..a11abac --- /dev/null +++ b/lib/ui/views/learn_practice/screens/learn_practice_result_screen.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/views/learn_practice/learn_practice_viewmodel.dart'; +import 'package:yimaru_app/ui/widgets/cancel_learn_practice_sheet.dart'; +import 'package:yimaru_app/ui/widgets/custom_linear_progress_indicator.dart'; +import 'package:yimaru_app/ui/widgets/learn_practice_tip_section.dart'; +import 'package:yimaru_app/ui/widgets/practice_results_wrapper.dart'; + +import '../../../common/app_colors.dart'; +import '../../../common/ui_helpers.dart'; +import '../../../widgets/custom_column_button.dart'; +import '../../../widgets/custom_elevated_button.dart'; +import '../../../widgets/small_app_bar.dart'; + +class LearnPracticeResultScreen + extends ViewModelWidget { + const LearnPracticeResultScreen({super.key}); + + @override + Widget build(BuildContext context, LearnPracticeViewModel viewModel) => + _buildScaffoldWrapper(viewModel); + + Widget _buildScaffoldWrapper(LearnPracticeViewModel viewModel) => Scaffold( + backgroundColor: kcBackgroundColor, + body: _buildScaffold(viewModel), + ); + + Widget _buildScaffold(LearnPracticeViewModel viewModel) => + SafeArea(child: _buildBodyColumnWrapper(viewModel)); + + Widget _buildBodyColumnWrapper(LearnPracticeViewModel viewModel) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildBodyColumn(viewModel), + ); + + Widget _buildBodyColumn(viewModel) => Column( + children: _buildBodyColumnChildren(viewModel), + ); + + List _buildBodyColumnChildren(LearnPracticeViewModel viewModel) => [ + verticalSpaceMedium, + _buildAppBar(viewModel), + verticalSpaceMedium, + _buildBodyWrapper(viewModel) + ]; + + Widget _buildAppBar(LearnPracticeViewModel viewModel) => SmallAppBar( + title: 'Result', + showBackButton: true, + onTap: viewModel.goBack, + ); + + Widget _buildBodyWrapper(LearnPracticeViewModel viewMode) => Expanded( + child: _buildBodyScroller(viewMode), + ); + + Widget _buildBodyScroller(LearnPracticeViewModel viewModel) => + SingleChildScrollView( + child: _buildBody(viewModel), + ); + + Widget _buildBody(LearnPracticeViewModel viewModel) => Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: _buildBodyChildren(viewModel), + ); + + List _buildBodyChildren(LearnPracticeViewModel viewModel) => [ + _buildResultsSection(viewModel), + verticalSpaceMedium, + _buildLearnPracticeTipSection(), + verticalSpaceLarge, + _buildLowerButtonsSection(viewModel) + ]; + + Widget _buildResultsSection(LearnPracticeViewModel viewModel) => + PracticeResultsWrapper(data: viewModel.practiceResults); + + Widget _buildLearnPracticeTipSection() => const LearnPracticeTipSection(); + + Widget _buildLowerButtonsSection(LearnPracticeViewModel viewModel) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: _buildLowerButtonsSectionChildren(viewModel), + ); + + List _buildLowerButtonsSectionChildren( + LearnPracticeViewModel viewModel) => + [ + _buildContinueButton(viewModel), + verticalSpaceSmall, + _buildPracticeAgainButton(viewModel), + verticalSpaceMedium, + ]; + + Widget _buildContinueButton(LearnPracticeViewModel viewModel) => CustomElevatedButton( + height: 55, + text: 'Continue', + borderRadius: 12, + foregroundColor: kcWhite, + onTap: () => viewModel.goTo(6), + backgroundColor: kcPrimaryColor, + ); + + Widget _buildPracticeAgainButton(LearnPracticeViewModel viewModel) => + CustomElevatedButton( + height: 55, + text: 'Retry', + borderRadius: 12, + backgroundColor: kcWhite, + borderColor: kcPrimaryColor, + onTap: () => viewModel.goTo(1), + foregroundColor: kcPrimaryColor, + ); +} diff --git a/lib/ui/views/learn_practice/screens/listen_speaker_screen.dart b/lib/ui/views/learn_practice/screens/listen_learn_practice_speaker_screen.dart similarity index 94% rename from lib/ui/views/learn_practice/screens/listen_speaker_screen.dart rename to lib/ui/views/learn_practice/screens/listen_learn_practice_speaker_screen.dart index 7563726..f81bb5c 100644 --- a/lib/ui/views/learn_practice/screens/listen_speaker_screen.dart +++ b/lib/ui/views/learn_practice/screens/listen_learn_practice_speaker_screen.dart @@ -10,8 +10,9 @@ import '../../../common/ui_helpers.dart'; import '../../../widgets/custom_column_button.dart'; import '../../../widgets/small_app_bar.dart'; -class ListenSpeakerScreen extends ViewModelWidget { - const ListenSpeakerScreen({super.key}); +class ListenLearnPracticeSpeakerScreen + extends ViewModelWidget { + const ListenLearnPracticeSpeakerScreen({super.key}); Future _showSheet( {required BuildContext context, @@ -86,6 +87,7 @@ class ListenSpeakerScreen extends ViewModelWidget { ); Widget _buildAppBar(LearnPracticeViewModel viewModel) => SmallAppBar( + showBackButton: true, onTap: viewModel.goBack, title: 'Practice Speaking', ); @@ -190,7 +192,7 @@ class ListenSpeakerScreen extends ViewModelWidget { required LearnPracticeViewModel viewModel}) => [ _buildReplyButtonWrapper(), - _buildMicButtonWrapper(), + _buildMicButtonWrapper(viewModel), _buildCancelButtonWrapper(context: context, viewModel: viewModel) ]; @@ -199,10 +201,11 @@ class ListenSpeakerScreen extends ViewModelWidget { Widget _buildReplyButton() => const CustomColumnButton( icon: Icons.replay, label: 'Reply', color: kcPrimaryColor); - Widget _buildMicButtonWrapper() => Expanded(child: _buildMicButton()); + Widget _buildMicButtonWrapper(LearnPracticeViewModel viewModel) => + Expanded(child: _buildMicButton(viewModel)); - Widget _buildMicButton() => ElevatedButton( - onPressed: () {}, + Widget _buildMicButton(LearnPracticeViewModel viewModel) => ElevatedButton( + onPressed: () => viewModel.goTo(3), style: const ButtonStyle( shape: WidgetStatePropertyAll(CircleBorder()), padding: WidgetStatePropertyAll(EdgeInsets.all(15)), diff --git a/lib/ui/views/learn_practice/screens/speak_to_learn_practice_listener_screen.dart b/lib/ui/views/learn_practice/screens/speak_to_learn_practice_listener_screen.dart new file mode 100644 index 0000000..5a2b3e8 --- /dev/null +++ b/lib/ui/views/learn_practice/screens/speak_to_learn_practice_listener_screen.dart @@ -0,0 +1,232 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:stacked/stacked.dart'; +import 'package:yimaru_app/ui/views/learn_practice/learn_practice_viewmodel.dart'; +import 'package:yimaru_app/ui/widgets/cancel_learn_practice_sheet.dart'; +import 'package:yimaru_app/ui/widgets/custom_linear_progress_indicator.dart'; + +import '../../../common/app_colors.dart'; +import '../../../common/ui_helpers.dart'; +import '../../../widgets/custom_column_button.dart'; +import '../../../widgets/small_app_bar.dart'; + +class SpeakToLearnPracticeListenerScreen + extends ViewModelWidget { + const SpeakToLearnPracticeListenerScreen({super.key}); + + Future _showSheet( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) async => + await showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: kcTransparent, + builder: (_) => _buildSheet(viewModel), + ); + + @override + Widget build(BuildContext context, LearnPracticeViewModel viewModel) => + _buildScaffoldWrapper(context: context, viewModel: viewModel); + + Widget _buildScaffoldWrapper( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Scaffold( + backgroundColor: kcBackgroundColor, + body: _buildScaffold(context: context, viewModel: viewModel), + ); + + Widget _buildScaffold( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + SafeArea( + child: + _buildBodyColumnWrapper(context: context, viewModel: viewModel)); + + Widget _buildBodyColumnWrapper( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildBodyStack(context: context, viewModel: viewModel), + ); + + Widget _buildBodyStack( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Stack( + children: [ + _buildBodyColumn(context: context, viewModel: viewModel), + _buildProgressIndicatorWrapper() + ], + ); + + Widget _buildBodyColumn( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: + _buildBodyColumnChildren(context: context, viewModel: viewModel), + ); + + List _buildBodyColumnChildren( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + [ + _buildAppBarWrapper(viewModel), + _buildSpeakingIndicatorWrapper(viewModel), + _buildLowerButtonsSectionWrapper(context: context, viewModel: viewModel) + ]; + + Widget _buildAppBarWrapper(LearnPracticeViewModel viewModel) => Column( + children: [ + verticalSpaceMedium, + _buildAppBar(viewModel), + ], + ); + + Widget _buildAppBar(LearnPracticeViewModel viewModel) => SmallAppBar( + onTap: viewModel.goBack, + showBackButton: true, + title: 'Practice Speaking', + ); + + Widget _buildSpeakingIndicatorWrapper(LearnPracticeViewModel viewModel) => + Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: _buildSpeakingIndicatorChildren(), + ); + + List _buildSpeakingIndicatorChildren() => + [_buildSpeakerLabel(), verticalSpaceMedium, _buildSpeakingIndicator()]; + + Widget _buildSpeakerLabel() => Text( + 'You are speaking...', + style: style14P400, + textAlign: TextAlign.center, + ); + + Widget _buildSpeakingIndicator() => Container( + height: 100, + alignment: Alignment.center, + child: _buildSpinner(), + ); + + Widget _buildSpinner() => const SpinKitWave( + size: 75, + color: kcPrimaryColor, + type: SpinKitWaveType.center, + ); + + Widget _buildLowerButtonsSectionWrapper( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: + _buildLowerButtonsSection(context: context, viewModel: viewModel), + ); + + Widget _buildLowerButtonsSection( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + children: _buildLowerButtonsSectionChildren( + context: context, viewModel: viewModel), + ); + + List _buildLowerButtonsSectionChildren( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + [ + _buildActionLabel(), + verticalSpaceMedium, + _buildButtonsRowWrapper(context: context, viewModel: viewModel), + verticalSpaceMedium, + ]; + + Widget _buildActionLabel() => Text( + 'Tap the microphone to speak', + style: style14DG400, + textAlign: TextAlign.center, + ); + + Widget _buildButtonsRowWrapper( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: + _buildButtonsRowChildren(context: context, viewModel: viewModel), + ); + + List _buildButtonsRowChildren( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + [ + _buildEmptySpace(), + _buildCheckButtonWrapper(viewModel), + _buildCancelButtonWrapper(context: context, viewModel: viewModel) + ]; + + Widget _buildEmptySpace() => Expanded(child: Container()); + + Widget _buildCheckButtonWrapper(LearnPracticeViewModel viewModel) => + Expanded(child: _buildCheckButton(viewModel)); + + Widget _buildCheckButton(LearnPracticeViewModel viewModel) => ElevatedButton( + onPressed: () => viewModel.goTo(4), + style: const ButtonStyle( + shape: WidgetStatePropertyAll(CircleBorder()), + padding: WidgetStatePropertyAll(EdgeInsets.all(15)), + shadowColor: WidgetStatePropertyAll(kcPrimaryColor), + backgroundColor: WidgetStatePropertyAll(kcPrimaryColor), + ), + child: _buildCheckIcon(), + ); + + Widget _buildCheckIcon() => const Icon( + Icons.check, + size: 35, + color: kcWhite, + ); + + Widget _buildCancelButtonWrapper( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + Expanded( + child: _buildCancelButton(context: context, viewModel: viewModel)); + + Widget _buildCancelButton( + {required BuildContext context, + required LearnPracticeViewModel viewModel}) => + CustomColumnButton( + color: kcRed, + label: 'Cancel', + icon: Icons.close, + onTap: () async => + await _showSheet(context: context, viewModel: viewModel), + ); + + Widget _buildSheet(LearnPracticeViewModel viewModel) => + CancelLearnPracticeSheet( + onTap: viewModel.pop, + ); + + Widget _buildProgressIndicatorWrapper() => Positioned( + top: 75, + left: 0, + right: 0, + child: _buildProgressIndicator(), + ); + + Widget _buildProgressIndicator() => const CustomLinearProgressIndicator( + progress: 0.7, + activeColor: kcPrimaryColor, + backgroundColor: kcVeryLightGrey); +} diff --git a/lib/ui/views/learn_practice/screens/start_practice_screen.dart b/lib/ui/views/learn_practice/screens/start_learn_practice_screen.dart similarity index 87% rename from lib/ui/views/learn_practice/screens/start_practice_screen.dart rename to lib/ui/views/learn_practice/screens/start_learn_practice_screen.dart index 8f33ad4..91c7a0e 100644 --- a/lib/ui/views/learn_practice/screens/start_practice_screen.dart +++ b/lib/ui/views/learn_practice/screens/start_learn_practice_screen.dart @@ -7,8 +7,8 @@ import '../../../common/app_colors.dart'; import '../../../common/ui_helpers.dart'; import '../../../widgets/small_app_bar.dart'; -class StartPracticeScreen extends ViewModelWidget { - const StartPracticeScreen({super.key}); +class StartLearnPracticeScreen extends ViewModelWidget { + const StartLearnPracticeScreen({super.key}); @override Widget build(BuildContext context, LearnPracticeViewModel viewModel) => @@ -47,6 +47,7 @@ class StartPracticeScreen extends ViewModelWidget { Widget _buildAppBar(LearnPracticeViewModel viewModel) => SmallAppBar( onTap: viewModel.goBack, + showBackButton: true, title: 'Practice Speaking', ); @@ -122,7 +123,7 @@ class StartPracticeScreen extends ViewModelWidget { [ _buildActionLabel(), verticalSpaceMedium, - _buildButtonsRowWrapper(), + _buildButtonsRowWrapper(viewModel), verticalSpaceMedium, ]; @@ -132,15 +133,15 @@ class StartPracticeScreen extends ViewModelWidget { textAlign: TextAlign.center, ); - Widget _buildButtonsRowWrapper() => Row( + Widget _buildButtonsRowWrapper(LearnPracticeViewModel viewModel) => Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: _buildButtonsRowChildren(), + children: _buildButtonsRowChildren(viewModel), ); - List _buildButtonsRowChildren() => [ + List _buildButtonsRowChildren(LearnPracticeViewModel viewModel) => [ _buildReplyButtonWrapper(), - _buildMicButtonWrapper(), + _buildMicButtonWrapper(viewModel), _buildEmptySpace() ]; @@ -149,10 +150,11 @@ class StartPracticeScreen extends ViewModelWidget { Widget _buildReplyButton() => const CustomColumnButton( icon: Icons.replay, label: 'Reply', color: kcPrimaryColor); - Widget _buildMicButtonWrapper() => Expanded(child: _buildMicButton()); + Widget _buildMicButtonWrapper(LearnPracticeViewModel viewModel) => + Expanded(child: _buildMicButton(viewModel)); - Widget _buildMicButton() => ElevatedButton( - onPressed: () {}, + Widget _buildMicButton(LearnPracticeViewModel viewModel) => ElevatedButton( + onPressed: () => viewModel.goTo(2), style: const ButtonStyle( shape: WidgetStatePropertyAll(CircleBorder()), padding: WidgetStatePropertyAll(EdgeInsets.all(15)), diff --git a/lib/ui/views/login/login_view.dart b/lib/ui/views/login/login_view.dart index 6a44a13..a29b6f0 100644 --- a/lib/ui/views/login/login_view.dart +++ b/lib/ui/views/login/login_view.dart @@ -56,10 +56,6 @@ class LoginView extends StackedView with $LoginView { }, child: _buildBody(viewModel)); - - - - Widget _buildBody(LoginViewModel viewModel) => IndexedStack(index: viewModel.currentIndex, children: _buildScreens()); @@ -78,5 +74,4 @@ class LoginView extends StackedView with $LoginView { Widget _buildLoginOtpScreen() => LoginOtpScreen( otpController: otpController, phoneNumberController: phoneNumberController); - } diff --git a/lib/ui/views/login/login_viewmodel.dart b/lib/ui/views/login/login_viewmodel.dart index a87550b..a2051b7 100644 --- a/lib/ui/views/login/login_viewmodel.dart +++ b/lib/ui/views/login/login_viewmodel.dart @@ -142,7 +142,7 @@ class LoginViewModel extends FormViewModel { await _navigationService.navigateToForgetPasswordView(); Future replaceWithHome() async => - await _navigationService.clearStackAndShowView(const HomeView()); + await _navigationService.clearStackAndShow(Routes.homeView); // Remote api calls @@ -171,8 +171,9 @@ class LoginViewModel extends FormViewModel { } } - Future signInWithGoogle() async => await runBusyFuture(_signInWithGoogle(), - busyObject: StateObjects.loginWithGoogle); + Future signInWithGoogle() async => + await runBusyFuture(_signInWithGoogle(), + busyObject: StateObjects.loginWithGoogle); Future _signInWithGoogle() async { if (await _statusChecker.checkConnection()) { diff --git a/lib/ui/views/login/screens/login_otp_screen.dart b/lib/ui/views/login/screens/login_otp_screen.dart index a8fd53d..45abe4a 100644 --- a/lib/ui/views/login/screens/login_otp_screen.dart +++ b/lib/ui/views/login/screens/login_otp_screen.dart @@ -21,68 +21,83 @@ class LoginOtpScreen extends ViewModelWidget { required this.otpController, required this.phoneNumberController}); - Widget getPadding(context){ - double half = screenHeight(context)/2; - return SizedBox(height: half + 325 - half,); + Widget getPadding(context) { + double half = screenHeight(context) / 2; + return SizedBox( + height: half + 325 - half, + ); } @override Widget build(BuildContext context, LoginViewModel viewModel) => - _buildScaffoldWrapper(context: context,viewModel: viewModel); + _buildScaffoldWrapper(context: context, viewModel: viewModel); - Widget _buildScaffoldWrapper({required BuildContext context,required LoginViewModel viewModel}) => Scaffold( - backgroundColor: kcBackgroundColor, - body: _buildScaffold(context: context,viewModel: viewModel), - ); - - - - Widget _buildScaffold({required BuildContext context,required LoginViewModel viewModel}) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: _buildScaffoldChildren(context: context,viewModel: viewModel), - ); - - List _buildScaffoldChildren({required BuildContext context,required LoginViewModel viewModel}) => - [_buildAppBar(viewModel), _buildExpandedBody(context: context,viewModel: viewModel)]; - - Widget _buildAppBar(LoginViewModel viewModel) => const LargeAppBar( - showBackButton: false, - showLanguageSelection: true, - ); - - Widget _buildExpandedBody({required BuildContext context,required LoginViewModel viewModel}) => - Expanded(child: _buildColumnScroller(context: context,viewModel: viewModel)); - - Widget _buildColumnScroller({required BuildContext context,required LoginViewModel viewModel}) => - SingleChildScrollView( - child: _buildBodyWrapper(context: context,viewModel: viewModel), + Widget _buildScaffoldWrapper( + {required BuildContext context, required LoginViewModel viewModel}) => + Scaffold( + backgroundColor: kcBackgroundColor, + body: _buildScaffold(context: context, viewModel: viewModel), ); - Widget _buildBodyWrapper({required BuildContext context,required LoginViewModel viewModel}) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 15), - child: _buildBody(context: context,viewModel: viewModel), - ); + Widget _buildScaffold( + {required BuildContext context, required LoginViewModel viewModel}) => + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + _buildScaffoldChildren(context: context, viewModel: viewModel), + ); - Widget _buildBody({required BuildContext context,required LoginViewModel viewModel}) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: _buildBodyChildren(context: context,viewModel: viewModel), - ); + List _buildScaffoldChildren( + {required BuildContext context, required LoginViewModel viewModel}) => + [ + _buildAppBar(viewModel), + _buildExpandedBody(context: context, viewModel: viewModel) + ]; + Widget _buildAppBar(LoginViewModel viewModel) => const LargeAppBar( + showBackButton: false, + showLanguageSelection: true, + ); + Widget _buildExpandedBody( + {required BuildContext context, required LoginViewModel viewModel}) => + Expanded( + child: _buildColumnScroller(context: context, viewModel: viewModel)); + Widget _buildColumnScroller( + {required BuildContext context, required LoginViewModel viewModel}) => + SingleChildScrollView( + child: _buildBodyWrapper(context: context, viewModel: viewModel), + ); - List _buildBodyChildren({required BuildContext context,required LoginViewModel viewModel}) => - [_buildUpperColumn(viewModel),getPadding(context), _buildContinueButton(viewModel)]; + Widget _buildBodyWrapper( + {required BuildContext context, required LoginViewModel viewModel}) => + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildBody(context: context, viewModel: viewModel), + ); + Widget _buildBody( + {required BuildContext context, required LoginViewModel viewModel}) => + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _buildBodyChildren(context: context, viewModel: viewModel), + ); + List _buildBodyChildren( + {required BuildContext context, required LoginViewModel viewModel}) => + [ + _buildUpperColumn(viewModel), + getPadding(context), + _buildContinueButton(viewModel) + ]; Widget _buildUpperColumn(LoginViewModel viewModel) => Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: _buildUpperColumnChildren(viewModel), - ); - + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: _buildUpperColumnChildren(viewModel), + ); List _buildUpperColumnChildren(LoginViewModel viewModel) => [ verticalSpaceMedium, diff --git a/lib/ui/views/login/screens/login_with_email_screen.dart b/lib/ui/views/login/screens/login_with_email_screen.dart index f9c078f..33ed501 100644 --- a/lib/ui/views/login/screens/login_with_email_screen.dart +++ b/lib/ui/views/login/screens/login_with_email_screen.dart @@ -22,10 +22,11 @@ class LoginWithEmailScreen extends ViewModelWidget { required this.emailController, required this.passwordController}); - - Widget getPadding(context){ - double half = screenHeight(context)/2; - return SizedBox(height: half + 25 - half,); + Widget getPadding(context) { + double half = screenHeight(context) / 2; + return SizedBox( + height: half + 25 - half, + ); } Future _login(LoginViewModel viewModel) async { @@ -42,57 +43,75 @@ class LoginWithEmailScreen extends ViewModelWidget { @override Widget build(BuildContext context, LoginViewModel viewModel) => - _buildScaffoldWrapper(context: context,viewModel: viewModel); + _buildScaffoldWrapper(context: context, viewModel: viewModel); - Widget _buildScaffoldWrapper({required BuildContext context,required LoginViewModel viewModel}) => Scaffold( - backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(context: context,viewModel: viewModel), - ); + Widget _buildScaffoldWrapper( + {required BuildContext context, required LoginViewModel viewModel}) => + Scaffold( + backgroundColor: kcBackgroundColor, + body: _buildScaffoldStack(context: context, viewModel: viewModel), + ); - Widget _buildScaffoldStack({required BuildContext context,required LoginViewModel viewModel}) => Stack(children: [ - _buildScaffold(context: context,viewModel: viewModel), - _buildLoginWithEmailState(viewModel), - _buildLoginWithGoogleState(viewModel) - ]); + Widget _buildScaffoldStack( + {required BuildContext context, required LoginViewModel viewModel}) => + Stack(children: [ + _buildScaffold(context: context, viewModel: viewModel), + _buildLoginWithEmailState(viewModel), + _buildLoginWithGoogleState(viewModel) + ]); - Widget _buildScaffold({required BuildContext context,required LoginViewModel viewModel}) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: _buildScaffoldChildren(context: context,viewModel: viewModel), - ); + Widget _buildScaffold( + {required BuildContext context, required LoginViewModel viewModel}) => + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + _buildScaffoldChildren(context: context, viewModel: viewModel), + ); - List _buildScaffoldChildren({required BuildContext context,required LoginViewModel viewModel}) => - [_buildAppBar(viewModel), _buildExpandedBody(context: context,viewModel: viewModel)]; + List _buildScaffoldChildren( + {required BuildContext context, required LoginViewModel viewModel}) => + [ + _buildAppBar(viewModel), + _buildExpandedBody(context: context, viewModel: viewModel) + ]; Widget _buildAppBar(LoginViewModel viewModel) => const LargeAppBar( - showBackButton: false, - showLanguageSelection: true, - ); + showBackButton: false, + showLanguageSelection: true, + ); - Widget _buildExpandedBody({required BuildContext context,required LoginViewModel viewModel}) => - Expanded(child: _buildColumnScroller(context: context,viewModel: viewModel)); + Widget _buildExpandedBody( + {required BuildContext context, required LoginViewModel viewModel}) => + Expanded( + child: _buildColumnScroller(context: context, viewModel: viewModel)); - Widget _buildColumnScroller({required BuildContext context,required LoginViewModel viewModel}) => + Widget _buildColumnScroller( + {required BuildContext context, required LoginViewModel viewModel}) => SingleChildScrollView( - child: _buildBodyWrapper(context: context,viewModel: viewModel), + child: _buildBodyWrapper(context: context, viewModel: viewModel), ); - Widget _buildBodyWrapper({required BuildContext context,required LoginViewModel viewModel}) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 15), - child: _buildBody(context: context,viewModel: viewModel), - ); + Widget _buildBodyWrapper( + {required BuildContext context, required LoginViewModel viewModel}) => + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildBody(context: context, viewModel: viewModel), + ); - Widget _buildBody({required BuildContext context,required LoginViewModel viewModel}) => Column( + Widget _buildBody( + {required BuildContext context, required LoginViewModel viewModel}) => + Column( crossAxisAlignment: CrossAxisAlignment.start, - children: _buildBodyChildren(context: context,viewModel: viewModel), + children: _buildBodyChildren(context: context, viewModel: viewModel), ); - - - - List _buildBodyChildren({required BuildContext context,required LoginViewModel viewModel}) => - [_buildUpperColumn(viewModel),getPadding(context), _buildLowerColumn(viewModel)]; - - + List _buildBodyChildren( + {required BuildContext context, required LoginViewModel viewModel}) => + [ + _buildUpperColumn(viewModel), + getPadding(context), + _buildLowerColumn(viewModel) + ]; Widget _buildUpperColumn(LoginViewModel viewModel) => Column( mainAxisSize: MainAxisSize.min, @@ -246,7 +265,6 @@ class LoginWithEmailScreen extends ViewModelWidget { text: 'Login with Phone Number', ); - Widget _buildLoginWithEmailState(LoginViewModel viewModel) => viewModel.busy(StateObjects.loginWithEmail) ? const PageLoadingIndicator() diff --git a/lib/ui/views/login/screens/login_with_phone_number_screen.dart b/lib/ui/views/login/screens/login_with_phone_number_screen.dart index 29ee135..8370a6f 100644 --- a/lib/ui/views/login/screens/login_with_phone_number_screen.dart +++ b/lib/ui/views/login/screens/login_with_phone_number_screen.dart @@ -18,70 +18,82 @@ class LoginWithPhoneNumberScreen extends ViewModelWidget { const LoginWithPhoneNumberScreen( {super.key, required this.phoneNumberController}); - Widget getPadding(context){ - double half = screenHeight(context)/2; - return SizedBox(height: half + 175 - half,); + Widget getPadding(context) { + double half = screenHeight(context) / 2; + return SizedBox( + height: half + 175 - half, + ); } @override Widget build(BuildContext context, LoginViewModel viewModel) => + _buildScaffoldWrapper(context: context, viewModel: viewModel); - _buildScaffoldWrapper(context: context,viewModel: viewModel); - - - - Widget _buildScaffoldWrapper({required BuildContext context,required LoginViewModel viewModel}) => Scaffold( - backgroundColor: kcBackgroundColor, - body: _buildScaffold(context: context,viewModel: viewModel), - ); - - - - Widget _buildScaffold({required BuildContext context,required LoginViewModel viewModel}) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: _buildScaffoldChildren(context: context,viewModel: viewModel), - ); - - List _buildScaffoldChildren({required BuildContext context,required LoginViewModel viewModel}) => - [_buildAppBar(viewModel), _buildExpandedBody(context: context,viewModel: viewModel)]; - - Widget _buildAppBar(LoginViewModel viewModel) => const LargeAppBar( - showBackButton: false, - showLanguageSelection: true, - ); - - Widget _buildExpandedBody({required BuildContext context,required LoginViewModel viewModel}) => - Expanded(child: _buildColumnScroller(context: context,viewModel: viewModel)); - - Widget _buildColumnScroller({required BuildContext context,required LoginViewModel viewModel}) => - SingleChildScrollView( - child: _buildBodyWrapper(context: context,viewModel: viewModel), + Widget _buildScaffoldWrapper( + {required BuildContext context, required LoginViewModel viewModel}) => + Scaffold( + backgroundColor: kcBackgroundColor, + body: _buildScaffold(context: context, viewModel: viewModel), ); - Widget _buildBodyWrapper({required BuildContext context,required LoginViewModel viewModel}) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 15), - child: _buildBody(context: context,viewModel: viewModel), - ); + Widget _buildScaffold( + {required BuildContext context, required LoginViewModel viewModel}) => + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + _buildScaffoldChildren(context: context, viewModel: viewModel), + ); - Widget _buildBody({required BuildContext context,required LoginViewModel viewModel}) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: _buildBodyChildren(context: context,viewModel: viewModel), - ); + List _buildScaffoldChildren( + {required BuildContext context, required LoginViewModel viewModel}) => + [ + _buildAppBar(viewModel), + _buildExpandedBody(context: context, viewModel: viewModel) + ]; + Widget _buildAppBar(LoginViewModel viewModel) => const LargeAppBar( + showBackButton: false, + showLanguageSelection: true, + ); + Widget _buildExpandedBody( + {required BuildContext context, required LoginViewModel viewModel}) => + Expanded( + child: _buildColumnScroller(context: context, viewModel: viewModel)); + Widget _buildColumnScroller( + {required BuildContext context, required LoginViewModel viewModel}) => + SingleChildScrollView( + child: _buildBodyWrapper(context: context, viewModel: viewModel), + ); - List _buildBodyChildren({required BuildContext context,required LoginViewModel viewModel}) => - [_buildUpperColumn(viewModel),getPadding(context), _buildLowerColumn(viewModel)]; + Widget _buildBodyWrapper( + {required BuildContext context, required LoginViewModel viewModel}) => + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildBody(context: context, viewModel: viewModel), + ); + Widget _buildBody( + {required BuildContext context, required LoginViewModel viewModel}) => + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: _buildBodyChildren(context: context, viewModel: viewModel), + ); + List _buildBodyChildren( + {required BuildContext context, required LoginViewModel viewModel}) => + [ + _buildUpperColumn(viewModel), + getPadding(context), + _buildLowerColumn(viewModel) + ]; Widget _buildUpperColumn(LoginViewModel viewModel) => Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: _buildUpperColumnChildren(viewModel), - ); - + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: _buildUpperColumnChildren(viewModel), + ); List _buildUpperColumnChildren(LoginViewModel viewModel) => [ verticalSpaceMedium, diff --git a/lib/ui/views/onboarding/onboarding_viewmodel.dart b/lib/ui/views/onboarding/onboarding_viewmodel.dart index 61953d6..7b2a635 100644 --- a/lib/ui/views/onboarding/onboarding_viewmodel.dart +++ b/lib/ui/views/onboarding/onboarding_viewmodel.dart @@ -481,5 +481,5 @@ class OnboardingViewModel extends FormViewModel { await _navigationService.navigateToAssessmentView(data: _userData); Future replaceWithHome() async => - await _navigationService.clearStackAndShowView(const HomeView()); + await _navigationService.clearStackAndShow(Routes.homeView); } diff --git a/lib/ui/views/ongoing_progress/ongoing_progress_view.dart b/lib/ui/views/ongoing_progress/ongoing_progress_view.dart index 4cd3fc3..f22fb60 100644 --- a/lib/ui/views/ongoing_progress/ongoing_progress_view.dart +++ b/lib/ui/views/ongoing_progress/ongoing_progress_view.dart @@ -58,6 +58,7 @@ class OngoingProgressView extends StackedView { Widget _buildAppbar(OngoingProgressViewModel viewModel) => SmallAppBar( title: 'My Progress', + showBackButton: true, onTap: viewModel.pop, ); diff --git a/lib/ui/views/privacy_policy/privacy_policy_view.dart b/lib/ui/views/privacy_policy/privacy_policy_view.dart index f4a04f5..521191f 100644 --- a/lib/ui/views/privacy_policy/privacy_policy_view.dart +++ b/lib/ui/views/privacy_policy/privacy_policy_view.dart @@ -54,8 +54,9 @@ class PrivacyPolicyView extends StackedView { ); Widget _buildAppbar(PrivacyPolicyViewModel viewModel) => SmallAppBar( - title: 'Privacy Policy', + showBackButton: true, onTap: viewModel.pop, + title: 'Privacy Policy', ); Widget _buildContentWrapper(PrivacyPolicyViewModel viewModel) => diff --git a/lib/ui/views/profile/profile_viewmodel.dart b/lib/ui/views/profile/profile_viewmodel.dart index ebe64f7..c9c75f2 100644 --- a/lib/ui/views/profile/profile_viewmodel.dart +++ b/lib/ui/views/profile/profile_viewmodel.dart @@ -42,7 +42,7 @@ class ProfileViewModel extends ReactiveViewModel { pop(); if (image != null) { await updateProfilePicture(image); - await _authenticationService.saveProfileImage(image); + await _authenticationService.saveProfilePicture(image); } } @@ -54,7 +54,7 @@ class ProfileViewModel extends ReactiveViewModel { pop(); if (image != null) { await updateProfilePicture(image); - await _authenticationService.saveProfileImage(image); + await _authenticationService.saveProfilePicture(image); } } diff --git a/lib/ui/views/profile_detail/profile_detail_view.dart b/lib/ui/views/profile_detail/profile_detail_view.dart index bb5305a..c407fb2 100644 --- a/lib/ui/views/profile_detail/profile_detail_view.dart +++ b/lib/ui/views/profile_detail/profile_detail_view.dart @@ -148,8 +148,9 @@ class ProfileDetailView extends StackedView ]; Widget _buildAppbar(ProfileDetailViewModel viewModel) => SmallAppBar( - title: 'Edit Profile', onTap: viewModel.pop, + showBackButton: true, + title: 'Edit Profile', ); Widget _buildColumnWrapper( diff --git a/lib/ui/views/profile_detail/profile_detail_viewmodel.dart b/lib/ui/views/profile_detail/profile_detail_viewmodel.dart index fb73aa4..42322a6 100644 --- a/lib/ui/views/profile_detail/profile_detail_viewmodel.dart +++ b/lib/ui/views/profile_detail/profile_detail_viewmodel.dart @@ -185,7 +185,7 @@ class ProfileDetailViewModel extends ReactiveViewModel pop(); if (image != null) { await updateProfilePicture(image); - await _authenticationService.saveProfileImage(image); + await _authenticationService.saveProfilePicture(image); } } @@ -197,7 +197,7 @@ class ProfileDetailViewModel extends ReactiveViewModel pop(); if (image != null) { await updateProfilePicture(image); - await _authenticationService.saveProfileImage(image); + await _authenticationService.saveProfilePicture(image); } } diff --git a/lib/ui/views/progress/progress_view.dart b/lib/ui/views/progress/progress_view.dart index 4b42ac7..7e64758 100644 --- a/lib/ui/views/progress/progress_view.dart +++ b/lib/ui/views/progress/progress_view.dart @@ -57,6 +57,7 @@ class ProgressView extends StackedView { Widget _buildAppbar(ProgressViewModel viewModel) => SmallAppBar( title: 'My Progress', onTap: viewModel.pop, + showBackButton: true, ); Widget _buildContentWrapper(ProgressViewModel viewModel) => diff --git a/lib/ui/views/register/register_view.dart b/lib/ui/views/register/register_view.dart index d50a053..5548831 100644 --- a/lib/ui/views/register/register_view.dart +++ b/lib/ui/views/register/register_view.dart @@ -87,8 +87,6 @@ class RegisterView extends StackedView with $RegisterView { _pop(value: value, viewModel: viewModel), child: _buildBody(viewModel)); - - Widget _buildBody(RegisterViewModel viewModel) => IndexedStack(index: viewModel.currentPage, children: _buildScreens()); @@ -114,5 +112,4 @@ class RegisterView extends StackedView with $RegisterView { Widget _buildCreatePasswordScreen() => CreatePasswordScreen( passwordController: passwordController, confirmPasswordController: confirmPasswordController); - } diff --git a/lib/ui/views/register/register_viewmodel.dart b/lib/ui/views/register/register_viewmodel.dart index 62a3eb6..6c51bfa 100644 --- a/lib/ui/views/register/register_viewmodel.dart +++ b/lib/ui/views/register/register_viewmodel.dart @@ -23,7 +23,6 @@ class RegisterViewModel extends FormViewModel { final _googleAuthService = locator(); - final _authenticationService = locator(); // Navigation @@ -284,17 +283,18 @@ class RegisterViewModel extends FormViewModel { await _navigationService.replaceWithLoginView(); Future replaceWithHome() async => - await _navigationService.clearStackAndShowView(const HomeView()); + await _navigationService.clearStackAndShow(Routes.homeView); // Remote api calls // Register - Future registerWithEmail() async => - await runBusyFuture(_register(), busyObject: StateObjects.registerWithEmail); + Future registerWithEmail() async => await runBusyFuture(_register(), + busyObject: StateObjects.registerWithEmail); Future _register() async { if (await _statusChecker.checkConnection()) { - Map response = await _apiService.registerWithEmail(_userData); + Map response = + await _apiService.registerWithEmail(_userData); if (response['status'] == ResponseStatus.success) { goTo(page: 3); diff --git a/lib/ui/views/register/screens/register_with_email_screen.dart b/lib/ui/views/register/screens/register_with_email_screen.dart index a434168..c3cefce 100644 --- a/lib/ui/views/register/screens/register_with_email_screen.dart +++ b/lib/ui/views/register/screens/register_with_email_screen.dart @@ -231,8 +231,6 @@ class RegisterWithEmailScreen extends ViewModelWidget { onTap: () => viewModel.goTo(page: 1), ); - - Widget _buildRegisterWithGoogleState(RegisterViewModel viewModel) => viewModel.busy(StateObjects.registerWithEmail) ? const PageLoadingIndicator() diff --git a/lib/ui/views/register/screens/registration_otp_screen.dart b/lib/ui/views/register/screens/registration_otp_screen.dart index d156c30..ef3ee00 100644 --- a/lib/ui/views/register/screens/registration_otp_screen.dart +++ b/lib/ui/views/register/screens/registration_otp_screen.dart @@ -26,10 +26,11 @@ class RegistrationOtpScreen extends ViewModelWidget { required this.emailController, required this.phoneNumberController}); - - Widget getPadding(context){ - double half = screenHeight(context)/2; - return SizedBox(height: half + 325 - half,); + Widget getPadding(context) { + double half = screenHeight(context) / 2; + return SizedBox( + height: half + 325 - half, + ); } Future _verifyOtp(RegisterViewModel viewModel) async { @@ -45,20 +46,21 @@ class RegistrationOtpScreen extends ViewModelWidget { await viewModel.verifyOtp(); } - @override Widget build(BuildContext context, RegisterViewModel viewModel) => _buildScaffoldWrapper(context: context, viewModel: viewModel); - Widget _buildScaffoldWrapper( {required BuildContext context, - required RegisterViewModel viewModel}) => Scaffold( - backgroundColor: kcBackgroundColor, - body: _buildScaffoldStack(context: context, viewModel: viewModel), - ); + Widget _buildScaffoldWrapper( + {required BuildContext context, + required RegisterViewModel viewModel}) => + Scaffold( + backgroundColor: kcBackgroundColor, + body: _buildScaffoldStack(context: context, viewModel: viewModel), + ); Widget _buildScaffoldStack( - {required BuildContext context, - required RegisterViewModel viewModel}) => + {required BuildContext context, + required RegisterViewModel viewModel}) => Stack( children: [ _buildScaffold(context: context, viewModel: viewModel), @@ -66,49 +68,66 @@ class RegistrationOtpScreen extends ViewModelWidget { ], ); - Widget _buildScaffold( {required BuildContext context, - required RegisterViewModel viewModel}) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: _buildScaffoldChildren(context: context, viewModel: viewModel), - ); + Widget _buildScaffold( + {required BuildContext context, + required RegisterViewModel viewModel}) => + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: + _buildScaffoldChildren(context: context, viewModel: viewModel), + ); - List _buildScaffoldChildren( {required BuildContext context, - required RegisterViewModel viewModel}) => - [_buildAppBar(viewModel), _buildExpandedBody(context: context, viewModel: viewModel)]; + List _buildScaffoldChildren( + {required BuildContext context, + required RegisterViewModel viewModel}) => + [ + _buildAppBar(viewModel), + _buildExpandedBody(context: context, viewModel: viewModel) + ]; Widget _buildAppBar(RegisterViewModel viewModel) => const LargeAppBar( - showBackButton: false, - showLanguageSelection: true, - ); + showBackButton: false, + showLanguageSelection: true, + ); - Widget _buildExpandedBody( {required BuildContext context, - required RegisterViewModel viewModel}) => - Expanded(child: _buildColumnScroller(context: context, viewModel: viewModel)); + Widget _buildExpandedBody( + {required BuildContext context, + required RegisterViewModel viewModel}) => + Expanded( + child: _buildColumnScroller(context: context, viewModel: viewModel)); - Widget _buildColumnScroller( {required BuildContext context, - required RegisterViewModel viewModel}) => + Widget _buildColumnScroller( + {required BuildContext context, + required RegisterViewModel viewModel}) => SingleChildScrollView( child: _buildBodyWrapper(context: context, viewModel: viewModel), ); - Widget _buildBodyWrapper( {required BuildContext context, - required RegisterViewModel viewModel}) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 15), - child: _buildBody(context: context, viewModel: viewModel), - ); - - Widget _buildBody( {required BuildContext context, - required RegisterViewModel viewModel}) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: _buildBodyChildren(context: context, viewModel: viewModel), - ); - - List _buildBodyChildren( {required BuildContext context, - required RegisterViewModel viewModel}) => - [_buildUpperColumn(viewModel),getPadding(context), _buildContinueButtonWrapper(viewModel)]; + Widget _buildBodyWrapper( + {required BuildContext context, + required RegisterViewModel viewModel}) => + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15), + child: _buildBody(context: context, viewModel: viewModel), + ); + Widget _buildBody( + {required BuildContext context, + required RegisterViewModel viewModel}) => + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: _buildBodyChildren(context: context, viewModel: viewModel), + ); + List _buildBodyChildren( + {required BuildContext context, + required RegisterViewModel viewModel}) => + [ + _buildUpperColumn(viewModel), + getPadding(context), + _buildContinueButtonWrapper(viewModel) + ]; Widget _buildUpperColumn(RegisterViewModel viewModel) => Column( mainAxisSize: MainAxisSize.min, diff --git a/lib/ui/views/startup/startup_view.dart b/lib/ui/views/startup/startup_view.dart index 77f9458..c2853b4 100644 --- a/lib/ui/views/startup/startup_view.dart +++ b/lib/ui/views/startup/startup_view.dart @@ -70,8 +70,7 @@ class StartupView extends StackedView { _buildIndicatorWrapper(), ]; - Widget _buildLoadingText() => - Text('$label ...', style: const TextStyle(color: kcWhite, fontSize: 16)); + Widget _buildLoadingText() => Text('$label ...', style: style16W600); Widget _buildIndicatorWrapper() => SizedBox( width: 16, @@ -83,7 +82,7 @@ class StartupView extends StackedView { const CustomCircularProgressIndicator(color: kcWhite); Widget _buildIconWrapper() => Padding( - padding: const EdgeInsets.only(top: 100), + padding: const EdgeInsets.only(top: 120), child: _buildIcon(), ); diff --git a/lib/ui/views/support/support_view.dart b/lib/ui/views/support/support_view.dart index 0010b9f..f1f865e 100644 --- a/lib/ui/views/support/support_view.dart +++ b/lib/ui/views/support/support_view.dart @@ -52,6 +52,7 @@ class SupportView extends StackedView { Widget _buildAppbar(SupportViewModel viewModel) => SmallAppBar( title: 'Need Help?', + showBackButton: true, onTap: viewModel.pop, ); diff --git a/lib/ui/views/telegram_support/telegram_support_view.dart b/lib/ui/views/telegram_support/telegram_support_view.dart index 0d5507e..8687a3e 100644 --- a/lib/ui/views/telegram_support/telegram_support_view.dart +++ b/lib/ui/views/telegram_support/telegram_support_view.dart @@ -49,8 +49,9 @@ class TelegramSupportView extends StackedView { ); Widget _buildAppbar(TelegramSupportViewModel viewModel) => SmallAppBar( - title: 'Telegram Support', onTap: viewModel.pop, + showBackButton: true, + title: 'Telegram Support', ); Widget _buildExpandedColumn(TelegramSupportViewModel viewModel) => diff --git a/lib/ui/views/terms_and_conditions/terms_and_conditions_view.dart b/lib/ui/views/terms_and_conditions/terms_and_conditions_view.dart index 2b03944..f007d96 100644 --- a/lib/ui/views/terms_and_conditions/terms_and_conditions_view.dart +++ b/lib/ui/views/terms_and_conditions/terms_and_conditions_view.dart @@ -57,8 +57,9 @@ class TermsAndConditionsView extends StackedView { ); Widget _buildAppbar(TermsAndConditionsViewModel viewModel) => SmallAppBar( - title: 'Terms and Conditions', onTap: viewModel.pop, + showBackButton: true, + title: 'Terms and Conditions', ); Widget _buildContentWrapper(TermsAndConditionsViewModel viewModel) => diff --git a/lib/ui/views/welcome/screens/first_welcome_screen.dart b/lib/ui/views/welcome/screens/first_welcome_screen.dart index 7efacdd..17663a8 100644 --- a/lib/ui/views/welcome/screens/first_welcome_screen.dart +++ b/lib/ui/views/welcome/screens/first_welcome_screen.dart @@ -59,14 +59,10 @@ class FirstWelcomeScreen extends ViewModelWidget { height: 50, ); - Widget _buildTitle() => const Text( + Widget _buildTitle() => Text( 'Small daily practice. Big lifelong results.', + style: style25W600, textAlign: TextAlign.center, - style: TextStyle( - fontSize: 30, - color: kcWhite, - fontWeight: FontWeight.w600, - ), ); Widget _buildContinueButtonWrapper(WelcomeViewModel viewModel) => Align( @@ -85,8 +81,8 @@ class FirstWelcomeScreen extends ViewModelWidget { borderRadius: 12, text: 'Start Learning', backgroundColor: kcWhite, - trailingIcon: Icons.arrow_forward, onTap: () => viewModel.next(), foregroundColor: kcPrimaryColor, + trailingIcon: Icons.arrow_forward, ); } diff --git a/lib/ui/widgets/cancel_learn_practice_sheet.dart b/lib/ui/widgets/cancel_learn_practice_sheet.dart index 632559c..a94ba48 100644 --- a/lib/ui/widgets/cancel_learn_practice_sheet.dart +++ b/lib/ui/widgets/cancel_learn_practice_sheet.dart @@ -37,8 +37,7 @@ class CancelLearnPracticeSheet extends StatelessWidget { verticalSpaceLarge, _buildContinueButton(), _buildEndButton(), - - ]; + ]; Widget _buildImage() => const SpeakingPartnerImage( radius: 45, diff --git a/lib/ui/widgets/custom_circular_progress_indicator.dart b/lib/ui/widgets/custom_circular_progress_indicator.dart index 64fab28..b6a8ede 100644 --- a/lib/ui/widgets/custom_circular_progress_indicator.dart +++ b/lib/ui/widgets/custom_circular_progress_indicator.dart @@ -9,6 +9,6 @@ class CustomCircularProgressIndicator extends StatelessWidget { Widget _buildIndicator() => CircularProgressIndicator( color: color, - strokeWidth: 6, + strokeWidth: 5, ); } diff --git a/lib/ui/widgets/custom_column_button.dart b/lib/ui/widgets/custom_column_button.dart index b1bf3d2..4affa1a 100644 --- a/lib/ui/widgets/custom_column_button.dart +++ b/lib/ui/widgets/custom_column_button.dart @@ -29,22 +29,25 @@ class CustomColumnButton extends StatelessWidget { children: _buildColumnChildren(), ); - List _buildColumnChildren() => [ - _buildIconWrapper(), - _buildLabel() - ]; + List _buildColumnChildren() => [_buildIconWrapper(), _buildLabel()]; Widget _buildIconWrapper() => Container( - padding:const EdgeInsets.all(5), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: color.withOpacity(0.1), - border: Border.all(color: color.withOpacity(0.75)) - ), - child: _buildIcon(), - ); + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: color.withOpacity(0.1), + border: Border.all(color: color.withOpacity(0.75))), + child: _buildIcon(), + ); - Widget _buildLabel()=> Text(label,style: style14LG400.copyWith(color: color),); + Widget _buildLabel() => Text( + label, + style: style14LG400.copyWith(color: color), + ); - Widget _buildIcon()=> Icon(icon,size: 14,color: color,); + Widget _buildIcon() => Icon( + icon, + size: 14, + color: color, + ); } diff --git a/lib/ui/widgets/custom_list_tile.dart b/lib/ui/widgets/custom_list_tile.dart index c345915..01359e4 100644 --- a/lib/ui/widgets/custom_list_tile.dart +++ b/lib/ui/widgets/custom_list_tile.dart @@ -57,10 +57,7 @@ class CustomListTile extends StatelessWidget { Widget _buildTrailingText() => Text( language ?? '', - style: const TextStyle( - fontSize: 12, - color: kcDarkGrey, - ), + style: style12DG400, ); Widget _buildTrailingIcon() => const Icon( diff --git a/lib/ui/widgets/learn_lesson_tile.dart b/lib/ui/widgets/learn_lesson_tile.dart index ef60c78..c9d2a4c 100644 --- a/lib/ui/widgets/learn_lesson_tile.dart +++ b/lib/ui/widgets/learn_lesson_tile.dart @@ -13,10 +13,12 @@ class LearnLessonTile extends StatelessWidget { final String thumbnail; final ProgressStatuses status; final GestureTapCallback? onLessonTap; + final GestureTapCallback? onPracticeTap; const LearnLessonTile({ super.key, this.onLessonTap, + this.onPracticeTap, required this.title, required this.status, required this.thumbnail, @@ -181,11 +183,12 @@ class LearnLessonTile extends StatelessWidget { _buildLessonButton(), ]; - Widget _buildPracticeButton() => const CustomElevatedButton( + Widget _buildPracticeButton() => CustomElevatedButton( height: 15, width: 135, text: 'Practice', borderRadius: 12, + onTap: onPracticeTap, trailingIcon: Icons.mic, backgroundColor: kcWhite, borderColor: kcPrimaryColor, diff --git a/lib/ui/widgets/learn_module_tile.dart b/lib/ui/widgets/learn_module_tile.dart index 478e261..e336e30 100644 --- a/lib/ui/widgets/learn_module_tile.dart +++ b/lib/ui/widgets/learn_module_tile.dart @@ -218,8 +218,9 @@ class LearnModuleTile extends ViewModelWidget { backgroundColor: kcWhite, borderColor: kcPrimaryColor, foregroundColor: kcPrimaryColor, - onTap: () async => - await _showSheet(context: context, viewModel: viewModel), + onTap: () async => status == ProgressStatuses.completed + ? await viewModel.navigateToLearnPractice() + : await _showSheet(context: context, viewModel: viewModel), ); Widget _buildSheet(LearnModuleViewModel viewModel) => FinishPracticeSheet( diff --git a/lib/ui/widgets/learn_practice_tip_section.dart b/lib/ui/widgets/learn_practice_tip_section.dart new file mode 100644 index 0000000..03582d4 --- /dev/null +++ b/lib/ui/widgets/learn_practice_tip_section.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:yimaru_app/ui/common/app_colors.dart'; +import 'package:yimaru_app/ui/common/ui_helpers.dart'; +import 'package:yimaru_app/ui/widgets/custom_list_tile.dart'; + +class LearnPracticeTipSection extends StatelessWidget { + const LearnPracticeTipSection({super.key}); + + @override + Widget build(BuildContext context) => _buildContainer(); + + Widget _buildContainer() => Container( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 25), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + color: kcBlue.withOpacity(0.1), + ), + child: _buildColumn(), + ); + + Widget _buildColumn() => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: _buildColumnChildren(), + ); + + List _buildColumnChildren() => + [_buildTitleWrapper(), verticalSpaceTiny, _buildContent()]; + + Widget _buildTitleWrapper() => + Row( + children: [ + _buildLeading(),horizontalSpaceSmall,_buildTitle() + ], + ); + + + Widget _buildLeading() => const Icon( + Icons.lightbulb_outline_rounded, + color: kcBlue, + ); + + Widget _buildTitle() => Text( + 'Quick Tip', + style: style16B600, + ); + + + Widget _buildContent() => Text( + "You can always do better!\nSpeak in full sentences instead of short phrases.\nMaintain a steady pace, not too fast, not too slow.\nUse varied vocabulary to make your answers richer.\nPause naturally instead of using fillers like “um” or “uh”.", + style: style14B400, + textAlign: TextAlign.start, + ); +} diff --git a/lib/ui/widgets/learn_sub_level_tile.dart b/lib/ui/widgets/learn_sub_level_tile.dart index b50e48a..a1c1783 100644 --- a/lib/ui/widgets/learn_sub_level_tile.dart +++ b/lib/ui/widgets/learn_sub_level_tile.dart @@ -123,14 +123,14 @@ class LearnSubLevelTile extends ViewModelWidget { ); Widget _buildPracticeButton(LearnLevelViewModel viewModel) => - const CustomElevatedButton( + CustomElevatedButton( height: 15, text: 'Practice', borderRadius: 12, backgroundColor: kcWhite, borderColor: kcPrimaryColor, foregroundColor: kcPrimaryColor, - + onTap: () async => await viewModel.navigateToLearnPractice() // onTap: () async => await viewModel.navigateToLearnLevel(), ); } diff --git a/lib/ui/widgets/practice_response_card.dart b/lib/ui/widgets/practice_response_card.dart new file mode 100644 index 0000000..e6fb23a --- /dev/null +++ b/lib/ui/widgets/practice_response_card.dart @@ -0,0 +1,71 @@ +import 'package:flutter/material.dart'; +import 'package:yimaru_app/ui/common/app_colors.dart'; +import 'package:yimaru_app/ui/common/ui_helpers.dart'; + +class PracticeResponseCard extends StatelessWidget { + final String title; + final String subtitle; + + const PracticeResponseCard( + {super.key, required this.title, required this.subtitle}); + + @override + Widget build(BuildContext context) => _buildContainer(); + + Widget _buildContainer() => Container( + decoration: BoxDecoration( + color: kcWhite, + borderRadius: BorderRadius.circular(12), + ), + padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5), + child: _buildRow(), + ); + + Widget _buildRow() => Row( + children: [ + _buildPlayButton(), + _buildColumnWrapper() + ], + ); + + Widget _buildPlayButton() => ElevatedButton( + onPressed: () {}, + style: const ButtonStyle( + shape: WidgetStatePropertyAll(CircleBorder()), + padding: WidgetStatePropertyAll(EdgeInsets.all(5)), + shadowColor: WidgetStatePropertyAll(kcPrimaryColor), + backgroundColor: WidgetStatePropertyAll(kcPrimaryColor), + ), + child: _buildPlayIcon(), + ); + + Widget _buildPlayIcon() => const Icon( + Icons.play_arrow_rounded, + size: 25, + color: kcWhite, + ); + + Widget _buildColumnWrapper() => Expanded(child: _buildColumn()); + + Widget _buildColumn() => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: _buildColumnChildren(), + ); + + List _buildColumnChildren() => [_buildTitle(), _buildSubtitle()]; + + Widget _buildTitle() => Text( + title, + maxLines: 1, + softWrap: false, + style: style12RP600, + ); + + Widget _buildSubtitle() => Text( + subtitle, + maxLines: 1, + softWrap: false, + style: style12RP600, + ); +} diff --git a/lib/ui/widgets/practice_result_card.dart b/lib/ui/widgets/practice_result_card.dart new file mode 100644 index 0000000..2b15090 --- /dev/null +++ b/lib/ui/widgets/practice_result_card.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:yimaru_app/ui/common/ui_helpers.dart'; +import 'package:yimaru_app/ui/widgets/practice_response_card.dart'; + +class PracticeResultCard extends StatelessWidget { + final int index; + final Map data; + const PracticeResultCard( + {super.key, required this.index, required this.data}); + + @override + Widget build(BuildContext context) => _buildColumnWrapper(); + + Widget _buildColumnWrapper() => SizedBox(height: 100,width: double.maxFinite,child: _buildColumn(),); + + Widget _buildColumn() => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: _buildColumnChildren(), + ); + + List _buildColumnChildren() => [_buildQuestion(),verticalSpaceSmall, _buildRow()]; + + Widget _buildQuestion() => Text( + '$index. ${data['question']}', + style: style14DG400, + ); + + Widget _buildRow() => Row( + children: _buildRowChildren(), + ); + + List _buildRowChildren() => + [_buildSampleResponseWrapper(),horizontalSpaceSmall, _buildActualResponseWrapper()]; + + Widget _buildSampleResponseWrapper() => + Expanded(child: _buildSampleResponse()); + + Widget _buildSampleResponse() => + const PracticeResponseCard(title: 'Sample Answer', subtitle: '0:54'); + + Widget _buildActualResponseWrapper() => + Expanded(child: _buildActualResponse()); + + Widget _buildActualResponse() => + const PracticeResponseCard(title: 'Sample Answer', subtitle: '0:54'); +} diff --git a/lib/ui/widgets/practice_results_wrapper.dart b/lib/ui/widgets/practice_results_wrapper.dart new file mode 100644 index 0000000..e42943b --- /dev/null +++ b/lib/ui/widgets/practice_results_wrapper.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:yimaru_app/ui/common/ui_helpers.dart'; +import 'package:yimaru_app/ui/widgets/practice_result_card.dart'; + +import '../common/app_colors.dart'; + +class PracticeResultsWrapper extends StatelessWidget { + final List> data; + + const PracticeResultsWrapper({super.key, required this.data}); + + @override + Widget build(BuildContext context) => _buildContainer(); + + Widget _buildContainer() => Container( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 25), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(15), + color: kcPrimaryColor.withOpacity(0.1), + ), + child: _buildColumn(), + ); + + Widget _buildColumn() => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: _buildColumnChildren(), + ); + + List _buildColumnChildren() => + [_buildTitle(), verticalSpaceSmall, _buildResults()]; + + Widget _buildTitle() => Text( + 'Conversation Review', + style: style16DG600, + textAlign: TextAlign.center, + ); + + Widget _buildResults() => ListView.separated( + shrinkWrap: true, + itemCount: data.length, + padding: EdgeInsets.zero, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) => _buildResult(index), + separatorBuilder: (context, index) => verticalSpaceSmall, + ); + + Widget _buildResult(int index) => + PracticeResultCard(index: index + 1, data: data[index]); +} diff --git a/lib/ui/widgets/small_app_bar.dart b/lib/ui/widgets/small_app_bar.dart index 97a28af..cc5b160 100644 --- a/lib/ui/widgets/small_app_bar.dart +++ b/lib/ui/widgets/small_app_bar.dart @@ -4,9 +4,11 @@ import 'package:yimaru_app/ui/widgets/custom_back_button.dart'; class SmallAppBar extends StatelessWidget { final String? title; + final bool showBackButton; final GestureTapCallback? onTap; - const SmallAppBar({super.key, this.onTap, this.title}); + const SmallAppBar( + {super.key, this.onTap, this.title, required this.showBackButton}); @override Widget build(BuildContext context) => _buildAppBar(); @@ -16,8 +18,10 @@ class SmallAppBar extends StatelessWidget { children: _buildAppBarChildren(), ); - List _buildAppBarChildren() => - [_buildBackButtonWrapper(), if (title != null) _buildTitleWrapper()]; + List _buildAppBarChildren() => [ + if (showBackButton) _buildBackButtonWrapper(), + if (title != null) _buildTitleWrapper() + ]; Widget _buildBackButtonWrapper() => Align( alignment: Alignment.centerLeft, diff --git a/lib/ui/widgets/speaking_partner_image.dart b/lib/ui/widgets/speaking_partner_image.dart index 0d8c4ad..22e0dd1 100644 --- a/lib/ui/widgets/speaking_partner_image.dart +++ b/lib/ui/widgets/speaking_partner_image.dart @@ -4,17 +4,17 @@ import '../common/app_colors.dart'; class SpeakingPartnerImage extends StatelessWidget { final double radius; - const SpeakingPartnerImage({super.key,required this.radius}); + const SpeakingPartnerImage({super.key, required this.radius}); @override Widget build(BuildContext context) => _buildProfileImage(); - Widget _buildProfileImage() => CircleAvatar( - radius: radius, - backgroundColor: kcViolet, - backgroundImage: _buildImageBuilder(), - ); + radius: radius, + backgroundColor: kcViolet, + backgroundImage: _buildImageBuilder(), + ); - AssetImage? _buildImageBuilder() => const AssetImage('assets/images/profile.png'); + AssetImage? _buildImageBuilder() => + const AssetImage('assets/images/profile.png'); } diff --git a/test/helpers/test_helpers.mocks.dart b/test/helpers/test_helpers.mocks.dart deleted file mode 100644 index 5762ae1..0000000 --- a/test/helpers/test_helpers.mocks.dart +++ /dev/null @@ -1,1424 +0,0 @@ -// Mocks generated by Mockito 5.4.4 from annotations -// in yimaru_app/test/helpers/test_helpers.dart. -// Do not manually edit this file. - -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i8; -import 'dart:ui' as _i9; - -import 'package:dio/dio.dart' as _i2; -import 'package:flutter/material.dart' as _i7; -import 'package:google_sign_in/google_sign_in.dart' as _i4; -import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i6; -import 'package:permission_handler/permission_handler.dart' as _i17; -import 'package:stacked_services/stacked_services.dart' as _i5; -import 'package:yimaru_app/models/assessment.dart' as _i13; -import 'package:yimaru_app/models/user_model.dart' as _i11; -import 'package:yimaru_app/services/api_service.dart' as _i12; -import 'package:yimaru_app/services/authentication_service.dart' as _i10; -import 'package:yimaru_app/services/dio_service.dart' as _i14; -import 'package:yimaru_app/services/google_auth_service.dart' as _i19; -import 'package:yimaru_app/services/image_downloader_service.dart' as _i20; -import 'package:yimaru_app/services/image_picker_service.dart' as _i18; -import 'package:yimaru_app/services/permission_handler_service.dart' as _i16; -import 'package:yimaru_app/services/secure_storage_service.dart' as _i3; -import 'package:yimaru_app/services/status_checker_service.dart' as _i15; - -// ignore_for_file: type=lint -// ignore_for_file: avoid_redundant_argument_values -// ignore_for_file: avoid_setters_without_getters -// ignore_for_file: comment_references -// ignore_for_file: deprecated_member_use -// ignore_for_file: deprecated_member_use_from_same_package -// ignore_for_file: implementation_imports -// ignore_for_file: invalid_use_of_visible_for_testing_member -// ignore_for_file: prefer_const_constructors -// ignore_for_file: unnecessary_parenthesis -// ignore_for_file: camel_case_types -// ignore_for_file: subtype_of_sealed_class - -class _FakeDio_0 extends _i1.SmartFake implements _i2.Dio { - _FakeDio_0( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeSecureStorageService_1 extends _i1.SmartFake - implements _i3.SecureStorageService { - _FakeSecureStorageService_1( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -class _FakeGoogleSignIn_2 extends _i1.SmartFake implements _i4.GoogleSignIn { - _FakeGoogleSignIn_2( - Object parent, - Invocation parentInvocation, - ) : super( - parent, - parentInvocation, - ); -} - -/// A class which mocks [NavigationService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockNavigationService extends _i1.Mock implements _i5.NavigationService { - @override - String get previousRoute => (super.noSuchMethod( - Invocation.getter(#previousRoute), - returnValue: _i6.dummyValue( - this, - Invocation.getter(#previousRoute), - ), - returnValueForMissingStub: _i6.dummyValue( - this, - Invocation.getter(#previousRoute), - ), - ) as String); - - @override - String get currentRoute => (super.noSuchMethod( - Invocation.getter(#currentRoute), - returnValue: _i6.dummyValue( - this, - Invocation.getter(#currentRoute), - ), - returnValueForMissingStub: _i6.dummyValue( - this, - Invocation.getter(#currentRoute), - ), - ) as String); - - @override - _i7.GlobalKey<_i7.NavigatorState>? nestedNavigationKey(int? index) => - (super.noSuchMethod( - Invocation.method( - #nestedNavigationKey, - [index], - ), - returnValueForMissingStub: null, - ) as _i7.GlobalKey<_i7.NavigatorState>?); - - @override - void config({ - bool? enableLog, - bool? defaultPopGesture, - bool? defaultOpaqueRoute, - Duration? defaultDurationTransition, - bool? defaultGlobalState, - _i5.Transition? defaultTransitionStyle, - String? defaultTransition, - }) => - super.noSuchMethod( - Invocation.method( - #config, - [], - { - #enableLog: enableLog, - #defaultPopGesture: defaultPopGesture, - #defaultOpaqueRoute: defaultOpaqueRoute, - #defaultDurationTransition: defaultDurationTransition, - #defaultGlobalState: defaultGlobalState, - #defaultTransitionStyle: defaultTransitionStyle, - #defaultTransition: defaultTransition, - }, - ), - returnValueForMissingStub: null, - ); - - @override - _i8.Future? navigateWithTransition( - _i7.Widget? page, { - bool? opaque, - String? transition = r'', - Duration? duration, - bool? popGesture, - int? id, - _i7.Curve? curve, - bool? fullscreenDialog = false, - bool? preventDuplicates = true, - _i5.Transition? transitionClass, - _i5.Transition? transitionStyle, - String? routeName, - }) => - (super.noSuchMethod( - Invocation.method( - #navigateWithTransition, - [page], - { - #opaque: opaque, - #transition: transition, - #duration: duration, - #popGesture: popGesture, - #id: id, - #curve: curve, - #fullscreenDialog: fullscreenDialog, - #preventDuplicates: preventDuplicates, - #transitionClass: transitionClass, - #transitionStyle: transitionStyle, - #routeName: routeName, - }, - ), - returnValueForMissingStub: null, - ) as _i8.Future?); - - @override - _i8.Future? replaceWithTransition( - _i7.Widget? page, { - bool? opaque, - String? transition = r'', - Duration? duration, - bool? popGesture, - int? id, - _i7.Curve? curve, - bool? fullscreenDialog = false, - bool? preventDuplicates = true, - _i5.Transition? transitionClass, - _i5.Transition? transitionStyle, - String? routeName, - }) => - (super.noSuchMethod( - Invocation.method( - #replaceWithTransition, - [page], - { - #opaque: opaque, - #transition: transition, - #duration: duration, - #popGesture: popGesture, - #id: id, - #curve: curve, - #fullscreenDialog: fullscreenDialog, - #preventDuplicates: preventDuplicates, - #transitionClass: transitionClass, - #transitionStyle: transitionStyle, - #routeName: routeName, - }, - ), - returnValueForMissingStub: null, - ) as _i8.Future?); - - @override - bool back({ - dynamic result, - int? id, - }) => - (super.noSuchMethod( - Invocation.method( - #back, - [], - { - #result: result, - #id: id, - }, - ), - returnValue: false, - returnValueForMissingStub: false, - ) as bool); - - @override - void popUntil( - _i7.RoutePredicate? predicate, { - int? id, - }) => - super.noSuchMethod( - Invocation.method( - #popUntil, - [predicate], - {#id: id}, - ), - returnValueForMissingStub: null, - ); - - @override - void popRepeated(int? popTimes) => super.noSuchMethod( - Invocation.method( - #popRepeated, - [popTimes], - ), - returnValueForMissingStub: null, - ); - - @override - _i8.Future? navigateTo( - String? routeName, { - dynamic arguments, - int? id, - bool? preventDuplicates = true, - Map? parameters, - _i7.RouteTransitionsBuilder? transition, - }) => - (super.noSuchMethod( - Invocation.method( - #navigateTo, - [routeName], - { - #arguments: arguments, - #id: id, - #preventDuplicates: preventDuplicates, - #parameters: parameters, - #transition: transition, - }, - ), - returnValueForMissingStub: null, - ) as _i8.Future?); - - @override - _i8.Future? navigateToView( - _i7.Widget? view, { - dynamic arguments, - int? id, - bool? opaque, - _i7.Curve? curve, - Duration? duration, - bool? fullscreenDialog = false, - bool? popGesture, - bool? preventDuplicates = true, - _i5.Transition? transition, - _i5.Transition? transitionStyle, - }) => - (super.noSuchMethod( - Invocation.method( - #navigateToView, - [view], - { - #arguments: arguments, - #id: id, - #opaque: opaque, - #curve: curve, - #duration: duration, - #fullscreenDialog: fullscreenDialog, - #popGesture: popGesture, - #preventDuplicates: preventDuplicates, - #transition: transition, - #transitionStyle: transitionStyle, - }, - ), - returnValueForMissingStub: null, - ) as _i8.Future?); - - @override - _i8.Future? replaceWith( - String? routeName, { - dynamic arguments, - int? id, - bool? preventDuplicates = true, - Map? parameters, - _i7.RouteTransitionsBuilder? transition, - }) => - (super.noSuchMethod( - Invocation.method( - #replaceWith, - [routeName], - { - #arguments: arguments, - #id: id, - #preventDuplicates: preventDuplicates, - #parameters: parameters, - #transition: transition, - }, - ), - returnValueForMissingStub: null, - ) as _i8.Future?); - - @override - _i8.Future? clearStackAndShow( - String? routeName, { - dynamic arguments, - int? id, - Map? parameters, - }) => - (super.noSuchMethod( - Invocation.method( - #clearStackAndShow, - [routeName], - { - #arguments: arguments, - #id: id, - #parameters: parameters, - }, - ), - returnValueForMissingStub: null, - ) as _i8.Future?); - - @override - _i8.Future? clearStackAndShowView( - _i7.Widget? view, { - dynamic arguments, - int? id, - }) => - (super.noSuchMethod( - Invocation.method( - #clearStackAndShowView, - [view], - { - #arguments: arguments, - #id: id, - }, - ), - returnValueForMissingStub: null, - ) as _i8.Future?); - - @override - _i8.Future? clearTillFirstAndShow( - String? routeName, { - dynamic arguments, - int? id, - bool? preventDuplicates = true, - Map? parameters, - }) => - (super.noSuchMethod( - Invocation.method( - #clearTillFirstAndShow, - [routeName], - { - #arguments: arguments, - #id: id, - #preventDuplicates: preventDuplicates, - #parameters: parameters, - }, - ), - returnValueForMissingStub: null, - ) as _i8.Future?); - - @override - _i8.Future? clearTillFirstAndShowView( - _i7.Widget? view, { - dynamic arguments, - int? id, - }) => - (super.noSuchMethod( - Invocation.method( - #clearTillFirstAndShowView, - [view], - { - #arguments: arguments, - #id: id, - }, - ), - returnValueForMissingStub: null, - ) as _i8.Future?); - - @override - _i8.Future? pushNamedAndRemoveUntil( - String? routeName, { - _i7.RoutePredicate? predicate, - dynamic arguments, - int? id, - }) => - (super.noSuchMethod( - Invocation.method( - #pushNamedAndRemoveUntil, - [routeName], - { - #predicate: predicate, - #arguments: arguments, - #id: id, - }, - ), - returnValueForMissingStub: null, - ) as _i8.Future?); -} - -/// A class which mocks [BottomSheetService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockBottomSheetService extends _i1.Mock - implements _i5.BottomSheetService { - @override - void setCustomSheetBuilders(Map? builders) => - super.noSuchMethod( - Invocation.method( - #setCustomSheetBuilders, - [builders], - ), - returnValueForMissingStub: null, - ); - - @override - _i8.Future<_i5.SheetResponse?> showBottomSheet({ - required String? title, - String? description, - String? confirmButtonTitle = r'Ok', - String? cancelButtonTitle, - bool? enableDrag = true, - bool? barrierDismissible = true, - bool? isScrollControlled = false, - Duration? exitBottomSheetDuration, - Duration? enterBottomSheetDuration, - bool? ignoreSafeArea, - bool? useRootNavigator = false, - double? elevation = 1.0, - }) => - (super.noSuchMethod( - Invocation.method( - #showBottomSheet, - [], - { - #title: title, - #description: description, - #confirmButtonTitle: confirmButtonTitle, - #cancelButtonTitle: cancelButtonTitle, - #enableDrag: enableDrag, - #barrierDismissible: barrierDismissible, - #isScrollControlled: isScrollControlled, - #exitBottomSheetDuration: exitBottomSheetDuration, - #enterBottomSheetDuration: enterBottomSheetDuration, - #ignoreSafeArea: ignoreSafeArea, - #useRootNavigator: useRootNavigator, - #elevation: elevation, - }, - ), - returnValue: _i8.Future<_i5.SheetResponse?>.value(), - returnValueForMissingStub: - _i8.Future<_i5.SheetResponse?>.value(), - ) as _i8.Future<_i5.SheetResponse?>); - - @override - _i8.Future<_i5.SheetResponse?> showCustomSheet({ - dynamic variant, - String? title, - String? description, - bool? hasImage = false, - String? imageUrl, - bool? showIconInMainButton = false, - String? mainButtonTitle, - bool? showIconInSecondaryButton = false, - String? secondaryButtonTitle, - bool? showIconInAdditionalButton = false, - String? additionalButtonTitle, - bool? takesInput = false, - _i9.Color? barrierColor = const _i9.Color(2315255808), - double? elevation = 1.0, - bool? barrierDismissible = true, - bool? isScrollControlled = false, - String? barrierLabel = r'', - dynamic customData, - R? data, - bool? enableDrag = true, - Duration? exitBottomSheetDuration, - Duration? enterBottomSheetDuration, - bool? ignoreSafeArea, - bool? useRootNavigator = false, - }) => - (super.noSuchMethod( - Invocation.method( - #showCustomSheet, - [], - { - #variant: variant, - #title: title, - #description: description, - #hasImage: hasImage, - #imageUrl: imageUrl, - #showIconInMainButton: showIconInMainButton, - #mainButtonTitle: mainButtonTitle, - #showIconInSecondaryButton: showIconInSecondaryButton, - #secondaryButtonTitle: secondaryButtonTitle, - #showIconInAdditionalButton: showIconInAdditionalButton, - #additionalButtonTitle: additionalButtonTitle, - #takesInput: takesInput, - #barrierColor: barrierColor, - #elevation: elevation, - #barrierDismissible: barrierDismissible, - #isScrollControlled: isScrollControlled, - #barrierLabel: barrierLabel, - #customData: customData, - #data: data, - #enableDrag: enableDrag, - #exitBottomSheetDuration: exitBottomSheetDuration, - #enterBottomSheetDuration: enterBottomSheetDuration, - #ignoreSafeArea: ignoreSafeArea, - #useRootNavigator: useRootNavigator, - }, - ), - returnValue: _i8.Future<_i5.SheetResponse?>.value(), - returnValueForMissingStub: _i8.Future<_i5.SheetResponse?>.value(), - ) as _i8.Future<_i5.SheetResponse?>); - - @override - void completeSheet(_i5.SheetResponse? response) => - super.noSuchMethod( - Invocation.method( - #completeSheet, - [response], - ), - returnValueForMissingStub: null, - ); -} - -/// A class which mocks [DialogService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockDialogService extends _i1.Mock implements _i5.DialogService { - @override - void registerCustomDialogBuilders( - Map? builders) => - super.noSuchMethod( - Invocation.method( - #registerCustomDialogBuilders, - [builders], - ), - returnValueForMissingStub: null, - ); - - @override - void registerCustomDialogBuilder({ - required dynamic variant, - required _i7.Widget Function( - _i7.BuildContext, - _i5.DialogRequest, - dynamic Function(_i5.DialogResponse), - )? builder, - }) => - super.noSuchMethod( - Invocation.method( - #registerCustomDialogBuilder, - [], - { - #variant: variant, - #builder: builder, - }, - ), - returnValueForMissingStub: null, - ); - - @override - _i8.Future<_i5.DialogResponse?> showDialog({ - String? title, - String? description, - String? cancelTitle, - _i9.Color? cancelTitleColor, - String? buttonTitle = r'Ok', - _i9.Color? buttonTitleColor, - bool? barrierDismissible = false, - _i7.RouteSettings? routeSettings, - _i7.GlobalKey<_i7.NavigatorState>? navigatorKey, - _i5.DialogPlatform? dialogPlatform, - }) => - (super.noSuchMethod( - Invocation.method( - #showDialog, - [], - { - #title: title, - #description: description, - #cancelTitle: cancelTitle, - #cancelTitleColor: cancelTitleColor, - #buttonTitle: buttonTitle, - #buttonTitleColor: buttonTitleColor, - #barrierDismissible: barrierDismissible, - #routeSettings: routeSettings, - #navigatorKey: navigatorKey, - #dialogPlatform: dialogPlatform, - }, - ), - returnValue: _i8.Future<_i5.DialogResponse?>.value(), - returnValueForMissingStub: - _i8.Future<_i5.DialogResponse?>.value(), - ) as _i8.Future<_i5.DialogResponse?>); - - @override - _i8.Future<_i5.DialogResponse?> showCustomDialog({ - dynamic variant, - String? title, - String? description, - bool? hasImage = false, - String? imageUrl, - bool? showIconInMainButton = false, - String? mainButtonTitle, - bool? showIconInSecondaryButton = false, - String? secondaryButtonTitle, - bool? showIconInAdditionalButton = false, - String? additionalButtonTitle, - bool? takesInput = false, - _i9.Color? barrierColor = const _i9.Color(2315255808), - bool? barrierDismissible = false, - String? barrierLabel = r'', - bool? useSafeArea = true, - _i7.RouteSettings? routeSettings, - _i7.GlobalKey<_i7.NavigatorState>? navigatorKey, - _i7.RouteTransitionsBuilder? transitionBuilder, - dynamic customData, - R? data, - }) => - (super.noSuchMethod( - Invocation.method( - #showCustomDialog, - [], - { - #variant: variant, - #title: title, - #description: description, - #hasImage: hasImage, - #imageUrl: imageUrl, - #showIconInMainButton: showIconInMainButton, - #mainButtonTitle: mainButtonTitle, - #showIconInSecondaryButton: showIconInSecondaryButton, - #secondaryButtonTitle: secondaryButtonTitle, - #showIconInAdditionalButton: showIconInAdditionalButton, - #additionalButtonTitle: additionalButtonTitle, - #takesInput: takesInput, - #barrierColor: barrierColor, - #barrierDismissible: barrierDismissible, - #barrierLabel: barrierLabel, - #useSafeArea: useSafeArea, - #routeSettings: routeSettings, - #navigatorKey: navigatorKey, - #transitionBuilder: transitionBuilder, - #customData: customData, - #data: data, - }, - ), - returnValue: _i8.Future<_i5.DialogResponse?>.value(), - returnValueForMissingStub: _i8.Future<_i5.DialogResponse?>.value(), - ) as _i8.Future<_i5.DialogResponse?>); - - @override - _i8.Future<_i5.DialogResponse?> showConfirmationDialog({ - String? title, - String? description, - String? cancelTitle = r'Cancel', - _i9.Color? cancelTitleColor, - String? confirmationTitle = r'Ok', - _i9.Color? confirmationTitleColor, - bool? barrierDismissible = false, - _i7.RouteSettings? routeSettings, - _i5.DialogPlatform? dialogPlatform, - }) => - (super.noSuchMethod( - Invocation.method( - #showConfirmationDialog, - [], - { - #title: title, - #description: description, - #cancelTitle: cancelTitle, - #cancelTitleColor: cancelTitleColor, - #confirmationTitle: confirmationTitle, - #confirmationTitleColor: confirmationTitleColor, - #barrierDismissible: barrierDismissible, - #routeSettings: routeSettings, - #dialogPlatform: dialogPlatform, - }, - ), - returnValue: _i8.Future<_i5.DialogResponse?>.value(), - returnValueForMissingStub: - _i8.Future<_i5.DialogResponse?>.value(), - ) as _i8.Future<_i5.DialogResponse?>); - - @override - void completeDialog(_i5.DialogResponse? response) => - super.noSuchMethod( - Invocation.method( - #completeDialog, - [response], - ), - returnValueForMissingStub: null, - ); -} - -/// A class which mocks [AuthenticationService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockAuthenticationService extends _i1.Mock - implements _i10.AuthenticationService { - @override - int get listenersCount => (super.noSuchMethod( - Invocation.getter(#listenersCount), - returnValue: 0, - returnValueForMissingStub: 0, - ) as int); - - @override - _i8.Future userLoggedIn() => (super.noSuchMethod( - Invocation.method( - #userLoggedIn, - [], - ), - returnValue: _i8.Future.value(false), - returnValueForMissingStub: _i8.Future.value(false), - ) as _i8.Future); - - @override - _i8.Future getAccessToken() => (super.noSuchMethod( - Invocation.method( - #getAccessToken, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future getRefreshToken() => (super.noSuchMethod( - Invocation.method( - #getRefreshToken, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future getUserId() => (super.noSuchMethod( - Invocation.method( - #getUserId, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future saveTokens({ - required String? access, - required String? refresh, - }) => - (super.noSuchMethod( - Invocation.method( - #saveTokens, - [], - { - #access: access, - #refresh: refresh, - }, - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future saveUserName(Map? data) => - (super.noSuchMethod( - Invocation.method( - #saveUserName, - [data], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future saveUserCredential(Map? data) => - (super.noSuchMethod( - Invocation.method( - #saveUserCredential, - [data], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future saveProfileStatus(bool? value) => (super.noSuchMethod( - Invocation.method( - #saveProfileStatus, - [value], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future saveProfileImage(String? image) => (super.noSuchMethod( - Invocation.method( - #saveProfileImage, - [image], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future saveUserData({ - required String? image, - required _i11.UserModel? data, - }) => - (super.noSuchMethod( - Invocation.method( - #saveUserData, - [], - { - #image: image, - #data: data, - }, - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future updateUserData(Map? data) => - (super.noSuchMethod( - Invocation.method( - #updateUserData, - [data], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future isFirstTimeInstall() => (super.noSuchMethod( - Invocation.method( - #isFirstTimeInstall, - [], - ), - returnValue: _i8.Future.value(false), - returnValueForMissingStub: _i8.Future.value(false), - ) as _i8.Future); - - @override - _i8.Future setFirstTimeInstall(bool? value) => (super.noSuchMethod( - Invocation.method( - #setFirstTimeInstall, - [value], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future<_i11.UserModel?> getUser() => (super.noSuchMethod( - Invocation.method( - #getUser, - [], - ), - returnValue: _i8.Future<_i11.UserModel?>.value(), - returnValueForMissingStub: _i8.Future<_i11.UserModel?>.value(), - ) as _i8.Future<_i11.UserModel?>); - - @override - _i8.Future logOut() => (super.noSuchMethod( - Invocation.method( - #logOut, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - void listenToReactiveValues(List? reactiveValues) => - super.noSuchMethod( - Invocation.method( - #listenToReactiveValues, - [reactiveValues], - ), - returnValueForMissingStub: null, - ); - - @override - void addListener(void Function()? listener) => super.noSuchMethod( - Invocation.method( - #addListener, - [listener], - ), - returnValueForMissingStub: null, - ); - - @override - void removeListener(void Function()? listener) => super.noSuchMethod( - Invocation.method( - #removeListener, - [listener], - ), - returnValueForMissingStub: null, - ); - - @override - void notifyListeners() => super.noSuchMethod( - Invocation.method( - #notifyListeners, - [], - ), - returnValueForMissingStub: null, - ); -} - -/// A class which mocks [ApiService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockApiService extends _i1.Mock implements _i12.ApiService { - @override - _i8.Future> registerWithEmail(Map? data) => - (super.noSuchMethod( - Invocation.method( - #register, - [data], - ), - returnValue: - _i8.Future>.value({}), - returnValueForMissingStub: - _i8.Future>.value({}), - ) as _i8.Future>); - - @override - _i8.Future> emailLogin(Map? data) => - (super.noSuchMethod( - Invocation.method( - #emailLogin, - [data], - ), - returnValue: - _i8.Future>.value({}), - returnValueForMissingStub: - _i8.Future>.value({}), - ) as _i8.Future>); - - @override - _i8.Future> googleAuth(Map? data) => - (super.noSuchMethod( - Invocation.method( - #googleLogin, - [data], - ), - returnValue: - _i8.Future>.value({}), - returnValueForMissingStub: - _i8.Future>.value({}), - ) as _i8.Future>); - - @override - _i8.Future> verifyOtp(Map? data) => - (super.noSuchMethod( - Invocation.method( - #verifyOtp, - [data], - ), - returnValue: - _i8.Future>.value({}), - returnValueForMissingStub: - _i8.Future>.value({}), - ) as _i8.Future>); - - @override - _i8.Future> resendOtp(Map? data) => - (super.noSuchMethod( - Invocation.method( - #resendOtp, - [data], - ), - returnValue: - _i8.Future>.value({}), - returnValueForMissingStub: - _i8.Future>.value({}), - ) as _i8.Future>); - - @override - _i8.Future> requestResetCode( - Map? data) => - (super.noSuchMethod( - Invocation.method( - #requestResetCode, - [data], - ), - returnValue: - _i8.Future>.value({}), - returnValueForMissingStub: - _i8.Future>.value({}), - ) as _i8.Future>); - - @override - _i8.Future> resetPassword(Map? data) => - (super.noSuchMethod( - Invocation.method( - #resetPassword, - [data], - ), - returnValue: - _i8.Future>.value({}), - returnValueForMissingStub: - _i8.Future>.value({}), - ) as _i8.Future>); - - @override - _i8.Future> getProfileStatus(_i11.UserModel? user) => - (super.noSuchMethod( - Invocation.method( - #getProfileStatus, - [user], - ), - returnValue: - _i8.Future>.value({}), - returnValueForMissingStub: - _i8.Future>.value({}), - ) as _i8.Future>); - - @override - _i8.Future> getProfileData(int? userId) => - (super.noSuchMethod( - Invocation.method( - #getProfileData, - [userId], - ), - returnValue: - _i8.Future>.value({}), - returnValueForMissingStub: - _i8.Future>.value({}), - ) as _i8.Future>); - - @override - _i8.Future> completeProfile( - Map? data) => - (super.noSuchMethod( - Invocation.method( - #completeProfile, - [data], - ), - returnValue: - _i8.Future>.value({}), - returnValueForMissingStub: - _i8.Future>.value({}), - ) as _i8.Future>); - - @override - _i8.Future> updateProfileImage({ - required int? userId, - required Map? data, - }) => - (super.noSuchMethod( - Invocation.method( - #updateProfileImage, - [], - { - #userId: userId, - #data: data, - }, - ), - returnValue: - _i8.Future>.value({}), - returnValueForMissingStub: - _i8.Future>.value({}), - ) as _i8.Future>); - - @override - _i8.Future> getAssessments() => (super.noSuchMethod( - Invocation.method( - #getAssessments, - [], - ), - returnValue: - _i8.Future>.value(<_i13.Assessment>[]), - returnValueForMissingStub: - _i8.Future>.value(<_i13.Assessment>[]), - ) as _i8.Future>); -} - -/// A class which mocks [SecureStorageService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockSecureStorageService extends _i1.Mock - implements _i3.SecureStorageService { - @override - _i8.Future clear() => (super.noSuchMethod( - Invocation.method( - #clear, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future getBool(String? key) => (super.noSuchMethod( - Invocation.method( - #getBool, - [key], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future getString(String? key) => (super.noSuchMethod( - Invocation.method( - #getString, - [key], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future getInt(String? key) => (super.noSuchMethod( - Invocation.method( - #getInt, - [key], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future setString( - String? key, - String? value, - ) => - (super.noSuchMethod( - Invocation.method( - #setString, - [ - key, - value, - ], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future setInt( - String? key, - int? value, - ) => - (super.noSuchMethod( - Invocation.method( - #setInt, - [ - key, - value, - ], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future setBool( - String? key, - bool? value, - ) => - (super.noSuchMethod( - Invocation.method( - #setBool, - [ - key, - value, - ], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); -} - -/// A class which mocks [DioService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockDioService extends _i1.Mock implements _i14.DioService { - @override - _i2.Dio get dio => (super.noSuchMethod( - Invocation.getter(#dio), - returnValue: _FakeDio_0( - this, - Invocation.getter(#dio), - ), - returnValueForMissingStub: _FakeDio_0( - this, - Invocation.getter(#dio), - ), - ) as _i2.Dio); -} - -/// A class which mocks [StatusCheckerService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockStatusCheckerService extends _i1.Mock - implements _i15.StatusCheckerService { - @override - _i3.SecureStorageService get storage => (super.noSuchMethod( - Invocation.getter(#storage), - returnValue: _FakeSecureStorageService_1( - this, - Invocation.getter(#storage), - ), - returnValueForMissingStub: _FakeSecureStorageService_1( - this, - Invocation.getter(#storage), - ), - ) as _i3.SecureStorageService); - - @override - bool get previousConnection => (super.noSuchMethod( - Invocation.getter(#previousConnection), - returnValue: false, - returnValueForMissingStub: false, - ) as bool); - - @override - _i8.Future getBatteryLevel() => (super.noSuchMethod( - Invocation.method( - #getBatteryLevel, - [], - ), - returnValue: _i8.Future.value(0), - returnValueForMissingStub: _i8.Future.value(0), - ) as _i8.Future); - - @override - _i8.Future userAuthenticated() => (super.noSuchMethod( - Invocation.method( - #userAuthenticated, - [], - ), - returnValue: _i8.Future.value(false), - returnValueForMissingStub: _i8.Future.value(false), - ) as _i8.Future); - - @override - _i8.Future checkConnection() => (super.noSuchMethod( - Invocation.method( - #checkConnection, - [], - ), - returnValue: _i8.Future.value(false), - returnValueForMissingStub: _i8.Future.value(false), - ) as _i8.Future); - - @override - _i8.Future getAvailableStorage() => (super.noSuchMethod( - Invocation.method( - #getAvailableStorage, - [], - ), - returnValue: _i8.Future.value(0), - returnValueForMissingStub: _i8.Future.value(0), - ) as _i8.Future); - - @override - _i8.Future checkAndUpdate() => (super.noSuchMethod( - Invocation.method( - #checkAndUpdate, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); -} - -/// A class which mocks [PermissionHandlerService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockPermissionHandlerService extends _i1.Mock - implements _i16.PermissionHandlerService { - @override - _i8.Future<_i17.PermissionStatus> requestPermission( - _i17.Permission? requestedPermission) => - (super.noSuchMethod( - Invocation.method( - #requestPermission, - [requestedPermission], - ), - returnValue: _i8.Future<_i17.PermissionStatus>.value( - _i17.PermissionStatus.denied), - returnValueForMissingStub: _i8.Future<_i17.PermissionStatus>.value( - _i17.PermissionStatus.denied), - ) as _i8.Future<_i17.PermissionStatus>); - - @override - _i8.Future<_i17.PermissionStatus> request(_i17.Permission? permission) => - (super.noSuchMethod( - Invocation.method( - #request, - [permission], - ), - returnValue: _i8.Future<_i17.PermissionStatus>.value( - _i17.PermissionStatus.denied), - returnValueForMissingStub: _i8.Future<_i17.PermissionStatus>.value( - _i17.PermissionStatus.denied), - ) as _i8.Future<_i17.PermissionStatus>); -} - -/// A class which mocks [ImagePickerService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockImagePickerService extends _i1.Mock - implements _i18.ImagePickerService { - @override - _i8.Future gallery() => (super.noSuchMethod( - Invocation.method( - #gallery, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); - - @override - _i8.Future camera() => (super.noSuchMethod( - Invocation.method( - #camera, - [], - ), - returnValue: _i8.Future.value(), - returnValueForMissingStub: _i8.Future.value(), - ) as _i8.Future); -} - -/// A class which mocks [GoogleAuthService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockGoogleAuthService extends _i1.Mock implements _i19.GoogleAuthService { - @override - _i4.GoogleSignIn get signIn => (super.noSuchMethod( - Invocation.getter(#signIn), - returnValue: _FakeGoogleSignIn_2( - this, - Invocation.getter(#signIn), - ), - returnValueForMissingStub: _FakeGoogleSignIn_2( - this, - Invocation.getter(#signIn), - ), - ) as _i4.GoogleSignIn); - - @override - _i8.Future<_i4.GoogleSignInAccount?> googleAuth() => (super.noSuchMethod( - Invocation.method( - #googleSignIn, - [], - ), - returnValue: _i8.Future<_i4.GoogleSignInAccount?>.value(), - returnValueForMissingStub: _i8.Future<_i4.GoogleSignInAccount?>.value(), - ) as _i8.Future<_i4.GoogleSignInAccount?>); -} - -/// A class which mocks [ImageDownloaderService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockImageDownloaderService extends _i1.Mock - implements _i20.ImageDownloaderService { - @override - _i8.Future downloader(String? networkImage) => (super.noSuchMethod( - Invocation.method( - #downloader, - [networkImage], - ), - returnValue: _i8.Future.value(_i6.dummyValue( - this, - Invocation.method( - #downloader, - [networkImage], - ), - )), - returnValueForMissingStub: - _i8.Future.value(_i6.dummyValue( - this, - Invocation.method( - #downloader, - [networkImage], - ), - )), - ) as _i8.Future); -}