Feat: fix bug navbar and queue porter

This commit is contained in:
orangdeso 2025-04-24 18:30:46 +07:00
parent 7d86393425
commit 0668f8d3dc
9 changed files with 156 additions and 110 deletions

View File

@ -638,7 +638,7 @@
"languageVersion": "3.4"
}
],
"generated": "2025-04-22T06:48:38.993021Z",
"generated": "2025-04-23T15:39:37.293764Z",
"generator": "pub",
"generatorVersion": "3.5.0",
"flutterRoot": "file:///D:/Flutter/flutter_sdk/flutter_3.24.0",

View File

@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.3333 3.33325C7.944 3.33325 6 5.27725 6 7.66659V21.9999H17.6667C19.3207 21.9999 20.6667 23.3459 20.6667 24.9999V26.6666C20.6667 27.7666 21.5589 28.66 22.6576 28.6653H22.6758C23.7698 28.66 24.658 27.7729 24.6654 26.6796C24.666 26.3263 24.6667 5.33325 24.6667 5.33325C24.6667 4.57992 24.9269 3.89192 25.3503 3.33325H10.3333ZM28 3.33325C26.8973 3.33325 26 4.23059 26 5.33325V9.33325H28.3333C29.2527 9.33325 30 8.58592 30 7.66659V5.33325C30 4.23059 29.1027 3.33325 28 3.33325ZM11 7.99992H19.6667C20.2187 7.99992 20.6667 8.44792 20.6667 8.99992C20.6667 9.55192 20.2187 9.99992 19.6667 9.99992H11C10.448 9.99992 10 9.55192 10 8.99992C10 8.44792 10.448 7.99992 11 7.99992ZM11 12.6666H19.6667C20.2187 12.6666 20.6667 13.1146 20.6667 13.6666C20.6667 14.2186 20.2187 14.6666 19.6667 14.6666H11C10.448 14.6666 10 14.2186 10 13.6666C10 13.1146 10.448 12.6666 11 12.6666ZM11 17.3333H18.3333C18.8853 17.3333 19.3333 17.7813 19.3333 18.3333C19.3333 18.8853 18.8853 19.3333 18.3333 19.3333H11C10.448 19.3333 10 18.8853 10 18.3333C10 17.7813 10.448 17.3333 11 17.3333ZM3.66667 23.3333C2.74733 23.3333 2 24.0806 2 24.9999V25.6666C2 27.3206 3.346 28.6666 5 28.6666H20.0169C19.5936 28.1079 19.3333 27.4199 19.3333 26.6666V24.9999C19.3333 24.0806 18.586 23.3333 17.6667 23.3333H3.66667Z" fill="#004B87"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.3333 3.33325C7.95204 3.33325 6 5.28529 6 7.66659V22.6666H3.66667C2.7576 22.6666 2 23.4242 2 24.3333V25.6666C2 27.3116 3.355 28.6666 5 28.6666H23C24.645 28.6666 26 27.3116 26 25.6666V9.33325H28.3333C29.2424 9.33325 30 8.57565 30 7.66659V6.33325C30 4.74209 28.7292 3.43357 27.1576 3.34888C27.1055 3.33951 27.0528 3.33429 27 3.33325H10.3333ZM10.3333 5.33325H24.2044C24.0897 5.64957 24 5.97952 24 6.33325V8.16919C23.9824 8.27654 23.9824 8.38605 24 8.49341V25.6666C24 26.2309 23.5643 26.6666 23 26.6666C22.4357 26.6666 22 26.2309 22 25.6666V24.3333C22 23.4242 21.2424 22.6666 20.3333 22.6666H8V7.66659C8 6.36654 9.03329 5.33325 10.3333 5.33325ZM27 5.33325C27.5643 5.33325 28 5.76892 28 6.33325V7.33325H26V6.33325C26 5.76892 26.4357 5.33325 27 5.33325ZM11.6667 8.66659C11.5342 8.66471 11.4026 8.68919 11.2796 8.73861C11.1567 8.78802 11.0447 8.86138 10.9504 8.95443C10.856 9.04747 10.7811 9.15834 10.7299 9.2806C10.6788 9.40286 10.6524 9.53406 10.6524 9.66659C10.6524 9.79911 10.6788 9.93031 10.7299 10.0526C10.7811 10.1748 10.856 10.2857 10.9504 10.3787C11.0447 10.4718 11.1567 10.5452 11.2796 10.5946C11.4026 10.644 11.5342 10.6685 11.6667 10.6666H20.3333C20.4658 10.6685 20.5974 10.644 20.7204 10.5946C20.8433 10.5452 20.9553 10.4718 21.0496 10.3787C21.144 10.2857 21.2189 10.1748 21.2701 10.0526C21.3212 9.93031 21.3476 9.79911 21.3476 9.66659C21.3476 9.53406 21.3212 9.40286 21.2701 9.2806C21.2189 9.15834 21.144 9.04747 21.0496 8.95443C20.9553 8.86138 20.8433 8.78802 20.7204 8.73861C20.5974 8.68919 20.4658 8.66471 20.3333 8.66659H11.6667ZM11.6667 13.3333C11.5342 13.3314 11.4026 13.3559 11.2796 13.4053C11.1567 13.4547 11.0447 13.528 10.9504 13.6211C10.856 13.7141 10.7811 13.825 10.7299 13.9473C10.6788 14.0695 10.6524 14.2007 10.6524 14.3333C10.6524 14.4658 10.6788 14.597 10.7299 14.7192C10.7811 14.8415 10.856 14.9524 10.9504 15.0454C11.0447 15.1385 11.1567 15.2118 11.2796 15.2612C11.4026 15.3106 11.5342 15.3351 11.6667 15.3333H20.3333C20.4658 15.3351 20.5974 15.3106 20.7204 15.2612C20.8433 15.2118 20.9553 15.1385 21.0496 15.0454C21.144 14.9524 21.2189 14.8415 21.2701 14.7192C21.3212 14.597 21.3476 14.4658 21.3476 14.3333C21.3476 14.2007 21.3212 14.0695 21.2701 13.9473C21.2189 13.825 21.144 13.7141 21.0496 13.6211C20.9553 13.528 20.8433 13.4547 20.7204 13.4053C20.5974 13.3559 20.4658 13.3314 20.3333 13.3333H11.6667ZM11.6667 17.9999C11.5342 17.998 11.4026 18.0225 11.2796 18.0719C11.1567 18.1214 11.0447 18.1947 10.9504 18.2878C10.856 18.3808 10.7811 18.4917 10.7299 18.6139C10.6788 18.7362 10.6524 18.8674 10.6524 18.9999C10.6524 19.1324 10.6788 19.2636 10.7299 19.3859C10.7811 19.5082 10.856 19.619 10.9504 19.7121C11.0447 19.8051 11.1567 19.8785 11.2796 19.9279C11.4026 19.9773 11.5342 20.0018 11.6667 19.9999H19C19.1325 20.0018 19.2641 19.9773 19.387 19.9279C19.51 19.8785 19.6219 19.8051 19.7163 19.7121C19.8107 19.619 19.8856 19.5082 19.9368 19.3859C19.9879 19.2636 20.0142 19.1324 20.0142 18.9999C20.0142 18.8674 19.9879 18.7362 19.9368 18.6139C19.8856 18.4917 19.8107 18.3808 19.7163 18.2878C19.6219 18.1947 19.51 18.1214 19.387 18.0719C19.2641 18.0225 19.1325 17.998 19 17.9999H11.6667ZM4 24.6666H6.83594C6.94329 24.6842 7.0528 24.6842 7.16016 24.6666H20V25.6666C20 26.0203 20.0897 26.3503 20.2044 26.6666H5C4.43567 26.6666 4 26.2309 4 25.6666V24.6666Z" fill="#9CA3AF"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -330,14 +330,16 @@ class SimpleAppbarComponent extends StatelessWidget implements PreferredSizeWidg
],
),
),
actions: [
ZoomTapAnimation(
child: IconButton(
onPressed: onTab,
icon: CustomeIcons.OrderHistoryOutline(),
),
)
],
actions: onTab != null
? [
ZoomTapAnimation(
child: IconButton(
onPressed: onTab,
icon: CustomeIcons.OrderHistoryOutline(),
),
)
]
: null,
);
}

