Commit 56e8b038 authored by DatHV's avatar DatHV
Browse files

update game, shopping

parent c285d072
...@@ -10,13 +10,13 @@ import '../resouce/define_image.dart'; ...@@ -10,13 +10,13 @@ import '../resouce/define_image.dart';
import '../resouce/text_style.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';
abstract class BaseScreen extends StatefulWidget { abstract class BaseScreen extends StatefulWidget {
const BaseScreen({super.key}); const BaseScreen({super.key});
} }
abstract class BaseState<Screen extends BaseScreen> extends State<Screen> { abstract class BaseState<Screen extends BaseScreen> extends State<Screen> {
var isShowLoading = false;
@override @override
void initState() { void initState() {
...@@ -26,87 +26,26 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen> { ...@@ -26,87 +26,26 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen> {
} }
} }
AppBar headerView( showPopup({
{required String title, required PopupDataModel data,
Color backgroundColor = Colors.white, bool? barrierDismissibl,
Color iconColor = Colors.white, bool showCloseButton = false,
Color textColor = BaseColor.second900, ButtonsDirection direction = ButtonsDirection.column,
List<Widget>? actions, }) {
Widget? leading, Get.dialog(
TabBar? tabBar, CustomAlertDialog(alertData: data.dataAlertModel, showCloseButton: showCloseButton, direction: direction),
double elevation = 0.5, barrierDismissible: barrierDismissibl ?? true,
bool isShowBack = true}) {
return AppBar(
iconTheme: IconThemeData(
color: iconColor, //change your color here
),
elevation: elevation,
bottom: tabBar,
backgroundColor: backgroundColor,
centerTitle: true,
automaticallyImplyLeading: isShowBack,
actions: actions,
leading: leading,
title: Text(
title.tr,
textAlign: TextAlign.center,
style: textSemiBold.copyWith(fontSize: 18, color: textColor),
),
);
}
double heightBottomSafa() {
return MediaQuery.of(context).padding.bottom;
}
FToast fToast = FToast();
showMessage(BuildContext context, String message) {
fToast.init(context);
Widget toast = Container(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
color: BaseColor.second400,
),
child: Row(mainAxisSize: MainAxisSize.min, children: [
SvgPicture.asset(icLogo, width: 16, height: 16),
const SizedBox(width: 12),
Flexible(
child: Text(message,
style:
textNormal.copyWith(fontSize: 16, color: Colors.white)))
]));
fToast.showToast(
child: toast,
gravity: ToastGravity.BOTTOM,
toastDuration: const Duration(seconds: 2),
); );
} }
showAlertDialog(BuildContext context, String message, showAlert({
{Callback<bool>? callback}) { required DataAlertModel data,
context.showAlertDialog(message, callback: callback);
}
showConfirmAlertDialog(BuildContext context, String message,
{String cancel = "Huỷ",
String confirm = "Xác nhận",
Callback<bool>? callback}) {
context.showConfirmAlertDialog(message, cancel: cancel, confirm: confirm, callback: callback);
}
showAlert({required DataAlertModel data,
bool? barrierDismissibl, bool? barrierDismissibl,
bool showCloseButton = true, bool showCloseButton = true,
ButtonsDirection direction = ButtonsDirection.column}) { ButtonsDirection direction = ButtonsDirection.column,
}) {
Get.dialog( Get.dialog(
CustomAlertDialog( CustomAlertDialog(alertData: data, showCloseButton: showCloseButton, direction: direction),
alertData: data,
showCloseButton: showCloseButton,
direction: direction,
),
barrierDismissible: barrierDismissibl ?? false, barrierDismissible: barrierDismissibl ?? false,
); );
} }
...@@ -115,9 +54,9 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen> { ...@@ -115,9 +54,9 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen> {
Get.dialog( Get.dialog(
CustomAlertDialog( CustomAlertDialog(
alertData: DataAlertModel( alertData: DataAlertModel(
background: "assets/images/ic_pipi_03.png", localHeaderImage: "assets/images/ic_pipi_03.png",
title: "", title: "",
content: content, description: content,
buttons: [ buttons: [
AlertButton( AlertButton(
text: "Đã Hiểu", text: "Đã Hiểu",
...@@ -129,7 +68,6 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen> { ...@@ -129,7 +68,6 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen> {
}, },
bgColor: BaseColor.primary500, bgColor: BaseColor.primary500,
textColor: Colors.white, textColor: Colors.white,
isPrimary: true,
), ),
], ],
), ),
......
...@@ -32,4 +32,6 @@ class APIPaths { ...@@ -32,4 +32,6 @@ class APIPaths {
static const String productCustomerLikes = "/product/api/v2.0/customer/likes"; static const String productCustomerLikes = "/product/api/v2.0/customer/likes";
static const String productCustomerUnlikes = "/product/api/v2.0/customer/likes/%@"; static const String productCustomerUnlikes = "/product/api/v2.0/customer/likes/%@";
static const String getGames = "/campaign/api/v3.0/games"; static const String getGames = "/campaign/api/v3.0/games";
static const String verifyOrderProduct = "/order/api/v1.0/verify-product";
static const String getGameDetail = "/campaign/api/v3.0/games/%@/play";
} }
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
class Constants { class Constants {
static get 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 get 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 var otpTtl = 180; static var otpTtl = 180;
// device key static var directionInApp = "IN-APP";
} }
class ErrorCodes { class ErrorCodes {
......
import 'dart:ui';
extension ColorExtension on Color {
Color get invert => Color.fromARGB(
alpha,
255 - red,
255 - green,
255 - blue,
);
}
\ No newline at end of file
...@@ -53,3 +53,19 @@ extension StringDateExtension on String { ...@@ -53,3 +53,19 @@ extension StringDateExtension on String {
} }
} }
} }
extension HexColorExtension on String {
Color? toColor() {
try {
final hex = replaceAll('#', '').toUpperCase();
if (hex.length == 6) {
return Color(int.parse('FF$hex', radix: 16)); // thêm alpha mặc định
} else if (hex.length == 8) {
return Color(int.parse(hex, radix: 16));
}
} catch (_) {
// Ignored – return null bên dưới
}
return null;
}
}
\ No newline at end of file
...@@ -14,6 +14,7 @@ import '../model/auth/profile_response_model.dart'; ...@@ -14,6 +14,7 @@ import '../model/auth/profile_response_model.dart';
import '../model/update_response_model.dart'; import '../model/update_response_model.dart';
import '../preference/point/header_home_model.dart'; import '../preference/point/header_home_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/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';
import '../screen/otp/model/create_otp_response_model.dart'; import '../screen/otp/model/create_otp_response_model.dart';
...@@ -30,12 +31,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -30,12 +31,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<UpdateResponseModel>> 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.21.7", "build_number": "1"}; final body = {"operating_system": "iOS", "software_model": "MyPoint", "version": "1.21.7", "build_number": "1"};
return requestNormal( return requestNormal(APIPaths.checkUpdate, Method.POST, body, (data) => UpdateResponseModel.fromJson(data as Json));
APIPaths.checkUpdate,
Method.POST,
body,
(data) => UpdateResponseModel.fromJson(data as Json),
);
} }
Future<BaseResponseModel<OnboardingInfoModel>> getOnboardingInfo() async { Future<BaseResponseModel<OnboardingInfoModel>> getOnboardingInfo() async {
...@@ -84,17 +80,14 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -84,17 +80,14 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
APIPaths.otpDeleteAccountRequest, APIPaths.otpDeleteAccountRequest,
Method.POST, Method.POST,
{}, {},
(data) => CreateOTPResponseModel.fromJson(data as Json), (data) => CreateOTPResponseModel.fromJson(data as Json),
); );
} }
Future<BaseResponseModel<CreateOTPResponseModel>> verifyDeleteAccount(String otp) async { Future<BaseResponseModel<CreateOTPResponseModel>> verifyDeleteAccount(String otp) async {
return requestNormal( return requestNormal(APIPaths.verifyDeleteAccount, Method.POST, {
APIPaths.verifyDeleteAccount, "otp": otp,
Method.POST, }, (data) => CreateOTPResponseModel.fromJson(data as Json));
{"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 {
...@@ -109,19 +102,21 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -109,19 +102,21 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
"username": phone, "username": phone,
"password": password.toSha256(), "password": password.toSha256(),
"device_key": deviceKey, "device_key": deviceKey,
"workspace_code": "8854"}; "workspace_code": "8854",
};
return requestNormal(APIPaths.login, Method.POST, body, (data) => LoginTokenResponseModel.fromJson(data as Json)); return requestNormal(APIPaths.login, Method.POST, body, (data) => LoginTokenResponseModel.fromJson(data as Json));
} }
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) ?? ""; var bioToken = await DataPreference.instance.getBioToken(phone) ?? "";
final body = { final body = {"username": phone, "bioToken": bioToken, "deviceKey": deviceKey, "workspaceCode": "8854"};
"username": phone, return requestNormal(
"bioToken": bioToken, APIPaths.loginWithBiometric,
"deviceKey": deviceKey, Method.POST,
"workspaceCode": "8854"}; body,
return requestNormal(APIPaths.loginWithBiometric, Method.POST, body, (data) => LoginTokenResponseModel.fromJson(data as Json)); (data) => LoginTokenResponseModel.fromJson(data as Json),
);
} }
Future<BaseResponseModel<ProfileResponseModel>> getUserProfile() async { Future<BaseResponseModel<ProfileResponseModel>> getUserProfile() async {
...@@ -196,7 +191,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -196,7 +191,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
APIPaths.accountPasswordReset, APIPaths.accountPasswordReset,
Method.POST, Method.POST,
body, body,
(data) => EmptyCodable.fromJson(data as Json), (data) => EmptyCodable.fromJson(data as Json),
); );
} }
...@@ -207,7 +202,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -207,7 +202,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
APIPaths.accountPasswordChange, APIPaths.accountPasswordChange,
Method.POST, Method.POST,
body, body,
(data) => EmptyCodable.fromJson(data as Json), (data) => EmptyCodable.fromJson(data as Json),
); );
} }
...@@ -218,7 +213,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -218,7 +213,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
APIPaths.accountLoginForPasswordChange, APIPaths.accountLoginForPasswordChange,
Method.POST, Method.POST,
body, body,
(data) => EmptyCodable.fromJson(data as Json), (data) => EmptyCodable.fromJson(data as Json),
); );
} }
...@@ -229,7 +224,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -229,7 +224,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
APIPaths.bioCredential, APIPaths.bioCredential,
Method.POST, Method.POST,
body, body,
(data) => BiometricRegisterResponseModel.fromJson(data as Json), (data) => BiometricRegisterResponseModel.fromJson(data as Json),
); );
} }
...@@ -240,7 +235,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -240,7 +235,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
APIPaths.registerBiometric, APIPaths.registerBiometric,
Method.POST, Method.POST,
body, body,
(data) => BiometricRegisterResponseModel.fromJson(data as Json), (data) => BiometricRegisterResponseModel.fromJson(data as Json),
); );
} }
...@@ -248,21 +243,11 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -248,21 +243,11 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
var deviceKey = await DeviceInfo.getDeviceId(); var deviceKey = await DeviceInfo.getDeviceId();
final path = "${APIPaths.unRegisterBiometric}/$deviceKey"; final path = "${APIPaths.unRegisterBiometric}/$deviceKey";
final body = {"deviceKey": deviceKey}; final body = {"deviceKey": deviceKey};
return requestNormal( return requestNormal(path, Method.POST, body, (data) => EmptyCodable.fromJson(data as Json));
path,
Method.POST,
body,
(data) => EmptyCodable.fromJson(data as Json),
);
} }
Future<BaseResponseModel<HeaderHomeModel>> getHomeHeaderData() async { Future<BaseResponseModel<HeaderHomeModel>> getHomeHeaderData() async {
return requestNormal( return requestNormal(APIPaths.headerHome, Method.GET, {}, (data) => HeaderHomeModel.fromJson(data as Json));
APIPaths.headerHome,
Method.GET,
{},
(data) => HeaderHomeModel.fromJson(data as Json),
);
} }
Future<BaseResponseModel<List<ProductModel>>> getProducts(Json body) async { Future<BaseResponseModel<List<ProductModel>>> getProducts(Json body) async {
...@@ -277,18 +262,13 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -277,18 +262,13 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
APIPaths.getSearchProducts, APIPaths.getSearchProducts,
Method.POST, Method.POST,
body, body,
(data) =>SearchProductResponseModel.fromJson(data as Json), (data) => SearchProductResponseModel.fromJson(data as Json),
); );
} }
Future<BaseResponseModel<ProductModel>> getProduct(int id) async { Future<BaseResponseModel<ProductModel>> getProduct(int id) async {
final path = APIPaths.getProductDetail.replaceAll("%@", id.toString()); final path = APIPaths.getProductDetail.replaceAll("%@", id.toString());
return requestNormal( return requestNormal(path, Method.GET, {}, (data) => ProductModel.fromJson(data as Json));
path,
Method.GET,
{},
(data) =>ProductModel.fromJson(data as Json),
);
} }
Future<BaseResponseModel<List<ProductStoreModel>>> getProductStores(int id) async { Future<BaseResponseModel<List<ProductStoreModel>>> getProductStores(int id) async {
...@@ -308,12 +288,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -308,12 +288,7 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
Future<BaseResponseModel<EmptyCodable>> unlikeProduct(int id) async { Future<BaseResponseModel<EmptyCodable>> unlikeProduct(int id) async {
final path = APIPaths.productCustomerUnlikes.replaceAll("%@", id.toString()); final path = APIPaths.productCustomerUnlikes.replaceAll("%@", id.toString());
return requestNormal( return requestNormal(path, Method.DELETE, {}, (data) => EmptyCodable.fromJson(data as Json));
path,
Method.DELETE,
{},
(data) => EmptyCodable.fromJson(data as Json),
);
} }
Future<BaseResponseModel<GameBundleResponse>> getGames() async { Future<BaseResponseModel<GameBundleResponse>> getGames() async {
...@@ -321,4 +296,18 @@ extension RestfullAPIClientAllApi on RestfulAPIClient { ...@@ -321,4 +296,18 @@ extension RestfullAPIClientAllApi on RestfulAPIClient {
return GameBundleResponse.fromJson(data as Json); return GameBundleResponse.fromJson(data as Json);
}); });
} }
}
\ No newline at end of file Future<BaseResponseModel<List<EmptyCodable>>> verifyOrderProduct(Json body) async {
return requestNormal(APIPaths.verifyOrderProduct, Method.POST, body, (data) {
final list = data as List<dynamic>;
return list.map((e) => EmptyCodable.fromJson(e)).toList();
});
}
Future<BaseResponseModel<GameBundleItemModel>> getGameDetail(String id) async {
final path = APIPaths.getGameDetail.replaceAll("%@", id);
return requestNormal(path, Method.POST, {}, (data) {
return GameBundleItemModel.fromJson(data as Json);
});
}
}
...@@ -71,23 +71,21 @@ class BiometricManager { ...@@ -71,23 +71,21 @@ class BiometricManager {
final result = await Get.dialog<bool>( final result = await Get.dialog<bool>(
CustomAlertDialog( CustomAlertDialog(
alertData: DataAlertModel( alertData: DataAlertModel(
background: "assets/images/bg_alert_header.png", localHeaderImage: "assets/images/bg_alert_header.png",
title: title, title: title,
content: content, description: content,
buttons: [ buttons: [
AlertButton( AlertButton(
text: "Huỷ", text: "Huỷ",
onPressed: () => Get.back(result: false), onPressed: () => Get.back(result: false),
bgColor: BaseColor.primary500, bgColor: BaseColor.primary500,
textColor: Colors.white, textColor: Colors.white,
isPrimary: true,
), ),
AlertButton( AlertButton(
text: "Đồng ý", text: "Đồng ý",
onPressed: () => Get.back(result: true), onPressed: () => Get.back(result: true),
bgColor: BaseColor.primary500, bgColor: BaseColor.primary500,
textColor: Colors.white, textColor: Colors.white,
isPrimary: true,
), ),
], ],
), ),
......
...@@ -40,16 +40,15 @@ class _BiometricAuthScreenState extends BaseState<BiometricAuthScreen> with Basi ...@@ -40,16 +40,15 @@ class _BiometricAuthScreenState extends BaseState<BiometricAuthScreen> with Basi
? "Từ bây giờ bạn có thể sử dụng $type để đăng nhập thay vì nhập mật khẩu." ? "Từ bây giờ bạn có thể sử dụng $type để đăng nhập thay vì nhập mật khẩu."
: "Đã có lỗi xảy ra khi xác thực thông tin sinh trắc học. Vui lòng thử lại sau."; : "Đã có lỗi xảy ra khi xác thực thông tin sinh trắc học. Vui lòng thử lại sau.";
DataAlertModel alertData = DataAlertModel( DataAlertModel alertData = DataAlertModel(
background: result? "assets/images/ic_pipi_05.png" : "assets/images/ic_pipi_03.png", localHeaderImage: result? "assets/images/ic_pipi_05.png" : "assets/images/ic_pipi_03.png",
title: title, title: title,
content: message, description: message,
buttons: [ buttons: [
AlertButton( AlertButton(
text: "Đã hiểu", text: "Đã hiểu",
onPressed: () => Get.offAll(MainTabScreen()), onPressed: () => Get.offAll(MainTabScreen()),
bgColor: BaseColor.primary500, bgColor: BaseColor.primary500,
textColor: Colors.white, textColor: Colors.white,
isPrimary: true,
), ),
], ],
); );
......
...@@ -163,8 +163,8 @@ class _ChangePassScreenState extends BaseState<ChangePassScreen> with BasicState ...@@ -163,8 +163,8 @@ class _ChangePassScreenState extends BaseState<ChangePassScreen> with BasicState
onPressed: () { onPressed: () {
final dataAlert = DataAlertModel( final dataAlert = DataAlertModel(
title: "Quên mật khẩu", 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ứ?.", description: "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", localHeaderImage: "assets/images/ic_pipi_03.png",
buttons: [AlertButton( buttons: [AlertButton(
text: "Đồng ý", text: "Đồng ý",
onPressed: () { onPressed: () {
...@@ -173,14 +173,12 @@ class _ChangePassScreenState extends BaseState<ChangePassScreen> with BasicState ...@@ -173,14 +173,12 @@ class _ChangePassScreenState extends BaseState<ChangePassScreen> with BasicState
}, },
bgColor: BaseColor.primary500, bgColor: BaseColor.primary500,
textColor: Colors.white, textColor: Colors.white,
isPrimary: true,
), ),
AlertButton( AlertButton(
text: "Huỷ", text: "Huỷ",
onPressed: () => Get.back(), onPressed: () => Get.back(),
bgColor: Colors.white, bgColor: Colors.white,
textColor: BaseColor.second500, textColor: BaseColor.second500,
isPrimary: false,
),], ),],
); );
showAlert(data: dataAlert); showAlert(data: dataAlert);
......
...@@ -25,6 +25,18 @@ class _GameTabScreenState extends BaseState<GameTabScreen> with BasicState { ...@@ -25,6 +25,18 @@ class _GameTabScreenState extends BaseState<GameTabScreen> with BasicState {
void initState() { void initState() {
super.initState(); super.initState();
_viewModel.getGames(); _viewModel.getGames();
_viewModel.onShowAlertError = (message) {
if (message.isNotEmpty) {
showAlertError(content: message);
}
};
_viewModel.gotoGameDetail = (data) {
if (data.popup != null) {
showPopup(data: data.popup!);
} else {
Get.toNamed(gameCardScreen, arguments: data);
}
};
} }
@override @override
...@@ -70,7 +82,7 @@ class _GameTabScreenState extends BaseState<GameTabScreen> with BasicState { ...@@ -70,7 +82,7 @@ class _GameTabScreenState extends BaseState<GameTabScreen> with BasicState {
final item = _viewModel.games[index]; final item = _viewModel.games[index];
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
Get.toNamed(gameCardScreen, arguments: item); _viewModel.getGameDetail(item.id ?? "");
}, },
child: AspectRatio( child: AspectRatio(
aspectRatio: 343/132, aspectRatio: 343/132,
......
...@@ -9,13 +9,14 @@ class GameTabViewModel extends RestfulApiViewModel { ...@@ -9,13 +9,14 @@ class GameTabViewModel extends RestfulApiViewModel {
final RxList<GameBundleItemModel> games = <GameBundleItemModel>[].obs; final RxList<GameBundleItemModel> games = <GameBundleItemModel>[].obs;
var turnsNumberText = "".obs; var turnsNumberText = "".obs;
var isLoading = false.obs; var isLoading = false.obs;
var errorMessage = "".obs; void Function(String message)? onShowAlertError;
void Function(GameBundleItemModel data)? gotoGameDetail;
void getGames() { void getGames() {
isLoading(true); isLoading(true);
client.getGames().then((value) { client.getGames().then((value) {
if (!value.isSuccess) { if (!value.isSuccess) {
errorMessage.value = value.errorMessage ?? Constants.commonError; onShowAlertError?.call(value.errorMessage ?? Constants.commonError);
} else { } else {
games.value = value.data?.games ?? []; games.value = value.data?.games ?? [];
turnsNumberText.value = value.data?.turnsNumberText ?? ""; turnsNumberText.value = value.data?.turnsNumberText ?? "";
...@@ -23,4 +24,18 @@ class GameTabViewModel extends RestfulApiViewModel { ...@@ -23,4 +24,18 @@ class GameTabViewModel extends RestfulApiViewModel {
isLoading(false); isLoading(false);
}); });
} }
void getGameDetail(String gameId) {
isLoading(true);
client.getGameDetail(gameId).then((value) {
if (!value.isSuccess) {
onShowAlertError?.call(value.errorMessage ?? Constants.commonError);
} else if (value.data != null) {
gotoGameDetail?.call(value.data!);
} else {
onShowAlertError?.call(Constants.commonError);
}
isLoading(false);
});
}
} }
\ No newline at end of file
import 'package:json_annotation/json_annotation.dart'; import 'package:json_annotation/json_annotation.dart';
import '../../../widgets/alert/popup_data_model.dart';
import 'game_card_item_model.dart'; import 'game_card_item_model.dart';
part 'game_bundle_item_model.g.dart'; part 'game_bundle_item_model.g.dart';
...@@ -11,6 +12,7 @@ class GameBundleItemModel { ...@@ -11,6 +12,7 @@ class GameBundleItemModel {
final String? background; final String? background;
final String? description; final String? description;
final List<GameCardItemModel>? options; final List<GameCardItemModel>? options;
final PopupDataModel? popup;
GameBundleItemModel({ GameBundleItemModel({
this.id, this.id,
...@@ -19,6 +21,7 @@ class GameBundleItemModel { ...@@ -19,6 +21,7 @@ class GameBundleItemModel {
this.background, this.background,
this.description, this.description,
this.options, this.options,
this.popup
}); });
factory GameBundleItemModel.fromJson(Map<String, dynamic> json) => _$GameBundleItemModelFromJson(json); factory GameBundleItemModel.fromJson(Map<String, dynamic> json) => _$GameBundleItemModelFromJson(json);
......
...@@ -19,6 +19,10 @@ GameBundleItemModel _$GameBundleItemModelFromJson(Map<String, dynamic> json) => ...@@ -19,6 +19,10 @@ GameBundleItemModel _$GameBundleItemModelFromJson(Map<String, dynamic> json) =>
(e) => GameCardItemModel.fromJson(e as Map<String, dynamic>), (e) => GameCardItemModel.fromJson(e as Map<String, dynamic>),
) )
.toList(), .toList(),
popup:
json['popup'] == null
? null
: PopupDataModel.fromJson(json['popup'] as Map<String, dynamic>),
); );
Map<String, dynamic> _$GameBundleItemModelToJson( Map<String, dynamic> _$GameBundleItemModelToJson(
...@@ -30,4 +34,5 @@ Map<String, dynamic> _$GameBundleItemModelToJson( ...@@ -30,4 +34,5 @@ Map<String, dynamic> _$GameBundleItemModelToJson(
'background': instance.background, 'background': instance.background,
'description': instance.description, 'description': instance.description,
'options': instance.options, 'options': instance.options,
'popup': instance.popup,
}; };
// home_screen.dart // home_screen.dart
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:game_miniapp/game_miniapp.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/shared/router_gage.dart'; import 'package:mypoint_flutter_app/shared/router_gage.dart';
...@@ -16,6 +17,7 @@ class HomeScreen extends StatelessWidget { ...@@ -16,6 +17,7 @@ class HomeScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
ElevatedButton(onPressed: () => _showMiniGame(context), child: const Text('Mini Game')),
ElevatedButton(onPressed: () => _logout(context), child: const Text('Đăng xuất')), ElevatedButton(onPressed: () => _logout(context), child: const Text('Đăng xuất')),
ElevatedButton(onPressed: () => _showSetting(context), child: const Text('Setting')), ElevatedButton(onPressed: () => _showSetting(context), child: const Text('Setting')),
], ],
...@@ -24,6 +26,13 @@ class HomeScreen extends StatelessWidget { ...@@ -24,6 +26,13 @@ class HomeScreen extends StatelessWidget {
); );
} }
void _showMiniGame(BuildContext context) async {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => const GameMiniAppScreen()),
);
}
void _logout(BuildContext context) async { void _logout(BuildContext context) async {
final confirm = await showDialog<bool>( final confirm = await showDialog<bool>(
context: context, context: context,
......
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