Commit 417358c5 authored by DatHV's avatar DatHV
Browse files

update authen 401, device manager, interestied category

parent efb4662c
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:mypoint_flutter_app/extensions/context_extensions.dart';
import '../configs/callbacks.dart';
import '../dio_http_service/dio_http_service.dart'; import '../dio_http_service/dio_http_service.dart';
import '../resouce/base_color.dart'; import '../resources/base_color.dart';
import '../resouce/define_image.dart';
import '../resouce/text_style.dart';
import '../widgets/alert/custom_alert_dialog.dart'; import '../widgets/alert/custom_alert_dialog.dart';
import '../widgets/alert/data_alert_model.dart'; import '../widgets/alert/data_alert_model.dart';
import '../widgets/alert/popup_data_model.dart'; import '../widgets/alert/popup_data_model.dart';
......
...@@ -93,4 +93,12 @@ class APIPaths { ...@@ -93,4 +93,12 @@ class APIPaths {
static const String submitCampaignMission = "/campaign/api/v3.0/%@/mission/%@/submit"; static const String submitCampaignMission = "/campaign/api/v3.0/%@/mission/%@/submit";
static const String getQuizCampaign = "/quiz/api/v1.0/quiz/%@/"; static const String getQuizCampaign = "/quiz/api/v1.0/quiz/%@/";
static const String quizSubmitCampaign = "/quiz/api/v1.0/quiz/%@/submit/"; static const String quizSubmitCampaign = "/quiz/api/v1.0/quiz/%@/submit/";
static const String getCurrentDevice = "/user/api/v2.0/devices/current";
static const String getLogoutDevices = "/user/api/v2.0/devices/logout";
static const String deleteDevice = "/user/api/v2.0/devices/%@/delete";
static const String categoryTopLevelGetList = "/categoryTopLevelGetList/1.0.0";
static const String categorySubscribeList = "/categorySubscribeList/1.0.0";
static const String categoryUnsubscribeList = "/categoryUnsubscribeList/1.0.0";
static const String customerEvnPaymentGatewayRequest = "/customerEvnPaymentGatewayRequest/1.0.0";
static const String getPopup = "/getPopup/1.0.0";
} }
\ No newline at end of file
...@@ -6,9 +6,14 @@ class Constants { ...@@ -6,9 +6,14 @@ class Constants {
} }
class ErrorCodes { class ErrorCodes {
static const List<String> tokenInvalidCodes = [
authTokenInvalid, authTokenEmpty
];
static const String deviceLock = "ERR_DEVICE_LOCK"; static const String deviceLock = "ERR_DEVICE_LOCK";
static const String deviceUndefined = "ERR_DEVICE_UNDEFINED"; static const String deviceUndefined = "ERR_DEVICE_UNDEFINED";
static const String requiredChangePass = "ERR_ACCOUNT_LOGIN_PASSWORD_CHANGE_WEAK"; static const String requiredChangePass = "ERR_ACCOUNT_LOGIN_PASSWORD_CHANGE_WEAK";
static const String invalidAccount = "ERR_INVALID_ACCOUNT"; static const String invalidAccount = "ERR_INVALID_ACCOUNT";
static const String bioTokenInvalid = "ERR_INVALID_BIO_TOKEN"; static const String bioTokenInvalid = "ERR_INVALID_BIO_TOKEN";
static const String authTokenInvalid = "ERR_AUTH_TOKEN_INVALID";
static const String authTokenEmpty = "ERR_AUTH_TOKEN_EMPTY";
} }
\ No newline at end of file
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:get/get_core/src/get_main.dart';
import 'package:mypoint_flutter_app/resouce/base_color.dart';
import '../configs/callbacks.dart'; import '../configs/callbacks.dart';
import '../resouce/text_style.dart'; import '../resources/base_color.dart';
import '../resources/text_style.dart';
import '../widgets/button_container.dart'; import '../widgets/button_container.dart';
extension BuildContextAndAlert on BuildContext { extension BuildContextAndAlert on BuildContext {
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:mypoint_flutter_app/networking/app_navigator.dart';
import 'package:mypoint_flutter_app/preference/data_preference.dart'; import 'package:mypoint_flutter_app/preference/data_preference.dart';
import 'package:mypoint_flutter_app/preference/point/point_manager.dart'; import 'package:mypoint_flutter_app/preference/point/point_manager.dart';
import 'package:mypoint_flutter_app/resouce/base_color.dart'; import 'package:mypoint_flutter_app/resources/base_color.dart';
import 'package:mypoint_flutter_app/shared/router_gage.dart'; import 'package:mypoint_flutter_app/shared/router_gage.dart';
void main() async { void main() async {
...@@ -19,6 +20,7 @@ class MyApp extends StatelessWidget { ...@@ -19,6 +20,7 @@ class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GetMaterialApp( return GetMaterialApp(
navigatorKey: AppNavigator.key,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
initialRoute: '/splash', initialRoute: '/splash',
theme: ThemeData( theme: ThemeData(
......
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:mypoint_flutter_app/configs/api_paths.dart';
import 'package:mypoint_flutter_app/model/check_update_response_model.dart';
import 'package:mypoint_flutter_app/networking/request_manager.dart';
class ApiService {
final RequestManager _requestManager = RequestManager();
Future<CheckUpdateResponseModel?> checkUpdateWithRequestManager() async {
String version = Platform.version;
try {
Map<String, String> params = {
"operating_system": "iOS",
"software_model": "MyPoint",
"version": version,
"build_number": "1",
};
final response = await _requestManager.request(method: 'POST', path: APIPaths.checkUpdate);
return CheckUpdateResponseModel.fromJson(response.data);
} catch (e) {
throw Exception('Failed to check update');
}
}
}
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../preference/data_preference.dart';
import '../resources/base_color.dart';
import '../shared/router_gage.dart';
import '../widgets/alert/custom_alert_dialog.dart';
import '../widgets/alert/data_alert_model.dart';
class AppNavigator {
static final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
static bool _authDialogShown = false;
static BuildContext? get _ctx => key.currentContext;
static Future<void> showAuthAlertAndGoLogin(String message) async {
if (_authDialogShown || _ctx == null) return;
_authDialogShown = true;
final dataAlert = DataAlertModel(
title: "Thông Báo",
description: message.isNotEmpty ? message : 'Phiên đăng nhập đã hết hạn. Vui lòng đăng nhập lại.',
localHeaderImage: "assets/images/ic_pipi_03.png",
buttons: [
AlertButton(
text: "Đã hiểu",
onPressed: () {
final phone = DataPreference.instance.phoneNumberUsedForLoginScreen;
if (phone.isNotEmpty) {
Get.offAllNamed(loginScreen, arguments: {'phone': phone});
} else {
DataPreference.instance.clearData();
Get.offAllNamed(onboardingScreen);
}
_authDialogShown = false;
},
bgColor: BaseColor.primary500,
textColor: Colors.white,
),
],
);
Get.dialog(CustomAlertDialog(alertData: dataAlert, showCloseButton: false), barrierDismissible: false);
}
}
import 'package:dio/dio.dart';
import '../configs/constants.dart';
import 'app_navigator.dart';
import 'package:mypoint_flutter_app/preference/data_preference.dart';
class AuthInterceptor extends Interceptor {
bool _handling = false; // chặn bắn 2 lần nếu nhiều request fail cùng lúc
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
final data = response.data;
if (_isInvalidTokenPayload(data)) {
_handleInvalidToken(data);
// chặn parse tiếp: reject error để upstream biết đã fail
return handler.reject(
DioException(
requestOptions: response.requestOptions,
response: response,
type: DioExceptionType.badResponse,
error: 'ERR_AUTH_TOKEN_INVALID',
),
);
}
super.onResponse(response, handler);
}
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
final data = err.response?.data;
final status = err.response?.statusCode;
if (status == 401 || _isInvalidTokenPayload(data)) {
_handleInvalidToken(data);
// vẫn reject để caller biết yêu cầu đã fail
return handler.reject(err);
}
super.onError(err, handler);
}
bool _isInvalidTokenPayload(dynamic data) {
if (data is Map<String, dynamic>) {
final code = data['error_code'] ?? data['errorCode'];
return ErrorCodes.tokenInvalidCodes.contains(code);
}
return false;
}
void _handleInvalidToken(dynamic data) async {
if (_handling) return;
_handling = true;
// Xoá token / session
await DataPreference.instance.clearData();
final message = (data is Map && data['error_message'] is String)
? data['error_message'] as String
: '';
// Hiện alert + điều hướng login
await AppNavigator.showAuthAlertAndGoLogin(message);
_handling = false;
}
}
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:mypoint_flutter_app/base/base_response_model.dart'; import 'package:mypoint_flutter_app/base/base_response_model.dart';
import 'package:mypoint_flutter_app/networking/auth_interceptor.dart';
import 'package:mypoint_flutter_app/preference/data_preference.dart'; import 'package:mypoint_flutter_app/preference/data_preference.dart';
import '../configs/callbacks.dart'; import '../configs/callbacks.dart';
import '../configs/constants.dart'; import '../configs/constants.dart';
...@@ -12,7 +13,9 @@ enum Method { ...@@ -12,7 +13,9 @@ enum Method {
class RestfulAPIClient { class RestfulAPIClient {
final Dio _dio; final Dio _dio;
RestfulAPIClient(this._dio); RestfulAPIClient(this._dio) {
_dio.interceptors.add(AuthInterceptor());
}
Json header = {}; Json header = {};
Future<BaseResponseModel<T>> fetchObject<T>( Future<BaseResponseModel<T>> fetchObject<T>(
...@@ -59,6 +62,10 @@ class RestfulAPIClient { ...@@ -59,6 +62,10 @@ class RestfulAPIClient {
final result = await _dio.fetch<Map<String, dynamic>>(option); final result = await _dio.fetch<Map<String, dynamic>>(option);
final json = result.data; final json = result.data;
if (json == null) return null; if (json == null) return null;
final code = json['error_code'] ?? json['errorCode'];
if (ErrorCodes.tokenInvalidCodes.contains(code)) {
return null;
}
return parser(json); return parser(json);
} on DioException catch(e) { } on DioException catch(e) {
_print(e.toString()); _print(e.toString());
......
...@@ -23,7 +23,9 @@ import '../screen/campaign7day/models/campaign_7day_mission_model.dart'; ...@@ -23,7 +23,9 @@ import '../screen/campaign7day/models/campaign_7day_mission_model.dart';
import '../screen/campaign7day/models/campaign_7day_reward_model.dart'; import '../screen/campaign7day/models/campaign_7day_reward_model.dart';
import '../screen/daily_checkin/daily_checkin_models.dart'; import '../screen/daily_checkin/daily_checkin_models.dart';
import '../screen/data_network_service/product_network_data_model.dart'; import '../screen/data_network_service/product_network_data_model.dart';
import '../screen/electric_payment/customer_contract_object_model.dart'; import '../screen/device_manager/device_manager_model.dart';
import '../screen/electric_payment/models/customer_contract_object_model.dart';
import '../screen/electric_payment/models/electric_payment_response_model.dart';
import '../screen/faqs/faqs_model.dart'; import '../screen/faqs/faqs_model.dart';
import '../screen/game/models/game_bundle_item_model.dart'; import '../screen/game/models/game_bundle_item_model.dart';
import '../screen/history_point_cashback/models/history_point_cashback_model.dart'; import '../screen/history_point_cashback/models/history_point_cashback_model.dart';
...@@ -33,6 +35,7 @@ import '../screen/home/models/main_section_config_model.dart'; ...@@ -33,6 +35,7 @@ import '../screen/home/models/main_section_config_model.dart';
import '../screen/home/models/my_product_model.dart'; import '../screen/home/models/my_product_model.dart';
import '../screen/home/models/notification_unread_model.dart'; import '../screen/home/models/notification_unread_model.dart';
import '../screen/home/models/pipi_detail_model.dart'; import '../screen/home/models/pipi_detail_model.dart';
import '../screen/interested_categories/models/interested_categories_model.dart';
import '../screen/invite_friend_campaign/models/invite_friend_campaign_model.dart'; import '../screen/invite_friend_campaign/models/invite_friend_campaign_model.dart';
import '../screen/location_address/models/district_address_model.dart'; import '../screen/location_address/models/district_address_model.dart';
import '../screen/location_address/models/province_address_model.dart'; import '../screen/location_address/models/province_address_model.dart';
...@@ -49,6 +52,7 @@ import '../screen/otp/model/create_otp_response_model.dart'; ...@@ -49,6 +52,7 @@ import '../screen/otp/model/create_otp_response_model.dart';
import '../screen/otp/model/otp_verify_response_model.dart'; import '../screen/otp/model/otp_verify_response_model.dart';
import '../screen/pageDetail/model/campaign_detail_model.dart'; import '../screen/pageDetail/model/campaign_detail_model.dart';
import '../screen/pageDetail/model/detail_page_rule_type.dart'; import '../screen/pageDetail/model/detail_page_rule_type.dart';
import '../screen/popup_manager/popup_manager_model.dart';
import '../screen/quiz_campaign/quiz_campaign_model.dart'; import '../screen/quiz_campaign/quiz_campaign_model.dart';
import '../screen/register_campaign/model/registration_form_package_model.dart'; import '../screen/register_campaign/model/registration_form_package_model.dart';
import '../screen/splash/splash_screen_viewmodel.dart'; import '../screen/splash/splash_screen_viewmodel.dart';
...@@ -491,7 +495,12 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -491,7 +495,12 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
}) async { }) async {
final items = final items =
products.map((product) { products.map((product) {
return {'product_id': product.id, 'product_type': product.type ?? '', 'quantity': quantity, 'target_phone_number': targetPhoneNumber ?? ''}; return {
'product_id': product.id,
'product_type': product.type ?? '',
'quantity': quantity,
'target_phone_number': targetPhoneNumber ?? '',
};
}).toList(); }).toList();
final Map<String, dynamic> params = {'request_id': requestId, 'items': items, 'flow': '21'}; final Map<String, dynamic> params = {'request_id': requestId, 'items': items, 'flow': '21'};
// flash_sale // flash_sale
...@@ -666,12 +675,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -666,12 +675,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<EmptyCodable>> redeemProductTopUps(String productId, String phoneNumber) async { Future<BaseResponseModel<EmptyCodable>> redeemProductTopUps(String productId, String phoneNumber) async {
String? token = DataPreference.instance.token ?? ""; String? token = DataPreference.instance.token ?? "";
final body = { final body = {"access_token": token, "product_id": productId, "quantity": 1, "phone_number": phoneNumber};
"access_token": token,
"product_id": productId,
"quantity": 1,
"phone_number": phoneNumber,
};
return requestNormal(APIPaths.redeemProductTopUps, Method.POST, body, (data) { return requestNormal(APIPaths.redeemProductTopUps, Method.POST, body, (data) {
return EmptyCodable.fromJson(data as Json); return EmptyCodable.fromJson(data as Json);
}); });
...@@ -687,10 +691,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -687,10 +691,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<AffiliateBrandDetailModel>> getAffiliateBrandDetail(String brandId) async { Future<BaseResponseModel<AffiliateBrandDetailModel>> getAffiliateBrandDetail(String brandId) async {
String? token = DataPreference.instance.token ?? ""; String? token = DataPreference.instance.token ?? "";
final body = { final body = {"access_token": token, "brand_id": brandId};
"access_token": token,
"brand_id": brandId,
};
return requestNormal(APIPaths.affiliateBrandGetDetail, Method.POST, body, (data) { return requestNormal(APIPaths.affiliateBrandGetDetail, Method.POST, body, (data) {
return AffiliateBrandDetailModel.fromJson(data as Json); return AffiliateBrandDetailModel.fromJson(data as Json);
}); });
...@@ -698,9 +699,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -698,9 +699,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<InviteFriendDetailModel>> getCampaignInviteFriend() async { Future<BaseResponseModel<InviteFriendDetailModel>> getCampaignInviteFriend() async {
String? token = DataPreference.instance.token ?? ""; String? token = DataPreference.instance.token ?? "";
final body = { final body = {"access_token": token};
"access_token": token,
};
return requestNormal(APIPaths.campaignInviteFriend, Method.GET, body, (data) { return requestNormal(APIPaths.campaignInviteFriend, Method.GET, body, (data) {
return InviteFriendDetailModel.fromJson(data as Json); return InviteFriendDetailModel.fromJson(data as Json);
}); });
...@@ -708,9 +707,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -708,9 +707,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<CampaignInviteFriendDetail>> getDetailCampaignInviteFriend() async { Future<BaseResponseModel<CampaignInviteFriendDetail>> getDetailCampaignInviteFriend() async {
String? token = DataPreference.instance.token ?? ""; String? token = DataPreference.instance.token ?? "";
final body = { final body = {"access_token": token};
"access_token": token,
};
return requestNormal(APIPaths.inviteFriendCampaigns, Method.GET, body, (data) { return requestNormal(APIPaths.inviteFriendCampaigns, Method.GET, body, (data) {
return CampaignInviteFriendDetail.fromJson(data as Json); return CampaignInviteFriendDetail.fromJson(data as Json);
}); });
...@@ -718,10 +715,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -718,10 +715,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<InviteFriendResponse>> phoneInviteFriend(String phone) async { Future<BaseResponseModel<InviteFriendResponse>> phoneInviteFriend(String phone) async {
String? token = DataPreference.instance.token ?? ""; String? token = DataPreference.instance.token ?? "";
final body = { final body = {"access_token": token, 'username': phone};
"access_token": token,
'username': phone,
};
return requestNormal(APIPaths.phoneInviteFriend, Method.POST, body, (data) { return requestNormal(APIPaths.phoneInviteFriend, Method.POST, body, (data) {
return InviteFriendResponse.fromJson(data as Json); return InviteFriendResponse.fromJson(data as Json);
}); });
...@@ -729,10 +723,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -729,10 +723,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<CheckInDataModel>> rewardOpportunityGetList() async { Future<BaseResponseModel<CheckInDataModel>> rewardOpportunityGetList() async {
String? token = DataPreference.instance.token ?? ""; String? token = DataPreference.instance.token ?? "";
final body = { final body = {"access_token": token, 'number_day': '7'};
"access_token": token,
'number_day': '7',
};
return requestNormal(APIPaths.rewardOpportunityGetList, Method.POST, body, (data) { return requestNormal(APIPaths.rewardOpportunityGetList, Method.POST, body, (data) {
return CheckInDataModel.fromJson(data as Json); return CheckInDataModel.fromJson(data as Json);
}); });
...@@ -740,9 +731,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -740,9 +731,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<SubmitCheckInData>> submitCheckIn() async { Future<BaseResponseModel<SubmitCheckInData>> submitCheckIn() async {
String? token = DataPreference.instance.token ?? ""; String? token = DataPreference.instance.token ?? "";
final body = { final body = {"access_token": token};
"access_token": token,
};
return requestNormal(APIPaths.rewardOpportunityOpenRequest, Method.POST, body, (data) { return requestNormal(APIPaths.rewardOpportunityOpenRequest, Method.POST, body, (data) {
return SubmitCheckInData.fromJson(data as Json); return SubmitCheckInData.fromJson(data as Json);
}); });
...@@ -763,10 +752,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -763,10 +752,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<CustomerContractModel>> customerContractRequestSearch(String maKH) async { Future<BaseResponseModel<CustomerContractModel>> customerContractRequestSearch(String maKH) async {
String? token = DataPreference.instance.token ?? ""; String? token = DataPreference.instance.token ?? "";
final body = { final body = {"access_token": token, 'ma_khang': maKH};
"access_token": token,
'ma_khang': maKH,
};
return requestNormal(APIPaths.customerContractRequestSearch, Method.POST, body, (data) { return requestNormal(APIPaths.customerContractRequestSearch, Method.POST, body, (data) {
return CustomerContractModel.fromJson(data as Json); return CustomerContractModel.fromJson(data as Json);
}); });
...@@ -774,9 +760,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -774,9 +760,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<List<CustomerContractModel>>> customerContractSearchHistoryGetList() async { Future<BaseResponseModel<List<CustomerContractModel>>> customerContractSearchHistoryGetList() async {
String? token = DataPreference.instance.token ?? ""; String? token = DataPreference.instance.token ?? "";
final body = { final body = {"access_token": token};
"access_token": token,
};
return requestNormal(APIPaths.customerContractSearchHistoryGetList, Method.POST, body, (data) { return requestNormal(APIPaths.customerContractSearchHistoryGetList, Method.POST, body, (data) {
final list = data as List<dynamic>; final list = data as List<dynamic>;
return list.map((e) => CustomerContractModel.fromJson(e)).toList(); return list.map((e) => CustomerContractModel.fromJson(e)).toList();
...@@ -785,10 +769,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -785,10 +769,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<bool>> customerContractDelete(String maKHs) async { Future<BaseResponseModel<bool>> customerContractDelete(String maKHs) async {
String? token = DataPreference.instance.token ?? ""; String? token = DataPreference.instance.token ?? "";
final body = { final body = {"access_token": token, 'ma_khang': maKHs};
"access_token": token,
'ma_khang': maKHs,
};
return requestNormal(APIPaths.customerContractDelete, Method.POST, body, (data) { return requestNormal(APIPaths.customerContractDelete, Method.POST, body, (data) {
return data == true; return data == true;
}); });
...@@ -808,9 +789,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -808,9 +789,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
} }
Future<BaseResponseModel<EmptyCodable>> submitPerformMission(Campaign7DayMissionModel mission, String id) async { Future<BaseResponseModel<EmptyCodable>> submitPerformMission(Campaign7DayMissionModel mission, String id) async {
final path = APIPaths.submitCampaignMission final path = APIPaths.submitCampaignMission.replaceFirst('%@', id).replaceFirst('%@', mission.id.toString());
.replaceFirst('%@', id)
.replaceFirst('%@', mission.id.toString());
return requestNormal(path, Method.POST, {}, (data) { return requestNormal(path, Method.POST, {}, (data) {
return EmptyCodable.fromJson(data as Json); return EmptyCodable.fromJson(data as Json);
...@@ -855,4 +834,69 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -855,4 +834,69 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
return QuizCampaignSubmitResponseModel.fromJson(data as Json); return QuizCampaignSubmitResponseModel.fromJson(data as Json);
}); });
} }
}
\ No newline at end of file Future<BaseResponseModel<DeviceItemModel>> getCurrentDevice() async {
return requestNormal(APIPaths.getCurrentDevice, Method.GET, {}, (data) {
return DeviceItemModel.fromJson(data as Json);
});
}
Future<BaseResponseModel<DevicesLogoutListResponse>> getLogoutDevices(Json body) async {
return requestNormal(APIPaths.getLogoutDevices, Method.GET, body, (data) {
return DevicesLogoutListResponse.fromJson(data as Json);
});
}
Future<BaseResponseModel<String>> deleteDevice(String deviceKey) async {
final path = APIPaths.deleteDevice.replaceFirst('%@', deviceKey);
return requestNormal(path, Method.DELETE, {}, (data) => data as String);
}
Future<BaseResponseModel<InterestedCategoriesResponse>> categoryTopLevelGetList() async {
String? token = DataPreference.instance.token ?? "";
final body = {"access_token": token, "lang": "vi"};
return requestNormal(APIPaths.categoryTopLevelGetList, Method.POST, body, (data) {
return InterestedCategoriesResponse.fromJson(data as Json);
});
}
Future<BaseResponseModel<EmptyCodable>> submitCategorySubscribe(String code) async {
String? token = DataPreference.instance.token ?? "";
final body = {"access_token": token, 'category_codes': code};
return requestNormal(APIPaths.categorySubscribeList, Method.POST, body, (data) {
return EmptyCodable.fromJson(data as Json);
});
}
Future<BaseResponseModel<EmptyCodable>> submitCategoryUnsubscribeList(String code) async {
String? token = DataPreference.instance.token ?? "";
final body = {"access_token": token, 'category_codes': code};
return requestNormal(APIPaths.categoryUnsubscribeList, Method.POST, body, (data) {
return EmptyCodable.fromJson(data as Json);
});
}
Future<BaseResponseModel<ElectricPaymentResponseModel>> customerEvnPaymentGatewayRequest(
CustomerContractModel contract,
String paymentMethod,
) async {
String? token = DataPreference.instance.token ?? "";
final body = {
"access_token": token,
'ma_khang': contract.maKH ?? '',
'evn_bill_id': contract.idHoaHon ?? '',
'amount': contract.amount ?? 0,
'payment_method': paymentMethod,
};
return requestNormal(APIPaths.customerEvnPaymentGatewayRequest, Method.POST, body, (data) {
return ElectricPaymentResponseModel.fromJson(data as Json);
});
}
Future<BaseResponseModel<List<PopupManagerModel>>> getPopup() async {
return requestNormal(APIPaths.getPopup, Method.POST, {}, (data) {
final list = data as List<dynamic>;
return list.map((e) => PopupManagerModel.fromJson(e)).toList();
});
}
}
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:local_auth/local_auth.dart'; import 'package:local_auth/local_auth.dart';
import '../resources/base_color.dart';
import '../resouce/base_color.dart';
import '../widgets/alert/custom_alert_dialog.dart'; import '../widgets/alert/custom_alert_dialog.dart';
import '../widgets/alert/data_alert_model.dart'; import '../widgets/alert/data_alert_model.dart';
......
...@@ -10,6 +10,7 @@ class DataPreference { ...@@ -10,6 +10,7 @@ class DataPreference {
LoginTokenResponseModel? _loginToken; LoginTokenResponseModel? _loginToken;
ProfileResponseModel? _profile; ProfileResponseModel? _profile;
String phoneNumberUsedForLoginScreen = "";
Future<void> init() async { Future<void> init() async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
...@@ -21,6 +22,7 @@ class DataPreference { ...@@ -21,6 +22,7 @@ class DataPreference {
final profileJson = prefs.getString('user_profile'); final profileJson = prefs.getString('user_profile');
if (profileJson != null) { if (profileJson != null) {
_profile = ProfileResponseModel.fromJson(jsonDecode(profileJson)); _profile = ProfileResponseModel.fromJson(jsonDecode(profileJson));
phoneNumberUsedForLoginScreen = _profile?.workerSite?.phoneNumber ?? "";
} }
} }
String get displayName { String get displayName {
...@@ -44,6 +46,7 @@ class DataPreference { ...@@ -44,6 +46,7 @@ class DataPreference {
Future<void> saveUserProfile(ProfileResponseModel profile) async { Future<void> saveUserProfile(ProfileResponseModel profile) async {
_profile = profile; _profile = profile;
phoneNumberUsedForLoginScreen = _profile?.workerSite?.phoneNumber ?? "";
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
await prefs.setString('user_profile', jsonEncode(profile.toJson())); await prefs.setString('user_profile', jsonEncode(profile.toJson()));
} }
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mypoint_flutter_app/resouce/base_color.dart';
enum TextStyleIconAndText { enum TextStyleIconAndText {
header1, header1,
......
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/resouce/base_color.dart';
import 'package:mypoint_flutter_app/widgets/image_loader.dart'; import 'package:mypoint_flutter_app/widgets/image_loader.dart';
import '../../resources/base_color.dart';
import '../../shared/router_gage.dart'; import '../../shared/router_gage.dart';
import 'model/affiliate_brand_model.dart'; import 'model/affiliate_brand_model.dart';
......
...@@ -5,7 +5,7 @@ import 'package:mypoint_flutter_app/screen/affiliate/sub_widget/build_affiliate_ ...@@ -5,7 +5,7 @@ import 'package:mypoint_flutter_app/screen/affiliate/sub_widget/build_affiliate_
import 'package:mypoint_flutter_app/screen/affiliate/sub_widget/build_affiliate_product_topsale.dart'; import 'package:mypoint_flutter_app/screen/affiliate/sub_widget/build_affiliate_product_topsale.dart';
import '../../base/base_screen.dart'; import '../../base/base_screen.dart';
import '../../base/basic_state.dart'; import '../../base/basic_state.dart';
import '../../resouce/base_color.dart'; import '../../resources/base_color.dart';
import '../../shared/router_gage.dart'; import '../../shared/router_gage.dart';
import '../../widgets/bottom_sheet_helper.dart'; import '../../widgets/bottom_sheet_helper.dart';
import '../../widgets/custom_navigation_bar.dart'; import '../../widgets/custom_navigation_bar.dart';
......
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/extensions/string_extension.dart'; import 'package:mypoint_flutter_app/extensions/string_extension.dart';
import '../../../resouce/base_color.dart'; import '../../../resources/base_color.dart';
import '../../../shared/router_gage.dart'; import '../../../shared/router_gage.dart';
import '../model/affiliate_brand_model.dart'; import '../model/affiliate_brand_model.dart';
......
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