Commit fa01087d authored by DatHV's avatar DatHV
Browse files

update brand, detail..

parent c8abf95b
......@@ -166,8 +166,8 @@ class _PaymentWebViewScreenState extends BaseState<PaymentWebViewScreen> with Ba
if (input.isContract) {
_navigateToContractScreen();
} else if (input.callback != null) {
Get.back();
input.callback!(result);
Get.back(); // hoặc điều hướng phù hợp
} else {
_backToRoot();
}
......
......@@ -3,9 +3,11 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/widgets/back_button.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:webview_flutter/webview_flutter.dart';
import '../../base/base_screen.dart';
import '../../base/basic_state.dart';
import '../../directional/directional_screen.dart';
class BaseWebViewInput {
final String? title;
......@@ -31,7 +33,7 @@ class _BaseWebViewScreenState extends BaseState<BaseWebViewScreen> with BasicSta
void initState() {
super.initState();
final args = Get.arguments;
if (args is BaseWebViewInput) {
if (args is BaseWebViewInput && args.url.isNotEmpty) {
input = args;
} else {
WidgetsBinding.instance.addPostFrameCallback((_) {
......@@ -52,14 +54,24 @@ class _BaseWebViewScreenState extends BaseState<BaseWebViewScreen> with BasicSta
});
},
onWebResourceError: (error) {
if (error.description != 'about:blank') {
showAlertError(content: error.description);
}
},
onNavigationRequest: _handleNavigation,
),
)
..loadRequest(Uri.parse(input.url));
..loadRequest(Uri.parse(formatUrl(input.url)));
_clearCookies();
}
String formatUrl(String inputUrl) {
if (!inputUrl.startsWith('http://') && !inputUrl.startsWith('https://')) {
return 'https://$inputUrl';
}
return inputUrl;
}
@override
Widget createBody() {
return Scaffold(
......@@ -69,20 +81,24 @@ class _BaseWebViewScreenState extends BaseState<BaseWebViewScreen> with BasicSta
: AppBar(
title: Text(
input.title ?? _dynamicTitle ?? Uri.parse(input.url).host,
style: const TextStyle(fontSize: 16),
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black87),
),
leading: CustomBackButton(onPressed: _handleBack),
),
body: SafeArea(
body: Stack(
children: [
SafeArea(
child: WebViewWidget(
controller: _controller,
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{
Factory<VerticalDragGestureRecognizer>(
VerticalDragGestureRecognizer.new,
),
Factory<VerticalDragGestureRecognizer>(VerticalDragGestureRecognizer.new),
},
),
),
if (input.isFullScreen)
Positioned(top: MediaQuery.of(context).padding.top + 8, left: 8, child: CustomBackButton()),
],
),
);
}
......@@ -98,4 +114,22 @@ class _BaseWebViewScreenState extends BaseState<BaseWebViewScreen> with BasicSta
if (context.mounted) Navigator.of(context).pop();
}
}
NavigationDecision _handleNavigation(NavigationRequest request) {
final url = request.url;
debugPrint("➡️ Navigating: $url");
if (url.isEmpty || url == 'about:blank') {
return NavigationDecision.prevent;
}
if (url.startsWith('itms-apps://')) {
openAppStore(url);
return NavigationDecision.prevent;
}
if (url.startsWith('sms:')) {
final uri = Uri.parse(url);
launchUrl(uri);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
}
}
......@@ -2,11 +2,19 @@ import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:mypoint_flutter_app/screen/news/news_list_screen.dart';
import '../screen/achievement/achievement_list_screen.dart';
import '../screen/affiliate/affiliate_tab_screen.dart';
import '../screen/affiliate_brand_detail/affiliate_brand_detail_screen.dart';
import '../screen/affiliate_brand_detail/affiliate_brand_list_screen.dart';
import '../screen/affiliate_brand_detail/affiliate_category_grid_screen.dart';
import '../screen/data_network_service/data_network_service_screen.dart';
import '../screen/game/game_cards/game_card_screen.dart';
import '../screen/game/game_tab_screen.dart';
import '../screen/history_point_cashback/history_point_cashback_screen.dart';
import '../screen/location_address/location_address_screen.dart';
import '../screen/login/login_screen.dart';
import '../screen/main_tab_screen/main_tab_screen.dart';
import '../screen/membership/membership_screen.dart';
import '../screen/mobile_card/product_mobile_card_screen.dart';
import '../screen/notification/notification_screen.dart';
import '../screen/onboarding/onboarding_screen.dart';
import '../screen/order_menu/order_menu_screen.dart';
......@@ -16,6 +24,7 @@ import '../screen/register_campaign/register_form_input_screen.dart';
import '../screen/setting/setting_screen.dart';
import '../screen/splash/splash_screen.dart';
import '../screen/support/support_screen.dart';
import '../screen/topup/topup_screen.dart';
import '../screen/transaction/history/transaction_history_detail_screen.dart';
import '../screen/transaction/transaction_detail_screen.dart';
import '../screen/voucher/detail/voucher_detail_screen.dart';
......@@ -49,6 +58,15 @@ const personalEditScreen = '/personalEditScreen';
const orderMenuScreen = '/orderMenuScreen';
const locationAddressScreen = '/locationAddressScreen';
const membershipScreen = '/membershipScreen';
const phoneTopUpScreen = '/phoneTopUpScreen';
const productMobileCardScreen = '/productMobileCardScreen';
const dataNetworkServiceScreen = '/dataNetworkServiceScreen';
const affiliateTabScreen = '/affiliateTabScreen';
const gameTabScreen = '/gameTabScreen';
const historyPointCashBackScreen = '/historyPointCashBackScreen';
const affiliateBrandDetailScreen = '/affiliateBrandDetailScreen';
const affiliateBrandListScreen = '/affiliateBrandListScreen';
const affiliateCategoryGridScreen = '/affiliateCategoryGridScreen';
class RouterPage {
static List<GetPage> pages() {
......@@ -83,6 +101,15 @@ class RouterPage {
GetPage(name: orderMenuScreen, page: () => OrderMenuScreen()),
GetPage(name: locationAddressScreen, page: () => LocationAddressScreen()),
GetPage(name: membershipScreen, page: () => MembershipScreen()),
GetPage(name: phoneTopUpScreen, page: () => PhoneTopUpScreen()),
GetPage(name: productMobileCardScreen, page: () => ProductMobileCardScreen()),
GetPage(name: dataNetworkServiceScreen, page: () => DataNetworkServiceScreen()),
GetPage(name: affiliateTabScreen, page: () => AffiliateTabScreen()),
GetPage(name: gameTabScreen, page: () => GameTabScreen()),
GetPage(name: historyPointCashBackScreen, page: () => HistoryPointCashBackScreen()),
GetPage(name: affiliateBrandDetailScreen, page: () => AffiliateBrandDetailScreen()),
GetPage(name: affiliateBrandListScreen, page: () => AffiliateBrandListScreen()),
GetPage(name: affiliateCategoryGridScreen, page: () => AffiliateCategoryGridScreen()),
];
}
}
......
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:mypoint_flutter_app/directional/directional_action_type.dart';
import 'package:mypoint_flutter_app/extensions/color_extension.dart';
import 'package:mypoint_flutter_app/extensions/string_extension.dart';
import '../../directional/directional_screen.dart';
import 'data_alert_model.dart';
part 'button_config_model.g.dart';
@JsonSerializable()
class ButtonConfigModel {
final String? text;
......@@ -16,12 +18,7 @@ class ButtonConfigModel {
@JsonKey(name: "click_action_param")
final String? clickActionParam;
ButtonConfigModel({
this.text,
this.color,
this.clickActionType,
this.clickActionParam,
});
ButtonConfigModel({this.text, this.color, this.clickActionType, this.clickActionParam});
AlertButton get alertButton {
final bgColor = color?.toColor() ?? Colors.white;
......@@ -29,23 +26,17 @@ class ButtonConfigModel {
text: text ?? "",
textColor: bgColor.invert,
bgColor: bgColor,
onPressed: () {
if (directionScreen != null) {
directionScreen?.begin();
} else {
onPressed: () async {
DirectionalScreen? directional = DirectionalScreen.build(
clickActionType: clickActionType,
clickActionParam: clickActionParam,
);
Get.back();
}
directional?.begin();
},
);
}
factory ButtonConfigModel.fromJson(Map<String, dynamic> json) => _$ButtonConfigModelFromJson(json);
Map<String, dynamic> toJson() => _$ButtonConfigModelToJson(this);
DirectionalScreen? get directionScreen {
DirectionalScreen.build(
clickActionType: clickActionType,
clickActionParam: clickActionParam,
);
}
}
......@@ -55,6 +55,7 @@ class CustomAlertDialog extends StatelessWidget {
textAlign: TextAlign.center,
),
// Buttons
const SizedBox(height: 8),
_buildButtons(),
],
),
......
......@@ -18,10 +18,7 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
/// 🔥 AppBar mặc định với nút back và title
static CustomAppBar back({required String title}) {
return CustomAppBar(
title: title,
leftButtons: [CustomBackButton()],
);
return CustomAppBar(title: title, leftButtons: [CustomBackButton()]);
}
@override
......@@ -35,14 +32,15 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(children: leftButtons),
Row(children: rightButtons),
],
children: [Row(children: leftButtons), Row(children: rightButtons)],
),
Center(
Padding(
padding: const EdgeInsets.only(left: 24, right: 24),
child: Center(
child: Text(
title,
textAlign: TextAlign.center,
maxLines: 1,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
......@@ -50,6 +48,7 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
),
),
),
),
],
),
),
......
import 'package:contacts_service/contacts_service.dart';
import 'package:permission_handler/permission_handler.dart';
// Future<void> pickContact(BuildContext context) async {
// // Yêu cầu quyền truy cập danh bạ
// final status = await Permission.contacts.request();
// if (!status.isGranted) {
// ScaffoldMessenger.of(context).showSnackBar(
// const SnackBar(content: Text('Bạn cần cấp quyền truy cập danh bạ')),
// );
// return;
// }
//
// // Mở danh sách liên hệ và chọn
// try {
// final Contact? contact = await ContactsService.openDeviceContactPicker();
// if (contact != null && contact.phones != null && contact.phones!.isNotEmpty) {
// final phoneNumber = contact.phones!.first.value;
// print("Số điện thoại được chọn: $phoneNumber");
//
// // TODO: bạn có thể gán vào TextEditingController ở đây
// _phoneController.text = phoneNumber ?? '';
// }
// } catch (e) {
// print("Lỗi khi chọn danh bạ: $e");
// }
// }
......@@ -49,11 +49,14 @@ dependencies:
pin_code_fields:
intl: ^0.18.1
webview_flutter: ^4.2.2
webview_flutter_wkwebview: ^3.9.4
qr_flutter: ^4.0.0
barcode_widget: ^2.0.1
infinite_carousel: ^1.0.3
package_info_plus: ^4.1.0
dotted_border: ^2.0.0
contacts_service: ^0.6.3
permission_handler: ^11.0.0
game_miniapp:
path: ../mini_app/game_miniapp
dev_dependencies:
......
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