Commit 55151ba2 authored by DatHV's avatar DatHV
Browse files

update history point, manager

parent f714cdcc
abstract class BaseModel {
BaseModel.fromJson(Map<String, dynamic> json);
BaseModel();
}
\ No newline at end of file
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../dio_http_service/dio_http_service.dart';
import '../networking/dio_http_service.dart';
import '../resources/base_color.dart';
import '../widgets/alert/custom_alert_dialog.dart';
import '../widgets/alert/data_alert_model.dart';
......@@ -112,9 +112,12 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen> {
}
hideLoading() {
if (isShowLoading) {
isShowLoading = false;
Get.back();
}
if (!isShowLoading) return;
isShowLoading = false;
try {
if (Get.isDialogOpen == true) {
Get.back();
}
} catch (_) {}
}
}
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get/get.dart';
import '../dio_http_service/dio_http_service.dart';
import '../networking/dio_http_service.dart';
class BaseViewModel extends GetxController with WidgetsBindingObserver {
var isShowLoading = false;
......@@ -61,10 +61,13 @@ class BaseViewModel extends GetxController with WidgetsBindingObserver {
}
hideLoading() {
if (isShowLoading) {
isShowLoading = false;
Get.back();
}
if (!isShowLoading) return;
isShowLoading = false;
try {
if (Get.isDialogOpen == true) {
Get.back();
}
} catch (_) {}
}
showMessage(BuildContext context, String message) {
......
......@@ -33,10 +33,6 @@ mixin BasicState<Screen extends BaseScreen> on BaseState<Screen> {
}
if (!isScaffold) {
return PopScope(
// onWillPop: () {
// callBackView();
// return willPopToPreviousScreen();
// },
child: createBody());
}
return WillPopScope(
......
class APIPaths {
class APIPaths {//sandbox
static const String baseUrl = "https://api.mypoint.com.vn/8854/gup2start/rest";
static const String checkUpdate = "/version-management-service/api/v1.0/check-customer-software-update";
static const String getOnboardingInfo = "/resource/api/v2.0/intro-screen";
......@@ -104,5 +104,9 @@ class APIPaths {
static const String getMyProductGetExpiredList = "/myProductGetExpiredList/2.0.0";
static const String getMyProductGetUsedList = "/myProductGetUsedList/2.0.0";
static const String getMyProductGetWaitingList = "/myProductGetWaitingList/2.0.0";
static const String orderPaymentMyAccounts = "order/api/v1.0/payment/my-accounts";
static const String orderPaymentMyAccounts = "/order/api/v1.0/payment/my-accounts";
static const String bankAccountSetDefault = "/order/api/v1.0/payment/bank-accounts/%@/set-default";
static const String bankAccountDelete = "/order/api/v1.0/payment/bank-accounts/%@/delete";
static const String transactionHistoryGetList = "/transactionHistoryGetList/1.0.0";
static const String transactionGetSummaryByDate = "/transactionGetSummaryByDate/1.0.0";
}
\ No newline at end of file
typedef CallbackActionBool = Callback<bool>;
typedef CallbackActionString = Callback<String>;
typedef Callback<T> = CallbackReturn<void, T>;
typedef CallbackReturn<R, I> = R Function(I data);
\ No newline at end of file
typedef CallbackReturn<R, I> = R Function(I data);
typedef Json = Map<String, dynamic>;
extension JsonEncode on Json {
Json toJson() {
return this;
}
}
\ No newline at end of file
......@@ -17,4 +17,8 @@ class ErrorCodes {
static const String bioTokenInvalid = "ERR_INVALID_BIO_TOKEN";
static const String authTokenInvalid = "ERR_AUTH_TOKEN_INVALID";
static const String authTokenEmpty = "ERR_AUTH_TOKEN_EMPTY";
static const String commonError = "Hệ thống không thể xử lý yêu cầu hiện tại. Vui lòng thử lại sau hoặc liên hệ hotline 1900599863 để được trợ giúp.";
static const String networkError = 'Kết nối mạng không ổn định. Vui lòng thử lại!';
static const String serverErrorMessage = 'Hệ thống không thể xử lý yêu cầu hiện tại. Vui lòng thử lại sau!';
static const String tokenInvalidMessage = 'Phiên đăng nhập đã hết hạn. Vui lòng đăng nhập lại.';
}
\ No newline at end of file
class EvnConfig {
// static final EvnConfig _instance = EvnConfig._internal();
}
\ No newline at end of file
import 'package:dio/dio.dart';
import 'dio_http_service.dart';
mixin ApiHelper {
final DioHttpService _api = DioHttpService();
initNetWork(String baseUrl) {
_api.init();
_api.setBaseUrl(baseUrl);
}
Dio getDio() {
return _api.getDio();
}
String getBaseUrl() {
return _api.getDio().options.baseUrl;
}
}
\ No newline at end of file
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'exception_interceptor.dart';
import 'logger_interceptor.dart';
import 'modify_request_interceptor.dart';
const int connectTimeout = 10; // seconds
const int receiveTimeout = 15; // second
class DioHttpService {
static final DioHttpService _instance = DioHttpService._internal();
late Dio _dio;
String domain = '';
factory DioHttpService() {
return _instance;
}
void init() async {
final Map<String, String> defaultHeaders = {'Accept': '*/*', 'Content-type': 'application/json'};
// Set default configs
_dio.options.connectTimeout = const Duration(seconds: connectTimeout); //10s
_dio.options.receiveTimeout = const Duration(seconds: receiveTimeout);
_dio.options.headers = defaultHeaders;
_dio.interceptors.add(ModifyRequestInterceptor());
if(kDebugMode) {
_dio.interceptors.add(LoggerInterceptor());
}
_dio.interceptors.add(ExceptionInterceptor());
}
void setBaseUrl(String newUrl) {
_dio.options.baseUrl = newUrl;
}
DioHttpService._internal() {
// Initialize Dio instance with default configurations
_dio = Dio(BaseOptions(
baseUrl: domain,
connectTimeout: Duration(seconds: connectTimeout),
receiveTimeout: Duration(seconds: receiveTimeout),
));
}
Dio getDio() {
return _dio;
}
}
\ No newline at end of file
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:mypoint_flutter_app/shared/navigate_helper.dart';
class ExceptionInterceptor extends Interceptor with navigateHelper {
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
switch (err.type) {
case DioExceptionType.connectionTimeout:
case DioExceptionType.receiveTimeout:
case DioExceptionType.connectionError:
showPopupErrorMessage("Kết nối mạng không ổn định.\nVui lòng thử lại!");
break;
default:
return super.onError(err, handler);
}
}
_handleStatusCode(int? statusCode) {
switch (statusCode) {
case 400:
//FIXME
print('Bad request.');
break;
case 401:
//FIXME
break;
case 500:
showPopupErrorMessage("Lỗi không xác định");
break;
default:
if (kDebugMode) {
print('Something went wrong');
}
break;
}
}
}
import 'package:dio/dio.dart';
import 'package:logger/logger.dart';
class LoggerInterceptor extends Interceptor {
Logger logger = Logger(
// Customize the printer
printer: PrettyPrinter(
methodCount: 0,
lineLength: 5000,
printTime: false,
),
);
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
final options = err.requestOptions;
final requestPath = '${options.baseUrl}${options.path}';
logger.e('${options.method} request => $requestPath\nError: ${err.error}, Message: ${err.message}');
return super.onError(err, handler);
}
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
final requestBody = options.data;
final requestPath = '${options.baseUrl}${options.path}';
final requestQuery = '${options.queryParameters}';
final header = options.headers;
logger.i('${options.method} request => $requestPath\nheader ===> $header\nquery ===> $requestQuery\nbody ==> $requestBody'); // Info log
return super.onRequest(options, handler);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
final options = response.requestOptions;
final requestPath = '${options.baseUrl}${options.path}';
logger.d('HTTPCode: ${response.statusCode}, URL: ${requestPath}\nData: ===> \n${response.data}'); // Debug log
return super.onResponse(response, handler);
}
}
\ No newline at end of file
......@@ -162,6 +162,9 @@ class DirectionalScreen {
case DirectionalScreenName.bankAccountManager:
Get.toNamed(bankAccountManagerScreen);
return true;
case DirectionalScreenName.pointHistory:
Get.toNamed(historyPointScreen);
return true;
default:
print("Không nhận diện được action type: $clickActionType");
return false;
......
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../configs/callbacks.dart';
import '../resources/base_color.dart';
import '../resources/text_style.dart';
import '../widgets/button_container.dart';
extension BuildContextAndAlert on BuildContext {
showAlertDialog(String message, {Callback<bool>? callback}) {
_showConfirmAlertDialogTwoButton(message, callback: callback);
}
showConfirmAlertDialog(String message,
{String cancel = "Huỷ",
String confirm = "Xác nhận",
Callback<bool>? callback}) {
_showConfirmAlertDialogTwoButton(message, cancel: cancel, confirm: confirm, callback: callback);
}
_showConfirmAlertDialogTwoButton(String message,
{String cancel = "",
String confirm = "Xác nhận",
Callback<bool>? callback}) {
showDialog<void>(
context: this,
builder: (BuildContext context) {
return AlertDialog(
backgroundColor: Colors.white,
title: Text('Thông báo',
textAlign: TextAlign.center,
style: textSemiBold.copyWith(fontSize: 16)),
content: SingleChildScrollView(
child: ListBody(children: [
Text(message),
])),
actionsAlignment: MainAxisAlignment.center,
actionsPadding: EdgeInsets.symmetric(horizontal: 20).copyWith(bottom: 20),
actions: [
ButtonContainer(
height: 40,
color: BaseColor.primary500,
visible: cancel.isNotEmpty,
child: TextButton(
child: Text(cancel,
style: textSemiBold.copyWith(
fontSize: 14, color: Colors.white)),
onPressed: () {
Get.back();
if (callback != null) {
callback(false);
}
})),
ButtonContainer(
height: 40,
color: BaseColor.primary500,
visible: confirm.isNotEmpty,
child: TextButton(
child: Text(confirm,
style: textSemiBold.copyWith(
fontSize: 14, color: Colors.white)),
onPressed: () {
Get.back();
if (callback != null) {
callback(true);
}
}))
]);
},
);
}
}
\ No newline at end of file
......@@ -3,4 +3,5 @@ class DateFormat {
static const String server = "yyyy-MM-dd HH:mm:ss";
static const String ddMMyyyy = "dd/MM/yyyy";
static const String ddMMyyyyhhmm = "dd/MM/yyyy hh:mm";
static const String viFull = "d 'tháng' M',' y HH:mm";
}
......@@ -9,6 +9,13 @@ extension PhoneValidator on String {
}
}
extension NullableString on String? {
String orIfBlank(String fallback) {
final s = this?.trim();
return (s == null || s.isEmpty) ? fallback : s;
}
}
extension StringUrlExtension on String {
String get urlDecoded => Uri.decodeFull(this);
}
......@@ -91,6 +98,20 @@ extension ParseInt on String {
return 0;
}
}
int? toInt() {
final s = trim();
if (s.isEmpty) return null;
final normalized = s.replaceAll(RegExp(r'[,\s_]'), '');
final asInt = int.tryParse(normalized);
if (asInt != null) return asInt;
final asDouble = double.tryParse(normalized);
if (asDouble != null && asDouble == asDouble.truncateToDouble()) {
return asDouble.toInt();
}
return null;
}
}
bool isHttpUrl(String? url) {
......
......@@ -2,16 +2,19 @@ import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/networking/app_navigator.dart';
import 'package:mypoint_flutter_app/configs/api_paths.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/resources/base_color.dart';
import 'package:mypoint_flutter_app/screen/home/header_home_viewmodel.dart';
import 'package:mypoint_flutter_app/shared/router_gage.dart';
import 'networking/dio_http_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
Get.put(HeaderThemeController(), permanent: true);
await DataPreference.instance.init();
DioHttpService().setBaseUrl(APIPaths.baseUrl);
await UserPointManager().fetchUserPoint();
runApp(const MyApp());
}
......
import '../base/base_model.dart';
class User extends BaseModel {
final int id;
final String username;
final String? name;
final String? email;
final String? phone;
User({required this.id, required this.username, this.name, this.email, this.phone,});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
username: json['username'],
name: json['name'],
email: json['email'],
phone: json['phone'],
);
}
}
\ No newline at end of file
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../configs/constants.dart';
import '../preference/data_preference.dart';
import '../resources/base_color.dart';
import '../shared/router_gage.dart';
......@@ -38,4 +39,25 @@ class AppNavigator {
);
Get.dialog(CustomAlertDialog(alertData: dataAlert, showCloseButton: false), barrierDismissible: false);
}
static Future<void> showAlert(String message) async {
if (_authDialogShown || _ctx == null) return;
_authDialogShown = true;
final dataAlert = DataAlertModel(
title: "Thông Báo",
description: message.isNotEmpty ? message : ErrorCodes.serverErrorMessage,
localHeaderImage: "assets/images/ic_pipi_03.png",
buttons: [
AlertButton(
text: "Đã hiểu",
onPressed: () {
_authDialogShown = false;
},
bgColor: BaseColor.primary500,
textColor: Colors.white,
),
],
);
Get.dialog(CustomAlertDialog(alertData: dataAlert, showCloseButton: false), barrierDismissible: false);
}
}
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