View File

@ -52,7 +52,9 @@ class CustomeIcons {
static SvgPicture LogoutOutline({double? size, Color? color}) => getIcon('ic_logout', color: color);
static SvgPicture RemoveOutline({double? size, Color? color}) => getIcon('ic_remove', color: color);
static SvgPicture UploadOutline({double? size, Color? color}) => getIcon('ic_upload', color: color);
static SvgPicture ScrollOutline({double? size, Color? color}) => getIcon('ic_scroll_outline', color: color);
static SvgPicture ScrollFilled({double? size, Color? color}) => getIcon('ic_scroll_filled', color: color);
static SvgPicture FlightSeatFilled({double? size, Color? color}) => getIcon('ic_flight_seat_filled', color: color);
static SvgPicture PlaneRightFilled({double? size, Color? color}) => getIcon('ic_plane_filled', color: color);
static SvgPicture VIPFilled({double? size, Color? color}) => getIcon('ic_vip', color: color);

View File

@ -1,9 +1,19 @@
import 'dart:developer';
import 'package:get/get.dart';
class NavigationController extends GetxController {
RxInt currentPage = 0.obs;
final RxInt _currentPage = 0.obs;
// Property untuk Obx
RxInt get currentPage => _currentPage;
void goToTab(int page) {
currentPage.value = page;
log("Changing tab to: $page (type: ${page.runtimeType})");
// Langsung gunakan page sebagai int
_currentPage.value = page;
log("Current page is now: ${_currentPage.value} (type: ${_currentPage.value.runtimeType})");
}
}

View File

@ -120,19 +120,25 @@ class _HomeScreenState extends State<HomeScreen> {
return;
}
if (!_porterQueueController.validatePorterQueueForDeletion()) {
if (_porterQueueController.currentPorter.value == null) {
SnackbarHelper.showError(
'Gagal',
'Tidak ada antrian porter yang aktif.',
);
return;
}
final confirm = await _showStopConfirmationDialog();
final porterId = _porterQueueController.currentPorter.value!.id!;
final canProceed = await _porterQueueController.checkConditionForPorter(porterId);
if (!canProceed) {
return;
}
final confirm = await _showStopConfirmationDialog();
if (!confirm) return;
_showLoadingDialog();
final porterId = _porterQueueController.currentPorter.value!.id!;
final success = await _porterQueueController.deletePorterQueue(porterId);
if (Get.isDialogOpen == true) {
@ -145,20 +151,14 @@ class _HomeScreenState extends State<HomeScreen> {
'Anda telah berhenti dari antrian porter',
);
setState(() {});
} else {
SnackbarHelper.showError(
'Gagal',
'Gagal menghentikan antrian porter: ${_porterQueueController.error.value}',
);
}
} catch (e) {
if (Get.isDialogOpen == true) {
Get.back();
}
SnackbarHelper.showError(
'Gagal',
'Gagal menghentikan antrian porter: ${e.toString()}',
'Gagal menghentikan antrian porter.',
);
}
}
@ -422,49 +422,44 @@ class _HomeScreenState extends State<HomeScreen> {
),
SizedBox(height: 32.w),
CustomeShadowCotainner(
child: ZoomTapAnimation(
child: GestureDetector(
onTap: () => _porterQueueController.currentPorter.value != null
? _handleStopPorterQueue()
: _handlePorterQueueCreation(),
child: Column(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 6.h),
decoration: BoxDecoration(
color: _porterQueueController.currentPorter.value != null
? RedColors.red100
: PrimaryColors.primary200,
borderRadius: BorderRadius.circular(10.r),
child: Obx(() {
final hasPorter = _porterQueueController.currentPorter.value != null;
return ZoomTapAnimation(
child: GestureDetector(
onTap: hasPorter
? _handleStopPorterQueue // sekarang benar-benar terpilih saat Obx rebuild
: _handlePorterQueueCreation,
child: Column(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 6.h),
decoration: BoxDecoration(
color: hasPorter ? RedColors.red100 : PrimaryColors.primary200,
borderRadius: BorderRadius.circular(10.r),
),
child: hasPorter
? Icon(
Icons.power_settings_new,
color: Colors.red,
size: 32.w,
)
: SvgPicture.asset(
'assets/icons/ic_account.svg',
width: 32.w,
height: 32.h,
),
),
child: Obx(() => _porterQueueController.currentPorter.value != null
? Icon(
Icons.power_settings_new,
color: Colors.red,
size: 32.w,
)
: SvgPicture.asset(
'assets/icons/ic_account.svg',
width: 32.w,
height: 32.h,
)),
),
SizedBox(height: 10.h),
Obx(
() => _porterQueueController.currentPorter.value != null
? TypographyStyles.body(
'Stop',
color: GrayColors.gray800,
)
: TypographyStyles.body(
'Mulai Antrian',
),
),
],
SizedBox(height: 10.h),
TypographyStyles.body(
hasPorter ? 'Stop' : 'Mulai Antrian',
color: GrayColors.gray800,
),
],
),
),
),
),
)
);
}),
),
],
),
),

