"lib/screen/onboarding/onboarding_viewmodel.dart" did not exist on "e41fc4fe4b6799e5d07be8edcaffbc6ede444dbf"
Commit 5fb93f2d authored by DatHV's avatar DatHV
Browse files

update logic authen

parent 73074efa
...@@ -105,7 +105,6 @@ ...@@ -105,7 +105,6 @@
4095AD98D6AA41A025D05981 /* Pods-RunnerTests.release.xcconfig */, 4095AD98D6AA41A025D05981 /* Pods-RunnerTests.release.xcconfig */,
40F35D12C549F03EDF2680DB /* Pods-RunnerTests.profile.xcconfig */, 40F35D12C549F03EDF2680DB /* Pods-RunnerTests.profile.xcconfig */,
); );
name = Pods;
path = Pods; path = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
...@@ -470,16 +469,20 @@ ...@@ -470,16 +469,20 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = T3AV8NC2D4; DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = Z99P65VHXA;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.icom.vn.mypointFlutterApp; PRODUCT_BUNDLE_IDENTIFIER = com.icom.vn.MyPoint;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "MyPoint development";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
...@@ -491,12 +494,16 @@ ...@@ -491,12 +494,16 @@
baseConfigurationReference = DEA7D70911C640B733B46F56 /* Pods-RunnerTests.debug.xcconfig */; baseConfigurationReference = DEA7D70911C640B733B46F56 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = Z99P65VHXA;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.icom.vn.mypointFlutterApp.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.icom.vn.MyPoint;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "MyPoint development";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
...@@ -509,12 +516,16 @@ ...@@ -509,12 +516,16 @@
baseConfigurationReference = 4095AD98D6AA41A025D05981 /* Pods-RunnerTests.release.xcconfig */; baseConfigurationReference = 4095AD98D6AA41A025D05981 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = Z99P65VHXA;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.icom.vn.mypointFlutterApp.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.icom.vn.MyPoint;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "MyPoint development";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
}; };
...@@ -525,12 +536,16 @@ ...@@ -525,12 +536,16 @@
baseConfigurationReference = 40F35D12C549F03EDF2680DB /* Pods-RunnerTests.profile.xcconfig */; baseConfigurationReference = 40F35D12C549F03EDF2680DB /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = Z99P65VHXA;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.icom.vn.mypointFlutterApp.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.icom.vn.MyPoint;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "MyPoint development";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
}; };
...@@ -653,16 +668,20 @@ ...@@ -653,16 +668,20 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = T3AV8NC2D4; DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = Z99P65VHXA;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.icom.vn.mypointFlutterApp; PRODUCT_BUNDLE_IDENTIFIER = com.icom.vn.MyPoint;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "MyPoint development";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
...@@ -676,16 +695,20 @@ ...@@ -676,16 +695,20 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = T3AV8NC2D4; DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = Z99P65VHXA;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.icom.vn.mypointFlutterApp; PRODUCT_BUNDLE_IDENTIFIER = com.icom.vn.MyPoint;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "MyPoint development";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
...@@ -24,6 +26,12 @@ ...@@ -24,6 +26,12 @@
<string>$(FLUTTER_BUILD_NUMBER)</string> <string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>NSFaceIDUsageDescription</key>
<string>We need Face ID to authenticate your identity</string>
<key>NSLocalAuthenticationUseFaceID</key>
<string>true</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIMainStoryboardFile</key> <key>UIMainStoryboardFile</key>
...@@ -41,13 +49,5 @@ ...@@ -41,13 +49,5 @@
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>NSFaceIDUsageDescription</key>
<string>We need Face ID to authenticate your identity</string>
<key>NSLocalAuthenticationUseFaceID</key>
<string>true</string>
</dict> </dict>
</plist> </plist>
...@@ -97,10 +97,15 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen> { ...@@ -97,10 +97,15 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen> {
context.showConfirmAlertDialog(message, cancel: cancel, confirm: confirm, callback: callback); context.showConfirmAlertDialog(message, cancel: cancel, confirm: confirm, callback: callback);
} }
showAlert({required DataAlertModel data, bool? barrierDismissibl}) { showAlert({required DataAlertModel data,
bool? barrierDismissibl,
bool showCloseButton = true,
ButtonsDirection direction = ButtonsDirection.column}) {
Get.dialog( Get.dialog(
CustomAlertDialog( CustomAlertDialog(
alertData: data, alertData: data,
showCloseButton: showCloseButton,
direction: direction,
), ),
barrierDismissible: barrierDismissibl ?? false, barrierDismissible: barrierDismissibl ?? false,
); );
......
...@@ -19,4 +19,10 @@ class APIPaths { ...@@ -19,4 +19,10 @@ class APIPaths {
static const String bioCredential = "/iam/v1/account/me/bio-credential"; static const String bioCredential = "/iam/v1/account/me/bio-credential";
static const String accountLoginForPasswordChange = "/accountLoginForPasswordChange/1.0.0"; static const String accountLoginForPasswordChange = "/accountLoginForPasswordChange/1.0.0";
static const String accountPasswordChange = "/accountPasswordChange/1.0.0"; static const String accountPasswordChange = "/accountPasswordChange/1.0.0";
static const String registerBiometric = "/iam/v1/account/me/bio-credential";
static const String unRegisterBiometric = "/iam/v1/account/me/bio-credential";
static const String customerBalanceGetDetail = "/customerBalanceGetDetail/1.0.0";
static const String headerHome = "/dynamic-home/api/v1.0/header-home";
static const String otpDeleteAccountRequest = "/user/api/v2.0/me/delete/request";
static const String verifyDeleteAccount = "/user/api/v2.0/me/delete/verify";
} }
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:mypoint_flutter_app/preference/data_preference.dart'; import 'package:mypoint_flutter_app/preference/data_preference.dart';
import 'package:mypoint_flutter_app/screen/login/login_screen.dart'; import 'package:mypoint_flutter_app/shared/router_gage.dart';
import 'package:mypoint_flutter_app/screen/main_tab_screen/main_tab_screen.dart';
import 'package:mypoint_flutter_app/screen/onboarding/onboarding_screen.dart';
import 'package:mypoint_flutter_app/screen/onboarding/onboarding_viewmodel.dart';
import 'package:mypoint_flutter_app/screen/splash/splash_screen.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await DataPreference.instance.loadLoginToken(); await DataPreference.instance.init();
Get.put(OnboardingViewModel());
runApp(const MyApp()); runApp(const MyApp());
} }
...@@ -21,17 +16,13 @@ class MyApp extends StatelessWidget { ...@@ -21,17 +16,13 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetMaterialApp( return GetMaterialApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
initialRoute: '/login', initialRoute: '/splash',
theme: ThemeData( theme: ThemeData(
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.deepPurple), colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.deepPurple),
primaryColor: Colors.deepPurple, primaryColor: Colors.deepPurple,
), ),
home: SplashScreen(), // home: SplashScreen(),
getPages: [ getPages: RouterPage.pages(),
GetPage(name: '/login', page: () => const LoginScreen(phoneNumber: '091212121',)),
GetPage(name: '/main', page: () => const MainTabScreen()),
GetPage(name: '/onboarding', page: () => const OnboardingScreen()),
],
); );
} }
} }
\ No newline at end of file
...@@ -6,7 +6,7 @@ part 'update_response_model.g.dart'; ...@@ -6,7 +6,7 @@ part 'update_response_model.g.dart';
@JsonSerializable() @JsonSerializable()
class UpdateResponseModel { class UpdateResponseModel {
@JsonKey(name: 'update_request') @JsonKey(name: 'update_request')
List<CheckUpdateResponseModel?>? updateRequest; List<CheckUpdateResponseModel>? updateRequest;
UpdateResponseModel({this.updateRequest}); UpdateResponseModel({this.updateRequest});
......
...@@ -6,20 +6,16 @@ part of 'update_response_model.dart'; ...@@ -6,20 +6,16 @@ part of 'update_response_model.dart';
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
UpdateResponseModel _$UpdateResponseModelFromJson(Map<String, dynamic> json) => UpdateResponseModel _$UpdateResponseModelFromJson(
UpdateResponseModel( Map<String, dynamic> json,
updateRequest: ) => UpdateResponseModel(
(json['update_request'] as List<dynamic>?) updateRequest:
?.map( (json['update_request'] as List<dynamic>?)
(e) => ?.map(
e == null (e) => CheckUpdateResponseModel.fromJson(e as Map<String, dynamic>),
? null )
: CheckUpdateResponseModel.fromJson( .toList(),
e as Map<String, dynamic>, );
),
)
.toList(),
);
Map<String, dynamic> _$UpdateResponseModelToJson( Map<String, dynamic> _$UpdateResponseModelToJson(
UpdateResponseModel instance, UpdateResponseModel instance,
......
import 'package:json_annotation/json_annotation.dart';
import 'package:mypoint_flutter_app/model/update_response_model.dart';
part 'update_response_object.g.dart';
@JsonSerializable()
class UpdateResponseObject {
UpdateResponseModel? data;
UpdateResponseObject({this.data});
factory UpdateResponseObject.fromJson(Map<String, dynamic> json) => _$UpdateResponseObjectFromJson(json);
Map<String, dynamic> toJson() => _$UpdateResponseObjectToJson(this);
}
\ No newline at end of file
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'update_response_object.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
UpdateResponseObject _$UpdateResponseObjectFromJson(
Map<String, dynamic> json,
) => UpdateResponseObject(
data:
json['data'] == null
? null
: UpdateResponseModel.fromJson(json['data'] as Map<String, dynamic>),
);
Map<String, dynamic> _$UpdateResponseObjectToJson(
UpdateResponseObject instance,
) => <String, dynamic>{'data': instance.data};
...@@ -9,7 +9,8 @@ import '../configs/device_info.dart'; ...@@ -9,7 +9,8 @@ import '../configs/device_info.dart';
import '../model/auth/biometric_register_response_model.dart'; import '../model/auth/biometric_register_response_model.dart';
import '../model/auth/login_token_response_model.dart'; import '../model/auth/login_token_response_model.dart';
import '../model/auth/profile_response_model.dart'; import '../model/auth/profile_response_model.dart';
import '../model/update_response_object.dart'; import '../model/update_response_model.dart';
import '../preference/point/header_home_model.dart';
import '../screen/faqs/faqs_model.dart'; import '../screen/faqs/faqs_model.dart';
import '../screen/onboarding/model/check_phone_response_model.dart'; import '../screen/onboarding/model/check_phone_response_model.dart';
import '../screen/onboarding/model/onboarding_info_model.dart'; import '../screen/onboarding/model/onboarding_info_model.dart';
...@@ -21,14 +22,14 @@ import '../screen/splash/splash_screen_viewmodel.dart'; ...@@ -21,14 +22,14 @@ import '../screen/splash/splash_screen_viewmodel.dart';
import 'model_maker.dart'; import 'model_maker.dart';
extension RestfullAPIClientAllApi on RestfulAPIClient { extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<UpdateResponseObject>> checkUpdateApp() async { Future<BaseResponseModel<UpdateResponseModel>> checkUpdateApp() async {
String version = Platform.version; String version = Platform.version;
final body = {"operating_system": "iOS", "software_model": "MyPoint", "version": "1.12.1", "build_number": "1"}; final body = {"operating_system": "iOS", "software_model": "MyPoint", "version": "1.21.7", "build_number": "1"};
return requestNormal( return requestNormal(
APIPaths.checkUpdate, APIPaths.checkUpdate,
Method.POST, Method.POST,
body, body,
(data) => UpdateResponseObject.fromJson(data as Json), (data) => UpdateResponseModel.fromJson(data as Json),
); );
} }
...@@ -73,6 +74,24 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -73,6 +74,24 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
); );
} }
Future<BaseResponseModel<CreateOTPResponseModel>> requestOtpDeleteAccount() async {
return requestNormal(
APIPaths.otpDeleteAccountRequest,
Method.POST,
{},
(data) => CreateOTPResponseModel.fromJson(data as Json),
);
}
Future<BaseResponseModel<CreateOTPResponseModel>> verifyDeleteAccount(String otp) async {
return requestNormal(
APIPaths.verifyDeleteAccount,
Method.POST,
{"otp": otp},
(data) => CreateOTPResponseModel.fromJson(data as Json),
);
}
Future<BaseResponseModel<EmptyCodable>> signup(String phone, String password) async { Future<BaseResponseModel<EmptyCodable>> signup(String phone, String password) async {
var deviceKey = await DeviceInfo.getDeviceId(); var deviceKey = await DeviceInfo.getDeviceId();
final body = {"username": phone, "password": password.toSha256(), "device_key": deviceKey}; final body = {"username": phone, "password": password.toSha256(), "device_key": deviceKey};
...@@ -91,12 +110,13 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -91,12 +110,13 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<LoginTokenResponseModel>> loginWithBiometric(String phone) async { Future<BaseResponseModel<LoginTokenResponseModel>> loginWithBiometric(String phone) async {
var deviceKey = await DeviceInfo.getDeviceId(); var deviceKey = await DeviceInfo.getDeviceId();
var bioToken = await DataPreference.instance.getBioToken(phone) ?? "";
final body = { final body = {
"username": phone, "username": phone,
"bioToken": DataPreference.instance.getBioToken(phone) ?? "", "bioToken": bioToken,
"deviceKey": deviceKey, "deviceKey": deviceKey,
"workspaceCode": "8854"}; "workspaceCode": "8854"};
return requestNormal(APIPaths.login, Method.POST, body, (data) => LoginTokenResponseModel.fromJson(data as Json)); return requestNormal(APIPaths.loginWithBiometric, Method.POST, body, (data) => LoginTokenResponseModel.fromJson(data as Json));
} }
Future<BaseResponseModel<ProfileResponseModel>> getUserProfile() async { Future<BaseResponseModel<ProfileResponseModel>> getUserProfile() async {
...@@ -176,7 +196,8 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -176,7 +196,8 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
} }
Future<BaseResponseModel<EmptyCodable>> accountPasswordChange(String phone, String password) async { Future<BaseResponseModel<EmptyCodable>> accountPasswordChange(String phone, String password) async {
final body = {"login_name": phone, "password": password.toSha256(), "access_token": DataPreference.instance.token ?? ""}; String? token = await DataPreference.instance.token ?? "";
final body = {"login_name": phone, "password": password.toSha256(), "access_token": token};
return requestNormal( return requestNormal(
APIPaths.accountPasswordChange, APIPaths.accountPasswordChange,
Method.POST, Method.POST,
...@@ -185,6 +206,17 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -185,6 +206,17 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
); );
} }
Future<BaseResponseModel<EmptyCodable>> accountLoginForPasswordChange(String phone, String password) async {
String? token = await DataPreference.instance.token ?? "";
final body = {"login_name": phone, "password": password.toSha256(), "access_token": token};
return requestNormal(
APIPaths.accountLoginForPasswordChange,
Method.POST,
body,
(data) => EmptyCodable.fromJson(data as Json),
);
}
Future<BaseResponseModel<BiometricRegisterResponseModel>> accountBioCredential() async { Future<BaseResponseModel<BiometricRegisterResponseModel>> accountBioCredential() async {
var deviceKey = await DeviceInfo.getDeviceId(); var deviceKey = await DeviceInfo.getDeviceId();
final body = {"deviceKey": deviceKey}; final body = {"deviceKey": deviceKey};
...@@ -196,13 +228,35 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -196,13 +228,35 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
); );
} }
Future<BaseResponseModel<EmptyCodable>> accountCheckForPasswordChange(String password) async { Future<BaseResponseModel<BiometricRegisterResponseModel>> registerBiometric() async {
final body = {"password": password.toSha256()}; var deviceKey = await DeviceInfo.getDeviceId();
final body = {"deviceKey": deviceKey};
return requestNormal( return requestNormal(
APIPaths.accountLoginForPasswordChange, APIPaths.registerBiometric,
Method.POST,
body,
(data) => BiometricRegisterResponseModel.fromJson(data as Json),
);
}
Future<BaseResponseModel<EmptyCodable>> unRegisterBiometric() async {
var deviceKey = await DeviceInfo.getDeviceId();
final path = "${APIPaths.unRegisterBiometric}/$deviceKey";
final body = {"deviceKey": deviceKey};
return requestNormal(
path,
Method.POST, Method.POST,
body, body,
(data) => EmptyCodable.fromJson(data as Json), (data) => EmptyCodable.fromJson(data as Json),
); );
} }
Future<BaseResponseModel<HeaderHomeModel>> getHomeHeaderData() async {
return requestNormal(
APIPaths.headerHome,
Method.GET,
{},
(data) => HeaderHomeModel.fromJson(data as Json),
);
}
} }
...@@ -49,7 +49,10 @@ class BiometricManager { ...@@ -49,7 +49,10 @@ class BiometricManager {
try { try {
final didAuthenticate = await _localAuth.authenticate( final didAuthenticate = await _localAuth.authenticate(
localizedReason: localizedReason, localizedReason: localizedReason,
options: const AuthenticationOptions(biometricOnly: true), options: const AuthenticationOptions(
biometricOnly: false, // ✅ cho phép passcode hoặc vân tay / face ID
stickyAuth: true, // ✅ giữ lại phiên nếu app vào background
),
); );
return didAuthenticate; return didAuthenticate;
} catch (e) { } catch (e) {
......
...@@ -10,55 +10,35 @@ class DataPreference { ...@@ -10,55 +10,35 @@ class DataPreference {
LoginTokenResponseModel? _loginToken; LoginTokenResponseModel? _loginToken;
ProfileResponseModel? _profile; ProfileResponseModel? _profile;
ProfileResponseModel? get profile => _profile;
LoginTokenResponseModel? get loginToken => _loginToken;
String? get phone => _profile?.workerSite?.phoneNumber;
Future<bool> get logged async {
final currentToken = await token;
return (currentToken ?? "").isNotEmpty;
}
Future<String?> get token async {
if (_loginToken != null) {
return _loginToken?.accessToken;
} else {
await loadLoginToken();
return _loginToken?.accessToken;
}
}
Future<void> saveUserProfile(ProfileResponseModel profile) async { Future<void> init() async {
_profile = profile;
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
final jsonString = jsonEncode(profile.toJson()); final tokenJson = prefs.getString('login_token');
await prefs.setString('user_profile', jsonString); if (tokenJson != null) {
} _loginToken = LoginTokenResponseModel.fromJson(jsonDecode(tokenJson));
}
Future<void> loadProfile() async { final profileJson = prefs.getString('user_profile');
final prefs = await SharedPreferences.getInstance(); if (profileJson != null) {
final jsonString = prefs.getString('user_profile'); _profile = ProfileResponseModel.fromJson(jsonDecode(profileJson));
if (jsonString != null) {
final jsonMap = jsonDecode(jsonString);
_profile = ProfileResponseModel.fromJson(jsonMap);
} }
} }
String? get token => _loginToken?.accessToken;
String? get phone => _profile?.workerSite?.phoneNumber;
bool get logged => (token ?? "").isNotEmpty;
ProfileResponseModel? get profile => _profile;
Future<void> saveLoginToken(LoginTokenResponseModel token) async { Future<void> saveLoginToken(LoginTokenResponseModel token) async {
_loginToken = token; _loginToken = token;
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
final jsonString = jsonEncode(token.toJson()); await prefs.setString('login_token', jsonEncode(token.toJson()));
await prefs.setString('login_token', jsonString);
} }
Future<void> loadLoginToken() async { Future<void> saveUserProfile(ProfileResponseModel profile) async {
_profile = profile;
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
final jsonString = prefs.getString('login_token'); await prefs.setString('user_profile', jsonEncode(profile.toJson()));
if (jsonString != null) {
final jsonMap = jsonDecode(jsonString);
_loginToken = LoginTokenResponseModel.fromJson(jsonMap);
}
} }
Future<void> clearLoginToken() async { Future<void> clearLoginToken() async {
...@@ -67,23 +47,31 @@ class DataPreference { ...@@ -67,23 +47,31 @@ class DataPreference {
await prefs.remove('login_token'); await prefs.remove('login_token');
} }
Future<void> clearBioToken(String phone) async { Future<void> clearUserProfile() async {
_profile = null;
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
await prefs.remove('biometric_login_token_$phone'); await prefs.remove('user_profile');
}
Future<void> clearData() async {
await clearLoginToken();
await clearUserProfile();
} }
Future<void> saveBioToken(String bioToken) async { Future<void> saveBioToken(String bioToken) async {
if (phone == null) return; if (phone == null) return;
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
final jsonString = jsonEncode(bioToken); await prefs.setString('biometric_login_token_$phone', jsonEncode(bioToken));
await prefs.setString('biometric_login_token_$phone', jsonString);
} }
Future<String?> getBioToken(String phone) async { Future<String?> getBioToken(String phone) async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
final jsonString = prefs.getString('biometric_login_token_$phone'); final jsonString = prefs.getString('biometric_login_token_$phone');
if (jsonString != null) { return jsonString != null ? jsonDecode(jsonString) : null;
return jsonDecode(jsonString); }
}
Future<void> clearBioToken(String phone) async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove('biometric_login_token_$phone');
} }
} }
\ No newline at end of file
import 'package:json_annotation/json_annotation.dart';
part 'header_home_model.g.dart';
@JsonSerializable()
class HeaderHomeModel {
final String? greeting;
@JsonKey(name: 'total_voucher')
final int? totalVoucher;
@JsonKey(name: 'total_point_active')
final int? totalPointActive;
final String? background;
HeaderHomeModel({
this.greeting,
this.totalVoucher,
this.totalPointActive,
this.background,
});
factory HeaderHomeModel.fromJson(Map<String, dynamic> json) => _$HeaderHomeModelFromJson(json);
Map<String, dynamic> toJson() => _$HeaderHomeModelToJson(this);
}
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'header_home_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
HeaderHomeModel _$HeaderHomeModelFromJson(Map<String, dynamic> json) =>
HeaderHomeModel(
greeting: json['greeting'] as String?,
totalVoucher: (json['total_voucher'] as num?)?.toInt(),
totalPointActive: (json['total_point_active'] as num?)?.toInt(),
background: json['background'] as String?,
);
Map<String, dynamic> _$HeaderHomeModelToJson(HeaderHomeModel instance) =>
<String, dynamic>{
'greeting': instance.greeting,
'total_voucher': instance.totalVoucher,
'total_point_active': instance.totalPointActive,
'background': instance.background,
};
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/networking/restful_api_request.dart';
import '../../base/restful_api_viewmodel.dart';
import 'header_home_model.dart';
class UserPointManager extends RestfulApiViewModel {
static final UserPointManager _instance = UserPointManager._internal();
factory UserPointManager() => _instance;
UserPointManager._internal();
final RxInt _userPoint = 0.obs;
HeaderHomeModel? _headerInfo;
get point => _userPoint.value;
Future<int> fetchUserPoint() async {
try {
final response = await client.getHomeHeaderData();
if (response.isSuccess && response.data != null) {
_headerInfo = response.data;
_userPoint.value = _headerInfo?.totalPointActive ?? 0;
} else {
_userPoint.value = 0;
}
} catch (e) {
_userPoint.value = 0;
}
return _userPoint.value;
}
}
import 'package:flutter/material.dart';
class AppButtonStyle {
static ButtonStyle primary = ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
minimumSize: const Size.fromHeight(32),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
);
static ButtonStyle secondary = ElevatedButton.styleFrom(
backgroundColor: Colors.grey.shade300,
foregroundColor: Colors.black,
minimumSize: const Size.fromHeight(32),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
);
}
...@@ -84,31 +84,40 @@ TextStyle getTextStyle(TextStyleIconAndText? textType) { ...@@ -84,31 +84,40 @@ TextStyle getTextStyle(TextStyleIconAndText? textType) {
} }
} }
final BorderRadius _borderRadius = BorderRadius.circular(8.0);
final BorderSide _defaultBorderSide = BorderSide(color: BaseColor.second400);
final BorderSide _focusedBorderSide = BorderSide(color: Colors.blue);
final EdgeInsets _contentPadding = EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0);
class PTTextStyles { class AppTextStyle {
static final InputDecoration textFieldDecoration = InputDecoration( static const TextStyle title = TextStyle(
border: OutlineInputBorder( fontSize: 18,
borderRadius: _borderRadius, fontWeight: FontWeight.bold,
borderSide: _defaultBorderSide, color: Colors.black87,
), );
enabledBorder: OutlineInputBorder(
borderRadius: _borderRadius, static const TextStyle content = TextStyle(
borderSide: _defaultBorderSide, fontSize: 14,
), color: Colors.black87,
focusedBorder: OutlineInputBorder( );
borderRadius: _borderRadius,
borderSide: _focusedBorderSide, static const TextStyle boldContent = TextStyle(
), fontSize: 14,
labelText: 'Enter text', fontWeight: FontWeight.bold,
labelStyle: TextStyle(color: Colors.grey), color: Colors.black87,
hintText: 'Hint text', );
hintStyle: TextStyle(color: Colors.grey),
filled: true, static const TextStyle link = TextStyle(
fillColor: Colors.white, fontSize: 14,
contentPadding: _contentPadding, color: Colors.blue,
decoration: TextDecoration.underline,
);
static const TextStyle buttonPrimary = TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.white,
);
static const TextStyle buttonSecondary = TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.black,
); );
} }
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:mypoint_flutter_app/widgets/alert/data_alert_model.dart';
import '../../base/base_screen.dart'; import '../../base/base_screen.dart';
import '../../base/basic_state.dart'; import '../../base/basic_state.dart';
import '../../preference/data_preference.dart'; import '../../preference/data_preference.dart';
import '../../resouce/base_color.dart'; import '../../resouce/base_color.dart';
import '../../shared/router_gage.dart';
import '../../widgets/back_button.dart'; import '../../widgets/back_button.dart';
import '../../widgets/support_button.dart'; import '../../widgets/support_button.dart';
import '../login/login_viewmodel.dart'; import '../login/login_viewmodel.dart';
...@@ -28,6 +30,10 @@ class _ChangePassScreenState extends BaseState<ChangePassScreen> with BasicState ...@@ -28,6 +30,10 @@ class _ChangePassScreenState extends BaseState<ChangePassScreen> with BasicState
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_focusNode.requestFocus(); _focusNode.requestFocus();
}); });
viewModel.onShowAlertError = (message) {
showAlertError(content: message);
};
} }
@override @override
...@@ -155,7 +161,29 @@ class _ChangePassScreenState extends BaseState<ChangePassScreen> with BasicState ...@@ -155,7 +161,29 @@ class _ChangePassScreenState extends BaseState<ChangePassScreen> with BasicState
children: [ children: [
TextButton( TextButton(
onPressed: () { onPressed: () {
viewModel.onForgotPassPressed(_phone); final dataAlert = DataAlertModel(
title: "Quên mật khẩu",
content: "Bạn cần đăng xuất khỏi tài khoản này để đặt lại mật khẩu. Bạn chắc chứ?.",
background: "assets/images/ic_pipi_03.png",
buttons: [AlertButton(
text: "Đồng ý",
onPressed: () {
DataPreference.instance.clearLoginToken();
_safeBackToLogin();
},
bgColor: BaseColor.primary500,
textColor: Colors.white,
isPrimary: true,
),
AlertButton(
text: "Huỷ",
onPressed: () => Get.back(),
bgColor: Colors.white,
textColor: BaseColor.second500,
isPrimary: false,
),],
);
showAlert(data: dataAlert);
}, },
child: const Text("Quên mật khẩu?", style: TextStyle(fontSize: 14, color: Color(0xFF3662FE))), child: const Text("Quên mật khẩu?", style: TextStyle(fontSize: 14, color: Color(0xFF3662FE))),
), ),
...@@ -204,4 +232,22 @@ class _ChangePassScreenState extends BaseState<ChangePassScreen> with BasicState ...@@ -204,4 +232,22 @@ class _ChangePassScreenState extends BaseState<ChangePassScreen> with BasicState
); );
}); });
} }
void _safeBackToLogin() {
bool found = false;
Navigator.popUntil(Get.context!, (route) {
final matched = route.settings.name == loginScreen;
if (matched) found = true;
return matched;
});
final phone = DataPreference.instance.phone;
if (phone != null) {
if (!found) {
Get.offAllNamed(loginScreen, arguments: phone);
}
} else {
DataPreference.instance.clearData();
Get.offAllNamed(onboardingScreen);
}
}
} }
...@@ -39,10 +39,10 @@ class ChangePassViewModel extends RestfulApiViewModel { ...@@ -39,10 +39,10 @@ class ChangePassViewModel extends RestfulApiViewModel {
}); });
} }
void accountCheckForPasswordChange() { Future<void> accountCheckForPasswordChange() async {
showLoading(); showLoading();
final phone = DataPreference.instance.phone ?? ""; final phone = await DataPreference.instance.phone ?? "";
client.accountPasswordChange(phone, password.value).then((value) { client.accountLoginForPasswordChange(phone, password.value).then((value) {
hideLoading(); hideLoading();
if (value.isSuccess) { if (value.isSuccess) {
Get.to(CreatePasswordScreen(repository: ChangePasswordRepository(phone))); Get.to(CreatePasswordScreen(repository: ChangePasswordRepository(phone)));
......
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:mypoint_flutter_app/networking/restful_api_request.dart'; import 'package:mypoint_flutter_app/networking/restful_api_request.dart';
import 'package:mypoint_flutter_app/screen/create_pass/signup_create_password_repository.dart'; import 'package:mypoint_flutter_app/screen/create_pass/signup_create_password_repository.dart';
import 'package:mypoint_flutter_app/widgets/custom_toast_message.dart';
import '../../base/base_response_model.dart'; import '../../base/base_response_model.dart';
import '../../base/restful_api_viewmodel.dart'; import '../../base/restful_api_viewmodel.dart';
import '../login/login_screen.dart'; import '../login/login_screen.dart';
import '../main_tab_screen/main_tab_screen.dart';
import '../splash/splash_screen_viewmodel.dart'; import '../splash/splash_screen_viewmodel.dart';
class ChangePasswordRepository extends RestfulApiViewModel implements ICreatePasswordRepository { class ChangePasswordRepository extends RestfulApiViewModel implements ICreatePasswordRepository {
...@@ -18,7 +20,8 @@ class ChangePasswordRepository extends RestfulApiViewModel implements ICreatePas ...@@ -18,7 +20,8 @@ class ChangePasswordRepository extends RestfulApiViewModel implements ICreatePas
return client.accountPasswordChange(phoneNumber, password).then((value) { return client.accountPasswordChange(phoneNumber, password).then((value) {
hideLoading(); hideLoading();
if (value.status == "success" || value.code == 200) { if (value.status == "success" || value.code == 200) {
print("Change password success"); showToastMessage("Đổi mật khẩu thành công.");
Get.off(() => MainTabScreen());
} }
return value; return value;
}); });
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment