first commit
This commit is contained in:
parent
befbfb4727
commit
8f329f774d
|
|
@ -30,6 +30,8 @@ import 'package:yimaru_app/services/status_checker_service.dart';
|
||||||
import 'package:yimaru_app/ui/views/welcome/welcome_view.dart';
|
import 'package:yimaru_app/ui/views/welcome/welcome_view.dart';
|
||||||
import 'package:yimaru_app/ui/views/assessment/assessment_view.dart';
|
import 'package:yimaru_app/ui/views/assessment/assessment_view.dart';
|
||||||
import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart';
|
import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart';
|
||||||
|
import 'package:yimaru_app/ui/views/failure/failure_view.dart';
|
||||||
|
import 'package:yimaru_app/services/image_picker_service.dart';
|
||||||
// @stacked-import
|
// @stacked-import
|
||||||
|
|
||||||
@StackedApp(
|
@StackedApp(
|
||||||
|
|
@ -57,6 +59,7 @@ import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart';
|
||||||
MaterialRoute(page: WelcomeView),
|
MaterialRoute(page: WelcomeView),
|
||||||
MaterialRoute(page: AssessmentView),
|
MaterialRoute(page: AssessmentView),
|
||||||
MaterialRoute(page: LearnLessonView),
|
MaterialRoute(page: LearnLessonView),
|
||||||
|
MaterialRoute(page: FailureView),
|
||||||
// @stacked-route
|
// @stacked-route
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
|
@ -68,6 +71,7 @@ import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart';
|
||||||
LazySingleton(classType: SecureStorageService),
|
LazySingleton(classType: SecureStorageService),
|
||||||
LazySingleton(classType: DioService),
|
LazySingleton(classType: DioService),
|
||||||
LazySingleton(classType: StatusCheckerService),
|
LazySingleton(classType: StatusCheckerService),
|
||||||
|
LazySingleton(classType: ImagePickerService),
|
||||||
// @stacked-service
|
// @stacked-service
|
||||||
],
|
],
|
||||||
bottomsheets: [
|
bottomsheets: [
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import 'package:stacked_shared/stacked_shared.dart';
|
||||||
import '../services/api_service.dart';
|
import '../services/api_service.dart';
|
||||||
import '../services/authentication_service.dart';
|
import '../services/authentication_service.dart';
|
||||||
import '../services/dio_service.dart';
|
import '../services/dio_service.dart';
|
||||||
|
import '../services/image_picker_service.dart';
|
||||||
import '../services/secure_storage_service.dart';
|
import '../services/secure_storage_service.dart';
|
||||||
import '../services/status_checker_service.dart';
|
import '../services/status_checker_service.dart';
|
||||||
|
|
||||||
|
|
@ -36,4 +37,5 @@ Future<void> setupLocator({
|
||||||
locator.registerLazySingleton(() => SecureStorageService());
|
locator.registerLazySingleton(() => SecureStorageService());
|
||||||
locator.registerLazySingleton(() => DioService());
|
locator.registerLazySingleton(() => DioService());
|
||||||
locator.registerLazySingleton(() => StatusCheckerService());
|
locator.registerLazySingleton(() => StatusCheckerService());
|
||||||
|
locator.registerLazySingleton(() => ImagePickerService());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,17 @@
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||||
import 'package:flutter/material.dart' as _i25;
|
import 'package:flutter/material.dart' as _i26;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:stacked/stacked.dart' as _i1;
|
import 'package:stacked/stacked.dart' as _i1;
|
||||||
import 'package:stacked_services/stacked_services.dart' as _i26;
|
import 'package:stacked_services/stacked_services.dart' as _i27;
|
||||||
import 'package:yimaru_app/ui/views/account_privacy/account_privacy_view.dart'
|
import 'package:yimaru_app/ui/views/account_privacy/account_privacy_view.dart'
|
||||||
as _i10;
|
as _i10;
|
||||||
import 'package:yimaru_app/ui/views/assessment/assessment_view.dart' as _i23;
|
import 'package:yimaru_app/ui/views/assessment/assessment_view.dart' as _i23;
|
||||||
import 'package:yimaru_app/ui/views/call_support/call_support_view.dart'
|
import 'package:yimaru_app/ui/views/call_support/call_support_view.dart'
|
||||||
as _i13;
|
as _i13;
|
||||||
import 'package:yimaru_app/ui/views/downloads/downloads_view.dart' as _i7;
|
import 'package:yimaru_app/ui/views/downloads/downloads_view.dart' as _i7;
|
||||||
|
import 'package:yimaru_app/ui/views/failure/failure_view.dart' as _i25;
|
||||||
import 'package:yimaru_app/ui/views/home/home_view.dart' as _i2;
|
import 'package:yimaru_app/ui/views/home/home_view.dart' as _i2;
|
||||||
import 'package:yimaru_app/ui/views/language/language_view.dart' as _i14;
|
import 'package:yimaru_app/ui/views/language/language_view.dart' as _i14;
|
||||||
import 'package:yimaru_app/ui/views/learn/learn_view.dart' as _i19;
|
import 'package:yimaru_app/ui/views/learn/learn_view.dart' as _i19;
|
||||||
|
|
@ -89,6 +90,8 @@ class Routes {
|
||||||
|
|
||||||
static const learnLessonView = '/learn-lesson-view';
|
static const learnLessonView = '/learn-lesson-view';
|
||||||
|
|
||||||
|
static const failureView = '/failure-view';
|
||||||
|
|
||||||
static const all = <String>{
|
static const all = <String>{
|
||||||
homeView,
|
homeView,
|
||||||
onboardingView,
|
onboardingView,
|
||||||
|
|
@ -113,6 +116,7 @@ class Routes {
|
||||||
welcomeView,
|
welcomeView,
|
||||||
assessmentView,
|
assessmentView,
|
||||||
learnLessonView,
|
learnLessonView,
|
||||||
|
failureView,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,17 +214,21 @@ class StackedRouter extends _i1.RouterBase {
|
||||||
Routes.learnLessonView,
|
Routes.learnLessonView,
|
||||||
page: _i24.LearnLessonView,
|
page: _i24.LearnLessonView,
|
||||||
),
|
),
|
||||||
|
_i1.RouteDef(
|
||||||
|
Routes.failureView,
|
||||||
|
page: _i25.FailureView,
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
final _pagesMap = <Type, _i1.StackedRouteFactory>{
|
final _pagesMap = <Type, _i1.StackedRouteFactory>{
|
||||||
_i2.HomeView: (data) {
|
_i2.HomeView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i2.HomeView(),
|
builder: (context) => const _i2.HomeView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i3.OnboardingView: (data) {
|
_i3.OnboardingView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i3.OnboardingView(),
|
builder: (context) => const _i3.OnboardingView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
|
|
@ -229,133 +237,141 @@ class StackedRouter extends _i1.RouterBase {
|
||||||
final args = data.getArgs<StartupViewArguments>(
|
final args = data.getArgs<StartupViewArguments>(
|
||||||
orElse: () => const StartupViewArguments(),
|
orElse: () => const StartupViewArguments(),
|
||||||
);
|
);
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => _i4.StartupView(key: args.key, label: args.label),
|
builder: (context) => _i4.StartupView(key: args.key, label: args.label),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i5.ProfileView: (data) {
|
_i5.ProfileView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i5.ProfileView(),
|
builder: (context) => const _i5.ProfileView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i6.ProfileDetailView: (data) {
|
_i6.ProfileDetailView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i6.ProfileDetailView(),
|
builder: (context) => const _i6.ProfileDetailView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i7.DownloadsView: (data) {
|
_i7.DownloadsView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i7.DownloadsView(),
|
builder: (context) => const _i7.DownloadsView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i8.ProgressView: (data) {
|
_i8.ProgressView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i8.ProgressView(),
|
builder: (context) => const _i8.ProgressView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i9.OngoingProgressView: (data) {
|
_i9.OngoingProgressView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i9.OngoingProgressView(),
|
builder: (context) => const _i9.OngoingProgressView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i10.AccountPrivacyView: (data) {
|
_i10.AccountPrivacyView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i10.AccountPrivacyView(),
|
builder: (context) => const _i10.AccountPrivacyView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i11.SupportView: (data) {
|
_i11.SupportView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i11.SupportView(),
|
builder: (context) => const _i11.SupportView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i12.TelegramSupportView: (data) {
|
_i12.TelegramSupportView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i12.TelegramSupportView(),
|
builder: (context) => const _i12.TelegramSupportView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i13.CallSupportView: (data) {
|
_i13.CallSupportView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i13.CallSupportView(),
|
builder: (context) => const _i13.CallSupportView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i14.LanguageView: (data) {
|
_i14.LanguageView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i14.LanguageView(),
|
builder: (context) => const _i14.LanguageView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i15.PrivacyPolicyView: (data) {
|
_i15.PrivacyPolicyView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i15.PrivacyPolicyView(),
|
builder: (context) => const _i15.PrivacyPolicyView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i16.TermsAndConditionsView: (data) {
|
_i16.TermsAndConditionsView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i16.TermsAndConditionsView(),
|
builder: (context) => const _i16.TermsAndConditionsView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i17.RegisterView: (data) {
|
_i17.RegisterView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i17.RegisterView(),
|
builder: (context) => const _i17.RegisterView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i18.LoginView: (data) {
|
_i18.LoginView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i18.LoginView(),
|
builder: (context) => const _i18.LoginView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i19.LearnView: (data) {
|
_i19.LearnView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i19.LearnView(),
|
builder: (context) => const _i19.LearnView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i20.LearnLevelView: (data) {
|
_i20.LearnLevelView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i20.LearnLevelView(),
|
builder: (context) => const _i20.LearnLevelView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i21.LearnModuleView: (data) {
|
_i21.LearnModuleView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i21.LearnModuleView(),
|
builder: (context) => const _i21.LearnModuleView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i22.WelcomeView: (data) {
|
_i22.WelcomeView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i22.WelcomeView(),
|
builder: (context) => const _i22.WelcomeView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i23.AssessmentView: (data) {
|
_i23.AssessmentView: (data) {
|
||||||
final args = data.getArgs<AssessmentViewArguments>(nullOk: false);
|
final args = data.getArgs<AssessmentViewArguments>(nullOk: false);
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
_i23.AssessmentView(key: args.key, data: args.data),
|
_i23.AssessmentView(key: args.key, data: args.data),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
_i24.LearnLessonView: (data) {
|
_i24.LearnLessonView: (data) {
|
||||||
return _i25.MaterialPageRoute<dynamic>(
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
builder: (context) => const _i24.LearnLessonView(),
|
builder: (context) => const _i24.LearnLessonView(),
|
||||||
settings: data,
|
settings: data,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
_i25.FailureView: (data) {
|
||||||
|
final args = data.getArgs<FailureViewArguments>(nullOk: false);
|
||||||
|
return _i26.MaterialPageRoute<dynamic>(
|
||||||
|
builder: (context) =>
|
||||||
|
_i25.FailureView(key: args.key, label: args.label),
|
||||||
|
settings: data,
|
||||||
|
);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -371,7 +387,7 @@ class StartupViewArguments {
|
||||||
this.label = 'Loading',
|
this.label = 'Loading',
|
||||||
});
|
});
|
||||||
|
|
||||||
final _i25.Key? key;
|
final _i26.Key? key;
|
||||||
|
|
||||||
final String label;
|
final String label;
|
||||||
|
|
||||||
|
|
@ -398,7 +414,7 @@ class AssessmentViewArguments {
|
||||||
required this.data,
|
required this.data,
|
||||||
});
|
});
|
||||||
|
|
||||||
final _i25.Key? key;
|
final _i26.Key? key;
|
||||||
|
|
||||||
final Map<String, dynamic> data;
|
final Map<String, dynamic> data;
|
||||||
|
|
||||||
|
|
@ -419,7 +435,34 @@ class AssessmentViewArguments {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension NavigatorStateExtension on _i26.NavigationService {
|
class FailureViewArguments {
|
||||||
|
const FailureViewArguments({
|
||||||
|
this.key,
|
||||||
|
required this.label,
|
||||||
|
});
|
||||||
|
|
||||||
|
final _i26.Key? key;
|
||||||
|
|
||||||
|
final String label;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return '{"key": "$key", "label": "$label"}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(covariant FailureViewArguments other) {
|
||||||
|
if (identical(this, other)) return true;
|
||||||
|
return other.key == key && other.label == label;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return key.hashCode ^ label.hashCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension NavigatorStateExtension on _i27.NavigationService {
|
||||||
Future<dynamic> navigateToHomeView([
|
Future<dynamic> navigateToHomeView([
|
||||||
int? routerId,
|
int? routerId,
|
||||||
bool preventDuplicates = true,
|
bool preventDuplicates = true,
|
||||||
|
|
@ -449,7 +492,7 @@ extension NavigatorStateExtension on _i26.NavigationService {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<dynamic> navigateToStartupView({
|
Future<dynamic> navigateToStartupView({
|
||||||
_i25.Key? key,
|
_i26.Key? key,
|
||||||
String label = 'Loading',
|
String label = 'Loading',
|
||||||
int? routerId,
|
int? routerId,
|
||||||
bool preventDuplicates = true,
|
bool preventDuplicates = true,
|
||||||
|
|
@ -718,7 +761,7 @@ extension NavigatorStateExtension on _i26.NavigationService {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<dynamic> navigateToAssessmentView({
|
Future<dynamic> navigateToAssessmentView({
|
||||||
_i25.Key? key,
|
_i26.Key? key,
|
||||||
required Map<String, dynamic> data,
|
required Map<String, dynamic> data,
|
||||||
int? routerId,
|
int? routerId,
|
||||||
bool preventDuplicates = true,
|
bool preventDuplicates = true,
|
||||||
|
|
@ -748,6 +791,23 @@ extension NavigatorStateExtension on _i26.NavigationService {
|
||||||
transition: transition);
|
transition: transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<dynamic> navigateToFailureView({
|
||||||
|
_i26.Key? key,
|
||||||
|
required String label,
|
||||||
|
int? routerId,
|
||||||
|
bool preventDuplicates = true,
|
||||||
|
Map<String, String>? parameters,
|
||||||
|
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
|
||||||
|
transition,
|
||||||
|
}) async {
|
||||||
|
return navigateTo<dynamic>(Routes.failureView,
|
||||||
|
arguments: FailureViewArguments(key: key, label: label),
|
||||||
|
id: routerId,
|
||||||
|
preventDuplicates: preventDuplicates,
|
||||||
|
parameters: parameters,
|
||||||
|
transition: transition);
|
||||||
|
}
|
||||||
|
|
||||||
Future<dynamic> replaceWithHomeView([
|
Future<dynamic> replaceWithHomeView([
|
||||||
int? routerId,
|
int? routerId,
|
||||||
bool preventDuplicates = true,
|
bool preventDuplicates = true,
|
||||||
|
|
@ -777,7 +837,7 @@ extension NavigatorStateExtension on _i26.NavigationService {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<dynamic> replaceWithStartupView({
|
Future<dynamic> replaceWithStartupView({
|
||||||
_i25.Key? key,
|
_i26.Key? key,
|
||||||
String label = 'Loading',
|
String label = 'Loading',
|
||||||
int? routerId,
|
int? routerId,
|
||||||
bool preventDuplicates = true,
|
bool preventDuplicates = true,
|
||||||
|
|
@ -1046,7 +1106,7 @@ extension NavigatorStateExtension on _i26.NavigationService {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<dynamic> replaceWithAssessmentView({
|
Future<dynamic> replaceWithAssessmentView({
|
||||||
_i25.Key? key,
|
_i26.Key? key,
|
||||||
required Map<String, dynamic> data,
|
required Map<String, dynamic> data,
|
||||||
int? routerId,
|
int? routerId,
|
||||||
bool preventDuplicates = true,
|
bool preventDuplicates = true,
|
||||||
|
|
@ -1075,4 +1135,21 @@ extension NavigatorStateExtension on _i26.NavigationService {
|
||||||
parameters: parameters,
|
parameters: parameters,
|
||||||
transition: transition);
|
transition: transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<dynamic> replaceWithFailureView({
|
||||||
|
_i26.Key? key,
|
||||||
|
required String label,
|
||||||
|
int? routerId,
|
||||||
|
bool preventDuplicates = true,
|
||||||
|
Map<String, String>? parameters,
|
||||||
|
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
|
||||||
|
transition,
|
||||||
|
}) async {
|
||||||
|
return replaceWith<dynamic>(Routes.failureView,
|
||||||
|
arguments: FailureViewArguments(key: key, label: label),
|
||||||
|
id: routerId,
|
||||||
|
preventDuplicates: preventDuplicates,
|
||||||
|
parameters: parameters,
|
||||||
|
transition: transition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,13 @@ part 'user_model.g.dart';
|
||||||
|
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class UserModel {
|
class UserModel {
|
||||||
|
final String? firstName;
|
||||||
|
|
||||||
@JsonKey(name: 'user_id')
|
@JsonKey(name: 'user_id')
|
||||||
final int? userId;
|
final int? userId;
|
||||||
|
|
||||||
|
final String? profileImage;
|
||||||
|
|
||||||
final bool? profileCompleted;
|
final bool? profileCompleted;
|
||||||
|
|
||||||
@JsonKey(name: 'access_token')
|
@JsonKey(name: 'access_token')
|
||||||
|
|
@ -15,11 +19,14 @@ class UserModel {
|
||||||
@JsonKey(name: 'refresh_token')
|
@JsonKey(name: 'refresh_token')
|
||||||
final String? refreshToken;
|
final String? refreshToken;
|
||||||
|
|
||||||
const UserModel(
|
const UserModel({
|
||||||
{this.userId,
|
this.userId,
|
||||||
|
this.firstName,
|
||||||
this.accessToken,
|
this.accessToken,
|
||||||
|
this.profileImage,
|
||||||
|
this.refreshToken,
|
||||||
this.profileCompleted,
|
this.profileCompleted,
|
||||||
this.refreshToken});
|
});
|
||||||
|
|
||||||
factory UserModel.fromJson(Map<String, dynamic> json) =>
|
factory UserModel.fromJson(Map<String, dynamic> json) =>
|
||||||
_$UserModelFromJson(json);
|
_$UserModelFromJson(json);
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,17 @@ part of 'user_model.dart';
|
||||||
|
|
||||||
UserModel _$UserModelFromJson(Map<String, dynamic> json) => UserModel(
|
UserModel _$UserModelFromJson(Map<String, dynamic> json) => UserModel(
|
||||||
userId: (json['user_id'] as num?)?.toInt(),
|
userId: (json['user_id'] as num?)?.toInt(),
|
||||||
|
firstName: json['firstName'] as String?,
|
||||||
accessToken: json['access_token'] as String?,
|
accessToken: json['access_token'] as String?,
|
||||||
profileCompleted: json['profileCompleted'] as bool?,
|
profileImage: json['profileImage'] as String?,
|
||||||
refreshToken: json['refresh_token'] as String?,
|
refreshToken: json['refresh_token'] as String?,
|
||||||
|
profileCompleted: json['profileCompleted'] as bool?,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$UserModelToJson(UserModel instance) => <String, dynamic>{
|
Map<String, dynamic> _$UserModelToJson(UserModel instance) => <String, dynamic>{
|
||||||
|
'firstName': instance.firstName,
|
||||||
'user_id': instance.userId,
|
'user_id': instance.userId,
|
||||||
|
'profileImage': instance.profileImage,
|
||||||
'profileCompleted': instance.profileCompleted,
|
'profileCompleted': instance.profileCompleted,
|
||||||
'access_token': instance.accessToken,
|
'access_token': instance.accessToken,
|
||||||
'refresh_token': instance.refreshToken,
|
'refresh_token': instance.refreshToken,
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class ApiService {
|
||||||
Future<Map<String, dynamic>> register(Map<String, dynamic> data) async {
|
Future<Map<String, dynamic>> register(Map<String, dynamic> data) async {
|
||||||
try {
|
try {
|
||||||
Response response = await _service.dio.post(
|
Response response = await _service.dio.post(
|
||||||
'$baseUrl/$userUrl/$kRegisterUrl',
|
'$baseUrl/$kUserUrl/$kRegisterUrl',
|
||||||
data: data,
|
data: data,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ class ApiService {
|
||||||
Future<Map<String, dynamic>> verifyOtp(Map<String, dynamic> data) async {
|
Future<Map<String, dynamic>> verifyOtp(Map<String, dynamic> data) async {
|
||||||
try {
|
try {
|
||||||
Response response = await _service.dio.post(
|
Response response = await _service.dio.post(
|
||||||
'$baseUrl/$userUrl/$kVerifyOtpUrl',
|
'$baseUrl/$kUserUrl/$kVerifyOtpUrl',
|
||||||
data: data,
|
data: data,
|
||||||
);
|
);
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
|
|
@ -96,7 +96,7 @@ class ApiService {
|
||||||
Future<Map<String, dynamic>> resendOtp(Map<String, dynamic> data) async {
|
Future<Map<String, dynamic>> resendOtp(Map<String, dynamic> data) async {
|
||||||
try {
|
try {
|
||||||
Response response = await _service.dio.post(
|
Response response = await _service.dio.post(
|
||||||
'$baseUrl/$userUrl/$kResendOtpUrl',
|
'$baseUrl/$kUserUrl/$kResendOtpUrl',
|
||||||
data: data,
|
data: data,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -123,7 +123,7 @@ class ApiService {
|
||||||
Future<Map<String, dynamic>> getProfileStatus(UserModel? user) async {
|
Future<Map<String, dynamic>> getProfileStatus(UserModel? user) async {
|
||||||
try {
|
try {
|
||||||
Response response = await _service.dio.get(
|
Response response = await _service.dio.get(
|
||||||
'$baseUrl/$userUrl/${user?.userId}/$kProfileStatusUrl',
|
'$baseUrl/$kUserUrl/${user?.userId}/$kProfileStatusUrl',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
|
|
@ -146,18 +146,42 @@ class ApiService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get profile
|
||||||
|
Future<Map<String, dynamic>> getProfileData(int? userId) async {
|
||||||
|
try {
|
||||||
|
Response response = await _service.dio.get(
|
||||||
|
'$baseUrl/$kUserUrl/$kGetUserUrl/$userId',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
return {
|
||||||
|
'data': response.data['data'],
|
||||||
|
'status': ResponseStatus.success,
|
||||||
|
'message': 'Profile fetched successfully'
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'status': ResponseStatus.failure,
|
||||||
|
'message': 'Unknown Error Occurred'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return {
|
||||||
|
'message': e.toString(),
|
||||||
|
'status': ResponseStatus.failure,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update profile
|
// Update profile
|
||||||
Future<Map<String, dynamic>> updateProfile(
|
Future<Map<String, dynamic>> updateProfile(
|
||||||
{required UserModel? user, required Map<String, dynamic> data}) async {
|
{required UserModel? user, required Map<String, dynamic> data}) async {
|
||||||
try {
|
try {
|
||||||
Response response = await _service.dio.put(
|
Response response = await _service.dio.put(
|
||||||
'$baseUrl/$userUrl',
|
'$baseUrl/$kUserUrl',
|
||||||
data: data,
|
data: data,
|
||||||
);
|
);
|
||||||
|
|
||||||
print(response.statusCode);
|
|
||||||
print(response.data);
|
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
return {
|
return {
|
||||||
'status': ResponseStatus.success,
|
'status': ResponseStatus.success,
|
||||||
|
|
@ -170,7 +194,6 @@ class ApiService {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Exception ${e.toString()}');
|
|
||||||
return {
|
return {
|
||||||
'message': e.toString(),
|
'message': e.toString(),
|
||||||
'status': ResponseStatus.failure,
|
'status': ResponseStatus.failure,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,10 @@ import 'package:yimaru_app/services/secure_storage_service.dart';
|
||||||
class AuthenticationService {
|
class AuthenticationService {
|
||||||
final _secureService = locator<SecureStorageService>();
|
final _secureService = locator<SecureStorageService>();
|
||||||
|
|
||||||
|
UserModel? _user;
|
||||||
|
|
||||||
|
UserModel? get user => _user;
|
||||||
|
|
||||||
Future<bool> userLoggedIn() async {
|
Future<bool> userLoggedIn() async {
|
||||||
if (await _secureService.getString('userId') != null) {
|
if (await _secureService.getString('userId') != null) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -28,14 +32,56 @@ class AuthenticationService {
|
||||||
await _secureService.setString('refreshToken', refresh);
|
await _secureService.setString('refreshToken', refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveUserData(Map<String, dynamic> data) async {
|
Future<void> saveUserName(Map<String, dynamic> data) async {
|
||||||
|
await _secureService.setString('firstName', data['firstName']);
|
||||||
|
_user = UserModel(
|
||||||
|
firstName: await _secureService.getString('firstName'),
|
||||||
|
userId: _user?.userId,
|
||||||
|
accessToken: _user?.accessToken,
|
||||||
|
refreshToken: _user?.refreshToken,
|
||||||
|
profileCompleted: _user?.profileCompleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveBasicUserData(Map<String, dynamic> data) async {
|
||||||
await _secureService.setInt('userId', data['userId']);
|
await _secureService.setInt('userId', data['userId']);
|
||||||
await _secureService.setString('accessToken', data['accessToken']);
|
await _secureService.setString('accessToken', data['accessToken']);
|
||||||
await _secureService.setString('refreshToken', data['refreshToken']);
|
await _secureService.setString('refreshToken', data['refreshToken']);
|
||||||
|
|
||||||
|
_user = UserModel(
|
||||||
|
firstName: _user?.firstName,
|
||||||
|
profileImage: _user?.profileImage,
|
||||||
|
profileCompleted: _user?.profileCompleted,
|
||||||
|
userId: await _secureService.getInt('userId'),
|
||||||
|
accessToken: await _secureService.getString('accessToken'),
|
||||||
|
refreshToken: await _secureService.getString('refreshToken'),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveProfileCompleted(bool value) async {
|
Future<void> saveProfileStatus(bool value) async {
|
||||||
await _secureService.setBool('profileCompleted', value);
|
await _secureService.setBool('profileCompleted', value);
|
||||||
|
|
||||||
|
_user = UserModel(
|
||||||
|
userId: _user?.userId,
|
||||||
|
firstName: _user?.firstName,
|
||||||
|
accessToken: _user?.accessToken,
|
||||||
|
refreshToken: _user?.refreshToken,
|
||||||
|
profileImage: _user?.profileImage,
|
||||||
|
profileCompleted: await _secureService.getBool('profileCompleted'));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveProfileImage() async {}
|
||||||
|
|
||||||
|
Future<void> saveFullName(Map<String, dynamic> data) async {
|
||||||
|
await _secureService.setBool('profileCompleted', true);
|
||||||
|
await _secureService.setString('firstName', data['firstName']);
|
||||||
|
_user = UserModel(
|
||||||
|
userId: _user?.userId,
|
||||||
|
accessToken: _user?.accessToken,
|
||||||
|
refreshToken: _user?.refreshToken,
|
||||||
|
profileImage: _user?.profileImage,
|
||||||
|
firstName: await _secureService.getString('firstName'),
|
||||||
|
profileCompleted: await _secureService.getBool('profileCompleted'),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> isFirstTimeInstall() async =>
|
Future<bool> isFirstTimeInstall() async =>
|
||||||
|
|
@ -45,14 +91,16 @@ class AuthenticationService {
|
||||||
await _secureService.setBool('firstTimeInstall', value);
|
await _secureService.setBool('firstTimeInstall', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<UserModel> getUser() async {
|
Future<UserModel?> getUser() async {
|
||||||
UserModel user = UserModel(
|
_user = UserModel(
|
||||||
userId: await _secureService.getInt('userId'),
|
userId: await _secureService.getInt('userId'),
|
||||||
|
firstName: await _secureService.getString('firstName'),
|
||||||
accessToken: await _secureService.getString('accessToken'),
|
accessToken: await _secureService.getString('accessToken'),
|
||||||
refreshToken: await _secureService.getString('refreshToken'),
|
refreshToken: await _secureService.getString('refreshToken'),
|
||||||
|
profileImage: await _secureService.getString('profileImage'),
|
||||||
profileCompleted: await _secureService.getBool('profileCompleted'),
|
profileCompleted: await _secureService.getBool('profileCompleted'),
|
||||||
);
|
);
|
||||||
return user;
|
return _user;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> logOut() async {
|
Future<void> logOut() async {
|
||||||
|
|
|
||||||
|
|
@ -125,18 +125,17 @@ class DioService {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _refreshToken() async {
|
Future<bool> _refreshToken() async {
|
||||||
final UserModel user = await _authenticationService.getUser();
|
final UserModel? user = await _authenticationService.getUser();
|
||||||
|
|
||||||
if (user.refreshToken == null) return false;
|
if (user?.refreshToken == null) return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Map<String, dynamic> data = {
|
Map<String, dynamic> data = {
|
||||||
'role': 'STUDENT',
|
'role': 'STUDENT',
|
||||||
'user_id': user.userId,
|
'user_id': user?.userId,
|
||||||
'access_token': user.accessToken,
|
'access_token': user?.accessToken,
|
||||||
'refresh_token': user.refreshToken
|
'refresh_token': user?.refreshToken
|
||||||
};
|
};
|
||||||
print(data);
|
|
||||||
final response = await _refreshDio.post(
|
final response = await _refreshDio.post(
|
||||||
'$baseUrl/$kRefreshTokenUrl',
|
'$baseUrl/$kRefreshTokenUrl',
|
||||||
data: data,
|
data: data,
|
||||||
|
|
@ -150,8 +149,6 @@ class DioService {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
print('Refresh response');
|
|
||||||
print(response.data);
|
|
||||||
await _authenticationService.saveTokens(
|
await _authenticationService.saveTokens(
|
||||||
access: response.data['access_token'],
|
access: response.data['access_token'],
|
||||||
refresh: response.data['refresh_token'],
|
refresh: response.data['refresh_token'],
|
||||||
|
|
@ -159,10 +156,8 @@ class DioService {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Refresh response exception');
|
await _authenticationService.logOut();
|
||||||
print(e.toString());
|
await _navigationService.replaceWithLoginView();
|
||||||
// await _authenticationService.logOut();
|
|
||||||
// await _navigationService.replaceWithLoginView();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
lib/services/image_picker_service.dart
Normal file
1
lib/services/image_picker_service.dart
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
class ImagePickerService {}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
String baseUrl = 'http://195.35.29.82:8080';
|
String baseUrl = 'http://195.35.29.82:8080';
|
||||||
//String baseUrl = 'https://api.yimaru.yaltopia.com';
|
//String baseUrl = 'https://api.yimaru.yaltopia.com';
|
||||||
|
|
||||||
String userUrl = 'api/v1/user';
|
String kGetUserUrl = 'single';
|
||||||
|
|
||||||
|
String kUserUrl = 'api/v1/user';
|
||||||
|
|
||||||
String kRegisterUrl = 'register';
|
String kRegisterUrl = 'register';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -171,15 +171,9 @@ PinTheme errorPinTheme = defaultPin.copyBorderWith(
|
||||||
border: Border.all(color: Colors.red),
|
border: Border.all(color: Colors.red),
|
||||||
);
|
);
|
||||||
|
|
||||||
TextStyle validationStyle = const TextStyle(
|
TextStyle style18P600 = const TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 18,
|
||||||
color: Colors.red,
|
color: kcPrimaryColor,
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
);
|
|
||||||
|
|
||||||
TextStyle style25DG600 = const TextStyle(
|
|
||||||
fontSize: 25,
|
|
||||||
color: kcDarkGrey,
|
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -189,6 +183,21 @@ TextStyle style12R700 = const TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
TextStyle style14P400 = const TextStyle(
|
||||||
|
color: kcPrimaryColor,
|
||||||
|
);
|
||||||
|
|
||||||
|
TextStyle style14P600 = const TextStyle(
|
||||||
|
color: kcPrimaryColor,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
|
||||||
|
TextStyle style25DG600 = const TextStyle(
|
||||||
|
fontSize: 25,
|
||||||
|
color: kcDarkGrey,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
);
|
||||||
|
|
||||||
TextStyle style16DG600 = const TextStyle(
|
TextStyle style16DG600 = const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
color: kcDarkGrey,
|
color: kcDarkGrey,
|
||||||
|
|
@ -210,13 +219,15 @@ TextStyle style14DG400 = const TextStyle(
|
||||||
color: kcDarkGrey,
|
color: kcDarkGrey,
|
||||||
);
|
);
|
||||||
|
|
||||||
TextStyle style14P400 = const TextStyle(
|
TextStyle style14DG600 = const TextStyle(
|
||||||
color: kcPrimaryColor,
|
color: kcDarkGrey,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
);
|
);
|
||||||
|
|
||||||
TextStyle style14P600 = const TextStyle(
|
TextStyle validationStyle = const TextStyle(
|
||||||
color: kcPrimaryColor,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.w600,
|
color: Colors.red,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
);
|
);
|
||||||
|
|
||||||
Style htmlDefaultStyle = Style(color: kcDarkGrey, fontSize: FontSize(16));
|
Style htmlDefaultStyle = Style(color: kcDarkGrey, fontSize: FontSize(16));
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,20 @@ import 'package:stacked/stacked.dart';
|
||||||
import 'package:stacked_services/stacked_services.dart';
|
import 'package:stacked_services/stacked_services.dart';
|
||||||
import 'package:yimaru_app/ui/common/enmus.dart';
|
import 'package:yimaru_app/ui/common/enmus.dart';
|
||||||
|
|
||||||
|
import '../../../app/app.dialogs.dart';
|
||||||
import '../../../app/app.locator.dart';
|
import '../../../app/app.locator.dart';
|
||||||
import '../../../app/app.router.dart';
|
import '../../../app/app.router.dart';
|
||||||
import '../../../models/assessment.dart';
|
import '../../../models/assessment.dart';
|
||||||
import '../../../models/user_model.dart';
|
import '../../../models/user_model.dart';
|
||||||
import '../../../services/api_service.dart';
|
import '../../../services/api_service.dart';
|
||||||
import '../../../services/authentication_service.dart';
|
import '../../../services/authentication_service.dart';
|
||||||
|
import '../../common/app_colors.dart';
|
||||||
|
import '../../common/ui_helpers.dart';
|
||||||
import '../home/home_view.dart';
|
import '../home/home_view.dart';
|
||||||
|
|
||||||
class AssessmentViewModel extends BaseViewModel {
|
class AssessmentViewModel extends BaseViewModel {
|
||||||
final _apiService = locator<ApiService>();
|
final _apiService = locator<ApiService>();
|
||||||
|
final _dialogService = locator<DialogService>();
|
||||||
final _navigationService = locator<NavigationService>();
|
final _navigationService = locator<NavigationService>();
|
||||||
final _authenticationService = locator<AuthenticationService>();
|
final _authenticationService = locator<AuthenticationService>();
|
||||||
|
|
||||||
|
|
@ -73,9 +77,6 @@ class AssessmentViewModel extends BaseViewModel {
|
||||||
if (_currentQuestion == 5) {
|
if (_currentQuestion == 5) {
|
||||||
// A1
|
// A1
|
||||||
final correctCount = countCorrectAnswersUntil(5);
|
final correctCount = countCorrectAnswersUntil(5);
|
||||||
print('All : $_selectedAnswers');
|
|
||||||
print('Question page : $_currentQuestion');
|
|
||||||
print('Correct A1: $correctCount');
|
|
||||||
|
|
||||||
if (correctCount > 3) {
|
if (correctCount > 3) {
|
||||||
return {'continue': true, 'level': ProficiencyLevels.a1};
|
return {'continue': true, 'level': ProficiencyLevels.a1};
|
||||||
|
|
@ -86,9 +87,6 @@ class AssessmentViewModel extends BaseViewModel {
|
||||||
// A2
|
// A2
|
||||||
|
|
||||||
final correctCount = countCorrectAnswersUntil(10);
|
final correctCount = countCorrectAnswersUntil(10);
|
||||||
print('All : $_selectedAnswers');
|
|
||||||
print('Question page : $_currentQuestion');
|
|
||||||
print('Correct A2: $correctCount');
|
|
||||||
|
|
||||||
if (correctCount > 3) {
|
if (correctCount > 3) {
|
||||||
return {'continue': true, 'level': ProficiencyLevels.a2};
|
return {'continue': true, 'level': ProficiencyLevels.a2};
|
||||||
|
|
@ -98,9 +96,6 @@ class AssessmentViewModel extends BaseViewModel {
|
||||||
} else if (_currentQuestion == 16) {
|
} else if (_currentQuestion == 16) {
|
||||||
// B1
|
// B1
|
||||||
final correctCount = countCorrectAnswersUntil(16);
|
final correctCount = countCorrectAnswersUntil(16);
|
||||||
print('All : $_selectedAnswers');
|
|
||||||
print('Question page : $_currentQuestion');
|
|
||||||
print('Correct B1: $correctCount');
|
|
||||||
|
|
||||||
if (correctCount > 4) {
|
if (correctCount > 4) {
|
||||||
return {'continue': true, 'level': ProficiencyLevels.b1};
|
return {'continue': true, 'level': ProficiencyLevels.b1};
|
||||||
|
|
@ -109,9 +104,6 @@ class AssessmentViewModel extends BaseViewModel {
|
||||||
}
|
}
|
||||||
} else if (_currentQuestion == 22) {
|
} else if (_currentQuestion == 22) {
|
||||||
final correctCount = countCorrectAnswersUntil(16);
|
final correctCount = countCorrectAnswersUntil(16);
|
||||||
print('All : $_selectedAnswers');
|
|
||||||
print('Question page : $_currentQuestion');
|
|
||||||
print('Correct B2: $correctCount');
|
|
||||||
|
|
||||||
if (correctCount > 4) {
|
if (correctCount > 4) {
|
||||||
return {'continue': true, 'level': ProficiencyLevels.b2};
|
return {'continue': true, 'level': ProficiencyLevels.b2};
|
||||||
|
|
@ -178,17 +170,26 @@ class AssessmentViewModel extends BaseViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Complete profile
|
// Complete profile
|
||||||
Future<void> completeProfile() async {
|
|
||||||
Map<String, dynamic> response =
|
Future<void> saveProfileCompleted() async {
|
||||||
await runBusyFuture<Map<String, dynamic>>(_completeProfile());
|
Map<String, dynamic> data = {'firstName': _userData['firstName']};
|
||||||
|
await _authenticationService.saveFullName(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> completeProfile() async =>
|
||||||
|
await runBusyFuture<Map<String, dynamic>>(_completeProfile());
|
||||||
|
|
||||||
Future<Map<String, dynamic>> _completeProfile() async {
|
Future<Map<String, dynamic>> _completeProfile() async {
|
||||||
print(_userData);
|
UserModel? user = await _authenticationService.getUser();
|
||||||
UserModel user = await _authenticationService.getUser();
|
|
||||||
Map<String, dynamic> response =
|
Map<String, dynamic> response =
|
||||||
await _apiService.updateProfile(data: _userData, user: user);
|
await _apiService.updateProfile(data: _userData, user: user);
|
||||||
|
if (response['status'] == ResponseStatus.success) {
|
||||||
|
showSuccessToast(response['message']);
|
||||||
|
await saveProfileCompleted();
|
||||||
|
await replaceWithHome();
|
||||||
|
} else {
|
||||||
|
showErrorToast(response['message']);
|
||||||
|
}
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -203,8 +204,7 @@ class AssessmentViewModel extends BaseViewModel {
|
||||||
} else {
|
} else {
|
||||||
if (response['continue']) {
|
if (response['continue']) {
|
||||||
_pageController.jumpToPage(_currentQuestion);
|
_pageController.jumpToPage(_currentQuestion);
|
||||||
}
|
} else {
|
||||||
{
|
|
||||||
_proficiencyLevel = response['level'];
|
_proficiencyLevel = response['level'];
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
@ -218,8 +218,6 @@ class AssessmentViewModel extends BaseViewModel {
|
||||||
_pageController.previousPage(
|
_pageController.previousPage(
|
||||||
duration: const Duration(microseconds: 100), curve: Curves.linear);
|
duration: const Duration(microseconds: 100), curve: Curves.linear);
|
||||||
rebuildUi();
|
rebuildUi();
|
||||||
} else {
|
|
||||||
_navigationService.back();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,12 +236,34 @@ class AssessmentViewModel extends BaseViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop() {
|
void pop() {
|
||||||
if (_currentPage != 0) {
|
if (_currentPage == 3 /*7*/) {
|
||||||
|
_navigationService.back();
|
||||||
|
} else if (_currentPage != 0 && _currentPage != 3) {
|
||||||
_currentPage--;
|
_currentPage--;
|
||||||
rebuildUi();
|
rebuildUi();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool?> showAbortDialog() async {
|
||||||
|
DialogResponse? response = await _dialogService.showDialog(
|
||||||
|
cancelTitle: 'No',
|
||||||
|
buttonTitle: 'Yes',
|
||||||
|
barrierDismissible: true,
|
||||||
|
title: 'Abort Assessment',
|
||||||
|
cancelTitleColor: kcDarkGrey,
|
||||||
|
buttonTitleColor: kcPrimaryColor,
|
||||||
|
description: 'Are you sure to abort the assessment ?',
|
||||||
|
);
|
||||||
|
return response?.confirmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> abort() async {
|
||||||
|
bool? response = await showAbortDialog();
|
||||||
|
if (response != null && response) {
|
||||||
|
next(page: 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> navigateToLanguage() async =>
|
Future<void> navigateToLanguage() async =>
|
||||||
await _navigationService.navigateToLanguageView();
|
await _navigationService.navigateToLanguageView();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,10 @@ class AssessmentFormScreen extends ViewModelWidget<AssessmentViewModel> {
|
||||||
[_buildAppBar(viewModel), _buildExpandedBody(viewModel)];
|
[_buildAppBar(viewModel), _buildExpandedBody(viewModel)];
|
||||||
|
|
||||||
Widget _buildAppBar(AssessmentViewModel viewModel) => LargeAppBar(
|
Widget _buildAppBar(AssessmentViewModel viewModel) => LargeAppBar(
|
||||||
showBackButton: true,
|
onClose: viewModel.abort,
|
||||||
showLanguageSelection: false,
|
showLanguageSelection: false,
|
||||||
onPop: viewModel.previousQuestion,
|
onPop: viewModel.previousQuestion,
|
||||||
|
showBackButton: viewModel.currentQuestion == 0 ? false : true,
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildExpandedBody(AssessmentViewModel viewModel) =>
|
Widget _buildExpandedBody(AssessmentViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,8 @@ class AssessmentIntroScreen extends ViewModelWidget<AssessmentViewModel> {
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildAppBar(AssessmentViewModel viewModel) => LargeAppBar(
|
Widget _buildAppBar(AssessmentViewModel viewModel) => LargeAppBar(
|
||||||
showBackButton: false,
|
showBackButton: true,
|
||||||
|
onPop: viewModel.pop,
|
||||||
showLanguageSelection: true,
|
showLanguageSelection: true,
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import 'package:yimaru_app/ui/widgets/custom_elevated_button.dart';
|
||||||
import 'package:yimaru_app/ui/widgets/large_app_bar.dart';
|
import 'package:yimaru_app/ui/widgets/large_app_bar.dart';
|
||||||
|
|
||||||
import '../../../common/enmus.dart';
|
import '../../../common/enmus.dart';
|
||||||
|
import '../../../widgets/page_loading_indicator.dart';
|
||||||
import '../assessment_viewmodel.dart';
|
import '../assessment_viewmodel.dart';
|
||||||
|
|
||||||
class StartLessonScreen extends ViewModelWidget<AssessmentViewModel> {
|
class StartLessonScreen extends ViewModelWidget<AssessmentViewModel> {
|
||||||
|
|
@ -15,13 +16,11 @@ class StartLessonScreen extends ViewModelWidget<AssessmentViewModel> {
|
||||||
Future<void> _start(AssessmentViewModel viewModel) async {
|
Future<void> _start(AssessmentViewModel viewModel) async {
|
||||||
if (viewModel.proficiencyLevel != ProficiencyLevels.none) {
|
if (viewModel.proficiencyLevel != ProficiencyLevels.none) {
|
||||||
Map<String, dynamic> data = {
|
Map<String, dynamic> data = {
|
||||||
'preferred_language': 'en',
|
|
||||||
'knowledge_level': viewModel.proficiencyLevel.name.toUpperCase()
|
'knowledge_level': viewModel.proficiencyLevel.name.toUpperCase()
|
||||||
};
|
};
|
||||||
|
|
||||||
viewModel.addUserData(data);
|
viewModel.addUserData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
await viewModel.completeProfile();
|
await viewModel.completeProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,20 +30,24 @@ class StartLessonScreen extends ViewModelWidget<AssessmentViewModel> {
|
||||||
|
|
||||||
Widget _buildScaffoldWrapper(AssessmentViewModel viewModel) => Scaffold(
|
Widget _buildScaffoldWrapper(AssessmentViewModel viewModel) => Scaffold(
|
||||||
backgroundColor: kcBackgroundColor,
|
backgroundColor: kcBackgroundColor,
|
||||||
body: _buildScaffold(viewModel),
|
body: _buildScaffoldStack(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Widget _buildScaffoldStack(AssessmentViewModel viewModel) =>
|
||||||
|
Stack(children: [_buildScaffold(viewModel), _buildState(viewModel)]);
|
||||||
|
|
||||||
Widget _buildScaffold(AssessmentViewModel viewModel) => Column(
|
Widget _buildScaffold(AssessmentViewModel viewModel) => Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: _buildScaffoldChildren(viewModel),
|
children: _buildScaffoldChildren(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
List<Widget> _buildScaffoldChildren(AssessmentViewModel viewModel) =>
|
List<Widget> _buildScaffoldChildren(AssessmentViewModel viewModel) =>
|
||||||
[_buildAppBar(), _buildExpandedBody(viewModel)];
|
[_buildAppBar(viewModel), _buildExpandedBody(viewModel)];
|
||||||
|
|
||||||
Widget _buildAppBar() => const LargeAppBar(
|
Widget _buildAppBar(AssessmentViewModel viewModel) => LargeAppBar(
|
||||||
showBackButton: false,
|
showBackButton: true,
|
||||||
showLanguageSelection: false,
|
onPop: viewModel.pop,
|
||||||
|
showLanguageSelection: true,
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildExpandedBody(AssessmentViewModel viewModel) =>
|
Widget _buildExpandedBody(AssessmentViewModel viewModel) =>
|
||||||
|
|
@ -114,10 +117,13 @@ class StartLessonScreen extends ViewModelWidget<AssessmentViewModel> {
|
||||||
Widget _buildContinueButton(AssessmentViewModel viewModel) =>
|
Widget _buildContinueButton(AssessmentViewModel viewModel) =>
|
||||||
CustomElevatedButton(
|
CustomElevatedButton(
|
||||||
height: 55,
|
height: 55,
|
||||||
|
text: 'Finish',
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
text: 'Go to My Lessons',
|
|
||||||
foregroundColor: kcWhite,
|
foregroundColor: kcWhite,
|
||||||
backgroundColor: kcPrimaryColor,
|
backgroundColor: kcPrimaryColor,
|
||||||
onTap: () async => await _start(viewModel),
|
onTap: () async => await _start(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Widget _buildState(AssessmentViewModel viewModel) =>
|
||||||
|
viewModel.isBusy ? const PageLoadingIndicator() : Container();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
96
lib/ui/views/failure/failure_view.dart
Normal file
96
lib/ui/views/failure/failure_view.dart
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:stacked/stacked.dart';
|
||||||
|
|
||||||
|
import '../../common/app_colors.dart';
|
||||||
|
import '../../common/ui_helpers.dart';
|
||||||
|
import '../../widgets/custom_circular_progress_indicator.dart';
|
||||||
|
import 'failure_viewmodel.dart';
|
||||||
|
|
||||||
|
class FailureView extends StackedView<FailureViewModel> {
|
||||||
|
final String label;
|
||||||
|
const FailureView({Key? key, required this.label}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
FailureViewModel viewModelBuilder(BuildContext context) => FailureViewModel();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget builder(
|
||||||
|
BuildContext context,
|
||||||
|
FailureViewModel viewModel,
|
||||||
|
Widget? child,
|
||||||
|
) =>
|
||||||
|
_buildScaffoldWrapper();
|
||||||
|
|
||||||
|
Widget _buildScaffoldWrapper() => Scaffold(
|
||||||
|
backgroundColor: kcBackgroundColor,
|
||||||
|
body: _buildScaffold(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildScaffold() => Stack(
|
||||||
|
children: _buildScaffoldChildren(),
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Widget> _buildScaffoldChildren() => [
|
||||||
|
_buildBackground(),
|
||||||
|
_buildColumn(),
|
||||||
|
];
|
||||||
|
|
||||||
|
Widget _buildBackground() => Image.asset(
|
||||||
|
'assets/images/onboarding_1.png',
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
width: double.maxFinite,
|
||||||
|
height: double.maxFinite,
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildColumn() => Column(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: _buildUpperColumnChildren(),
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Widget> _buildUpperColumnChildren() =>
|
||||||
|
[_buildIconWrapper(), _buildSafeWrapper()];
|
||||||
|
|
||||||
|
Widget _buildSafeWrapper() => SafeArea(child: _buildLoadingTextContainer());
|
||||||
|
|
||||||
|
Widget _buildLoadingTextContainer() => Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 50),
|
||||||
|
child: _buildLoadingTextWrapper(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildLoadingTextWrapper() => Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: _buildLoadingTextChildren(),
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Widget> _buildLoadingTextChildren() => [
|
||||||
|
_buildLoadingText(),
|
||||||
|
horizontalSpaceSmall,
|
||||||
|
_buildIndicatorWrapper(),
|
||||||
|
];
|
||||||
|
|
||||||
|
Widget _buildLoadingText() =>
|
||||||
|
Text('$label ...', style: const TextStyle(color: kcWhite, fontSize: 16));
|
||||||
|
|
||||||
|
Widget _buildIndicatorWrapper() => SizedBox(
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
child: _buildIndicator(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildIndicator() =>
|
||||||
|
const CustomCircularProgressIndicator(color: kcWhite);
|
||||||
|
|
||||||
|
Widget _buildIconWrapper() => Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 100),
|
||||||
|
child: _buildIcon(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget _buildIcon() => SvgPicture.asset(
|
||||||
|
'assets/icons/logo.svg',
|
||||||
|
height: 50,
|
||||||
|
);
|
||||||
|
}
|
||||||
3
lib/ui/views/failure/failure_viewmodel.dart
Normal file
3
lib/ui/views/failure/failure_viewmodel.dart
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
import 'package:stacked/stacked.dart';
|
||||||
|
|
||||||
|
class FailureViewModel extends BaseViewModel {}
|
||||||
|
|
@ -15,8 +15,9 @@ class HomeView extends StackedView<HomeViewModel> {
|
||||||
HomeViewModel viewModelBuilder(BuildContext context) => HomeViewModel();
|
HomeViewModel viewModelBuilder(BuildContext context) => HomeViewModel();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onViewModelReady(HomeViewModel viewModel) {
|
void onViewModelReady(HomeViewModel viewModel) async {
|
||||||
viewModel.getProfileStatus();
|
await viewModel.getProfileStatus();
|
||||||
|
await viewModel.getProfileData();
|
||||||
super.onViewModelReady(viewModel);
|
super.onViewModelReady(viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,10 @@ import 'package:yimaru_app/services/status_checker_service.dart';
|
||||||
import 'package:yimaru_app/ui/common/app_strings.dart';
|
import 'package:yimaru_app/ui/common/app_strings.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:stacked_services/stacked_services.dart';
|
import 'package:stacked_services/stacked_services.dart';
|
||||||
|
import 'package:yimaru_app/ui/common/ui_helpers.dart';
|
||||||
|
import 'package:yimaru_app/ui/views/failure/failure_view.dart';
|
||||||
|
import 'package:yimaru_app/ui/views/login/login_view.dart';
|
||||||
|
import 'package:yimaru_app/ui/views/startup/startup_view.dart';
|
||||||
|
|
||||||
import '../../../services/api_service.dart';
|
import '../../../services/api_service.dart';
|
||||||
import '../../../services/authentication_service.dart';
|
import '../../../services/authentication_service.dart';
|
||||||
|
|
@ -46,28 +50,69 @@ class HomeViewModel extends BaseViewModel {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> saveFullName(String name) async {
|
||||||
|
Map<String, dynamic> data = {
|
||||||
|
'firstName': name,
|
||||||
|
};
|
||||||
|
await _authenticationService.saveFullName(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveProfileStatus(bool value) async =>
|
||||||
|
await _authenticationService.saveProfileStatus(value);
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
|
Future<void> replaceWithFailure() async =>
|
||||||
|
await _navigationService.clearStackAndShowView(
|
||||||
|
const FailureView(label: 'Check your internet connection to proceed'),
|
||||||
|
);
|
||||||
|
|
||||||
Future<void> replaceWithOnboarding() async =>
|
Future<void> replaceWithOnboarding() async =>
|
||||||
await _navigationService.replaceWithOnboardingView();
|
await _navigationService.replaceWithOnboardingView();
|
||||||
|
|
||||||
// Remote api calls
|
// Remote api calls
|
||||||
|
Future<void> getProfileData() async =>
|
||||||
|
await runBusyFuture<Map<String, dynamic>>(_getProfileData());
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> _getProfileData() async {
|
||||||
|
Map<String, dynamic> response = {};
|
||||||
|
|
||||||
|
UserModel? user = await _authenticationService.getUser();
|
||||||
|
|
||||||
|
if (user?.profileCompleted != null) {
|
||||||
|
if (await _statusChecker.checkConnection()) {
|
||||||
|
response = await _apiService.getProfileData(user?.userId);
|
||||||
|
if (response['status'] == ResponseStatus.success) {
|
||||||
|
Map<String, dynamic> data = {
|
||||||
|
'firstName': response['data']['first_name']
|
||||||
|
};
|
||||||
|
await _authenticationService.saveFullName(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> getProfileStatus() async {
|
Future<void> getProfileStatus() async {
|
||||||
Map<String, dynamic> response =
|
Map<String, dynamic> response =
|
||||||
await runBusyFuture<Map<String, dynamic>>(_getProfileStatus());
|
await runBusyFuture<Map<String, dynamic>>(_getProfileStatus());
|
||||||
if (response['status'] == ResponseStatus.success && !response['data']) {
|
if (response['status'] == ResponseStatus.success && !response['data']) {
|
||||||
await replaceWithOnboarding();
|
await replaceWithOnboarding();
|
||||||
|
} else if (response['status'] == ResponseStatus.success &&
|
||||||
|
response['data']) {
|
||||||
|
await saveProfileStatus(response['data']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> _getProfileStatus() async {
|
Future<Map<String, dynamic>> _getProfileStatus() async {
|
||||||
Map<String, dynamic> response = {};
|
Map<String, dynamic> response = {};
|
||||||
UserModel user = await _authenticationService.getUser();
|
|
||||||
|
|
||||||
if (user.profileCompleted == null) {
|
UserModel? user = await _authenticationService.getUser();
|
||||||
|
if (user?.profileCompleted == null) {
|
||||||
if (await _statusChecker.checkConnection()) {
|
if (await _statusChecker.checkConnection()) {
|
||||||
response = await _apiService.getProfileStatus(user);
|
response = await _apiService.getProfileStatus(user);
|
||||||
} else {
|
} else {
|
||||||
response = {'data': false, 'status': ResponseStatus.success};
|
await replaceWithFailure();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
response = {'data': true, 'status': ResponseStatus.success};
|
response = {'data': true, 'status': ResponseStatus.success};
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,15 @@ class LearnView extends StackedView<LearnViewModel> {
|
||||||
Widget _buildColumn(LearnViewModel viewModel) => Column(
|
Widget _buildColumn(LearnViewModel viewModel) => Column(
|
||||||
children: [
|
children: [
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
_buildAppBar(),
|
_buildAppBar(viewModel),
|
||||||
_buildLevelsColumnWrapper(viewModel)
|
_buildLevelsColumnWrapper(viewModel)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildAppBar() => const LearnAppBar();
|
Widget _buildAppBar(LearnViewModel viewModel) => LearnAppBar(
|
||||||
|
name: viewModel.user?.firstName,
|
||||||
|
profileImage: viewModel.user?.profileImage,
|
||||||
|
);
|
||||||
|
|
||||||
Widget _buildLevelsColumnWrapper(LearnViewModel viewModel) =>
|
Widget _buildLevelsColumnWrapper(LearnViewModel viewModel) =>
|
||||||
Expanded(child: _buildLevelsColumnScrollView(viewModel));
|
Expanded(child: _buildLevelsColumnScrollView(viewModel));
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,19 @@
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:stacked_services/stacked_services.dart';
|
import 'package:stacked_services/stacked_services.dart';
|
||||||
import 'package:yimaru_app/app/app.router.dart';
|
import 'package:yimaru_app/app/app.router.dart';
|
||||||
|
import 'package:yimaru_app/models/user_model.dart';
|
||||||
|
import 'package:yimaru_app/services/authentication_service.dart';
|
||||||
import 'package:yimaru_app/ui/common/enmus.dart';
|
import 'package:yimaru_app/ui/common/enmus.dart';
|
||||||
|
|
||||||
import '../../../app/app.locator.dart';
|
import '../../../app/app.locator.dart';
|
||||||
|
|
||||||
class LearnViewModel extends BaseViewModel {
|
class LearnViewModel extends BaseViewModel {
|
||||||
final _navigationService = locator<NavigationService>();
|
final _navigationService = locator<NavigationService>();
|
||||||
|
final _authenticationService = locator<AuthenticationService>();
|
||||||
|
|
||||||
|
late final UserModel? _user = _authenticationService.user;
|
||||||
|
|
||||||
|
UserModel? get user => _user;
|
||||||
|
|
||||||
final List<Map<String, dynamic>> _learnLevels = [
|
final List<Map<String, dynamic>> _learnLevels = [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -37,5 +37,6 @@ class LearnModuleViewModel extends BaseViewModel {
|
||||||
|
|
||||||
void pop() => _navigationService.back();
|
void pop() => _navigationService.back();
|
||||||
|
|
||||||
Future<void> navigateToLearnLesson() async=> await _navigationService.navigateToLearnLessonView();
|
Future<void> navigateToLearnLesson() async =>
|
||||||
|
await _navigationService.navigateToLearnLessonView();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ class LoginViewModel extends FormViewModel {
|
||||||
'refreshToken': user.refreshToken
|
'refreshToken': user.refreshToken
|
||||||
};
|
};
|
||||||
|
|
||||||
await _authenticationService.saveUserData(data);
|
await _authenticationService.saveBasicUserData(data);
|
||||||
showSuccessToast(response['message']);
|
showSuccessToast(response['message']);
|
||||||
} else {
|
} else {
|
||||||
showErrorToast(response['message']);
|
showErrorToast(response['message']);
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ class OnboardingView extends StackedView<OnboardingViewModel>
|
||||||
|
|
||||||
Widget _buildOnboardingScreensWrapper(OnboardingViewModel viewModel) =>
|
Widget _buildOnboardingScreensWrapper(OnboardingViewModel viewModel) =>
|
||||||
PopScope(
|
PopScope(
|
||||||
canPop: false,
|
canPop: viewModel.currentPage == 0 ? true : false,
|
||||||
onPopInvokedWithResult: (value, data) => viewModel.pop(),
|
onPopInvokedWithResult: (value, data) => viewModel.pop(),
|
||||||
child: _buildOnboardingScreens(viewModel));
|
child: _buildOnboardingScreens(viewModel));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,10 +54,13 @@ class OnboardingViewModel extends FormViewModel {
|
||||||
|
|
||||||
// Age group
|
// Age group
|
||||||
final List<String> _ageGroups = [
|
final List<String> _ageGroups = [
|
||||||
'8-14',
|
'UNDER_13',
|
||||||
'15-18',
|
'13_17',
|
||||||
'19-26',
|
'18_24',
|
||||||
'26+',
|
'25_34',
|
||||||
|
'35_44',
|
||||||
|
'45_54',
|
||||||
|
'55_PLUS'
|
||||||
];
|
];
|
||||||
|
|
||||||
List<String> get ageGroups => _ageGroups;
|
List<String> get ageGroups => _ageGroups;
|
||||||
|
|
@ -352,7 +355,6 @@ class OnboardingViewModel extends FormViewModel {
|
||||||
// Add user data
|
// Add user data
|
||||||
void addUserData(Map<String, dynamic> data) {
|
void addUserData(Map<String, dynamic> data) {
|
||||||
_userData.addAll(data);
|
_userData.addAll(data);
|
||||||
print('User data : $_userData');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearUserData() {
|
void clearUserData() {
|
||||||
|
|
@ -385,7 +387,7 @@ class OnboardingViewModel extends FormViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop() {
|
void pop() {
|
||||||
if (_currentPage == 8) {
|
if (_currentPage == 0) {
|
||||||
_navigationService.back();
|
_navigationService.back();
|
||||||
} else {
|
} else {
|
||||||
_currentPage--;
|
_currentPage--;
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,7 @@ class BirthdayFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
||||||
Future<void> _next(OnboardingViewModel viewModel) async {
|
Future<void> _next(OnboardingViewModel viewModel) async {
|
||||||
FocusManager.instance.primaryFocus?.unfocus();
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
|
|
||||||
Map<String, dynamic> data = {
|
Map<String, dynamic> data = {'birth_day': viewModel.selectedBirthday};
|
||||||
'birth_day': DateFormat('yyyy-MM-dd')
|
|
||||||
.parseUTC(viewModel.selectedBirthday ?? DateTime.now().toString())
|
|
||||||
.toIso8601String()
|
|
||||||
};
|
|
||||||
viewModel.addUserData(data);
|
viewModel.addUserData(data);
|
||||||
viewModel.next();
|
viewModel.next();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,13 +93,16 @@ class LearningGoalFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
||||||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildTitle(OnboardingViewModel viewModel) => Text(
|
Widget _buildTitle(OnboardingViewModel viewModel) => Text.rich(
|
||||||
'Hi ${viewModel.userData['first_name']}, Choose your learning goal.',
|
TextSpan(
|
||||||
style: const TextStyle(
|
text: 'Hi ${viewModel.userData['first_name']},',
|
||||||
fontSize: 25,
|
style: style18P600.copyWith(fontSize: 22),
|
||||||
color: kcDarkGrey,
|
children: [
|
||||||
fontWeight: FontWeight.w600,
|
TextSpan(
|
||||||
),
|
text: ' Choose your learning goal.',
|
||||||
|
style: style16DG600.copyWith(fontSize: 22),
|
||||||
|
)
|
||||||
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildLearningGoals(OnboardingViewModel viewModel) => ListView.builder(
|
Widget _buildLearningGoals(OnboardingViewModel viewModel) => ListView.builder(
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ class TopicFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
||||||
FocusManager.instance.primaryFocus?.unfocus();
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
|
|
||||||
Map<String, dynamic> data = {
|
Map<String, dynamic> data = {
|
||||||
|
'profile_completed': true,
|
||||||
|
'preferred_language': 'en',
|
||||||
'favoutite_topic': viewModel.selectedTopic ?? topicController.text,
|
'favoutite_topic': viewModel.selectedTopic ?? topicController.text,
|
||||||
};
|
};
|
||||||
viewModel.addUserData(data);
|
viewModel.addUserData(data);
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class ProfileView extends StackedView<ProfileViewModel> {
|
||||||
children: [
|
children: [
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
_buildNotificationIconWrapper(),
|
_buildNotificationIconWrapper(),
|
||||||
_buildProfileSection(),
|
_buildProfileSection(viewModel),
|
||||||
verticalSpaceSmall,
|
verticalSpaceSmall,
|
||||||
_buildViewProfileButton(viewModel),
|
_buildViewProfileButton(viewModel),
|
||||||
verticalSpaceLarge,
|
verticalSpaceLarge,
|
||||||
|
|
@ -66,27 +66,25 @@ class ProfileView extends StackedView<ProfileViewModel> {
|
||||||
color: kcDarkGrey,
|
color: kcDarkGrey,
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildProfileSection() => Column(
|
Widget _buildProfileSection(ProfileViewModel viewModel) => Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: _buildProfileSectionChildren(),
|
children: _buildProfileSectionChildren(viewModel),
|
||||||
);
|
);
|
||||||
|
|
||||||
List<Widget> _buildProfileSectionChildren() => [
|
List<Widget> _buildProfileSectionChildren(ProfileViewModel viewModel) => [
|
||||||
_buildProfileImage(),
|
_buildProfileImage(viewModel),
|
||||||
verticalSpaceSmall,
|
verticalSpaceSmall,
|
||||||
_buildProfileName(),
|
_buildProfileName(viewModel),
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildProfileImage() => const ProfileImage();
|
Widget _buildProfileImage(ProfileViewModel viewModel) => ProfileImage(
|
||||||
|
profileImage: viewModel.user?.profileImage,
|
||||||
|
);
|
||||||
|
|
||||||
Widget _buildProfileName() => const Text(
|
Widget _buildProfileName(ProfileViewModel viewModel) => Text(
|
||||||
'Hi, Bisrat 👋',
|
'Hi, ${viewModel.user?.firstName ?? ''} 👋',
|
||||||
style: TextStyle(
|
style: style25DG600,
|
||||||
fontSize: 25,
|
|
||||||
color: kcDarkGrey,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildViewProfileButton(ProfileViewModel viewModel) =>
|
Widget _buildViewProfileButton(ProfileViewModel viewModel) =>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import 'package:stacked_services/stacked_services.dart';
|
||||||
import 'package:yimaru_app/app/app.router.dart';
|
import 'package:yimaru_app/app/app.router.dart';
|
||||||
|
|
||||||
import '../../../app/app.locator.dart';
|
import '../../../app/app.locator.dart';
|
||||||
|
import '../../../models/user_model.dart';
|
||||||
import '../../../services/authentication_service.dart';
|
import '../../../services/authentication_service.dart';
|
||||||
|
|
||||||
class ProfileViewModel extends BaseViewModel {
|
class ProfileViewModel extends BaseViewModel {
|
||||||
|
|
@ -10,6 +11,10 @@ class ProfileViewModel extends BaseViewModel {
|
||||||
|
|
||||||
final _authenticationService = locator<AuthenticationService>();
|
final _authenticationService = locator<AuthenticationService>();
|
||||||
|
|
||||||
|
late final UserModel? _user = _authenticationService.user;
|
||||||
|
|
||||||
|
UserModel? get user => _user;
|
||||||
|
|
||||||
Future<void> logOut() async {
|
Future<void> logOut() async {
|
||||||
await _authenticationService.logOut();
|
await _authenticationService.logOut();
|
||||||
await _navigationService.replaceWithLoginView();
|
await _navigationService.replaceWithLoginView();
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ class ProfileDetailView extends StackedView<ProfileDetailViewModel>
|
||||||
|
|
||||||
List<Widget> _buildColumnChildren(ProfileDetailViewModel viewModel) => [
|
List<Widget> _buildColumnChildren(ProfileDetailViewModel viewModel) => [
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
_buildProfileImage(),
|
_buildProfileImageWrapper(viewModel),
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
_buildNameFormSection(viewModel),
|
_buildNameFormSection(viewModel),
|
||||||
verticalSpaceMedium,
|
verticalSpaceMedium,
|
||||||
|
|
@ -120,9 +120,12 @@ class ProfileDetailView extends StackedView<ProfileDetailViewModel>
|
||||||
_buildLowerColumn(viewModel)
|
_buildLowerColumn(viewModel)
|
||||||
];
|
];
|
||||||
|
|
||||||
Widget _buildProfileImage() =>
|
Widget _buildProfileImageWrapper(ProfileDetailViewModel viewModel) =>
|
||||||
const Align(alignment: Alignment.center, child: ProfileImage());
|
Align(alignment: Alignment.center, child: _buildProfileImage(viewModel));
|
||||||
|
|
||||||
|
Widget _buildProfileImage(ProfileDetailViewModel viewModel) => ProfileImage(
|
||||||
|
profileImage: viewModel.user?.profileImage,
|
||||||
|
);
|
||||||
Widget _buildNameFormSection(ProfileDetailViewModel viewModel) => Row(
|
Widget _buildNameFormSection(ProfileDetailViewModel viewModel) => Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: _buildNameFormChildren(viewModel),
|
children: _buildNameFormChildren(viewModel),
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,18 @@ import 'package:stacked/stacked.dart';
|
||||||
import 'package:stacked_services/stacked_services.dart';
|
import 'package:stacked_services/stacked_services.dart';
|
||||||
|
|
||||||
import '../../../app/app.locator.dart';
|
import '../../../app/app.locator.dart';
|
||||||
|
import '../../../models/user_model.dart';
|
||||||
|
import '../../../services/authentication_service.dart';
|
||||||
|
|
||||||
class ProfileDetailViewModel extends FormViewModel {
|
class ProfileDetailViewModel extends FormViewModel {
|
||||||
final _navigationService = locator<NavigationService>();
|
final _navigationService = locator<NavigationService>();
|
||||||
|
|
||||||
|
final _authenticationService = locator<AuthenticationService>();
|
||||||
|
|
||||||
|
late final UserModel? _user = _authenticationService.user;
|
||||||
|
|
||||||
|
UserModel? get user => _user;
|
||||||
|
|
||||||
// First name
|
// First name
|
||||||
bool _focusFirstName = false;
|
bool _focusFirstName = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -246,7 +246,7 @@ class RegisterViewModel extends FormViewModel {
|
||||||
// 'refreshToken': 'refreshToken'
|
// 'refreshToken': 'refreshToken'
|
||||||
// }
|
// }
|
||||||
|
|
||||||
await _authenticationService.saveUserData(data);
|
await _authenticationService.saveBasicUserData(data);
|
||||||
showSuccessToast(response['message']);
|
showSuccessToast(response['message']);
|
||||||
} else {
|
} else {
|
||||||
showErrorToast(response['message']);
|
showErrorToast(response['message']);
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,13 @@ class LargeAppBar extends StatelessWidget {
|
||||||
final bool showBackButton;
|
final bool showBackButton;
|
||||||
final GestureTapCallback? onPop;
|
final GestureTapCallback? onPop;
|
||||||
final bool showLanguageSelection;
|
final bool showLanguageSelection;
|
||||||
|
final GestureTapCallback? onClose;
|
||||||
final GestureTapCallback? onLanguage;
|
final GestureTapCallback? onLanguage;
|
||||||
|
|
||||||
const LargeAppBar(
|
const LargeAppBar(
|
||||||
{super.key,
|
{super.key,
|
||||||
this.onPop,
|
this.onPop,
|
||||||
|
this.onClose,
|
||||||
this.onLanguage,
|
this.onLanguage,
|
||||||
required this.showBackButton,
|
required this.showBackButton,
|
||||||
required this.showLanguageSelection});
|
required this.showLanguageSelection});
|
||||||
|
|
@ -53,9 +55,9 @@ class LargeAppBar extends StatelessWidget {
|
||||||
|
|
||||||
Widget _buildRightButton() => Align(
|
Widget _buildRightButton() => Align(
|
||||||
alignment: Alignment.bottomRight,
|
alignment: Alignment.bottomRight,
|
||||||
child: showLanguageSelection ? _buildLanguageSelector() : Container()
|
child: showLanguageSelection
|
||||||
// _buildCloseButton()
|
? _buildLanguageSelector()
|
||||||
);
|
: _buildCloseButton());
|
||||||
|
|
||||||
Widget _buildLanguageSelector() => LanguageButton(
|
Widget _buildLanguageSelector() => LanguageButton(
|
||||||
language: 'EN',
|
language: 'EN',
|
||||||
|
|
@ -63,8 +65,9 @@ class LargeAppBar extends StatelessWidget {
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildCloseButton() => IconButton(
|
Widget _buildCloseButton() => IconButton(
|
||||||
onPressed: () {},
|
onPressed: onClose,
|
||||||
icon: _buildCloseIcon(),
|
icon: _buildCloseIcon(),
|
||||||
|
padding: const EdgeInsets.only(top: 5),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildCloseIcon() => const Icon(
|
Widget _buildCloseIcon() => const Icon(
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:yimaru_app/ui/common/ui_helpers.dart';
|
import 'package:yimaru_app/ui/common/ui_helpers.dart';
|
||||||
|
|
||||||
import '../common/app_colors.dart';
|
import '../common/app_colors.dart';
|
||||||
|
|
||||||
class LearnAppBar extends StatelessWidget {
|
class LearnAppBar extends StatelessWidget {
|
||||||
const LearnAppBar({super.key});
|
final String? name;
|
||||||
|
final String? profileImage;
|
||||||
|
|
||||||
|
const LearnAppBar(
|
||||||
|
{super.key, required this.name, required this.profileImage});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => _buildStack();
|
Widget build(BuildContext context) => _buildStack();
|
||||||
|
|
@ -30,9 +35,22 @@ class LearnAppBar extends StatelessWidget {
|
||||||
List<Widget> _buildProfileRowChildren() =>
|
List<Widget> _buildProfileRowChildren() =>
|
||||||
[_buildProfileImage(), horizontalSpaceSmall, _buildGreetingTextColumn()];
|
[_buildProfileImage(), horizontalSpaceSmall, _buildGreetingTextColumn()];
|
||||||
|
|
||||||
Widget _buildProfileImage() => const CircleAvatar(
|
Widget _buildProfileImage() => CircleAvatar(
|
||||||
radius: 25,
|
radius: 25,
|
||||||
backgroundImage: AssetImage('assets/images/profile.png'),
|
backgroundColor: kcPrimaryColor,
|
||||||
|
backgroundImage: profileImage != null
|
||||||
|
? CachedNetworkImageProvider(profileImage!)
|
||||||
|
: null,
|
||||||
|
child: _buildImageBuilder(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget? _buildImageBuilder() =>
|
||||||
|
profileImage == null ? _buildPersonIcon() : null;
|
||||||
|
|
||||||
|
Widget _buildPersonIcon() => const Icon(
|
||||||
|
Icons.person,
|
||||||
|
size: 30,
|
||||||
|
color: kcWhite,
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildGreetingTextColumn() => Column(
|
Widget _buildGreetingTextColumn() => Column(
|
||||||
|
|
@ -44,28 +62,19 @@ class LearnAppBar extends StatelessWidget {
|
||||||
List<Widget> _buildGreetingChildren() =>
|
List<Widget> _buildGreetingChildren() =>
|
||||||
[_buildGreetingTitle(), _buildSubTitle()];
|
[_buildGreetingTitle(), _buildSubTitle()];
|
||||||
|
|
||||||
Widget _buildGreetingTitle() => const Text.rich(
|
Widget _buildGreetingTitle() => Text.rich(
|
||||||
|
TextSpan(text: 'Hello,', style: style14DG600, children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'Hello,',
|
text: ' $name!',
|
||||||
style: TextStyle(
|
style: style14P600,
|
||||||
color: kcDarkGrey,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
children: [
|
|
||||||
TextSpan(
|
|
||||||
text: ' Bisrat!',
|
|
||||||
style: TextStyle(
|
|
||||||
color: kcPrimaryColor,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildSubTitle() => const Text(
|
Widget _buildSubTitle() => Text(
|
||||||
'Ready to keep learning English today?',
|
'Ready to keep learning English today?',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(color: kcMediumGrey),
|
style: style14DG400,
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildNotificationIconWrapper() =>
|
Widget _buildNotificationIconWrapper() =>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:yimaru_app/ui/common/app_colors.dart';
|
import 'package:yimaru_app/ui/common/app_colors.dart';
|
||||||
|
|
||||||
class ProfileImage extends StatelessWidget {
|
class ProfileImage extends StatelessWidget {
|
||||||
const ProfileImage({super.key});
|
final String? profileImage;
|
||||||
|
const ProfileImage({super.key, required this.profileImage});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => _buildSizedBox();
|
Widget build(BuildContext context) => _buildSizedBox();
|
||||||
|
|
@ -22,9 +24,22 @@ class ProfileImage extends StatelessWidget {
|
||||||
child: _buildProfileImage(),
|
child: _buildProfileImage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildProfileImage() => const CircleAvatar(
|
Widget _buildProfileImage() => CircleAvatar(
|
||||||
radius: 50,
|
radius: 50,
|
||||||
backgroundImage: AssetImage('assets/images/profile.png'),
|
backgroundColor: kcPrimaryColor,
|
||||||
|
backgroundImage: profileImage != null
|
||||||
|
? CachedNetworkImageProvider(profileImage!)
|
||||||
|
: null,
|
||||||
|
child: _buildImageBuilder(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget? _buildImageBuilder() =>
|
||||||
|
profileImage == null ? _buildPersonIcon() : null;
|
||||||
|
|
||||||
|
Widget _buildPersonIcon() => const Icon(
|
||||||
|
Icons.person,
|
||||||
|
size: 50,
|
||||||
|
color: kcWhite,
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _buildCameraButtonWrapper() => Align(
|
Widget _buildCameraButtonWrapper() => Align(
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,11 @@ import Foundation
|
||||||
import battery_plus
|
import battery_plus
|
||||||
import connectivity_plus
|
import connectivity_plus
|
||||||
import flutter_secure_storage_darwin
|
import flutter_secure_storage_darwin
|
||||||
|
import sqflite_darwin
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
BatteryPlusMacosPlugin.register(with: registry.registrar(forPlugin: "BatteryPlusMacosPlugin"))
|
BatteryPlusMacosPlugin.register(with: registry.registrar(forPlugin: "BatteryPlusMacosPlugin"))
|
||||||
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
||||||
FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin"))
|
FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin"))
|
||||||
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
88
pubspec.lock
88
pubspec.lock
|
|
@ -129,6 +129,30 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.12.3"
|
version: "8.12.3"
|
||||||
|
cached_network_image:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: cached_network_image
|
||||||
|
sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.4.1"
|
||||||
|
cached_network_image_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cached_network_image_platform_interface
|
||||||
|
sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.1"
|
||||||
|
cached_network_image_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cached_network_image_web
|
||||||
|
sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.1"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -318,6 +342,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.1.1"
|
version: "9.1.1"
|
||||||
|
flutter_cache_manager:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_cache_manager
|
||||||
|
sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.4.1"
|
||||||
flutter_html:
|
flutter_html:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -704,6 +736,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.2.3"
|
version: "9.2.3"
|
||||||
|
octo_image:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: octo_image
|
||||||
|
sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
omni_datetime_picker:
|
omni_datetime_picker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -917,6 +957,46 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.1"
|
version: "1.10.1"
|
||||||
|
sqflite:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqflite
|
||||||
|
sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.2"
|
||||||
|
sqflite_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqflite_android
|
||||||
|
sha256: ecd684501ebc2ae9a83536e8b15731642b9570dc8623e0073d227d0ee2bfea88
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.2+2"
|
||||||
|
sqflite_common:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqflite_common
|
||||||
|
sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.6"
|
||||||
|
sqflite_darwin:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqflite_darwin
|
||||||
|
sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.2"
|
||||||
|
sqflite_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqflite_platform_interface
|
||||||
|
sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -989,6 +1069,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.1"
|
version: "1.4.1"
|
||||||
|
synchronized:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: synchronized
|
||||||
|
sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.4.0"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,10 @@ dependencies:
|
||||||
stacked_services: ^1.1.0
|
stacked_services: ^1.1.0
|
||||||
omni_datetime_picker: any
|
omni_datetime_picker: any
|
||||||
json_serializable: ^6.8.0
|
json_serializable: ^6.8.0
|
||||||
|
cached_network_image: ^3.4.1
|
||||||
flutter_secure_storage: ^10.0.0
|
flutter_secure_storage: ^10.0.0
|
||||||
flutter_timer_countdown: ^1.0.7
|
flutter_timer_countdown: ^1.0.7
|
||||||
|
|
||||||
internet_connection_checker_plus: ^2.9.1+2
|
internet_connection_checker_plus: ^2.9.1+2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
import 'package:mockito/annotations.dart';
|
|
||||||
import 'package:mockito/mockito.dart';
|
|
||||||
import 'package:yimaru_app/app/app.locator.dart';
|
|
||||||
import 'package:stacked_services/stacked_services.dart';
|
|
||||||
// @stacked-import
|
|
||||||
|
|
||||||
import 'test_helpers.mocks.dart';
|
|
||||||
|
|
||||||
@GenerateMocks(
|
|
||||||
[],
|
|
||||||
customMocks: [
|
|
||||||
MockSpec<NavigationService>(onMissingStub: OnMissingStub.returnDefault),
|
|
||||||
MockSpec<BottomSheetService>(onMissingStub: OnMissingStub.returnDefault),
|
|
||||||
MockSpec<DialogService>(onMissingStub: OnMissingStub.returnDefault),
|
|
||||||
// @stacked-mock-spec
|
|
||||||
],
|
|
||||||
)
|
|
||||||
void registerServices() {
|
|
||||||
getAndRegisterNavigationService();
|
|
||||||
getAndRegisterBottomSheetService();
|
|
||||||
getAndRegisterDialogService();
|
|
||||||
// @stacked-mock-register
|
|
||||||
}
|
|
||||||
|
|
||||||
MockNavigationService getAndRegisterNavigationService() {
|
|
||||||
_removeRegistrationIfExists<NavigationService>();
|
|
||||||
final service = MockNavigationService();
|
|
||||||
locator.registerSingleton<NavigationService>(service);
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
|
|
||||||
MockBottomSheetService getAndRegisterBottomSheetService<T>({
|
|
||||||
SheetResponse<T>? showCustomSheetResponse,
|
|
||||||
}) {
|
|
||||||
_removeRegistrationIfExists<BottomSheetService>();
|
|
||||||
final service = MockBottomSheetService();
|
|
||||||
|
|
||||||
when(
|
|
||||||
service.showCustomSheet<T, T>(
|
|
||||||
enableDrag: anyNamed('enableDrag'),
|
|
||||||
enterBottomSheetDuration: anyNamed('enterBottomSheetDuration'),
|
|
||||||
exitBottomSheetDuration: anyNamed('exitBottomSheetDuration'),
|
|
||||||
ignoreSafeArea: anyNamed('ignoreSafeArea'),
|
|
||||||
isScrollControlled: anyNamed('isScrollControlled'),
|
|
||||||
barrierDismissible: anyNamed('barrierDismissible'),
|
|
||||||
additionalButtonTitle: anyNamed('additionalButtonTitle'),
|
|
||||||
variant: anyNamed('variant'),
|
|
||||||
title: anyNamed('title'),
|
|
||||||
hasImage: anyNamed('hasImage'),
|
|
||||||
imageUrl: anyNamed('imageUrl'),
|
|
||||||
showIconInMainButton: anyNamed('showIconInMainButton'),
|
|
||||||
mainButtonTitle: anyNamed('mainButtonTitle'),
|
|
||||||
showIconInSecondaryButton: anyNamed('showIconInSecondaryButton'),
|
|
||||||
secondaryButtonTitle: anyNamed('secondaryButtonTitle'),
|
|
||||||
showIconInAdditionalButton: anyNamed('showIconInAdditionalButton'),
|
|
||||||
takesInput: anyNamed('takesInput'),
|
|
||||||
barrierColor: anyNamed('barrierColor'),
|
|
||||||
barrierLabel: anyNamed('barrierLabel'),
|
|
||||||
customData: anyNamed('customData'),
|
|
||||||
data: anyNamed('data'),
|
|
||||||
description: anyNamed('description'),
|
|
||||||
),
|
|
||||||
).thenAnswer(
|
|
||||||
(realInvocation) =>
|
|
||||||
Future.value(showCustomSheetResponse ?? SheetResponse<T>()),
|
|
||||||
);
|
|
||||||
|
|
||||||
locator.registerSingleton<BottomSheetService>(service);
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
|
|
||||||
MockDialogService getAndRegisterDialogService() {
|
|
||||||
_removeRegistrationIfExists<DialogService>();
|
|
||||||
final service = MockDialogService();
|
|
||||||
locator.registerSingleton<DialogService>(service);
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @stacked-mock-create
|
|
||||||
|
|
||||||
void _removeRegistrationIfExists<T extends Object>() {
|
|
||||||
if (locator.isRegistered<T>()) {
|
|
||||||
locator.unregister<T>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,684 +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 _i5;
|
|
||||||
import 'dart:ui' as _i6;
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart' as _i4;
|
|
||||||
import 'package:mockito/mockito.dart' as _i1;
|
|
||||||
import 'package:mockito/src/dummies.dart' as _i3;
|
|
||||||
import 'package:stacked_services/stacked_services.dart' as _i2;
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
/// A class which mocks [NavigationService].
|
|
||||||
///
|
|
||||||
/// See the documentation for Mockito's code generation for more information.
|
|
||||||
class MockNavigationService extends _i1.Mock implements _i2.NavigationService {
|
|
||||||
@override
|
|
||||||
String get previousRoute => (super.noSuchMethod(
|
|
||||||
Invocation.getter(#previousRoute),
|
|
||||||
returnValue: _i3.dummyValue<String>(
|
|
||||||
this,
|
|
||||||
Invocation.getter(#previousRoute),
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: _i3.dummyValue<String>(
|
|
||||||
this,
|
|
||||||
Invocation.getter(#previousRoute),
|
|
||||||
),
|
|
||||||
) as String);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get currentRoute => (super.noSuchMethod(
|
|
||||||
Invocation.getter(#currentRoute),
|
|
||||||
returnValue: _i3.dummyValue<String>(
|
|
||||||
this,
|
|
||||||
Invocation.getter(#currentRoute),
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: _i3.dummyValue<String>(
|
|
||||||
this,
|
|
||||||
Invocation.getter(#currentRoute),
|
|
||||||
),
|
|
||||||
) as String);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i4.GlobalKey<_i4.NavigatorState>? nestedNavigationKey(int? index) =>
|
|
||||||
(super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#nestedNavigationKey,
|
|
||||||
[index],
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: null,
|
|
||||||
) as _i4.GlobalKey<_i4.NavigatorState>?);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void config({
|
|
||||||
bool? enableLog,
|
|
||||||
bool? defaultPopGesture,
|
|
||||||
bool? defaultOpaqueRoute,
|
|
||||||
Duration? defaultDurationTransition,
|
|
||||||
bool? defaultGlobalState,
|
|
||||||
_i2.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
|
|
||||||
_i5.Future<T?>? navigateWithTransition<T>(
|
|
||||||
_i4.Widget? page, {
|
|
||||||
bool? opaque,
|
|
||||||
String? transition = r'',
|
|
||||||
Duration? duration,
|
|
||||||
bool? popGesture,
|
|
||||||
int? id,
|
|
||||||
_i4.Curve? curve,
|
|
||||||
bool? fullscreenDialog = false,
|
|
||||||
bool? preventDuplicates = true,
|
|
||||||
_i2.Transition? transitionClass,
|
|
||||||
_i2.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 _i5.Future<T?>?);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<T?>? replaceWithTransition<T>(
|
|
||||||
_i4.Widget? page, {
|
|
||||||
bool? opaque,
|
|
||||||
String? transition = r'',
|
|
||||||
Duration? duration,
|
|
||||||
bool? popGesture,
|
|
||||||
int? id,
|
|
||||||
_i4.Curve? curve,
|
|
||||||
bool? fullscreenDialog = false,
|
|
||||||
bool? preventDuplicates = true,
|
|
||||||
_i2.Transition? transitionClass,
|
|
||||||
_i2.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 _i5.Future<T?>?);
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool back<T>({
|
|
||||||
dynamic result,
|
|
||||||
int? id,
|
|
||||||
}) =>
|
|
||||||
(super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#back,
|
|
||||||
[],
|
|
||||||
{
|
|
||||||
#result: result,
|
|
||||||
#id: id,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
returnValue: false,
|
|
||||||
returnValueForMissingStub: false,
|
|
||||||
) as bool);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void popUntil(
|
|
||||||
_i4.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
|
|
||||||
_i5.Future<T?>? navigateTo<T>(
|
|
||||||
String? routeName, {
|
|
||||||
dynamic arguments,
|
|
||||||
int? id,
|
|
||||||
bool? preventDuplicates = true,
|
|
||||||
Map<String, String>? parameters,
|
|
||||||
_i4.RouteTransitionsBuilder? transition,
|
|
||||||
}) =>
|
|
||||||
(super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#navigateTo,
|
|
||||||
[routeName],
|
|
||||||
{
|
|
||||||
#arguments: arguments,
|
|
||||||
#id: id,
|
|
||||||
#preventDuplicates: preventDuplicates,
|
|
||||||
#parameters: parameters,
|
|
||||||
#transition: transition,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: null,
|
|
||||||
) as _i5.Future<T?>?);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<T?>? navigateToView<T>(
|
|
||||||
_i4.Widget? view, {
|
|
||||||
dynamic arguments,
|
|
||||||
int? id,
|
|
||||||
bool? opaque,
|
|
||||||
_i4.Curve? curve,
|
|
||||||
Duration? duration,
|
|
||||||
bool? fullscreenDialog = false,
|
|
||||||
bool? popGesture,
|
|
||||||
bool? preventDuplicates = true,
|
|
||||||
_i2.Transition? transition,
|
|
||||||
_i2.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 _i5.Future<T?>?);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<T?>? replaceWith<T>(
|
|
||||||
String? routeName, {
|
|
||||||
dynamic arguments,
|
|
||||||
int? id,
|
|
||||||
bool? preventDuplicates = true,
|
|
||||||
Map<String, String>? parameters,
|
|
||||||
_i4.RouteTransitionsBuilder? transition,
|
|
||||||
}) =>
|
|
||||||
(super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#replaceWith,
|
|
||||||
[routeName],
|
|
||||||
{
|
|
||||||
#arguments: arguments,
|
|
||||||
#id: id,
|
|
||||||
#preventDuplicates: preventDuplicates,
|
|
||||||
#parameters: parameters,
|
|
||||||
#transition: transition,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: null,
|
|
||||||
) as _i5.Future<T?>?);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<T?>? clearStackAndShow<T>(
|
|
||||||
String? routeName, {
|
|
||||||
dynamic arguments,
|
|
||||||
int? id,
|
|
||||||
Map<String, String>? parameters,
|
|
||||||
}) =>
|
|
||||||
(super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#clearStackAndShow,
|
|
||||||
[routeName],
|
|
||||||
{
|
|
||||||
#arguments: arguments,
|
|
||||||
#id: id,
|
|
||||||
#parameters: parameters,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: null,
|
|
||||||
) as _i5.Future<T?>?);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<T?>? clearStackAndShowView<T>(
|
|
||||||
_i4.Widget? view, {
|
|
||||||
dynamic arguments,
|
|
||||||
int? id,
|
|
||||||
}) =>
|
|
||||||
(super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#clearStackAndShowView,
|
|
||||||
[view],
|
|
||||||
{
|
|
||||||
#arguments: arguments,
|
|
||||||
#id: id,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: null,
|
|
||||||
) as _i5.Future<T?>?);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<T?>? clearTillFirstAndShow<T>(
|
|
||||||
String? routeName, {
|
|
||||||
dynamic arguments,
|
|
||||||
int? id,
|
|
||||||
bool? preventDuplicates = true,
|
|
||||||
Map<String, String>? parameters,
|
|
||||||
}) =>
|
|
||||||
(super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#clearTillFirstAndShow,
|
|
||||||
[routeName],
|
|
||||||
{
|
|
||||||
#arguments: arguments,
|
|
||||||
#id: id,
|
|
||||||
#preventDuplicates: preventDuplicates,
|
|
||||||
#parameters: parameters,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: null,
|
|
||||||
) as _i5.Future<T?>?);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<T?>? clearTillFirstAndShowView<T>(
|
|
||||||
_i4.Widget? view, {
|
|
||||||
dynamic arguments,
|
|
||||||
int? id,
|
|
||||||
}) =>
|
|
||||||
(super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#clearTillFirstAndShowView,
|
|
||||||
[view],
|
|
||||||
{
|
|
||||||
#arguments: arguments,
|
|
||||||
#id: id,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: null,
|
|
||||||
) as _i5.Future<T?>?);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<T?>? pushNamedAndRemoveUntil<T>(
|
|
||||||
String? routeName, {
|
|
||||||
_i4.RoutePredicate? predicate,
|
|
||||||
dynamic arguments,
|
|
||||||
int? id,
|
|
||||||
}) =>
|
|
||||||
(super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#pushNamedAndRemoveUntil,
|
|
||||||
[routeName],
|
|
||||||
{
|
|
||||||
#predicate: predicate,
|
|
||||||
#arguments: arguments,
|
|
||||||
#id: id,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: null,
|
|
||||||
) as _i5.Future<T?>?);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A class which mocks [BottomSheetService].
|
|
||||||
///
|
|
||||||
/// See the documentation for Mockito's code generation for more information.
|
|
||||||
class MockBottomSheetService extends _i1.Mock
|
|
||||||
implements _i2.BottomSheetService {
|
|
||||||
@override
|
|
||||||
void setCustomSheetBuilders(Map<dynamic, _i2.SheetBuilder>? builders) =>
|
|
||||||
super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#setCustomSheetBuilders,
|
|
||||||
[builders],
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<_i2.SheetResponse<dynamic>?> 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: _i5.Future<_i2.SheetResponse<dynamic>?>.value(),
|
|
||||||
returnValueForMissingStub:
|
|
||||||
_i5.Future<_i2.SheetResponse<dynamic>?>.value(),
|
|
||||||
) as _i5.Future<_i2.SheetResponse<dynamic>?>);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<_i2.SheetResponse<T>?> showCustomSheet<T, R>({
|
|
||||||
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,
|
|
||||||
_i6.Color? barrierColor = const _i6.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: _i5.Future<_i2.SheetResponse<T>?>.value(),
|
|
||||||
returnValueForMissingStub: _i5.Future<_i2.SheetResponse<T>?>.value(),
|
|
||||||
) as _i5.Future<_i2.SheetResponse<T>?>);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void completeSheet(_i2.SheetResponse<dynamic>? 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 _i2.DialogService {
|
|
||||||
@override
|
|
||||||
void registerCustomDialogBuilders(
|
|
||||||
Map<dynamic, _i2.DialogBuilder>? builders) =>
|
|
||||||
super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#registerCustomDialogBuilders,
|
|
||||||
[builders],
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void registerCustomDialogBuilder({
|
|
||||||
required dynamic variant,
|
|
||||||
required _i4.Widget Function(
|
|
||||||
_i4.BuildContext,
|
|
||||||
_i2.DialogRequest<dynamic>,
|
|
||||||
dynamic Function(_i2.DialogResponse<dynamic>),
|
|
||||||
)? builder,
|
|
||||||
}) =>
|
|
||||||
super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#registerCustomDialogBuilder,
|
|
||||||
[],
|
|
||||||
{
|
|
||||||
#variant: variant,
|
|
||||||
#builder: builder,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<_i2.DialogResponse<dynamic>?> showDialog({
|
|
||||||
String? title,
|
|
||||||
String? description,
|
|
||||||
String? cancelTitle,
|
|
||||||
_i6.Color? cancelTitleColor,
|
|
||||||
String? buttonTitle = r'Ok',
|
|
||||||
_i6.Color? buttonTitleColor,
|
|
||||||
bool? barrierDismissible = false,
|
|
||||||
_i4.RouteSettings? routeSettings,
|
|
||||||
_i4.GlobalKey<_i4.NavigatorState>? navigatorKey,
|
|
||||||
_i2.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: _i5.Future<_i2.DialogResponse<dynamic>?>.value(),
|
|
||||||
returnValueForMissingStub:
|
|
||||||
_i5.Future<_i2.DialogResponse<dynamic>?>.value(),
|
|
||||||
) as _i5.Future<_i2.DialogResponse<dynamic>?>);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<_i2.DialogResponse<T>?> showCustomDialog<T, R>({
|
|
||||||
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,
|
|
||||||
_i6.Color? barrierColor = const _i6.Color(2315255808),
|
|
||||||
bool? barrierDismissible = false,
|
|
||||||
String? barrierLabel = r'',
|
|
||||||
bool? useSafeArea = true,
|
|
||||||
_i4.RouteSettings? routeSettings,
|
|
||||||
_i4.GlobalKey<_i4.NavigatorState>? navigatorKey,
|
|
||||||
_i4.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: _i5.Future<_i2.DialogResponse<T>?>.value(),
|
|
||||||
returnValueForMissingStub: _i5.Future<_i2.DialogResponse<T>?>.value(),
|
|
||||||
) as _i5.Future<_i2.DialogResponse<T>?>);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_i5.Future<_i2.DialogResponse<dynamic>?> showConfirmationDialog({
|
|
||||||
String? title,
|
|
||||||
String? description,
|
|
||||||
String? cancelTitle = r'Cancel',
|
|
||||||
_i6.Color? cancelTitleColor,
|
|
||||||
String? confirmationTitle = r'Ok',
|
|
||||||
_i6.Color? confirmationTitleColor,
|
|
||||||
bool? barrierDismissible = false,
|
|
||||||
_i4.RouteSettings? routeSettings,
|
|
||||||
_i2.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: _i5.Future<_i2.DialogResponse<dynamic>?>.value(),
|
|
||||||
returnValueForMissingStub:
|
|
||||||
_i5.Future<_i2.DialogResponse<dynamic>?>.value(),
|
|
||||||
) as _i5.Future<_i2.DialogResponse<dynamic>?>);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void completeDialog(_i2.DialogResponse<dynamic>? response) =>
|
|
||||||
super.noSuchMethod(
|
|
||||||
Invocation.method(
|
|
||||||
#completeDialog,
|
|
||||||
[response],
|
|
||||||
),
|
|
||||||
returnValueForMissingStub: null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
11
test/services/image_picker_service_test.dart
Normal file
11
test/services/image_picker_service_test.dart
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:yimaru_app/app/app.locator.dart';
|
||||||
|
|
||||||
|
import '../helpers/test_helpers.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('ImagePickerServiceTest -', () {
|
||||||
|
setUp(() => registerServices());
|
||||||
|
tearDown(() => locator.reset());
|
||||||
|
});
|
||||||
|
}
|
||||||
11
test/viewmodels/failure_viewmodel_test.dart
Normal file
11
test/viewmodels/failure_viewmodel_test.dart
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:yimaru_app/app/app.locator.dart';
|
||||||
|
|
||||||
|
import '../helpers/test_helpers.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('FailureViewModel Tests -', () {
|
||||||
|
setUp(() => registerServices());
|
||||||
|
tearDown(() => locator.reset());
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user