View File

@ -1,4 +1,5 @@
import 'package:e_porter/_core/constants/colors.dart';
import 'package:e_porter/presentation/screens/boarding_pass/pages/history_porter_screen.dart';
import 'package:e_porter/presentation/screens/home/pages/home_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
@ -11,7 +12,6 @@ import '../../controllers/navigation_controller.dart';
import '../boarding_pass/pages/boarding_pass_screen.dart';
import '../profile/pages/profile_screen.dart';
class MainNavigation extends StatefulWidget {
final int initialTabIndex;
@ -23,67 +23,77 @@ class MainNavigation extends StatefulWidget {
class _MainNavigationState extends State<MainNavigation> {
final NavigationController navigationController = Get.find<NavigationController>();
late final String role;
late final List<Widget> pages;
@override
void initState() {
super.initState();
role = Get.arguments as String? ?? 'penumpang';
navigationController.currentPage.value = widget.initialTabIndex;
pages = [
HomeScreen(),
if (role == 'penumpang') BoardingPassScreen() else HistoryPorterScreen(),
ProfileScreen(),
];
}
@override
Widget build(BuildContext context) {
final bool isPassenger = role == 'penumpang';
return Scaffold(
body: Stack(
children: [
Obx(() {
final List<Widget> pages = [
HomeScreen(),
BoardingPassScreen(),
ProfileScreen(),
];
// Dapatkan nilai dari currentPage
int pageIndex = navigationController.currentPage.value;
// Pastikan nilai valid
if (pageIndex < 0 || pageIndex >= pages.length) {
pageIndex = 0;
}
return IndexedStack(
index: navigationController.currentPage.value,
index: pageIndex,
children: pages,
);
}),
})
],
),
bottomNavigationBar: Obx(() {
// final current = navigationController.currentPage.value;
int current = navigationController.currentPage.value;
return BottomAppBar(
color: Colors.white,
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: _bottomAppBarItem(
context,
iconPath: navigationController.currentPage.value == 0
? 'assets/icons/ic_home_filled.svg'
: 'assets/icons/ic_home.svg',
page: 0,
label: 'Home',
),
_buildNavItem(
iconActive: 'assets/icons/ic_home_filled.svg',
iconInactive: 'assets/icons/ic_home.svg',
label: 'Home',
page: 0,
current: current,
),
Expanded(
child: _bottomAppBarItem(
context,
iconPath: navigationController.currentPage.value == 1
? 'assets/icons/ic_boarding_pass_filled.svg'
: 'assets/icons/ic_boarding_pass.svg',
page: 1,
label: 'Boarding Pass',
),
_buildNavItem(
iconActive:
isPassenger ? 'assets/icons/ic_boarding_pass_filled.svg' : 'assets/icons/ic_scroll_filled.svg',
iconInactive:
isPassenger ? 'assets/icons/ic_boarding_pass.svg' : 'assets/icons/ic_scroll_outline.svg',
label: isPassenger ? 'Boarding Pass' : 'Riwayat',
page: 1,
current: current,
),
Expanded(
child: _bottomAppBarItem(
context,
iconPath: navigationController.currentPage.value == 2
? 'assets/icons/ic_profile_filled.svg'
: 'assets/icons/ic_profile.svg',
page: 2,
label: 'Profil',
),
_buildNavItem(
iconActive: 'assets/icons/ic_profile_filled.svg',
iconInactive: 'assets/icons/ic_profile.svg',
label: 'Profil',
page: 2,
current: current,
),
],
),
@ -93,24 +103,22 @@ class _MainNavigationState extends State<MainNavigation> {
);
}
Widget _bottomAppBarItem(
BuildContext context, {
required String iconPath,
required int page,
Widget _buildNavItem({
required String iconActive,
required String iconInactive,
required String label,
required int page,
required int current,
}) {
final controller = Get.find<NavigationController>();
final isActive = controller.currentPage.value == page;
return ZoomTapAnimation(
onTap: () => controller.goToTab(page),
child: Container(
color: Colors.transparent,
final isActive = current == page;
return Expanded(
child: ZoomTapAnimation(
onTap: () => navigationController.goToTab(page),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SvgPicture.asset(
iconPath,
isActive ? iconActive : iconInactive,
width: 24.w,
height: 24.h,
),
@ -118,7 +126,6 @@ class _MainNavigationState extends State<MainNavigation> {
TypographyStyles.caption(
label,
color: isActive ? PrimaryColors.primary800 : GrayColors.gray400,
letterSpacing: 0.2,
fontWeight: isActive ? FontWeight.w700 : FontWeight.w500,
),
],

View File

@ -7,13 +7,17 @@ import 'package:e_porter/domain/bindings/profil_binding.dart';
import 'package:e_porter/domain/bindings/search_flight_binding.dart';
import 'package:e_porter/domain/bindings/ticket_binding.dart';
import 'package:e_porter/domain/bindings/transaction_binding.dart';
import 'package:e_porter/domain/bindings/transaction_porter_binding.dart';
import 'package:e_porter/presentation/screens/auth/pages/forget_password_screen.dart';
import 'package:e_porter/presentation/screens/auth/pages/login_screen.dart';
import 'package:e_porter/presentation/screens/auth/pages/register_screen.dart';
import 'package:e_porter/presentation/screens/auth/pages/state_succes_screen.dart';
import 'package:e_porter/presentation/screens/boarding_pass/pages/boarding_pass_screen.dart';
import 'package:e_porter/presentation/screens/boarding_pass/pages/detail_ticket_screen.dart';
import 'package:e_porter/presentation/screens/boarding_pass/pages/history_porter_screen.dart';
import 'package:e_porter/presentation/screens/boarding_pass/pages/print_boarding_pass_screen.dart';
import 'package:e_porter/presentation/screens/boarding_pass/pages/search_porter_screen.dart';
import 'package:e_porter/presentation/screens/boarding_pass/pages/scan_qr_screen.dart';
import 'package:e_porter/presentation/screens/boarding_pass/pages/transaction_history.dart';
import 'package:e_porter/presentation/screens/home/pages/booking_tickets_screen.dart';
import 'package:e_porter/presentation/screens/home/pages/choose_seat_screen.dart';
@ -44,6 +48,7 @@ class AppRoutes {
MainNavigationBinding(),
HistoryBinding(),
PorterQueueBinding(),
TransactionPorterBinding(),
],
),
GetPage(
@ -149,6 +154,22 @@ class AppRoutes {
name: Routes.PRINTBOARDINGPASS,
page: () => PrintBoardingPassScreen(),
),
GetPage(
name: Routes.SCANQR,
page: () => ScanQRScreen(),
bindings: [
PorterQueueBinding(),
TransactionBinding(),
],
),
GetPage(
name: Routes.PROCESSING,
page: () => ProcessingPorterScreen(),
),
GetPage(
name: Routes.HISTORYPORTER,
page: () => HistoryPorterScreen(),
),
GetPage(
name: Routes.ADDPASSENGER,
page: () => AddPassengerScreen(),
@ -182,6 +203,9 @@ class Routes {
static const TRANSACTIONHISTORY = '/transaction_history';
static const DETAILTICKET = '/detail_ticket';
static const PRINTBOARDINGPASS = '/print_boarding_pass';
static const SCANQR = '/scan_qr';
static const PROCESSING = '/processing';
static const HISTORYPORTER = '/history_porter';
static const ADDPASSENGER = '/add_passenger';
}