Commit b3c72190 authored by DatHV's avatar DatHV
Browse files

update invite friend.

update config build
parent 6b980613
......@@ -33,7 +33,7 @@ class _SplashScreenState extends BaseState<SplashScreen> with BasicState {
return;
}
if (updateData.status == UpdateStatus.none) {
_viewModel.directionWhenTokenInvalid();
_viewModel.makeDataFollowInitApp();
} else {
_showSuggestUpdateAlert(updateData);
}
......
......@@ -106,7 +106,6 @@ class SplashScreenViewModel extends RestfulApiViewModel {
}
Future<void> directionWhenTokenInvalid() async {
if (Get.currentRoute == onboardingScreen) return;
// if (kIsWeb) {
// print('❌ No token found on web, closing app');
// final closeSuccess = await webCloseApp({
......
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../app/routing/directional_action_type.dart';
......@@ -32,14 +33,23 @@ class _VoucherTabScreenState extends State<VoucherTabScreen> with PopupOnInit {
return Scaffold(
appBar: CustomNavigationBar(
title: "Ưu đãi",
leftButtons: [],
leftButtons: [
if (kIsWeb)
IconButton(
icon: const Icon(Icons.search, color: Colors.white),
onPressed: () {
Get.toNamed(vouchersScreen, arguments: {"enableSearch": true});
},
),
],
rightButtons: [
IconButton(
icon: const Icon(Icons.search, color: Colors.white),
onPressed: () {
Get.toNamed(vouchersScreen, arguments: {"enableSearch": true});
},
),
if (!kIsWeb)
IconButton(
icon: const Icon(Icons.search, color: Colors.white),
onPressed: () {
Get.toNamed(vouchersScreen, arguments: {"enableSearch": true});
},
),
],
),
body: Obx(() {
......
......@@ -372,7 +372,7 @@ class DirectionalScreen {
}
}
void _logUnsupported(type) {
void _logUnsupported(DirectionalScreenName type) {
debugPrint("⚠️ DirectionalScreen action type không được hỗ trợ: ${type.rawValue}");
}
......
......@@ -68,6 +68,8 @@ const qrCodeScreen = '/qrCodeScreen';
const myMobileCardDetailScreen = '/myMobileCardDetailScreen';
const healthBookCardDetail = '/healthBookCardDetail';
const notificationDetailScreen = '/notificationDetailScreen';
const referralCodeInviteFriendScreen = '/referralCodeInviteFriendScreen';
const campaignInviteReferralInfoScreen = '/campaignInviteReferralInfoScreen';
class RouterPage {
static List<GetPage> pages() {
......@@ -138,6 +140,8 @@ class RouterPage {
GetPage(name: healthBookScreen, page: () => const HealthBookDeferredScreen()),
GetPage(name: healthBookCardDetail, page: () => const HealthBookCardDetailDeferredScreen()),
GetPage(name: notificationDetailScreen, page: () => NotificationDetailScreen()),
GetPage(name: referralCodeInviteFriendScreen, page: () => const ReferralCodeInviteFriendDeferredScreen()),
GetPage(name: campaignInviteReferralInfoScreen, page: () => const CampaignInviteReferralInfoDeferredScreen()),
];
}
}
}
\ No newline at end of file
import 'package:flutter/material.dart';
class ButtonContainer extends StatelessWidget {
final Color color;
final double cornerRadius;
final double? height;
final double? width;
final Widget child;
final bool visible;
const ButtonContainer({
super.key,
required this.child,
this.height,
this.width,
this.color = Colors.white,
this.cornerRadius = 8,
this.visible = true,
});
@override
Widget build(BuildContext context) {
return Visibility(
visible: visible,
child: Container(
decoration: BoxDecoration(borderRadius: BorderRadius.circular(cornerRadius), color: color),
width: width,
height: height,
child: child,
),
);
}
}
import 'package:flutter/material.dart';
import 'back_button.dart';
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
final String title;
final List<Widget> leftButtons;
final List<Widget> rightButtons;
final double height;
const CustomAppBar({
super.key,
required this.title,
this.leftButtons = const [],
this.rightButtons = const [],
this.height = 56,
});
static CustomAppBar back({required String title}) {
return CustomAppBar(title: title, leftButtons: [CustomBackButton()]);
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Container(
height: height,
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Stack(
alignment: Alignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [Row(children: leftButtons), Row(children: rightButtons)],
),
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,
color: Colors.black87,
),
),
),
),
],
),
),
);
}
@override
Size get preferredSize => Size.fromHeight(height);
}
\ No newline at end of file
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../app/config/constants.dart';
import '../../features/home/header_home_viewmodel.dart';
import 'back_button.dart';
import 'image_loader.dart';
......@@ -21,7 +23,15 @@ class CustomNavigationBar extends StatelessWidget implements PreferredSizeWidget
});
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
Size get preferredSize {
final dispatcher = WidgetsBinding.instance.platformDispatcher;
final view = dispatcher.implicitView ?? (dispatcher.views.isNotEmpty ? dispatcher.views.first : null);
double paddingTop = view != null ? MediaQueryData.fromView(view).padding.top : 0.0;
if (paddingTop == 0 && kIsWeb) {
paddingTop = Constants.webTopPadding;
}
return Size.fromHeight(kToolbarHeight + paddingTop);
}
@override
Widget build(BuildContext context) {
......@@ -37,27 +47,28 @@ class CustomNavigationBar extends StatelessWidget implements PreferredSizeWidget
}
Widget _buildAppBar(String bgImage, BuildContext context) {
final double statusBarHeight = MediaQuery.of(context).padding.top;
double statusBarHeight = MediaQuery.of(context).padding.top;
double extraWebPadding = 0;
if (statusBarHeight == 0 && kIsWeb) {
extraWebPadding = Constants.webTopPadding;
}
final double totalTopPadding = statusBarHeight + extraWebPadding;
final bool isHttp = bgImage.startsWith('http://') || bgImage.startsWith('https://');
final paddingTitle = (leftButtons.isNotEmpty || rightButtons.isNotEmpty) ? 48.0 : 16.0; // cách 2 đầu
return Container(
height: statusBarHeight + kToolbarHeight,
decoration: BoxDecoration(
color: bgImage.isEmpty ? Colors.white : null,
),
child: Stack(
fit: StackFit.expand,
children: [
if (bgImage.isNotEmpty)
isHttp
? loadNetworkImage(
url: bgImage,
fit: BoxFit.cover,
placeholderAsset: _defaultBgImage,
)
: Image.asset(_defaultBgImage, fit: BoxFit.cover),
SafeArea(
bottom: false,
height: totalTopPadding + kToolbarHeight,
decoration: BoxDecoration(color: bgImage.isEmpty ? Colors.white : null),
child: Stack(
fit: StackFit.expand,
children: [
if (bgImage.isNotEmpty)
isHttp
? loadNetworkImage(url: bgImage, fit: BoxFit.cover, placeholderAsset: _defaultBgImage)
: Image.asset(_defaultBgImage, fit: BoxFit.cover),
SafeArea(
bottom: false,
child: Padding(
padding: EdgeInsets.only(top: extraWebPadding),
child: Stack(
alignment: Alignment.center,
children: [
......@@ -66,49 +77,28 @@ class CustomNavigationBar extends StatelessWidget implements PreferredSizeWidget
child: AutoSizeText(
title,
maxLines: 1,
minFontSize: 12, // 👈 không nhỏ hơn 8
stepGranularity: 0.1, // scale mượt hơn
overflow: TextOverflow.visible, // giữ nguyên như bạn đang dùng
minFontSize: 12,
stepGranularity: 0.1,
overflow: TextOverflow.visible,
// giữ nguyên như bạn đang dùng
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 18, // 👈 cỡ tối đa mong muốn
fontSize: 18, // 👈 cỡ tối đa mong muốn
fontWeight: FontWeight.w800,
color: Colors.white,
),
),
// child: FittedBox(
// fit: BoxFit.scaleDown, // tự giảm font để vừa khung
// child: Text(
// title,
// maxLines: 1,
// softWrap: false,
// overflow: TextOverflow.visible, // không dùng ellipsis
// textAlign: TextAlign.center,
// style: const TextStyle(
// fontSize: 18, // cỡ tối đa
// fontWeight: FontWeight.w800,
// color: Colors.white,
// ),
// ),
// ),
),
// Text(
// title,
// maxLines: 1,
// style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w800, color: Colors.white),
// textAlign: TextAlign.center,
// ),
// Buttons bên trái
if (leftButtons.isNotEmpty)
Positioned(left: 12, child: Row(mainAxisSize: MainAxisSize.min, children: leftButtons)),
// Buttons bên phải
if (rightButtons.isNotEmpty)
Positioned(right: 12, child: Row(mainAxisSize: MainAxisSize.min, children: rightButtons)),
],
),
),
],
),
);
),
],
),
);
}
}
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../app/config/constants.dart';
import '../../features/home/header_home_viewmodel.dart';
import 'back_button.dart';
import 'image_loader.dart';
......@@ -21,7 +23,15 @@ class CustomSearchNavigationBar extends StatefulWidget implements PreferredSizeW
});
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
Size get preferredSize {
final dispatcher = WidgetsBinding.instance.platformDispatcher;
final view = dispatcher.implicitView ?? (dispatcher.views.isNotEmpty ? dispatcher.views.first : null);
double paddingTop = view != null ? MediaQueryData.fromView(view).padding.top : 0.0;
if (paddingTop == 0 && kIsWeb) {
paddingTop = Constants.webTopPadding;
}
return Size.fromHeight(kToolbarHeight + paddingTop);
}
@override
_CustomSearchNavigationBarState createState() => _CustomSearchNavigationBarState();
......@@ -51,16 +61,14 @@ class _CustomSearchNavigationBarState extends State<CustomSearchNavigationBar> {
Widget _buildAppBar(String bgImage, BuildContext context) {
final bool isHttp = bgImage.startsWith('http://') || bgImage.startsWith('https://');
final double statusBarHeight = MediaQuery.of(context).padding.top;
double statusBarHeight = MediaQuery.of(context).padding.top;
double extraWebPadding = 0;
if (statusBarHeight == 0 && kIsWeb) {
extraWebPadding = Constants.webTopPadding;
}
final double totalTopPadding = statusBarHeight + extraWebPadding;
return SizedBox(
height: statusBarHeight + kToolbarHeight,
// decoration: BoxDecoration(
// image:
// widget.backgroundImage != null
// ? DecorationImage(image: AssetImage(widget.backgroundImage!), fit: BoxFit.cover)
// : null,
// color: widget.backgroundImage == null ? Colors.white : null,
// ),
height: totalTopPadding + kToolbarHeight,
child: Stack(
fit: StackFit.expand,
children: [
......@@ -70,52 +78,55 @@ class _CustomSearchNavigationBarState extends State<CustomSearchNavigationBar> {
: Image.asset(_defaultBgImage, fit: BoxFit.cover),
SafeArea(
bottom: false,
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
left: widget.showBackButton ? 68 : 16,
right: widget.rightButtons.isNotEmpty ? 60 : 16,
child: Container(
height: 36,
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(12)),
child: Row(
children: [
const Icon(Icons.search, size: 20),
const SizedBox(width: 4),
Expanded(
child: TextField(
controller: _controller,
onChanged: (value) {
setState(() {}); // Update UI for suffix icon
widget.onSearchChanged?.call(value);
},
decoration: InputDecoration(
border: InputBorder.none,
hintText: widget.hintText,
isDense: true,
contentPadding: EdgeInsets.zero,
child: Padding(
padding: EdgeInsets.only(top: extraWebPadding),
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
left: widget.showBackButton ? 68 : 16,
right: widget.rightButtons.isNotEmpty ? 60 : 16,
child: Container(
height: 36,
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(12)),
child: Row(
children: [
const Icon(Icons.search, size: 20),
const SizedBox(width: 4),
Expanded(
child: TextField(
controller: _controller,
onChanged: (value) {
setState(() {}); // Update UI for suffix icon
widget.onSearchChanged?.call(value);
},
decoration: InputDecoration(
border: InputBorder.none,
hintText: widget.hintText,
isDense: true,
contentPadding: EdgeInsets.zero,
),
),
),
),
if (_controller.text.isNotEmpty)
GestureDetector(
onTap: () {
_controller.clear();
widget.onSearchChanged?.call('');
setState(() {});
},
child: const Icon(Icons.close, size: 20),
),
],
if (_controller.text.isNotEmpty)
GestureDetector(
onTap: () {
_controller.clear();
widget.onSearchChanged?.call('');
setState(() {});
},
child: const Icon(Icons.close, size: 20),
),
],
),
),
),
),
if (widget.showBackButton) Positioned(left: 12, child: CustomBackButton()),
if (widget.rightButtons.isNotEmpty)
Positioned(right: 12, child: Row(mainAxisSize: MainAxisSize.min, children: widget.rightButtons)),
],
if (widget.showBackButton) Positioned(left: 12, child: CustomBackButton()),
if (widget.rightButtons.isNotEmpty)
Positioned(right: 12, child: Row(mainAxisSize: MainAxisSize.min, children: widget.rightButtons)),
],
),
),
),
],
......
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