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/assessment/assessment_view.dart';
|
||||
import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart';
|
||||
import 'package:yimaru_app/ui/views/failure/failure_view.dart';
|
||||
import 'package:yimaru_app/services/image_picker_service.dart';
|
||||
// @stacked-import
|
||||
|
||||
@StackedApp(
|
||||
|
|
@ -57,6 +59,7 @@ import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart';
|
|||
MaterialRoute(page: WelcomeView),
|
||||
MaterialRoute(page: AssessmentView),
|
||||
MaterialRoute(page: LearnLessonView),
|
||||
MaterialRoute(page: FailureView),
|
||||
// @stacked-route
|
||||
],
|
||||
dependencies: [
|
||||
|
|
@ -68,6 +71,7 @@ import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart';
|
|||
LazySingleton(classType: SecureStorageService),
|
||||
LazySingleton(classType: DioService),
|
||||
LazySingleton(classType: StatusCheckerService),
|
||||
LazySingleton(classType: ImagePickerService),
|
||||
// @stacked-service
|
||||
],
|
||||
bottomsheets: [
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import 'package:stacked_shared/stacked_shared.dart';
|
|||
import '../services/api_service.dart';
|
||||
import '../services/authentication_service.dart';
|
||||
import '../services/dio_service.dart';
|
||||
import '../services/image_picker_service.dart';
|
||||
import '../services/secure_storage_service.dart';
|
||||
import '../services/status_checker_service.dart';
|
||||
|
||||
|
|
@ -36,4 +37,5 @@ Future<void> setupLocator({
|
|||
locator.registerLazySingleton(() => SecureStorageService());
|
||||
locator.registerLazySingleton(() => DioService());
|
||||
locator.registerLazySingleton(() => StatusCheckerService());
|
||||
locator.registerLazySingleton(() => ImagePickerService());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,16 +5,17 @@
|
|||
// **************************************************************************
|
||||
|
||||
// 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: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'
|
||||
as _i10;
|
||||
import 'package:yimaru_app/ui/views/assessment/assessment_view.dart' as _i23;
|
||||
import 'package:yimaru_app/ui/views/call_support/call_support_view.dart'
|
||||
as _i13;
|
||||
import 'package:yimaru_app/ui/views/downloads/downloads_view.dart' as _i7;
|
||||
import 'package:yimaru_app/ui/views/failure/failure_view.dart' as _i25;
|
||||
import 'package:yimaru_app/ui/views/home/home_view.dart' as _i2;
|
||||
import 'package:yimaru_app/ui/views/language/language_view.dart' as _i14;
|
||||
import 'package:yimaru_app/ui/views/learn/learn_view.dart' as _i19;
|
||||
|
|
@ -89,6 +90,8 @@ class Routes {
|
|||
|
||||
static const learnLessonView = '/learn-lesson-view';
|
||||
|
||||
static const failureView = '/failure-view';
|
||||
|
||||
static const all = <String>{
|
||||
homeView,
|
||||
onboardingView,
|
||||
|
|
@ -113,6 +116,7 @@ class Routes {
|
|||
welcomeView,
|
||||
assessmentView,
|
||||
learnLessonView,
|
||||
failureView,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -210,17 +214,21 @@ class StackedRouter extends _i1.RouterBase {
|
|||
Routes.learnLessonView,
|
||||
page: _i24.LearnLessonView,
|
||||
),
|
||||
_i1.RouteDef(
|
||||
Routes.failureView,
|
||||
page: _i25.FailureView,
|
||||
),
|
||||
];
|
||||
|
||||
final _pagesMap = <Type, _i1.StackedRouteFactory>{
|
||||
_i2.HomeView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i2.HomeView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i3.OnboardingView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i3.OnboardingView(),
|
||||
settings: data,
|
||||
);
|
||||
|
|
@ -229,133 +237,141 @@ class StackedRouter extends _i1.RouterBase {
|
|||
final args = data.getArgs<StartupViewArguments>(
|
||||
orElse: () => const StartupViewArguments(),
|
||||
);
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => _i4.StartupView(key: args.key, label: args.label),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i5.ProfileView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i5.ProfileView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i6.ProfileDetailView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i6.ProfileDetailView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i7.DownloadsView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i7.DownloadsView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i8.ProgressView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i8.ProgressView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i9.OngoingProgressView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i9.OngoingProgressView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i10.AccountPrivacyView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i10.AccountPrivacyView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i11.SupportView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i11.SupportView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i12.TelegramSupportView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i12.TelegramSupportView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i13.CallSupportView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i13.CallSupportView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i14.LanguageView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i14.LanguageView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i15.PrivacyPolicyView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i15.PrivacyPolicyView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i16.TermsAndConditionsView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i16.TermsAndConditionsView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i17.RegisterView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i17.RegisterView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i18.LoginView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i18.LoginView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i19.LearnView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i19.LearnView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i20.LearnLevelView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i20.LearnLevelView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i21.LearnModuleView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i21.LearnModuleView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i22.WelcomeView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i22.WelcomeView(),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i23.AssessmentView: (data) {
|
||||
final args = data.getArgs<AssessmentViewArguments>(nullOk: false);
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) =>
|
||||
_i23.AssessmentView(key: args.key, data: args.data),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i24.LearnLessonView: (data) {
|
||||
return _i25.MaterialPageRoute<dynamic>(
|
||||
return _i26.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => const _i24.LearnLessonView(),
|
||||
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
|
||||
|
|
@ -371,7 +387,7 @@ class StartupViewArguments {
|
|||
this.label = 'Loading',
|
||||
});
|
||||
|
||||
final _i25.Key? key;
|
||||
final _i26.Key? key;
|
||||
|
||||
final String label;
|
||||
|
||||
|
|
@ -398,7 +414,7 @@ class AssessmentViewArguments {
|
|||
required this.data,
|
||||
});
|
||||
|
||||
final _i25.Key? key;
|
||||
final _i26.Key? key;
|
||||
|
||||
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([
|
||||
int? routerId,
|
||||
bool preventDuplicates = true,
|
||||
|
|
@ -449,7 +492,7 @@ extension NavigatorStateExtension on _i26.NavigationService {
|
|||
}
|
||||
|
||||
Future<dynamic> navigateToStartupView({
|
||||
_i25.Key? key,
|
||||
_i26.Key? key,
|
||||
String label = 'Loading',
|
||||
int? routerId,
|
||||
bool preventDuplicates = true,
|
||||
|
|
@ -718,7 +761,7 @@ extension NavigatorStateExtension on _i26.NavigationService {
|
|||
}
|
||||
|
||||
Future<dynamic> navigateToAssessmentView({
|
||||
_i25.Key? key,
|
||||
_i26.Key? key,
|
||||
required Map<String, dynamic> data,
|
||||
int? routerId,
|
||||
bool preventDuplicates = true,
|
||||
|
|
@ -748,6 +791,23 @@ extension NavigatorStateExtension on _i26.NavigationService {
|
|||
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([
|
||||
int? routerId,
|
||||
bool preventDuplicates = true,
|
||||
|
|
@ -777,7 +837,7 @@ extension NavigatorStateExtension on _i26.NavigationService {
|
|||
}
|
||||
|
||||
Future<dynamic> replaceWithStartupView({
|
||||
_i25.Key? key,
|
||||
_i26.Key? key,
|
||||
String label = 'Loading',
|
||||
int? routerId,
|
||||
bool preventDuplicates = true,
|
||||
|
|
@ -1046,7 +1106,7 @@ extension NavigatorStateExtension on _i26.NavigationService {
|
|||
}
|
||||
|
||||
Future<dynamic> replaceWithAssessmentView({
|
||||
_i25.Key? key,
|
||||
_i26.Key? key,
|
||||
required Map<String, dynamic> data,
|
||||
int? routerId,
|
||||
bool preventDuplicates = true,
|
||||
|
|
@ -1075,4 +1135,21 @@ extension NavigatorStateExtension on _i26.NavigationService {
|
|||
parameters: parameters,
|
||||
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()
|
||||
class UserModel {
|
||||
final String? firstName;
|
||||
|
||||
@JsonKey(name: 'user_id')
|
||||
final int? userId;
|
||||
|
||||
final String? profileImage;
|
||||
|
||||
final bool? profileCompleted;
|
||||
|
||||
@JsonKey(name: 'access_token')
|
||||
|
|
@ -15,11 +19,14 @@ class UserModel {
|
|||
@JsonKey(name: 'refresh_token')
|
||||
final String? refreshToken;
|
||||
|
||||
const UserModel(
|
||||
{this.userId,
|
||||
const UserModel({
|
||||
this.userId,
|
||||
this.firstName,
|
||||
this.accessToken,
|
||||
this.profileImage,
|
||||
this.refreshToken,
|
||||
this.profileCompleted,
|
||||
this.refreshToken});
|
||||
});
|
||||
|
||||
factory UserModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$UserModelFromJson(json);
|
||||
|
|
|
|||
|
|
@ -8,13 +8,17 @@ part of 'user_model.dart';
|
|||
|
||||
UserModel _$UserModelFromJson(Map<String, dynamic> json) => UserModel(
|
||||
userId: (json['user_id'] as num?)?.toInt(),
|
||||
firstName: json['firstName'] as String?,
|
||||
accessToken: json['access_token'] as String?,
|
||||
profileCompleted: json['profileCompleted'] as bool?,
|
||||
profileImage: json['profileImage'] as String?,
|
||||
refreshToken: json['refresh_token'] as String?,
|
||||
profileCompleted: json['profileCompleted'] as bool?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$UserModelToJson(UserModel instance) => <String, dynamic>{
|
||||
'firstName': instance.firstName,
|
||||
'user_id': instance.userId,
|
||||
'profileImage': instance.profileImage,
|
||||
'profileCompleted': instance.profileCompleted,
|
||||
'access_token': instance.accessToken,
|
||||
'refresh_token': instance.refreshToken,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class ApiService {
|
|||
Future<Map<String, dynamic>> register(Map<String, dynamic> data) async {
|
||||
try {
|
||||
Response response = await _service.dio.post(
|
||||
'$baseUrl/$userUrl/$kRegisterUrl',
|
||||
'$baseUrl/$kUserUrl/$kRegisterUrl',
|
||||
data: data,
|
||||
);
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ class ApiService {
|
|||
Future<Map<String, dynamic>> verifyOtp(Map<String, dynamic> data) async {
|
||||
try {
|
||||
Response response = await _service.dio.post(
|
||||
'$baseUrl/$userUrl/$kVerifyOtpUrl',
|
||||
'$baseUrl/$kUserUrl/$kVerifyOtpUrl',
|
||||
data: data,
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
|
|
@ -96,7 +96,7 @@ class ApiService {
|
|||
Future<Map<String, dynamic>> resendOtp(Map<String, dynamic> data) async {
|
||||
try {
|
||||
Response response = await _service.dio.post(
|
||||
'$baseUrl/$userUrl/$kResendOtpUrl',
|
||||
'$baseUrl/$kUserUrl/$kResendOtpUrl',
|
||||
data: data,
|
||||
);
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ class ApiService {
|
|||
Future<Map<String, dynamic>> getProfileStatus(UserModel? user) async {
|
||||
try {
|
||||
Response response = await _service.dio.get(
|
||||
'$baseUrl/$userUrl/${user?.userId}/$kProfileStatusUrl',
|
||||
'$baseUrl/$kUserUrl/${user?.userId}/$kProfileStatusUrl',
|
||||
);
|
||||
|
||||
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
|
||||
Future<Map<String, dynamic>> updateProfile(
|
||||
{required UserModel? user, required Map<String, dynamic> data}) async {
|
||||
try {
|
||||
Response response = await _service.dio.put(
|
||||
'$baseUrl/$userUrl',
|
||||
'$baseUrl/$kUserUrl',
|
||||
data: data,
|
||||
);
|
||||
|
||||
print(response.statusCode);
|
||||
print(response.data);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return {
|
||||
'status': ResponseStatus.success,
|
||||
|
|
@ -170,7 +194,6 @@ class ApiService {
|
|||
};
|
||||
}
|
||||
} catch (e) {
|
||||
print('Exception ${e.toString()}');
|
||||
return {
|
||||
'message': e.toString(),
|
||||
'status': ResponseStatus.failure,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ import 'package:yimaru_app/services/secure_storage_service.dart';
|
|||
class AuthenticationService {
|
||||
final _secureService = locator<SecureStorageService>();
|
||||
|
||||
UserModel? _user;
|
||||
|
||||
UserModel? get user => _user;
|
||||
|
||||
Future<bool> userLoggedIn() async {
|
||||
if (await _secureService.getString('userId') != null) {
|
||||
return true;
|
||||
|
|
@ -28,14 +32,56 @@ class AuthenticationService {
|
|||
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.setString('accessToken', data['accessToken']);
|
||||
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);
|
||||
|
||||
_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 =>
|
||||
|
|
@ -45,14 +91,16 @@ class AuthenticationService {
|
|||
await _secureService.setBool('firstTimeInstall', value);
|
||||
}
|
||||
|
||||
Future<UserModel> getUser() async {
|
||||
UserModel user = UserModel(
|
||||
Future<UserModel?> getUser() async {
|
||||
_user = UserModel(
|
||||
userId: await _secureService.getInt('userId'),
|
||||
firstName: await _secureService.getString('firstName'),
|
||||
accessToken: await _secureService.getString('accessToken'),
|
||||
refreshToken: await _secureService.getString('refreshToken'),
|
||||
profileImage: await _secureService.getString('profileImage'),
|
||||
profileCompleted: await _secureService.getBool('profileCompleted'),
|
||||
);
|
||||
return user;
|
||||
return _user;
|
||||
}
|
||||
|
||||
Future<void> logOut() async {
|
||||
|
|
|
|||
|
|
@ -125,18 +125,17 @@ class DioService {
|
|||
}
|
||||
|
||||
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 {
|
||||
Map<String, dynamic> data = {
|
||||
'role': 'STUDENT',
|
||||
'user_id': user.userId,
|
||||
'access_token': user.accessToken,
|
||||
'refresh_token': user.refreshToken
|
||||
'user_id': user?.userId,
|
||||
'access_token': user?.accessToken,
|
||||
'refresh_token': user?.refreshToken
|
||||
};
|
||||
print(data);
|
||||
final response = await _refreshDio.post(
|
||||
'$baseUrl/$kRefreshTokenUrl',
|
||||
data: data,
|
||||
|
|
@ -150,8 +149,6 @@ class DioService {
|
|||
),
|
||||
);
|
||||
|
||||
print('Refresh response');
|
||||
print(response.data);
|
||||
await _authenticationService.saveTokens(
|
||||
access: response.data['access_token'],
|
||||
refresh: response.data['refresh_token'],
|
||||
|
|
@ -159,10 +156,8 @@ class DioService {
|
|||
|
||||
return true;
|
||||
} catch (e) {
|
||||
print('Refresh response exception');
|
||||
print(e.toString());
|
||||
// await _authenticationService.logOut();
|
||||
// await _navigationService.replaceWithLoginView();
|
||||
await _authenticationService.logOut();
|
||||
await _navigationService.replaceWithLoginView();
|
||||
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 = 'https://api.yimaru.yaltopia.com';
|
||||
|
||||
String userUrl = 'api/v1/user';
|
||||
String kGetUserUrl = 'single';
|
||||
|
||||
String kUserUrl = 'api/v1/user';
|
||||
|
||||
String kRegisterUrl = 'register';
|
||||
|
||||
|
|
|
|||
|
|
@ -171,15 +171,9 @@ PinTheme errorPinTheme = defaultPin.copyBorderWith(
|
|||
border: Border.all(color: Colors.red),
|
||||
);
|
||||
|
||||
TextStyle validationStyle = const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.red,
|
||||
fontWeight: FontWeight.w700,
|
||||
);
|
||||
|
||||
TextStyle style25DG600 = const TextStyle(
|
||||
fontSize: 25,
|
||||
color: kcDarkGrey,
|
||||
TextStyle style18P600 = const TextStyle(
|
||||
fontSize: 18,
|
||||
color: kcPrimaryColor,
|
||||
fontWeight: FontWeight.w600,
|
||||
);
|
||||
|
||||
|
|
@ -189,6 +183,21 @@ TextStyle style12R700 = const TextStyle(
|
|||
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(
|
||||
fontSize: 16,
|
||||
color: kcDarkGrey,
|
||||
|
|
@ -210,13 +219,15 @@ TextStyle style14DG400 = const TextStyle(
|
|||
color: kcDarkGrey,
|
||||
);
|
||||
|
||||
TextStyle style14P400 = const TextStyle(
|
||||
color: kcPrimaryColor,
|
||||
TextStyle style14DG600 = const TextStyle(
|
||||
color: kcDarkGrey,
|
||||
fontWeight: FontWeight.w600,
|
||||
);
|
||||
|
||||
TextStyle style14P600 = const TextStyle(
|
||||
color: kcPrimaryColor,
|
||||
fontWeight: FontWeight.w600,
|
||||
TextStyle validationStyle = const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.red,
|
||||
fontWeight: FontWeight.w700,
|
||||
);
|
||||
|
||||
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:yimaru_app/ui/common/enmus.dart';
|
||||
|
||||
import '../../../app/app.dialogs.dart';
|
||||
import '../../../app/app.locator.dart';
|
||||
import '../../../app/app.router.dart';
|
||||
import '../../../models/assessment.dart';
|
||||
import '../../../models/user_model.dart';
|
||||
import '../../../services/api_service.dart';
|
||||
import '../../../services/authentication_service.dart';
|
||||
import '../../common/app_colors.dart';
|
||||
import '../../common/ui_helpers.dart';
|
||||
import '../home/home_view.dart';
|
||||
|
||||
class AssessmentViewModel extends BaseViewModel {
|
||||
final _apiService = locator<ApiService>();
|
||||
final _dialogService = locator<DialogService>();
|
||||
final _navigationService = locator<NavigationService>();
|
||||
final _authenticationService = locator<AuthenticationService>();
|
||||
|
||||
|
|
@ -73,9 +77,6 @@ class AssessmentViewModel extends BaseViewModel {
|
|||
if (_currentQuestion == 5) {
|
||||
// A1
|
||||
final correctCount = countCorrectAnswersUntil(5);
|
||||
print('All : $_selectedAnswers');
|
||||
print('Question page : $_currentQuestion');
|
||||
print('Correct A1: $correctCount');
|
||||
|
||||
if (correctCount > 3) {
|
||||
return {'continue': true, 'level': ProficiencyLevels.a1};
|
||||
|
|
@ -86,9 +87,6 @@ class AssessmentViewModel extends BaseViewModel {
|
|||
// A2
|
||||
|
||||
final correctCount = countCorrectAnswersUntil(10);
|
||||
print('All : $_selectedAnswers');
|
||||
print('Question page : $_currentQuestion');
|
||||
print('Correct A2: $correctCount');
|
||||
|
||||
if (correctCount > 3) {
|
||||
return {'continue': true, 'level': ProficiencyLevels.a2};
|
||||
|
|
@ -98,9 +96,6 @@ class AssessmentViewModel extends BaseViewModel {
|
|||
} else if (_currentQuestion == 16) {
|
||||
// B1
|
||||
final correctCount = countCorrectAnswersUntil(16);
|
||||
print('All : $_selectedAnswers');
|
||||
print('Question page : $_currentQuestion');
|
||||
print('Correct B1: $correctCount');
|
||||
|
||||
if (correctCount > 4) {
|
||||
return {'continue': true, 'level': ProficiencyLevels.b1};
|
||||
|
|
@ -109,9 +104,6 @@ class AssessmentViewModel extends BaseViewModel {
|
|||
}
|
||||
} else if (_currentQuestion == 22) {
|
||||
final correctCount = countCorrectAnswersUntil(16);
|
||||
print('All : $_selectedAnswers');
|
||||
print('Question page : $_currentQuestion');
|
||||
print('Correct B2: $correctCount');
|
||||
|
||||
if (correctCount > 4) {
|
||||
return {'continue': true, 'level': ProficiencyLevels.b2};
|
||||
|
|
@ -178,17 +170,26 @@ class AssessmentViewModel extends BaseViewModel {
|
|||
}
|
||||
|
||||
// Complete profile
|
||||
Future<void> completeProfile() async {
|
||||
Map<String, dynamic> response =
|
||||
await runBusyFuture<Map<String, dynamic>>(_completeProfile());
|
||||
|
||||
Future<void> saveProfileCompleted() async {
|
||||
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 {
|
||||
print(_userData);
|
||||
UserModel user = await _authenticationService.getUser();
|
||||
UserModel? user = await _authenticationService.getUser();
|
||||
Map<String, dynamic> response =
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -203,8 +204,7 @@ class AssessmentViewModel extends BaseViewModel {
|
|||
} else {
|
||||
if (response['continue']) {
|
||||
_pageController.jumpToPage(_currentQuestion);
|
||||
}
|
||||
{
|
||||
} else {
|
||||
_proficiencyLevel = response['level'];
|
||||
next();
|
||||
}
|
||||
|
|
@ -218,8 +218,6 @@ class AssessmentViewModel extends BaseViewModel {
|
|||
_pageController.previousPage(
|
||||
duration: const Duration(microseconds: 100), curve: Curves.linear);
|
||||
rebuildUi();
|
||||
} else {
|
||||
_navigationService.back();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -238,12 +236,34 @@ class AssessmentViewModel extends BaseViewModel {
|
|||
}
|
||||
|
||||
void pop() {
|
||||
if (_currentPage != 0) {
|
||||
if (_currentPage == 3 /*7*/) {
|
||||
_navigationService.back();
|
||||
} else if (_currentPage != 0 && _currentPage != 3) {
|
||||
_currentPage--;
|
||||
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 =>
|
||||
await _navigationService.navigateToLanguageView();
|
||||
|
||||
|
|
|
|||
|
|
@ -45,9 +45,10 @@ class AssessmentFormScreen extends ViewModelWidget<AssessmentViewModel> {
|
|||
[_buildAppBar(viewModel), _buildExpandedBody(viewModel)];
|
||||
|
||||
Widget _buildAppBar(AssessmentViewModel viewModel) => LargeAppBar(
|
||||
showBackButton: true,
|
||||
onClose: viewModel.abort,
|
||||
showLanguageSelection: false,
|
||||
onPop: viewModel.previousQuestion,
|
||||
showBackButton: viewModel.currentQuestion == 0 ? false : true,
|
||||
);
|
||||
|
||||
Widget _buildExpandedBody(AssessmentViewModel viewModel) =>
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ class AssessmentIntroScreen extends ViewModelWidget<AssessmentViewModel> {
|
|||
];
|
||||
|
||||
Widget _buildAppBar(AssessmentViewModel viewModel) => LargeAppBar(
|
||||
showBackButton: false,
|
||||
showBackButton: true,
|
||||
onPop: viewModel.pop,
|
||||
showLanguageSelection: true,
|
||||
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 '../../../common/enmus.dart';
|
||||
import '../../../widgets/page_loading_indicator.dart';
|
||||
import '../assessment_viewmodel.dart';
|
||||
|
||||
class StartLessonScreen extends ViewModelWidget<AssessmentViewModel> {
|
||||
|
|
@ -15,13 +16,11 @@ class StartLessonScreen extends ViewModelWidget<AssessmentViewModel> {
|
|||
Future<void> _start(AssessmentViewModel viewModel) async {
|
||||
if (viewModel.proficiencyLevel != ProficiencyLevels.none) {
|
||||
Map<String, dynamic> data = {
|
||||
'preferred_language': 'en',
|
||||
'knowledge_level': viewModel.proficiencyLevel.name.toUpperCase()
|
||||
};
|
||||
|
||||
viewModel.addUserData(data);
|
||||
}
|
||||
|
||||
await viewModel.completeProfile();
|
||||
}
|
||||
|
||||
|
|
@ -31,20 +30,24 @@ class StartLessonScreen extends ViewModelWidget<AssessmentViewModel> {
|
|||
|
||||
Widget _buildScaffoldWrapper(AssessmentViewModel viewModel) => Scaffold(
|
||||
backgroundColor: kcBackgroundColor,
|
||||
body: _buildScaffold(viewModel),
|
||||
body: _buildScaffoldStack(viewModel),
|
||||
);
|
||||
|
||||
Widget _buildScaffoldStack(AssessmentViewModel viewModel) =>
|
||||
Stack(children: [_buildScaffold(viewModel), _buildState(viewModel)]);
|
||||
|
||||
Widget _buildScaffold(AssessmentViewModel viewModel) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: _buildScaffoldChildren(viewModel),
|
||||
);
|
||||
|
||||
List<Widget> _buildScaffoldChildren(AssessmentViewModel viewModel) =>
|
||||
[_buildAppBar(), _buildExpandedBody(viewModel)];
|
||||
[_buildAppBar(viewModel), _buildExpandedBody(viewModel)];
|
||||
|
||||
Widget _buildAppBar() => const LargeAppBar(
|
||||
showBackButton: false,
|
||||
showLanguageSelection: false,
|
||||
Widget _buildAppBar(AssessmentViewModel viewModel) => LargeAppBar(
|
||||
showBackButton: true,
|
||||
onPop: viewModel.pop,
|
||||
showLanguageSelection: true,
|
||||
);
|
||||
|
||||
Widget _buildExpandedBody(AssessmentViewModel viewModel) =>
|
||||
|
|
@ -114,10 +117,13 @@ class StartLessonScreen extends ViewModelWidget<AssessmentViewModel> {
|
|||
Widget _buildContinueButton(AssessmentViewModel viewModel) =>
|
||||
CustomElevatedButton(
|
||||
height: 55,
|
||||
text: 'Finish',
|
||||
borderRadius: 12,
|
||||
text: 'Go to My Lessons',
|
||||
foregroundColor: kcWhite,
|
||||
backgroundColor: kcPrimaryColor,
|
||||
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();
|
||||
|
||||
@override
|
||||
void onViewModelReady(HomeViewModel viewModel) {
|
||||
viewModel.getProfileStatus();
|
||||
void onViewModelReady(HomeViewModel viewModel) async {
|
||||
await viewModel.getProfileStatus();
|
||||
await viewModel.getProfileData();
|
||||
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:stacked/stacked.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/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
|
||||
Future<void> replaceWithFailure() async =>
|
||||
await _navigationService.clearStackAndShowView(
|
||||
const FailureView(label: 'Check your internet connection to proceed'),
|
||||
);
|
||||
|
||||
Future<void> replaceWithOnboarding() async =>
|
||||
await _navigationService.replaceWithOnboardingView();
|
||||
|
||||
// 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 {
|
||||
Map<String, dynamic> response =
|
||||
await runBusyFuture<Map<String, dynamic>>(_getProfileStatus());
|
||||
if (response['status'] == ResponseStatus.success && !response['data']) {
|
||||
await replaceWithOnboarding();
|
||||
} else if (response['status'] == ResponseStatus.success &&
|
||||
response['data']) {
|
||||
await saveProfileStatus(response['data']);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> _getProfileStatus() async {
|
||||
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()) {
|
||||
response = await _apiService.getProfileStatus(user);
|
||||
} else {
|
||||
response = {'data': false, 'status': ResponseStatus.success};
|
||||
await replaceWithFailure();
|
||||
}
|
||||
} else {
|
||||
response = {'data': true, 'status': ResponseStatus.success};
|
||||
|
|
|
|||
|
|
@ -38,12 +38,15 @@ class LearnView extends StackedView<LearnViewModel> {
|
|||
Widget _buildColumn(LearnViewModel viewModel) => Column(
|
||||
children: [
|
||||
verticalSpaceMedium,
|
||||
_buildAppBar(),
|
||||
_buildAppBar(viewModel),
|
||||
_buildLevelsColumnWrapper(viewModel)
|
||||
],
|
||||
);
|
||||
|
||||
Widget _buildAppBar() => const LearnAppBar();
|
||||
Widget _buildAppBar(LearnViewModel viewModel) => LearnAppBar(
|
||||
name: viewModel.user?.firstName,
|
||||
profileImage: viewModel.user?.profileImage,
|
||||
);
|
||||
|
||||
Widget _buildLevelsColumnWrapper(LearnViewModel viewModel) =>
|
||||
Expanded(child: _buildLevelsColumnScrollView(viewModel));
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
import 'package:stacked/stacked.dart';
|
||||
import 'package:stacked_services/stacked_services.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 '../../../app/app.locator.dart';
|
||||
|
||||
class LearnViewModel extends BaseViewModel {
|
||||
final _navigationService = locator<NavigationService>();
|
||||
final _authenticationService = locator<AuthenticationService>();
|
||||
|
||||
late final UserModel? _user = _authenticationService.user;
|
||||
|
||||
UserModel? get user => _user;
|
||||
|
||||
final List<Map<String, dynamic>> _learnLevels = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,5 +37,6 @@ class LearnModuleViewModel extends BaseViewModel {
|
|||
|
||||
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
|
||||
};
|
||||
|
||||
await _authenticationService.saveUserData(data);
|
||||
await _authenticationService.saveBasicUserData(data);
|
||||
showSuccessToast(response['message']);
|
||||
} else {
|
||||
showErrorToast(response['message']);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class OnboardingView extends StackedView<OnboardingViewModel>
|
|||
|
||||
Widget _buildOnboardingScreensWrapper(OnboardingViewModel viewModel) =>
|
||||
PopScope(
|
||||
canPop: false,
|
||||
canPop: viewModel.currentPage == 0 ? true : false,
|
||||
onPopInvokedWithResult: (value, data) => viewModel.pop(),
|
||||
child: _buildOnboardingScreens(viewModel));
|
||||
|
||||
|
|
|
|||
|
|
@ -54,10 +54,13 @@ class OnboardingViewModel extends FormViewModel {
|
|||
|
||||
// Age group
|
||||
final List<String> _ageGroups = [
|
||||
'8-14',
|
||||
'15-18',
|
||||
'19-26',
|
||||
'26+',
|
||||
'UNDER_13',
|
||||
'13_17',
|
||||
'18_24',
|
||||
'25_34',
|
||||
'35_44',
|
||||
'45_54',
|
||||
'55_PLUS'
|
||||
];
|
||||
|
||||
List<String> get ageGroups => _ageGroups;
|
||||
|
|
@ -352,7 +355,6 @@ class OnboardingViewModel extends FormViewModel {
|
|||
// Add user data
|
||||
void addUserData(Map<String, dynamic> data) {
|
||||
_userData.addAll(data);
|
||||
print('User data : $_userData');
|
||||
}
|
||||
|
||||
void clearUserData() {
|
||||
|
|
@ -385,7 +387,7 @@ class OnboardingViewModel extends FormViewModel {
|
|||
}
|
||||
|
||||
void pop() {
|
||||
if (_currentPage == 8) {
|
||||
if (_currentPage == 0) {
|
||||
_navigationService.back();
|
||||
} else {
|
||||
_currentPage--;
|
||||
|
|
|
|||
|
|
@ -15,11 +15,7 @@ class BirthdayFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
|||
Future<void> _next(OnboardingViewModel viewModel) async {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
|
||||
Map<String, dynamic> data = {
|
||||
'birth_day': DateFormat('yyyy-MM-dd')
|
||||
.parseUTC(viewModel.selectedBirthday ?? DateTime.now().toString())
|
||||
.toIso8601String()
|
||||
};
|
||||
Map<String, dynamic> data = {'birth_day': viewModel.selectedBirthday};
|
||||
viewModel.addUserData(data);
|
||||
viewModel.next();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,13 +93,16 @@ class LearningGoalFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
|||
onLanguage: () async => await viewModel.navigateToLanguage(),
|
||||
);
|
||||
|
||||
Widget _buildTitle(OnboardingViewModel viewModel) => Text(
|
||||
'Hi ${viewModel.userData['first_name']}, Choose your learning goal.',
|
||||
style: const TextStyle(
|
||||
fontSize: 25,
|
||||
color: kcDarkGrey,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
Widget _buildTitle(OnboardingViewModel viewModel) => Text.rich(
|
||||
TextSpan(
|
||||
text: 'Hi ${viewModel.userData['first_name']},',
|
||||
style: style18P600.copyWith(fontSize: 22),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: ' Choose your learning goal.',
|
||||
style: style16DG600.copyWith(fontSize: 22),
|
||||
)
|
||||
]),
|
||||
);
|
||||
|
||||
Widget _buildLearningGoals(OnboardingViewModel viewModel) => ListView.builder(
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ class TopicFormScreen extends ViewModelWidget<OnboardingViewModel> {
|
|||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
|
||||
Map<String, dynamic> data = {
|
||||
'profile_completed': true,
|
||||
'preferred_language': 'en',
|
||||
'favoutite_topic': viewModel.selectedTopic ?? topicController.text,
|
||||
};
|
||||
viewModel.addUserData(data);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class ProfileView extends StackedView<ProfileViewModel> {
|
|||
children: [
|
||||
verticalSpaceMedium,
|
||||
_buildNotificationIconWrapper(),
|
||||
_buildProfileSection(),
|
||||
_buildProfileSection(viewModel),
|
||||
verticalSpaceSmall,
|
||||
_buildViewProfileButton(viewModel),
|
||||
verticalSpaceLarge,
|
||||
|
|
@ -66,27 +66,25 @@ class ProfileView extends StackedView<ProfileViewModel> {
|
|||
color: kcDarkGrey,
|
||||
);
|
||||
|
||||
Widget _buildProfileSection() => Column(
|
||||
Widget _buildProfileSection(ProfileViewModel viewModel) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: _buildProfileSectionChildren(),
|
||||
children: _buildProfileSectionChildren(viewModel),
|
||||
);
|
||||
|
||||
List<Widget> _buildProfileSectionChildren() => [
|
||||
_buildProfileImage(),
|
||||
List<Widget> _buildProfileSectionChildren(ProfileViewModel viewModel) => [
|
||||
_buildProfileImage(viewModel),
|
||||
verticalSpaceSmall,
|
||||
_buildProfileName(),
|
||||
_buildProfileName(viewModel),
|
||||
];
|
||||
|
||||
Widget _buildProfileImage() => const ProfileImage();
|
||||
Widget _buildProfileImage(ProfileViewModel viewModel) => ProfileImage(
|
||||
profileImage: viewModel.user?.profileImage,
|
||||
);
|
||||
|
||||
Widget _buildProfileName() => const Text(
|
||||
'Hi, Bisrat 👋',
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
color: kcDarkGrey,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
Widget _buildProfileName(ProfileViewModel viewModel) => Text(
|
||||
'Hi, ${viewModel.user?.firstName ?? ''} 👋',
|
||||
style: style25DG600,
|
||||
);
|
||||
|
||||
Widget _buildViewProfileButton(ProfileViewModel viewModel) =>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'package:stacked_services/stacked_services.dart';
|
|||
import 'package:yimaru_app/app/app.router.dart';
|
||||
|
||||
import '../../../app/app.locator.dart';
|
||||
import '../../../models/user_model.dart';
|
||||
import '../../../services/authentication_service.dart';
|
||||
|
||||
class ProfileViewModel extends BaseViewModel {
|
||||
|
|
@ -10,6 +11,10 @@ class ProfileViewModel extends BaseViewModel {
|
|||
|
||||
final _authenticationService = locator<AuthenticationService>();
|
||||
|
||||
late final UserModel? _user = _authenticationService.user;
|
||||
|
||||
UserModel? get user => _user;
|
||||
|
||||
Future<void> logOut() async {
|
||||
await _authenticationService.logOut();
|
||||
await _navigationService.replaceWithLoginView();
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ class ProfileDetailView extends StackedView<ProfileDetailViewModel>
|
|||
|
||||
List<Widget> _buildColumnChildren(ProfileDetailViewModel viewModel) => [
|
||||
verticalSpaceMedium,
|
||||
_buildProfileImage(),
|
||||
_buildProfileImageWrapper(viewModel),
|
||||
verticalSpaceMedium,
|
||||
_buildNameFormSection(viewModel),
|
||||
verticalSpaceMedium,
|
||||
|
|
@ -120,9 +120,12 @@ class ProfileDetailView extends StackedView<ProfileDetailViewModel>
|
|||
_buildLowerColumn(viewModel)
|
||||
];
|
||||
|
||||
Widget _buildProfileImage() =>
|
||||
const Align(alignment: Alignment.center, child: ProfileImage());
|
||||
Widget _buildProfileImageWrapper(ProfileDetailViewModel viewModel) =>
|
||||
Align(alignment: Alignment.center, child: _buildProfileImage(viewModel));
|
||||
|
||||
Widget _buildProfileImage(ProfileDetailViewModel viewModel) => ProfileImage(
|
||||
profileImage: viewModel.user?.profileImage,
|
||||
);
|
||||
Widget _buildNameFormSection(ProfileDetailViewModel viewModel) => Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: _buildNameFormChildren(viewModel),
|
||||
|
|
|
|||
|
|
@ -2,9 +2,18 @@ import 'package:stacked/stacked.dart';
|
|||
import 'package:stacked_services/stacked_services.dart';
|
||||
|
||||
import '../../../app/app.locator.dart';
|
||||
import '../../../models/user_model.dart';
|
||||
import '../../../services/authentication_service.dart';
|
||||
|
||||
class ProfileDetailViewModel extends FormViewModel {
|
||||
final _navigationService = locator<NavigationService>();
|
||||
|
||||
final _authenticationService = locator<AuthenticationService>();
|
||||
|
||||
late final UserModel? _user = _authenticationService.user;
|
||||
|
||||
UserModel? get user => _user;
|
||||
|
||||
// First name
|
||||
bool _focusFirstName = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ class RegisterViewModel extends FormViewModel {
|
|||
// 'refreshToken': 'refreshToken'
|
||||
// }
|
||||
|
||||
await _authenticationService.saveUserData(data);
|
||||
await _authenticationService.saveBasicUserData(data);
|
||||
showSuccessToast(response['message']);
|
||||
} else {
|
||||
showErrorToast(response['message']);
|
||||
|
|
|
|||
|
|
@ -6,11 +6,13 @@ class LargeAppBar extends StatelessWidget {
|
|||
final bool showBackButton;
|
||||
final GestureTapCallback? onPop;
|
||||
final bool showLanguageSelection;
|
||||
final GestureTapCallback? onClose;
|
||||
final GestureTapCallback? onLanguage;
|
||||
|
||||
const LargeAppBar(
|
||||
{super.key,
|
||||
this.onPop,
|
||||
this.onClose,
|
||||
this.onLanguage,
|
||||
required this.showBackButton,
|
||||
required this.showLanguageSelection});
|
||||
|
|
@ -53,9 +55,9 @@ class LargeAppBar extends StatelessWidget {
|
|||
|
||||
Widget _buildRightButton() => Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: showLanguageSelection ? _buildLanguageSelector() : Container()
|
||||
// _buildCloseButton()
|
||||
);
|
||||
child: showLanguageSelection
|
||||
? _buildLanguageSelector()
|
||||
: _buildCloseButton());
|
||||
|
||||
Widget _buildLanguageSelector() => LanguageButton(
|
||||
language: 'EN',
|
||||
|
|
@ -63,8 +65,9 @@ class LargeAppBar extends StatelessWidget {
|
|||
);
|
||||
|
||||
Widget _buildCloseButton() => IconButton(
|
||||
onPressed: () {},
|
||||
onPressed: onClose,
|
||||
icon: _buildCloseIcon(),
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
);
|
||||
|
||||
Widget _buildCloseIcon() => const Icon(
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:yimaru_app/ui/common/ui_helpers.dart';
|
||||
|
||||
import '../common/app_colors.dart';
|
||||
|
||||
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
|
||||
Widget build(BuildContext context) => _buildStack();
|
||||
|
|
@ -30,9 +35,22 @@ class LearnAppBar extends StatelessWidget {
|
|||
List<Widget> _buildProfileRowChildren() =>
|
||||
[_buildProfileImage(), horizontalSpaceSmall, _buildGreetingTextColumn()];
|
||||
|
||||
Widget _buildProfileImage() => const CircleAvatar(
|
||||
Widget _buildProfileImage() => CircleAvatar(
|
||||
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(
|
||||
|
|
@ -44,28 +62,19 @@ class LearnAppBar extends StatelessWidget {
|
|||
List<Widget> _buildGreetingChildren() =>
|
||||
[_buildGreetingTitle(), _buildSubTitle()];
|
||||
|
||||
Widget _buildGreetingTitle() => const Text.rich(
|
||||
Widget _buildGreetingTitle() => Text.rich(
|
||||
TextSpan(text: 'Hello,', style: style14DG600, children: [
|
||||
TextSpan(
|
||||
text: 'Hello,',
|
||||
style: TextStyle(
|
||||
color: kcDarkGrey,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: ' Bisrat!',
|
||||
style: TextStyle(
|
||||
color: kcPrimaryColor,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
text: ' $name!',
|
||||
style: style14P600,
|
||||
)
|
||||
]),
|
||||
);
|
||||
|
||||
Widget _buildSubTitle() => const Text(
|
||||
Widget _buildSubTitle() => Text(
|
||||
'Ready to keep learning English today?',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: kcMediumGrey),
|
||||
style: style14DG400,
|
||||
);
|
||||
|
||||
Widget _buildNotificationIconWrapper() =>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:yimaru_app/ui/common/app_colors.dart';
|
||||
|
||||
class ProfileImage extends StatelessWidget {
|
||||
const ProfileImage({super.key});
|
||||
final String? profileImage;
|
||||
const ProfileImage({super.key, required this.profileImage});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => _buildSizedBox();
|
||||
|
|
@ -22,9 +24,22 @@ class ProfileImage extends StatelessWidget {
|
|||
child: _buildProfileImage(),
|
||||
);
|
||||
|
||||
Widget _buildProfileImage() => const CircleAvatar(
|
||||
Widget _buildProfileImage() => CircleAvatar(
|
||||
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(
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ import Foundation
|
|||
import battery_plus
|
||||
import connectivity_plus
|
||||
import flutter_secure_storage_darwin
|
||||
import sqflite_darwin
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
BatteryPlusMacosPlugin.register(with: registry.registrar(forPlugin: "BatteryPlusMacosPlugin"))
|
||||
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
||||
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"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -318,6 +342,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -704,6 +736,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -917,6 +957,46 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
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:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -989,6 +1069,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: synchronized
|
||||
sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ dependencies:
|
|||
stacked_services: ^1.1.0
|
||||
omni_datetime_picker: any
|
||||
json_serializable: ^6.8.0
|
||||
cached_network_image: ^3.4.1
|
||||
flutter_secure_storage: ^10.0.0
|
||||
flutter_timer_countdown: ^1.0.7
|
||||
|
||||
internet_connection_checker_plus: ^2.9.1+2
|
||||
|
||||
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